full
This commit is contained in:
@@ -6,13 +6,17 @@ 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 {
|
||||
resolveRatingForComment,
|
||||
recalculateUserRating
|
||||
} = require('../../../utils/commentRating')
|
||||
|
||||
const { resolveCommentModerationStatus } = require('../../../utils/contentModeration')
|
||||
const {
|
||||
canUseFreeCreation,
|
||||
consumeFreeCreation,
|
||||
freeCreationLimitResponse
|
||||
} = require('../../../utils/freeCreationLimit')
|
||||
const getOfferPriceFromDatabase = async (itemName) => {
|
||||
const item = await OfferTypeModel.findOne({ name: itemName })
|
||||
if (!item) {
|
||||
@@ -23,8 +27,12 @@ const getOfferPriceFromDatabase = async (itemName) => {
|
||||
|
||||
const getOfferTypes = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const authHeader = req.header('Authorization')
|
||||
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
||||
return res.status(401).json({ message: 'Access Denied' })
|
||||
}
|
||||
const token = authHeader.split(' ')[1]
|
||||
if (!token) return res.status(401).json({ message: 'Access Denied' })
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
@@ -35,22 +43,41 @@ const getOfferTypes = async (req, res, next) => {
|
||||
message: 'کاربر یافت نشد'
|
||||
})
|
||||
}
|
||||
let offerTypes = await OfferTypeModel.find({}, 'name price')
|
||||
let offerTypes = await OfferTypeModel.find({}, 'name price').lean()
|
||||
|
||||
// بررسی برای مواردی مانند پیدا نشدن انواع پروژه
|
||||
if (!offerTypes) {
|
||||
return res.status(404).json({ message: 'انواع پروژه یافت نشد.' })
|
||||
// اگر در دیتابیس نوعها خالی باشد، پیشفرض رایگان/پولی
|
||||
if (!offerTypes || offerTypes.length === 0) {
|
||||
offerTypes = [
|
||||
{ name: 'free', price: 0 },
|
||||
{ name: 'normal', price: 50000 }
|
||||
]
|
||||
}
|
||||
// اگر کاربر درخواست ماهانه نداشته باشد، نوع پروژه ماهانه را حذف کنید
|
||||
if (user.monthly_free_offer <= 0) {
|
||||
offerTypes = offerTypes.filter(projectType => projectType.name !== 'free')
|
||||
}
|
||||
// ارسال انواع پروژه به کاربر
|
||||
res.status(200).json({ offerTypes })
|
||||
|
||||
const canFree =
|
||||
(user.monthly_free_offer || 0) > 0 && canUseFreeCreation(user)
|
||||
|
||||
// رایگان را حذف نکن — اگر مجاز نیست، با فلگ disabled برگردان تا UI نشان دهد
|
||||
offerTypes = offerTypes.map((t) => {
|
||||
const plain = t.toObject ? t.toObject() : { ...t }
|
||||
if (plain.name === 'free') {
|
||||
plain.disabled = !canFree
|
||||
plain.unavailableReason = canFree
|
||||
? null
|
||||
: (user.monthly_free_offer || 0) <= 0
|
||||
? 'سهمیه رایگان ماهانه شما تمام شده است'
|
||||
: 'سقف ثبت رایگان شما به پایان رسیده است'
|
||||
}
|
||||
return plain
|
||||
})
|
||||
|
||||
res.status(200).json({
|
||||
offerTypes,
|
||||
canUseFree: canFree,
|
||||
monthly_free_offer: user.monthly_free_offer || 0
|
||||
})
|
||||
} catch (error) {
|
||||
// در صورت بروز خطا، ارسال پیام خطا به کاربر
|
||||
console.error('Error in getOfferTypes:', error)
|
||||
res.status(500).json({ message: 'خطا در دریافت انواع پروژه.' })
|
||||
res.status(500).json({ message: 'خطا در دریافت انواع درخواست.' })
|
||||
}
|
||||
}
|
||||
const getUserOffers = async (req, res, next) => {
|
||||
@@ -122,7 +149,6 @@ const updateOfferStatus = async (req, res, next) => {
|
||||
|
||||
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)
|
||||
|
||||
@@ -133,7 +159,6 @@ const updateOfferStatus = async (req, res, next) => {
|
||||
|
||||
// یافتن آفر موردنظر
|
||||
const offer = await OfferModel.findById(offerId)
|
||||
const senderUser = await UserModel.findById(offer?.sender)
|
||||
|
||||
if (!offer) {
|
||||
return res.status(404).json({ error: 'Offer not found' })
|
||||
@@ -153,59 +178,6 @@ const updateOfferStatus = async (req, res, next) => {
|
||||
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,
|
||||
@@ -232,12 +204,28 @@ const handleSuccessfulOfferPayment = async (req, res) => {
|
||||
const reciverUser = await UserModel.findById(reciverId)
|
||||
if (!user) return res.status(404).json({ error: 'User not found' })
|
||||
|
||||
// اگر گیرنده «دریافت پرداختی از چت» رو غیرفعال کرده باشه، درخواست همکاری براش
|
||||
// همیشه رایگانه — مستقل از سهمیهی رایگان ماهانهی فرستنده
|
||||
const receiverOffersFree = reciverUser?.offer_payment_enabled === false
|
||||
|
||||
let price
|
||||
if (user.monthly_free_offer > 0 && offerType === 'free') {
|
||||
// Use free offer and decrement counter
|
||||
if (receiverOffersFree) {
|
||||
price = 0
|
||||
} else if (user.monthly_free_offer > 0 && offerType === 'free' && canUseFreeCreation(user)) {
|
||||
const consumed = await consumeFreeCreation(user)
|
||||
if (!consumed.ok) {
|
||||
return res.status(403).json(freeCreationLimitResponse())
|
||||
}
|
||||
price = 0
|
||||
user.monthly_free_offer -= 1
|
||||
await user.save()
|
||||
} else if (offerType === 'free') {
|
||||
return res.status(403).json({
|
||||
error: true,
|
||||
message: canUseFreeCreation(user)
|
||||
? 'سهمیه درخواست رایگان ماهانه شما تمام شده است.'
|
||||
: freeCreationLimitResponse().message,
|
||||
})
|
||||
} else {
|
||||
// Retrieve offer price based on type
|
||||
price = await getOfferPriceFromDatabase(offerType)
|
||||
@@ -283,34 +271,6 @@ const handleSuccessfulOfferPayment = async (req, res) => {
|
||||
})
|
||||
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
|
||||
@@ -392,6 +352,8 @@ const createOfferComment = async (req, res, next) => {
|
||||
return res.status(400).send({ message: 'Rating must be between 1 and 5' })
|
||||
}
|
||||
|
||||
const commentStatus = resolveCommentModerationStatus(comment)
|
||||
|
||||
const newComment = new CommentModel({
|
||||
user: user_id,
|
||||
offer: offerId,
|
||||
@@ -399,7 +361,7 @@ const createOfferComment = async (req, res, next) => {
|
||||
rating: ratingValue,
|
||||
comment,
|
||||
comment_for: 'user',
|
||||
status: 'pending'
|
||||
status: commentStatus
|
||||
})
|
||||
await newComment.save()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user