This commit is contained in:
payacom
2026-08-31 20:45:41 +03:30
parent fa9f23c61d
commit 3f416a7a60
367 changed files with 621895 additions and 6443 deletions

View File

@@ -0,0 +1,81 @@
const cron = require('node-cron')
const OrderModel = require('../models/OrderModel')
const { releaseOrderFunds, PAYMENT_TIMEOUT_MINUTES } = require('../controllers/application/orders/orderController')
const { notifyUser } = require('../utils/notifyUser')
let ioInstance = null
/** Called once from index.js right after the socket.io server is created — cron jobs have no `req`. */
function setIo (io) {
ioInstance = io
}
/** Auto-release seller funds 7 days after fulfillment if the buyer never confirmed receipt. */
const autoReleaseFulfilledOrders = async () => {
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
try {
const orders = await OrderModel.find({
status: { $in: ['shipped', 'ready_for_pickup'] },
walletReleased: false,
fulfilledAt: { $lte: sevenDaysAgo }
})
for (const order of orders) {
try {
await releaseOrderFunds(order, 'auto_released', ioInstance)
} catch (err) {
console.error(`[OrderLifecycleCron] failed to release order ${order._id}:`, err)
}
}
if (orders.length) {
console.log(`[OrderLifecycleCron] auto-released ${orders.length} order(s)`)
}
} catch (error) {
console.error('[OrderLifecycleCron] auto-release query failed:', error)
}
}
/** Cancel unpaid orders that missed the 60-minute payment window. */
const autoCancelUnpaidOrders = async () => {
const cutoff = new Date(Date.now() - PAYMENT_TIMEOUT_MINUTES * 60 * 1000)
try {
const orders = await OrderModel.find({ status: 'pending_payment', createdAt: { $lte: cutoff } })
for (const order of orders) {
try {
order.status = 'cancelled'
order.cancelReason = 'عدم پرداخت در بازه زمانی مجاز'
await order.save()
await notifyUser(ioInstance, order.buyer, {
project_post_id: order._id,
type: 'shop_order',
title: 'لغو سفارش',
description: 'سفارش شما به دلیل عدم پرداخت در بازه زمانی مجاز لغو شد.'
})
} catch (err) {
console.error(`[OrderLifecycleCron] failed to cancel order ${order._id}:`, err)
}
}
if (orders.length) {
console.log(`[OrderLifecycleCron] auto-cancelled ${orders.length} unpaid order(s)`)
}
} catch (error) {
console.error('[OrderLifecycleCron] auto-cancel failed:', error)
}
}
// هر ساعت: بررسی سفارش‌های تحویل‌شده‌ی بدون تایید خریدار برای آزادسازی خودکار وجه
cron.schedule('0 * * * *', autoReleaseFulfilledOrders)
// هر ۱۰ دقیقه: لغو سفارش‌های پرداخت‌نشده‌ی خارج از مهلت ۶۰ دقیقه‌ای
cron.schedule('*/10 * * * *', autoCancelUnpaidOrders)
module.exports = {
autoReleaseFulfilledOrders,
autoCancelUnpaidOrders,
setIo
}