/var/www/verywell.gr/server/delivery/api/controllers
Edit: /var/www/verywell.gr/server/delivery/api/controllers/order.controller.js (40326B)
const logger = require('../../logger')({ service: 'api' })
const { Op } = require('sequelize')
const {
OrderHeaderClients,
OrderHeaderDrivers,
OrderHeaderOperators
} = require('../responseModels')
const { NotFound, BadRequest, ApiError } = require('../responseModels/errors')
const { isSet, isEmpty, isArray, isNumber } = require('../utils/validator.util')
const checkPermission = require('../utils/checkPermission.util')
const { performance } = require('perf_hooks')
const { getDateByDateRange, hoursList, daysOfWeekList } = require('../utils/date')
const fetch = require('node-fetch')
const config = require('../../config/app.json')
module.exports = function ({ db }) {
this.Statistic = async (req, res, next) => {
logger.child({ path: req.path, request: req.query }).info()
try {
let t1 = performance.now()
const { branchId, companyId, userId, driverId, operatorId, tableId, range } = req.query
let date
let rows
let list = []
let where = {}
if (isSet(branchId) && isNumber(branchId)) {
where['branchId'] = branchId
}
if (isSet(companyId) && isNumber(companyId)) {
where['companyId'] = companyId
}
if (isSet(driverId) && isNumber(driverId)) {
where['driverId'] = driverId
}
if (isSet(operatorId) && isNumber(operatorId)) {
where['operatorId'] = operatorId
}
if (isSet(tableId) && isNumber(tableId)) {
where['tableId'] = tableId
}
if (isSet(userId) && isNumber(userId)) {
where['userId'] = userId
}
switch (range) {
case DATE.RANGE.HOUR:
date = getDateByDateRange(DATE.RANGE.HOUR)
where['createdAt'] = {
[Op.between]: [date.begin, date.end]
}
rows = await db.order.count({
where,
attributes: [
[db.Sequelize.fn('HOUR', db.Sequelize.col('createdAt')), 'hour'],
[db.Sequelize.fn('MINUTE', db.Sequelize.col('createdAt')), 'minute']
],
group: ['status', 'minute', 'hour'],
order: ['minute', 'hour']
})
for (let i = 0; i < 60; i++) {
let dt = new Date(date.end)
dt.setMinutes(dt.getMinutes() - i)
dt.setSeconds(0)
dt.setMilliseconds(0)
list.push({
idx: 59 - i,
name: dt.getMinutes(),
date: dt,
complete: rows
.filter(
(x) =>
x.status == ORDER_STATUS.COMPLETE &&
x.minute == dt.getMinutes()
)
.reduce((s, x) => s + x.count, 0),
cancel: rows
.filter(
(x) =>
x.status == ORDER_STATUS.CANCEL &&
x.minute == dt.getMinutes()
)
.reduce((s, x) => s + x.count, 0)
})
}
break
case DATE.RANGE.DAY:
date = getDateByDateRange(DATE.RANGE.DAY)
where['createdAt'] = {
[Op.between]: [date.begin, date.end]
}
rows = await db.order.count({
where,
attributes: [
[db.Sequelize.fn('HOUR', db.Sequelize.col('createdAt')), 'hour'],
[db.Sequelize.fn('DAY', db.Sequelize.col('createdAt')), 'day']
],
group: ['status', 'day', 'hour'],
order: ['day', 'hour']
})
const hours = hoursList(req.user.languageCode)
for (let i = 0; i < hours.length; i++) {
let dt = new Date(date.end)
dt.setHours(dt.getHours() - i)
dt.setMinutes(0)
dt.setSeconds(0)
dt.setMilliseconds(0)
list.push({
idx: hours.length - 1 - i,
name: hours[dt.getHours()],
date: dt,
complete: rows
.filter(
(x) =>
x.status == ORDER_STATUS.COMPLETE &&
x.hour == dt.getUTCHours()
)
.reduce((s, x) => s + x.count, 0),
cancel: rows
.filter(
(x) =>
x.status == ORDER_STATUS.CANCEL &&
x.hour == dt.getUTCHours()
)
.reduce((s, x) => s + x.count, 0)
})
}
break
case DATE.RANGE.WEEK:
date = getDateByDateRange(DATE.RANGE.WEEK)
where['createdAt'] = {
[Op.between]: [date.begin, date.end]
}
rows = await db.order.count({
where,
attributes: [
[db.Sequelize.fn('DAY', db.Sequelize.col('createdAt')), 'day']
],
group: ['status', 'day'],
order: ['day', 'hour']
})
const days = daysOfWeekList(req.user.languageCode)
for (let i = 0; i < days.length; i++) {
let dt = new Date(date.end)
dt.setDate(dt.getDate() - i)
dt.setMinutes(0)
dt.setSeconds(0)
dt.setMilliseconds(0)
list.push({
idx: days.length - 1 - i,
name: days[dt.getDay()],
date: dt,
complete: rows
.filter(
(x) =>
x.status == ORDER_STATUS.COMPLETE && x.day == dt.getDate()
)
.reduce((s, x) => s + x.count, 0),
cancel: rows
.filter(
(x) => x.status == ORDER_STATUS.CANCEL && x.day == dt.getDate()
)
.reduce((s, x) => s + x.count, 0)
})
}
break
case DATE.RANGE.MONTH:
date = getDateByDateRange(DATE.RANGE.MONTH)
where['createdAt'] = {
[Op.between]: [date.begin, date.end]
}
rows = await db.order.count({
where,
attributes: [
[db.Sequelize.fn('DAY', db.Sequelize.col('order.createdAt')), 'day']
],
group: ['status', 'day'],
order: ['day']
})
for (let i = 0; i <= 30; i++) {
let dt = new Date(date.end)
dt.setDate(dt.getDate() - i)
dt.setMinutes(0)
dt.setSeconds(0)
dt.setMilliseconds(0)
list.push({
idx: 30 - i,
name: dt.getDate(),
date: dt,
complete: rows
.filter(
(x) =>
x.status == ORDER_STATUS.COMPLETE && x.day == dt.getDate()
)
.reduce((s, x) => s + x.count, 0),
cancel: rows
.filter(
(x) => x.status == ORDER_STATUS.CANCEL && x.day == dt.getDate()
)
.reduce((s, x) => s + x.count, 0)
})
}
break
}
const time = performance.now() - t1
if (!rows) throw new NotFound({ lang: req.user?.languageCode })
return res.status(200).json({
all: rows.reduce((s, x) => s + x.count, 0),
complete: rows
.filter((x) => x.status == ORDER_STATUS.COMPLETE)
.reduce((s, x) => s + x.count, 0),
cancel: rows
.filter((x) => x.status == ORDER_STATUS.CANCEL)
.reduce((s, x) => s + x.count, 0),
list,
date,
range,
time
})
} catch (err) {
next(err)
}
}
this.List = async (req, res, next) => {
logger.child({ path: req.path, request: req.query }).info()
try {
let t1 = performance.now()
let { limit, page, sort, branchId, status, statusExclude, includeItems } = req.query
let where = {}
let offset = page > 0 ? (page - 1) * (limit || 10) : 0
if (status) {
if (statusExclude === 'true') {
where['status'] = {
[Op.not]: status.split(',').map((p) => {
return p.trim()
})
}
} else {
where['status'] = {
[Op.in]: status.split(',').map((p) => {
return p.trim()
})
}
}
}
var find_includes = [
{ model: db.orderAddress },
{
model: db.branch,
include: [{ model: db.deliveryType }],
foreginKey: 'branchId'
},
{ model: db.payType, foreginKey: 'payTypeId', as: 'payType' },
{ model: db.payType, foreginKey: 'deliveryPayTypeId', as: 'deliveryPayType' },
{ model: db.deliveryType },
{
model: db.company,
as: 'company',
paranoid: false
// foreginKey: 'companyId'
// where: { deletedAt: null },
},
{
model: db.user,
foreginKey: 'userId',
as: 'user',
include: { model: db.userPhone }
},
{
model: db.user,
foreginKey: 'operatorId',
as: 'operator',
include: { model: db.userPhone }
},
{ model: db.user, foreginKey: 'orderId', as: 'orderWaiters' },
{
model: db.driver,
foreginKey: 'driverId',
as: 'driver',
include: [{ model: db.user, include: [{ model: db.userPhone }] }]
},
{ model: db.orderCancelCause },
{ model: db.table }
]
switch (req.user.app) {
case APP.CLIENT:
where['userId'] = req.user.id
break
case APP.DRIVER:
where['driverId'] = req.user.driverId
break
case APP.WAITER:
case APP.OPERATOR:
if (branchId) {
where['branchId'] = branchId
}
break
}
if (includeItems === 'true') {
find_includes.push({
model: db.orderItems,
include: [
{ model: db.product, include: [db.branchProduct, db.productImage, db.productVariant, db.productExtra, db.productIngridient] }
]
})
}
const rows = await db.order.findAll({
include: find_includes,
where,
offset,
order: [
['id', 'DESC']
// ['name', 'ASC'],
],
limit: parseInt(limit) || 10
// sort
})
if (rows.length == 0 || !rows) {
throw new NotFound({ lang: req.user?.languageCode })
}
const list = rows.map((row) => {
switch (req.user?.app) {
case APP.WAITER:
case APP.OPERATOR:
return new OrderHeaderOperators(row.dataValues)
case APP.DRIVER:
return new OrderHeaderDrivers(row)
case APP.CLIENT:
return new OrderHeaderClients(row)
default:
return new OrderHeaderClients(row)
}
})
const time = performance.now() - t1
return res.status(200).json({ list, time, count: list.length })
} catch (err) {
next(err)
}
}
this.History = async (req, res, next) => {
logger.child({ path: req.path, request: req.query }).info()
try {
let t1 = performance.now()
let { orderUid, limit, page, sort, event, eventExclude } = req.query
let where = {}
if (orderUid) {
const order = await db.order.findOne({ where: { uid: orderUid } })
if (order) where['orderId'] = order.id
else throw new BadRequest({ lang: req.user?.languageCode })
} else {
//throw new BadRequest({ lang: req.user?.languageCode })
}
let offset = page > 0 ? (page - 1) * (limit || 10) : 0
if (eventExclude) {
if (statusExclude === 'true') {
where['event'] = {
[Op.not]: event.split(',').map((p) => {
return p.trim()
})
}
} else {
where['event'] = {
[Op.in]: event.split(',').map((p) => {
return p.trim()
})
}
}
}
const list = await db.orderHistory.findAll({
//include: [{ model: db.order }],
where,
offset,
order: [
['id', 'DESC']
// ['name', 'ASC'],
],
limit: parseInt(limit) || 10
// sort
})
if (list.length == 0 || !list) {
throw new NotFound({ lang: req.user?.languageCode })
}
const time = performance.now() - t1
return res.status(200).json({ list, time, count: list.length })
} catch (err) {
next(err)
}
}
this.Details = async (req, res, next) => {
logger.child({ path: req.path, request: req.params }).info()
try {
// checkPermission(req, 'order_details')
const { uid } = req.params
const order = await db.order.findOne({
include: [
{ model: db.branch, foreginKey: 'branchId' },
{ model: db.company, foreginKey: 'companyId' },
{ model: db.user, foreginKey: 'userId', as: 'user', required: false },
{ model: db.user, foreginKey: 'operatorId', as: 'operator', required: false },
// { model: db.user, foreginKey: 'waiterId', as: 'waiter', required: false },
{ model: db.driver, foreginKey: 'driverId', as: 'driver', required: false },
{ model: db.table }
],
where: { uid: uid }
})
if (!order) {
throw new NotFound({ lang: req.user?.languageCode })
}
return res.status(200).json(order)
} catch (err) {
next(err)
}
}
this.Create = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
let transaction = await db.sequelize.transaction()
try {
let t1 = performance.now()
// checkPermission(req, 'order_create')
const {
companyId,
branchId,
status,
phone,
payTypeId,
deliveryPayTypeId,
deliveryTypeId,
deliveryTypeKey,
userId,
orderAddress,
comment,
tableId,
userCartItems
} = req.body
if (!isSet(userCartItems) || !isArray(userCartItems)) {
throw new BadRequest({ code: 1014, lang: req.user?.languageCode })
}
// получаем ид товаров
let productIds = userCartItems.map((p) => p.productId)
// получаем товары
const products = await db.product.findAll({
where: {
id: {
[Op.in]: productIds
}
},
include: [{ model: db.branchProduct }]
})
// пройти по корзине и заполнить массив
let discount = 0
let orderTotal = 0
let prepare_time = 0
let orderItems = userCartItems.map((userCartItem) => {
// найти товар
const product = products.find((p) => p.id == userCartItem.productId)
if (!product) {
throw new NotFound({ lang: req.user?.languageCode })
}
// найти цену в отделении или взять первую
const branchProduct =
product.branchProducts.find((p) => p.branchId == branchId) || // ??? по order.branchId или userCartItem.branchId ???
product.branchProduct[0]
if (!branchProduct) {
throw new NotFound({ lang: req.user?.languageCode })
}
// проверить тип кол-ва
if (branchProduct.availability == 'notavailable') {
throw new BadRequest({ code: 1013, lang: req.user?.languageCode })
}
// проверить тип кол-ва
if (
branchProduct.availability != 'unlimited' &&
branchProduct.availability != 'onorder'
) {
// проверить наличие
if (branchProduct.qty < userCartItem.qty) {
throw new BadRequest({ code: 1013, lang: req.user?.languageCode })
}
// изменить остатки товара
branchProduct.qty -= userCartItem.qty
branchProduct.save()
}
// максимальное время приготовления
if (branchProduct.prepare_time > prepare_time) {
prepare_time = branchProduct.prepare_time
}
orderTotal += branchProduct.price * userCartItem.qty
// вернуть новый orderItem
return {
productId: userCartItem.productId,
productVariant: userCartItem.productVariant,
productExtra: userCartItem.productExtra,
productIngridient: userCartItem.productIngridient,
qty: userCartItem.qty,
productName: product.name,
productPrinterId: product.printerId,
price: branchProduct.price
}
})
let params = {
companyId,
branchId,
status,
payTypeId,
deliveryPayTypeId,
deliveryTypeId,
prepare_time,
discount,
order_cost: orderTotal,
delivery_cost: 0,
comment,
orderItems
}
let inc = [{ model: db.orderItems }]
// discount
if (userId > 0) {
const user = await db.user.findOne({ where: { id: userId } })
if (user) {
user.ordersCreated++
user.save()
params['userId'] = userId
const companyClient = await db.companyClients.findOne({
where: { companyId: companyId, userId: userId }
})
if (companyClient) {
discount = parseInt(companyClient.discount)
if (discount > 0) {
params['discount'] = discount
}
} else {
// add company client
db.companyClients.create({
userId: userId,
companyId: companyId
})
// company counters
const company = await db.company.findOne({ where: { id: companyId } })
if (company) {
company.countClients++
company.save()
}
}
}
}
// Расчитаем роут и стоимость доставки --->
if (deliveryTypeKey == 'courier' || deliveryTypeKey == 'delivery') {
const branch = await SERVICES.BranchService.GetBranchById(branchId)
if (branch) {
// Проверяем адрес филиала
if (!branch.address) {
throw new BadRequest({ code: 1048, lang: req.user?.languageCode })
}
// Проверяем адрес доставки
if (!isSet(orderAddress)) {
throw new BadRequest({ code: 1015, lang: req.user?.languageCode })
}
// Собираем координаты для запроса маршрута (координаты перевернуты!!!)
const coordinates = [
[branch.address.longtitude, branch.address.latitude],
[orderAddress.longtitude, orderAddress.latitude]
]
// Ищем тариф
let shippingRate
await branch.shippingRates.forEach((rate) => {
if (rate.deliveryTypeId == deliveryTypeId) {
shippingRate = rate
}
})
// Проверяем наличие настроек тарифа
if (!shippingRate) {
// no shipping rate
throw new BadRequest({ code: 1045, lang: req.user?.languageCode })
}
// Запрос маршрута
const response = await Promise.all([
await fetch(`${config.osrm.url}${coordinates.join(';')}`),
])
// Проверяем наличие ответа
const data = await response[0].json()
if (!data || data?.code != 'Ok' || !isArray(data.routes) || data.routes.length == 0) {
// no route
throw new BadRequest({ code: 1046, lang: req.user?.languageCode })
}
const route = data.routes[0]
// Начинаем расчет доставки -----------
// Расстояяние всего
const distance = route.distance / 1000
// Проверяем максимальное расстояние
if (shippingRate.maxKm > 0 && distance > shippingRate.maxKm) {
throw new BadRequest({ code: 1049, lang: req.user?.languageCode })
}
// Расстояяние для оплаты
let distanceToPay = distance - shippingRate.freeKm
if (distanceToPay < 0) {
distanceToPay = 0
}
// Расчетное время
const routeTime = parseInt(route.duration / 60)
// Время для оплаты
let timeToPay = routeTime - shippingRate.freeMinutes
if (timeToPay < 0) {
timeToPay = 0
}
// Считаем стоимость доставки
const deliveryCostCalculated = parseFloat(shippingRate.initialCost) +
distanceToPay * parseFloat(shippingRate.costPerKm) +
timeToPay * parseFloat(shippingRate.costPerMinute)
let deliveryCost = 0
// Стоимость заказа не достигла бесплатной доставки
if (orderTotal <= shippingRate.freeMinCost) {
deliveryCost = deliveryCostCalculated
}
params['delivery_distance'] = distance;
params['delivery_cost'] = deliveryCost;
params['delivery_cost_calculated'] = deliveryCostCalculated;
params['delivery_time'] = routeTime;
params['orderAddress'] = orderAddress
inc.push({ model: db.orderAddress })
} else {
// no branch
throw new BadRequest({ code: 1047, lang: req.user?.languageCode })
}
}
// <---
// ИТОГО ------------
params['total'] =
params['delivery_cost'] +
params['order_cost'] -
((params['order_cost'] / 100) * params['discount'])
if (tableId > 0) {
params['tableId'] = tableId
}
if (phone != null && phone.length > 9) {
params['phone'] = phone
}
// создать заказ
let order = await db.order.create(params, { include: inc })
await db.orderHistory.create({
orderId: order.id,
userId: req.body.userId || null,
event: ORDER_HISTORY_EVENT.CREATE,
app: req.user?.app || APP.UNKNOWN
})
let orderPay = await db.orderPay.create({
orderId: order.id,
userId: order.userId,
payTypeId: order.payTypeId,
summ: order.total,
created: req.user?.app | 'system',
paid: req.user?.app | 'system',
pay_status: 'not_paid'
})
// company counters
const company = await db.company.findOne({ where: { id: order.companyId } })
if (company) {
company.ordersCreated++
company.save()
}
transaction.commit()
transaction = null
// форматирование и рассылка заказа
await SERVICES.OrderService.CreateOrder(order)
const time = performance.now() - t1
return res.status(200).json({
status: 'success',
order,
time
})
} catch (err) {
transaction?.rollback()
next(err)
}
}
this.Edit = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
// checkPermission(req, 'order_edit')
const { uid, name, prepare_time, tableId } = req.body
let order = await db.order.findOne({
where: { uid: uid }
})
if (!order) {
throw new NotFound({ lang: req.user?.languageCode })
}
if (name) order.name = name
if (prepare_time) order.prepare_time = prepare_time
if (tableId) order.tableId = tableId
await order.save()
await db.orderHistory.create({
orderId: order.id,
userId: req.body.userId || null,
event: ORDER_HISTORY_EVENT.EDIT,
app: req.user?.app || APP.UNKNOWN
})
return res.status(200).json(order)
} catch (err) {
next(err)
}
}
this.Delete = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
// checkPermission(req, 'order_delete')
const { uid } = req.body
if (!uid) {
throw new BadRequest({ lang: req.user?.languageCode })
}
const order = await db.order.findOne({ where: { uid: uid } })
if (!order) {
throw new NotFound({ lang: req.user?.languageCode })
}
await SERVICES.OrderService.RemoveOrder(uid)
await db.order.destroy({ where: { uid: uid } })
await db.orderHistory.create({
orderId: order.id,
userId: req.body.userId || null,
event: ORDER_HISTORY_EVENT.DELETE,
app: req.user?.app || APP.UNKNOWN
})
return res.status(200).json({ status: 'success', uid: order.uid })
} catch (err) {
next(err)
}
}
this.Pay = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
let transaction = await db.sequelize.transaction()
try {
// checkPermission(req, 'order_delete')
const { orderUid, userUid, summ } = req.body
if (!summ) throw new BadRequest({ lang: req.user?.languageCode })
if (!orderUid) throw new BadRequest({ lang: req.user?.languageCode })
if (!userUid) throw new BadRequest({ lang: req.user?.languageCode })
let order = await SERVICES.OrderService.GetOrder(orderUid)
// const order = await db.order.findOne({ where: { uid: orderUid } })
if (!order) {
throw new NotFound({ lang: req.user?.languageCode })
}
const user = await db.user.findOne({ where: { uid: userUid } })
if (!user) {
throw new NotFound({ lang: req.user?.languageCode })
}
let orderPay = await db.orderPay.findOne({
where: { orderId: order.id }
})
if (!orderPay) {
orderPay = await db.orderPay.create({
orderId: order.id,
userId: user.id,
payTypeId: order.payTypeId,
summ: summ,
status: 'paid'
})
} else if (orderPay.status === 'not_paid') {
if (!parseFloat(summ) !== parseFloat(orderPay.summ)) {
// throw new BadRequest({ code: 1031, lang: req.user?.languageCode })
}
// безнал
if (!order.payType.isCash) {
if (!order.userId) throw new NotFound({ code: 1028, lang: req.user?.languageCode })
const accountClient = await db.account.findOne({ where: { userId: order.userId, type: ACCOUNT_TYPE.CLIENT } })
if (!accountClient) throw new NotFound({ code: 1030, lang: req.user?.languageCode })
// проверить остаток на счете
if (parseFloat(accountClient.balance) < parseFloat(summ)) {
throw new BadRequest({ code: 1031, lang: req.user?.languageCode })
}
// снятие со счета клиента
const accountClientBalance = parseFloat(accountClient.balance)
accountClient.balance = accountClientBalance - parseFloat(summ)
await db.accountHistory.create({
accountId: accountClient.id,
summ: parseFloat(summ) * -1,
balanceBefore: accountClientBalance,
balanceAfter: accountClient.balance,
event: ACCOUNT_HISTORY_EVENT.TRANSFER
})
await accountClient.save()
// зачисление на счет филиала
const accountBranch = await db.account.findOne({ where: { branchId: order.branchId, type: ACCOUNT_TYPE.BRANCH } })
if (!accountBranch) throw new NotFound({ code: 1051, lang: req.user?.languageCode })
const accountBranchBalance = parseFloat(accountBranch.balance)
accountBranch.balance = accountBranchBalance + parseFloat(summ)
await db.accountHistory.create({
accountId: accountBranch.id,
summ: parseFloat(summ),
balanceBefore: accountBranchBalance,
balanceAfter: accountBranch.balance,
event: ACCOUNT_HISTORY_EVENT.TRANSFER
})
await accountBranch.save()
} else { // наличные
// зачисление в кассу филиала
const accountBranch = await db.account.findOne({ where: { branchId: order.branchId, type: ACCOUNT_TYPE.CASH } })
if (!accountBranch) throw new NotFound({ code: 1052, lang: req.user?.languageCode })
const accountBranchBalance = parseFloat(accountBranch.balance)
accountBranch.balance = accountBranchBalance + parseFloat(summ)
await db.accountHistory.create({
accountId: accountBranch.id,
summ: parseFloat(summ),
balanceBefore: accountBranchBalance,
balanceAfter: accountBranch.balance,
event: ACCOUNT_HISTORY_EVENT.TRANSFER
})
await accountBranch.save()
}
orderPay.status = 'paid'
orderPay.summ = summ
await orderPay.save()
order.pay_status_order = 'paid'
order.pay_status_delivery = 'paid'
order.payAt = Date.now()
await order.save()
await SERVICES.OrderService.PayOrder(order, orderPay)
} else if (orderPay.status === 'paid') {
if (order.pay_status_order !== 'paid') {
order.pay_status_order = 'paid'
order.pay_status_delivery = 'paid'
order.payAt = Date.now()
await order.save()
}
await SERVICES.OrderService.PayOrder(order, orderPay)
}
transaction.commit()
transaction = null
return res.status(200).json({ status: 'success', uid: order.uid })
} catch (err) {
transaction?.rollback()
next(err)
}
}
this.Accept = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
let transaction = await db.sequelize.transaction()
try {
let t1 = performance.now()
// checkPermission(req, 'order_accept')
const { uid, prepare_time } = req.body
let order = await SERVICES.OrderService.GetOrder(uid)
if (!isSet(order)) {
throw new NotFound({ lang: req.user?.languageCode })
}
// проверить статус заказа
// ...
// изменяем данные по заказу
// проверить кто принял
switch (req.user?.app) {
case APP.OPERATOR:
order.status = ORDER_STATUS.PENDING
order.operatorId = req.user.id
if (prepare_time && prepare_time !== order.prepare_time) {
order.prepare_time = prepare_time
}
break
case APP.DRIVER:
order.status = ORDER_STATUS.ACCEPT
order.driverId = req.user?.driverId
break
}
order.acceptAt = Date.now()
await order.save()
await db.orderHistory.create({
orderId: order.id,
userId: req.body.userId || null,
event: ORDER_HISTORY_EVENT.ACCEPT,
app: req.user?.app || APP.UNKNOWN
})
transaction.commit()
transaction = null
// форматирование и рассылка заказа
// проверить кто принял
switch (req.user?.app) {
case APP.OPERATOR:
await SERVICES.OrderService.PendOrder(order)
break
case APP.DRIVER:
await SERVICES.OrderService.AcceptOrder(order)
break
}
const time = performance.now() - t1
return res.status(200).json({ status: 'success', order, time })
} catch (err) {
transaction?.rollback()
next(err)
}
}
this.Ready = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
let transaction = await db.sequelize.transaction()
try {
let t1 = performance.now()
// checkPermission(req, 'order_ready')
const { uid } = req.body
// проверить пользователя
if (req.user?.app !== APP.OPERATOR) {
}
let order = await SERVICES.OrderService.GetOrder(uid)
if (!isSet(order)) {
throw new NotFound({ lang: req.user?.languageCode })
}
// проверить статус заказа
// ...
order.status = ORDER_STATUS.READY
order.readyAt = Date.now()
await order.save()
await db.orderHistory.create({
orderId: order.id,
userId: req.body.userId || null,
event: ORDER_HISTORY_EVENT.READY,
app: req.user?.app || APP.UNKNOWN
})
transaction.commit()
transaction = null
// форматирование и рассылка заказа
await SERVICES.OrderService.ReadyOrder(order)
const time = performance.now() - t1
return res.status(200).json({ status: 'success', order, time })
} catch (err) {
transaction?.rollback()
next(err)
}
}
this.Delivery = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
let transaction = await db.sequelize.transaction()
try {
let t1 = performance.now()
// checkPermission(req, 'order_accept')
const { uid } = req.body
// проверить пользователя
if (req.user?.app !== APP.OPERATOR) {
}
let order = await SERVICES.OrderService.GetOrder(uid)
if (!isSet(order)) {
throw new NotFound({ lang: req.user?.languageCode })
}
// проверить статус заказа
// ...
order.status = ORDER_STATUS.DELIVERY
order.deliveryAt = Date.now()
await order.save()
await db.orderHistory.create({
orderId: order.id,
userId: req.body.userId || null,
event: ORDER_HISTORY_EVENT.DELIVERY,
app: req.user?.app || APP.UNKNOWN
})
transaction.commit()
transaction = null
// форматирование и рассылка заказа
await SERVICES.OrderService.DeliveryOrder(order)
const time = performance.now() - t1
return res.status(200).json({ status: 'success', order, time })
} catch (err) {
transaction?.rollback()
next(err)
}
}
this.Arrived = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
let transaction = await db.sequelize.transaction()
try {
let t1 = performance.now()
// checkPermission(req, 'order_accept')
const { uid } = req.body
// проверить пользователя
if (req.user?.app !== APP.OPERATOR) {
}
let order = await SERVICES.OrderService.GetOrder(uid)
if (!isSet(order)) {
throw new NotFound({ lang: req.user?.languageCode })
}
// проверить статус заказа
// ...
order.status = ORDER_STATUS.ARRIVED
order.arrivedAt = Date.now()
await order.save()
await db.orderHistory.create({
orderId: order.id,
userId: req.body.userId || null,
event: ORDER_HISTORY_EVENT.ARRIVED,
app: req.user?.app || APP.UNKNOWN
})
transaction.commit()
transaction = null
// форматирование и рассылка заказа
await SERVICES.OrderService.ArrivedOrder(order)
const time = performance.now() - t1
return res.status(200).json({ status: 'success', order, time })
} catch (err) {
transaction?.rollback()
next(err)
}
}
this.Cancel = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
let transaction = await db.sequelize.transaction()
try {
let t1 = performance.now()
// checkPermission(req, 'order_delete')
const { uid, orderCancelCauseId } = req.body
if (!uid) {
throw new BadRequest({ lang: req.user?.languageCode })
}
if (!orderCancelCauseId) {
throw new BadRequest({ lang: req.user?.languageCode })
}
let order = await SERVICES.OrderService.GetOrder(uid)
if (!order) {
throw new NotFound({ lang: req.user?.languageCode })
}
order.status = ORDER_STATUS.CANCEL
order.orderCancelCauseId = orderCancelCauseId
order.completeAt = Date.now()
await order.save()
await db.orderHistory.create({
orderId: order.id,
userId: req.body.userId || null,
event: ORDER_HISTORY_EVENT.CANCEL,
app: req.user?.app || APP.UNKNOWN
})
if (order.userId > 0) {
const user = await db.user.findOne({ where: { id: order.userId } })
if (user) {
user.ordersCanceled++
user.save()
}
}
// company counters
const company = await db.company.findOne({ where: { id: order.companyId } })
if (company) {
company.ordersCanceled++
company.save()
}
transaction.commit()
transaction = null
// форматирование и рассылка заказа
await SERVICES.OrderService.CancelOrder(order)
const time = performance.now() - t1
return res.status(200).json({ status: 'success', uid: uid, time })
} catch (err) {
transaction?.rollback()
next(err)
}
}
this.Complete = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
let transaction = await db.sequelize.transaction()
try {
let t1 = performance.now()
// checkPermission(req, 'order_delete')
const { uid } = req.body
if (!uid) {
throw new BadRequest({ lang: req.user?.languageCode })
}
let order = await SERVICES.OrderService.GetOrder(uid)
if (!order) {
throw new NotFound({ lang: req.user?.languageCode })
}
// проверка оплаты
if (order.pay_status_order == ORDER_PAY_STATUS.NOT_PAID) {
throw new BadRequest({ lang: req.user?.languageCode, code: 1041 })
}
if (order.pay_status_order == ORDER_PAY_STATUS.PAY_ERROR) {
throw new BadRequest({ lang: req.user?.languageCode, code: 1042 })
}
// проверка оплаты доставки
// if (order.pay_status_delivery == ORDER_PAY_STATUS_DELIVERY.NOT_PAID) {
// throw new BadRequest({ lang: req.user?.languageCode, code: 1043 })
// }
// if (order.pay_status_delivery == ORDER_PAY_STATUS_DELIVERY.PAY_ERROR) {
// throw new BadRequest({ lang: req.user?.languageCode, code: 1044 })
// }
order.status = ORDER_STATUS.COMPLETE
order.completeAt = Date.now()
await order.save()
await db.orderHistory.create({
orderId: order.id,
userId: req.body.userId || null,
event: ORDER_HISTORY_EVENT.COMPLETE,
app: req.user?.app || APP.UNKNOWN
})
if (order.userId > 0) {
const user = await db.user.findOne({ where: { id: order.userId } })
if (user) {
user.ordersCompleted++
user.save()
}
}
// company counters
const company = await db.company.findOne({ where: { id: order.companyId } })
if (company) {
company.ordersCompleted++
company.save()
}
transaction.commit()
transaction = null
// форматирование и рассылка заказа
await SERVICES.OrderService.CompleteOrder(order)
const time = performance.now() - t1
return res.status(200).json({ status: 'success', order, time })
} catch (err) {
transaction?.rollback()
next(err)
}
}
this.SetTable = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
let transaction = await db.sequelize.transaction()
try {
let t1 = performance.now()
// checkPermission(req, 'order_delete')
const { uid, tableUid } = req.body
if (!uid) {
throw new BadRequest({ lang: req.user?.languageCode })
}
if (!tableUid) {
throw new BadRequest({ lang: req.user?.languageCode })
}
let order = await SERVICES.OrderService.GetOrder(uid)
if (!order) {
throw new NotFound({ lang: req.user?.languageCode })
}
const table = await db.table.findOne({ where: { uid: tableUid } })
order.setTable(table)
await order.save()
await order.reload()
transaction.commit()
transaction = null
const time = performance.now() - t1
return res.status(200).json({ status: 'success', order, time })
} catch (err) {
transaction?.rollback()
next(err)
}
}
this.SetUser = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
let transaction = await db.sequelize.transaction()
try {
let t1 = performance.now()
// checkPermission(req, 'order_delete')
const { uid, userUid } = req.body
if (!uid) {
throw new BadRequest({ lang: req.user?.languageCode })
}
if (!userUid) {
throw new BadRequest({ lang: req.user?.languageCode })
}
let order = await SERVICES.OrderService.GetOrder(uid)
if (!order) {
throw new NotFound({ lang: req.user?.languageCode })
}
const user = await db.user.findOne({ where: { uid: userUid } })
order.setUser(user)
await order.save()
await order.reload()
transaction.commit()
transaction = null
const time = performance.now() - t1
return res.status(200).json({ status: 'success', order, time })
} catch (err) {
transaction?.rollback()
next(err)
}
}
this.AddWaiter = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
let t1 = performance.now()
const { orderUid, userUid } = req.body
if (!orderUid) {
throw new BadRequest({ lang: req.user?.languageCode })
}
if (!userUid) {
throw new BadRequest({ lang: req.user?.languageCode })
}
let order = await SERVICES.OrderService.GetOrder(orderUid)
if (!order) {
throw new NotFound({ lang: req.user?.languageCode })
}
const user = await db.user.findOne({ where: { uid: userUid } })
if (!user) {
throw new NotFound({ lang: req.user?.languageCode })
}
order.addOrderWaiter(user)
await order.save()
const time = performance.now() - t1
await SERVICES.WebSocketService.SendToWaiter(user.id, 'orderAddWaiter', {
orderId: order.id,
waiterId: user.id
})
await SERVICES.WebSocketService.SendToClient(user.id, 'orderAddWaiter', {
orderId: order.id,
waiterId: user.id
})
await SERVICES.WebSocketService.SendToOperatorsByBranch(user.id, 'orderAddWaiter', {
orderId: order.id,
waiterId: user.id
})
return res.status(200).json({ status: 'success', time })
} catch (err) {
next(err)
}
}
this.RemoveWaiter = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
let t1 = performance.now()
const { orderUid, userUid } = req.body
if (!orderUid) {
throw new BadRequest({ lang: req.user?.languageCode })
}
if (!userUid) {
throw new BadRequest({ lang: req.user?.languageCode })
}
let order = await SERVICES.OrderService.GetOrder(orderUid)
if (!order) {
throw new NotFound({ lang: req.user?.languageCode })
}
const user = await db.user.findOne({ where: { uid: userUid } })
if (!user) {
throw new NotFound({ lang: req.user?.languageCode })
}
order.removeOrderWaiter(user)
await order.save()
const time = performance.now() - t1
return res.status(200).json({ status: 'success', time })
} catch (err) {
next(err)
}
}
this.Printed = async (req, res, next) => {
logger.child({ path: req.path, request: req.body }).info()
try {
const t1 = performance.now()
const { orderId, printedItems } = req.body
if (!orderId) throw new BadRequest({ lang: req.user?.languageCode })
if (!isArray(printedItems) || printedItems.length === 0)
throw new BadRequest({ lang: req.user?.languageCode })
let orderItems = await db.orderItems.findAll({
where: {
orderId,
id: { [db.Sequelize.Op.in]: printedItems },
productPrinted: { [db.Sequelize.Op.not]: true }
}
})
if (!isArray(orderItems) || orderItems.length === 0)
throw new NotFound({ lang: req.user?.languageCode })
const tasks = []
for (let orderItem of orderItems) {
orderItem.productPrinted = true
tasks.push(orderItem.save())
}
const result = await Promise.all(tasks)
const time = performance.now() - t1
return res.status(200).json({ status: 'success', time })
} catch (err) {
next(err)
}
}
}