import moment from 'moment' import Fragments from '../../graphql/Fragments' import { logger } from '../../utils/logger' import * as Slack from '../../utils/slack' import * as SendbirdController from '../../controllers/sendbird' import WalterService from '../../utils/walterService' import * as Notification from '../../utils/notification' import { prismaClient as prisma } from '../../prismaClient' export default async function verifyOrdersStatusBasedOnCurrentDateTime() { try { logger.info('Verify order status') if (moment().hours() >= 21 || moment().hours() <= 7) { logger.info("Will not process orders status because it's in the night") return Promise.resolve() } const orders = await prisma.order.findMany({ where: { status: { notIn: ['CANCELED', 'COMPLETED'], }, }, include: Fragments.ORDER_FIELDS, }) logger.info(`Number of orders to process ${orders.length}`) try { for await (const order of orders) { logger.info(`Processing order #${order.number}`) if (order.booking && order.booking.date) { try { const hoursSinceBookingDate = moment .duration(moment(order.booking.date).diff(moment())) .asHours() const hoursSinceCreatedAt = moment.duration(moment(order.createdAt).diff(moment())).asHours() * -1 // Order is in PENDING, just a small reminder if (order.status === 'PENDING' && hoursSinceCreatedAt > 4) { Notification.send({ forceSend: true, // For now, we want to force notification for order users: order.serviceProject.service.users, title: 'An order needs your attention', message: `Order #${order.number} on ${moment(order.booking.date).format( 'LLLL' )} is still pending. Please confirm or reschedule the order using the Walter Provider mobile application`, data: { id: order.id, }, serviceProjectId: order.serviceProject.id, type: 'ORDER_NEED_ATTENTION', }) Slack.send({ channel: 'order', // prettier-ignore subject: `🚨 Order #${order.number} on ${moment(order.booking.date).format( 'LLLL' )} is still pending.`, }).catch(logger.error) } // Order is in less then 12 hours! if (hoursSinceBookingDate > 0 && hoursSinceBookingDate < 12) { // AND It's Pending! if (order.status === 'PENDING') { Notification.send({ forceSend: true, // For now, we want to force notification for order users: order.serviceProject.service.users, title: 'An order needs your attention', message: `Order #${order.number} on ${moment(order.booking.date).format( 'LLLL' )} is happening in less than ${hoursSinceBookingDate} hours and status is still ${ order.status }. Please confirm or reschedule the order using the Walter Provider mobile application`, data: { id: order.id, }, serviceProjectId: order.serviceProject.id, type: 'ORDER_NEED_ATTENTION', }) Slack.send({ channel: 'order', // prettier-ignore subject: `🚨 Order #${order.number} is still pending and is happening in less than ${hoursSinceBookingDate} hours.`, }).catch(logger.error) } // AND It's Confirmed. Just make sure it's okay! else if (order.status === 'CONFIRMED') { Notification.send({ forceSend: true, // For now, we want to force notification for order users: order.serviceProject.service.users, title: 'An order is coming soon', message: `Order #${order.number} is happening in less than ${hoursSinceBookingDate} hours. Make sure everything is okay! Please make sure to contact the resident using the chat in the Walter Provider mobile application`, data: { id: order.id, }, serviceProjectId: order.serviceProject.id, type: 'ORDER_NEED_ATTENTION', }) Slack.send({ channel: 'order', // prettier-ignore subject: `Order #${order.number} is happening in less than ${hoursSinceBookingDate} hours. Make sure everything is okay!`, }).catch(logger.error) } } // 24 hours since booking date passed... if (hoursSinceBookingDate < -24) { // Charge and Complete yeah! if (order.status === 'CONFIRMED') { // TODO: customer has no "hasPaymentError" // if (order.customer.hasPaymentError) { // Slack.send({ // channel: 'order', // subject: `💰❌ Order #${ // order.number // } from ${await GeneralUtils.getUserNameAndUnits(order.customer)} on ${moment( // order.booking.date // ).format('LLLL')} couldn't be completed because payment couldn't go through` // }).catch(logger.error) // } else { if (!order.totalPrice || !order.totalTax || !order.subtotalPrice) { throw new Error(`Order ${order.id} doesn't is missing pricing informations`) } try { // await OrderController.charge(order) } catch (error) { // In case charging failed await prisma.user.update({ where: { id: order.customer.id, }, data: { hasPaymentError: true, }, }) throw error } await prisma.order.update({ where: { id: order.id, }, data: { status: 'COMPLETED', }, }) // Send thank you message SendbirdController.sendMessage({ message: `Hi ${ order.customer.firstName || '' }, we hope everything went well with your ${WalterService.getDataForServiceType( order.serviceProject.service.type, 'TITLE' )} order that was on ${moment(order.booking.date).format('LLLL')}.`, fromSendbirdUserId: 'walter', otherUserId: order.customer.id, isSupport: true, }) // Needed because we don't put in queue yet. In case of a crash, just log .catch(logger.error) Slack.send({ channel: 'order', subject: `✅ Order #${order.number} on ${moment(order.booking.date).format( 'LLLL' )} is now completed since it's been 24 hours since booking date`, }).catch(logger.error) } } // We need to do something asap if (order.status === 'PENDING' && hoursSinceBookingDate < 0) { Notification.send({ forceSend: true, // For now, we want to force notification for order users: order.serviceProject.service.users, title: 'An order needs your attention', message: `Order #${order.number} booking time was ${hoursSinceBookingDate} hours ago and status is still ${order.status}. Please make sure to contact the client to reschedule it or cancel it in the Walter Provider mobile application`, data: { id: order.id, }, serviceProjectId: order.serviceProject.id, type: 'ORDER_NEED_ATTENTION', }) Slack.send({ channel: 'order', subject: `🚨 Order #${order.number} needs attention. Booking time was ${hoursSinceBookingDate} hours ago and status is still ${order.status}`, }).catch(logger.error) } } catch (error) { logger.error(error) } } } } catch (error) { logger.error(error) } logger.info('Finish processing orders') } catch (e) { logger.error(e) throw e } }