82 lines
2.8 KiB
JavaScript
82 lines
2.8 KiB
JavaScript
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
|
||
}
|