Add full project files

This commit is contained in:
root
2026-07-04 19:24:56 +03:30
parent d54f5441a3
commit b245e7b71a
835 changed files with 30149 additions and 0 deletions

View File

@@ -0,0 +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
}