Merge branch 'main' of http://193.151.143.243:3000/modstagram/modstagram-back
# Conflicts: # controllers/application/projects/getProjectController.js # controllers/application/stories/storyController.js # controllers/application/users/getUserController.js # controllers/panel/projects/projectController.js # index.js
This commit is contained in:
@@ -1,221 +1,221 @@
|
||||
/* 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 {
|
||||
canCreateProject,
|
||||
respondProjectProfileIncomplete
|
||||
} = require('../../../utils/projectProfile')
|
||||
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 (!canCreateProject(user)) {
|
||||
return respondProjectProfileIncomplete(res)
|
||||
}
|
||||
// اعتبارسنجی درخواست
|
||||
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 {
|
||||
canCreateProject,
|
||||
respondProjectProfileIncomplete
|
||||
} = require('../../../utils/projectProfile')
|
||||
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 (!canCreateProject(user)) {
|
||||
return respondProjectProfileIncomplete(res)
|
||||
}
|
||||
// اعتبارسنجی درخواست
|
||||
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,15 +1,97 @@
|
||||
/* eslint-disable camelcase */
|
||||
const { default: mongoose } = require('mongoose')
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const { projectPublicStatusFilter } = require('../../../utils/moderationStatus')
|
||||
const RequestModel = require('../../../models/RequestModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const { buildUnifiedInterestScore, blendFreshIntoRanked } = require('../../../utils/exploreAlgorithm')
|
||||
|
||||
function getOptionalUserId (req) {
|
||||
try {
|
||||
const token = req.header('Authorization')?.split(' ')[1]
|
||||
if (!token) return null
|
||||
const decoded = jwt.verify(token, process.env.APP_SECRET)
|
||||
return decoded?.id || null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Projects matching the viewer's cross-content interest profile (built from their
|
||||
* post/shop/academy/billboard interactions) — projects carry their own `expertise` field
|
||||
* directly (no separate category model like shop/billboard), so interest tags are matched
|
||||
* straight against it. Mirrors getInterestMatchedAds in advertisingController.js.
|
||||
*/
|
||||
async function getInterestMatchedProjects (userId, filter, excludeIds, limit = 5) {
|
||||
if (!userId) return []
|
||||
const interestWeights = await buildUnifiedInterestScore(userId)
|
||||
const tags = Object.keys(interestWeights).filter((tag) => interestWeights[tag] > 0)
|
||||
if (!tags.length) return []
|
||||
|
||||
return ProjectModel.find({
|
||||
...filter,
|
||||
expertise: { $in: tags },
|
||||
_id: { $nin: excludeIds }
|
||||
})
|
||||
.sort({ createdAt: -1 })
|
||||
.limit(limit)
|
||||
.lean()
|
||||
}
|
||||
|
||||
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 REQUEST_USER_SELECT =
|
||||
'user_level first_name last_name user_name is_verified verify_badge user_score rate profile_image'
|
||||
|
||||
const enrichProjectsWithRequests = async (projectDocs) => {
|
||||
const docs = projectDocs.map((project) =>
|
||||
project.toObject ? project.toObject() : { ...project._doc }
|
||||
)
|
||||
|
||||
const projectIds = docs
|
||||
.filter(
|
||||
(project) =>
|
||||
Array.isArray(project.requested_users) && project.requested_users.length > 0
|
||||
)
|
||||
.map((project) => project._id)
|
||||
|
||||
if (projectIds.length === 0) return docs
|
||||
|
||||
const requests = await RequestModel.find({ project: { $in: projectIds } })
|
||||
.populate('user', REQUEST_USER_SELECT)
|
||||
.select('user status project')
|
||||
.sort({ status: 1, createdAt: -1 })
|
||||
.lean()
|
||||
|
||||
const requestsByProject = new Map()
|
||||
requests.forEach((request) => {
|
||||
const projectKey = String(request.project)
|
||||
if (!requestsByProject.has(projectKey)) {
|
||||
requestsByProject.set(projectKey, [])
|
||||
}
|
||||
requestsByProject.get(projectKey).push({
|
||||
_id: request._id,
|
||||
project: projectKey,
|
||||
user: request.user,
|
||||
status: request.status,
|
||||
price: null,
|
||||
time: null
|
||||
})
|
||||
})
|
||||
|
||||
return docs.map((project) => {
|
||||
const projectRequests = requestsByProject.get(String(project._id))
|
||||
if (!projectRequests?.length) return project
|
||||
return { ...project, projectRequests }
|
||||
})
|
||||
}
|
||||
const getProjects = async (req, res, next) => {
|
||||
try {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
@@ -17,7 +99,11 @@ const getProjects = async (req, res, next) => {
|
||||
// هر پروژهای که در پنل «انتشار» (accept) شده باشد در وباپ نمایش داده میشود —
|
||||
// بدون وابستگی به payment_status، public_status یا isExpired.
|
||||
const filter = {
|
||||
status: 'accepted'
|
||||
status: projectPublicStatusFilter(),
|
||||
$or: [
|
||||
{ selected_user: null },
|
||||
{ selected_user: { $exists: false } }
|
||||
]
|
||||
}
|
||||
if (expertise) {
|
||||
filter.expertise = expertise
|
||||
@@ -39,7 +125,7 @@ const getProjects = async (req, res, next) => {
|
||||
}
|
||||
const projects = await ProjectModel.paginate(filter, options)
|
||||
|
||||
const newProj = projects.docs
|
||||
const newProj = await enrichProjectsWithRequests(projects.docs)
|
||||
res.status(200).json({
|
||||
projects: newProj,
|
||||
totalPages: projects.totalPages, // ارسال تعداد کل صفحات
|
||||
@@ -53,7 +139,32 @@ const getProjects = async (req, res, next) => {
|
||||
sort: { acceptedAt: -1, createdAt: -1 } // مرتبسازی بر اساس acceptedAt و سپس createdAt
|
||||
}
|
||||
const projects = await ProjectModel.paginate(filter, options)
|
||||
const newProj = projects.docs
|
||||
let newProj = await enrichProjectsWithRequests(projects.docs)
|
||||
|
||||
// فقط توی مرور پیشفرض (بدون فیلتر تخصص، صفحه اول) چند پروژهی مرتبط با علاقهمندی
|
||||
// کاربر (بر اساس تعامل قبلیش با پست/فروشگاه/آموزشگاه/بیلبورد) قاطی نتایج میشه
|
||||
const isDefaultBrowsePath = !expertise && parseInt(page) === 1
|
||||
if (isDefaultBrowsePath) {
|
||||
try {
|
||||
const userId = getOptionalUserId(req)
|
||||
const interestProjects = await getInterestMatchedProjects(
|
||||
userId,
|
||||
filter,
|
||||
newProj.map((p) => p._id)
|
||||
)
|
||||
if (interestProjects.length) {
|
||||
const mappedInterestProjects = await enrichProjectsWithRequests(interestProjects)
|
||||
newProj = blendFreshIntoRanked(
|
||||
newProj,
|
||||
[...newProj, ...mappedInterestProjects],
|
||||
0.25
|
||||
).slice(0, parseInt(limit))
|
||||
}
|
||||
} catch {
|
||||
/* non-blocking: personalization is a bonus, never break the listing */
|
||||
}
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
projects: newProj,
|
||||
totalPages: projects.totalPages, // ارسال تعداد کل صفحات
|
||||
@@ -136,6 +247,26 @@ const getUserProjects = async (req, res, next) => {
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' })
|
||||
}
|
||||
|
||||
if (req.query.linkable === '1') {
|
||||
const options = {
|
||||
page: req.query.page || 1,
|
||||
limit: req.query.limit || 100,
|
||||
sort: { createdAt: -1 },
|
||||
}
|
||||
const projects = await ProjectModel.paginate(
|
||||
{ creator_id: user._id, status: { $in: ['accepted', 'done'] } },
|
||||
options
|
||||
)
|
||||
return res.status(200).json({
|
||||
data: {
|
||||
projects: projects.docs,
|
||||
totalPages: projects.totalPages,
|
||||
totalItems: projects.totalDocs,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const response = {}
|
||||
if (user.user_type === 'user') {
|
||||
const options = {
|
||||
@@ -166,8 +297,8 @@ const getUserProjects = async (req, res, next) => {
|
||||
|
||||
// پیجینیشن بر روی لیست پروژههای کاربر اعمال میشود
|
||||
const projects = await ProjectModel.paginate(
|
||||
{ creator_id: user._id, status: { $in: ['done', 'accepted'] } }, // فیلتر
|
||||
options // گزینههای پیجینیشن
|
||||
{ creator_id: user._id, status: { $nin: ['done', 'cancled', 'ongoing'] } },
|
||||
options
|
||||
)
|
||||
response.projects = projects.docs
|
||||
response.totalPages = projects.totalPages // ارسال تعداد کل صفحات
|
||||
@@ -195,6 +326,24 @@ const getUserProjectsWeb = async (req, res, next) => {
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' })
|
||||
}
|
||||
|
||||
if (req.query.linkable === '1') {
|
||||
const options = {
|
||||
page: req.query.page || 1,
|
||||
limit: req.query.limit || 100,
|
||||
sort: { createdAt: -1 },
|
||||
}
|
||||
const projects = await ProjectModel.paginate(
|
||||
{ creator_id: user._id, status: { $in: ['accepted', 'done'] } },
|
||||
options
|
||||
)
|
||||
return res.status(200).json({
|
||||
projects: projects.docs,
|
||||
totalPages: projects.totalPages,
|
||||
totalItems: projects.totalDocs,
|
||||
})
|
||||
}
|
||||
|
||||
const data = {}
|
||||
if (user.user_type === 'user') {
|
||||
const options = {
|
||||
@@ -225,8 +374,8 @@ const getUserProjectsWeb = async (req, res, next) => {
|
||||
|
||||
// پیجینیشن بر روی لیست پروژههای کاربر اعمال میشود
|
||||
const projects = await ProjectModel.paginate(
|
||||
{ creator_id: user._id, status: { $in: ['done', 'accepted'] } }, // فیلتر
|
||||
options // گزینههای پیجینیشن
|
||||
{ creator_id: user._id, status: { $nin: ['done', 'cancled', 'ongoing'] } },
|
||||
options
|
||||
)
|
||||
data.projects = projects.docs
|
||||
data.totalPages = projects.totalPages // ارسال تعداد کل صفحات
|
||||
|
||||
@@ -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,209 +1,209 @@
|
||||
/* 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) {
|
||||
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 project = await ProjectModel.findById(project_id)
|
||||
if (!project) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'پروژه یافت نشد'
|
||||
})
|
||||
}
|
||||
if (String(project.creator_id) === String(user._id)) {
|
||||
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 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) {
|
||||
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) {
|
||||
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 project = await ProjectModel.findById(project_id)
|
||||
if (!project) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'پروژه یافت نشد'
|
||||
})
|
||||
}
|
||||
if (String(project.creator_id) === String(user._id)) {
|
||||
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 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) {
|
||||
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,390 +1,390 @@
|
||||
/* 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 {
|
||||
resolveRatingForComment,
|
||||
recalculateUserRating
|
||||
} = require('../../../utils/commentRating')
|
||||
const {
|
||||
canCreateProject,
|
||||
respondProjectProfileIncomplete
|
||||
} = require('../../../utils/projectProfile')
|
||||
|
||||
const saveProjectComment = async ({
|
||||
targetUserId,
|
||||
projectId,
|
||||
creatorId,
|
||||
comment,
|
||||
rate,
|
||||
commentFor
|
||||
}) => {
|
||||
const { ratingValue, isNewRating, requiresRating, alreadyRated } = await resolveRatingForComment({
|
||||
creatorId,
|
||||
targetUserId,
|
||||
rate
|
||||
})
|
||||
|
||||
if (alreadyRated) {
|
||||
return { error: { status: 400, message: 'شما قبلاً به این کاربر امتیاز دادهاید.' } }
|
||||
}
|
||||
|
||||
if (requiresRating) {
|
||||
return { error: { status: 400, message: 'Rating must be between 1 and 5' } }
|
||||
}
|
||||
|
||||
const newComment = new CommentModel({
|
||||
user: targetUserId,
|
||||
project: projectId,
|
||||
creator: creatorId,
|
||||
rating: ratingValue,
|
||||
comment,
|
||||
comment_for: commentFor,
|
||||
status: 'pending'
|
||||
})
|
||||
await newComment.save()
|
||||
|
||||
if (isNewRating && commentFor === 'user') {
|
||||
await recalculateUserRating(targetUserId)
|
||||
}
|
||||
|
||||
return { ratingValue, isNewRating }
|
||||
}
|
||||
|
||||
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 || !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 commentResult = await saveProjectComment({
|
||||
targetUserId: user_id,
|
||||
projectId: project_id,
|
||||
creatorId: userId,
|
||||
comment,
|
||||
rate,
|
||||
commentFor: 'user'
|
||||
})
|
||||
|
||||
if (commentResult.error) {
|
||||
return res.status(commentResult.error.status).send({ message: commentResult.error.message })
|
||||
}
|
||||
|
||||
const user = await UserModel.findById(user_id)
|
||||
|
||||
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 || !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 commentResult = await saveProjectComment({
|
||||
targetUserId: user_id,
|
||||
projectId: project_id,
|
||||
creatorId: userId,
|
||||
comment,
|
||||
rate,
|
||||
commentFor: 'user'
|
||||
})
|
||||
|
||||
if (commentResult.error) {
|
||||
return res.status(commentResult.error.status).send({ message: commentResult.error.message })
|
||||
}
|
||||
|
||||
const user = await UserModel.findById(user_id)
|
||||
|
||||
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 || !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 commentResult = await saveProjectComment({
|
||||
targetUserId: user_id,
|
||||
projectId: project_id,
|
||||
creatorId: userId,
|
||||
comment,
|
||||
rate,
|
||||
commentFor: 'project'
|
||||
})
|
||||
|
||||
if (commentResult.error) {
|
||||
return res.status(commentResult.error.status).send({ message: commentResult.error.message })
|
||||
}
|
||||
|
||||
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 (!canCreateProject(user)) {
|
||||
return respondProjectProfileIncomplete(res)
|
||||
}
|
||||
|
||||
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.' })
|
||||
}
|
||||
|
||||
const alreadyRated = project.ratings.some((item) =>
|
||||
item.creator_id.toString() === userId.toString()
|
||||
)
|
||||
if (alreadyRated) {
|
||||
return res.status(400).send({ message: 'شما قبلاً به این پروژه امتیاز دادهاید' })
|
||||
}
|
||||
|
||||
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 {
|
||||
resolveRatingForComment,
|
||||
recalculateUserRating
|
||||
} = require('../../../utils/commentRating')
|
||||
const {
|
||||
canCreateProject,
|
||||
respondProjectProfileIncomplete
|
||||
} = require('../../../utils/projectProfile')
|
||||
|
||||
const saveProjectComment = async ({
|
||||
targetUserId,
|
||||
projectId,
|
||||
creatorId,
|
||||
comment,
|
||||
rate,
|
||||
commentFor
|
||||
}) => {
|
||||
const { ratingValue, isNewRating, requiresRating, alreadyRated } = await resolveRatingForComment({
|
||||
creatorId,
|
||||
targetUserId,
|
||||
rate
|
||||
})
|
||||
|
||||
if (alreadyRated) {
|
||||
return { error: { status: 400, message: 'شما قبلاً به این کاربر امتیاز دادهاید.' } }
|
||||
}
|
||||
|
||||
if (requiresRating) {
|
||||
return { error: { status: 400, message: 'Rating must be between 1 and 5' } }
|
||||
}
|
||||
|
||||
const newComment = new CommentModel({
|
||||
user: targetUserId,
|
||||
project: projectId,
|
||||
creator: creatorId,
|
||||
rating: ratingValue,
|
||||
comment,
|
||||
comment_for: commentFor,
|
||||
status: 'pending'
|
||||
})
|
||||
await newComment.save()
|
||||
|
||||
if (isNewRating && commentFor === 'user') {
|
||||
await recalculateUserRating(targetUserId)
|
||||
}
|
||||
|
||||
return { ratingValue, isNewRating }
|
||||
}
|
||||
|
||||
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 || !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 commentResult = await saveProjectComment({
|
||||
targetUserId: user_id,
|
||||
projectId: project_id,
|
||||
creatorId: userId,
|
||||
comment,
|
||||
rate,
|
||||
commentFor: 'user'
|
||||
})
|
||||
|
||||
if (commentResult.error) {
|
||||
return res.status(commentResult.error.status).send({ message: commentResult.error.message })
|
||||
}
|
||||
|
||||
const user = await UserModel.findById(user_id)
|
||||
|
||||
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 || !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 commentResult = await saveProjectComment({
|
||||
targetUserId: user_id,
|
||||
projectId: project_id,
|
||||
creatorId: userId,
|
||||
comment,
|
||||
rate,
|
||||
commentFor: 'user'
|
||||
})
|
||||
|
||||
if (commentResult.error) {
|
||||
return res.status(commentResult.error.status).send({ message: commentResult.error.message })
|
||||
}
|
||||
|
||||
const user = await UserModel.findById(user_id)
|
||||
|
||||
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 || !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 commentResult = await saveProjectComment({
|
||||
targetUserId: user_id,
|
||||
projectId: project_id,
|
||||
creatorId: userId,
|
||||
comment,
|
||||
rate,
|
||||
commentFor: 'project'
|
||||
})
|
||||
|
||||
if (commentResult.error) {
|
||||
return res.status(commentResult.error.status).send({ message: commentResult.error.message })
|
||||
}
|
||||
|
||||
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 (!canCreateProject(user)) {
|
||||
return respondProjectProfileIncomplete(res)
|
||||
}
|
||||
|
||||
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.' })
|
||||
}
|
||||
|
||||
const alreadyRated = project.ratings.some((item) =>
|
||||
item.creator_id.toString() === userId.toString()
|
||||
)
|
||||
if (alreadyRated) {
|
||||
return res.status(400).send({ message: 'شما قبلاً به این پروژه امتیاز دادهاید' })
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user