| Current Path : /home/deltalab/PMS/partner-manager-backend/rest/routes/ |
| Current File : //home/deltalab/PMS/partner-manager-backend/rest/routes/orders.js |
/* eslint-disable no-await-in-loop */
/* eslint-disable no-use-before-define */
/* eslint-disable max-len */
const express = require('express');
const { productModel } = require('../../models/mongoose/product');
const { orderModel } = require('../../models/mongoose/order');
const { partnerModel } = require('../../models/mongoose/partner');
const { warehouseJournalModel } = require('../../models/mongoose/warehouse-journal');
const { taxQuery } = require('../queries');
const oms = require('../../services/oms');
const router = express.Router();
// TODO: controllo sul channel
router.get('/summary/admin/:partnerId/:channelId/:year/:month/:day', async (req, res) => {
try {
const monthlyList = {};
const orders = await orderModel.find({
partnerId: req.params.partnerId,
createdAt: {
$gte: new Date(req.params.year, req.params.month - 1, 1),
$lt: new Date(req.params.year, req.params.month - 1, 31),
},
});
for (let i = 0; i < orders.length; i++) {
let orderTotal = 0.0;
for (let j = 0; j < orders[i].items.length; j++) {
const product = await productModel.findOne({ sku: orders[i].items[j].sku });
if (!product) {
console.log('continuo perchè il prodotto non esiste');
continue; // The only case this should occur is with test orders with products that do not exist anymore
}
if (!product || !product.channelId.equals(req.params.channelId)) {
break;
}
const date = new Date(orders[i].createdAt);
const year = date.getFullYear();
const month = date.toLocaleString('it-IT', {
month: 'long',
}); // date.getMonth() + 1;
const tax = await getTaxCode(product.imsTaxCode, req.params.channelId);
const day = date.getDate();
if (!monthlyList[year]) {
monthlyList[year] = {};
}
if (!monthlyList[year][month]) {
monthlyList[year][month] = {};
}
if (!monthlyList[year][month][day]) {
monthlyList[year][month][day] = {};
}
if (!monthlyList[year][month][day][tax]) {
monthlyList[year][month][day][tax] = {};
monthlyList[year][month][day][tax].amount = 0.0;
}
monthlyList[year][month][day][tax].amount += (Math.round((orders[i].items[j].totalPriceSet.amount + Number.EPSILON) * 100) / 100);
orderTotal += orders[i].items[j].totalPriceSet.amount;
if (j === orders[i].items.length - 1) {
if (orderTotal < orders[i].totalPriceSet.amount) {
const baseVat = await getTaxCode(2, req.params.channelId);
if (!monthlyList[year][month][day][baseVat]) {
monthlyList[year][month][day][baseVat] = {};
monthlyList[year][month][day][baseVat].amount = 0.0;
}
monthlyList[year][month][day][baseVat].amount += (Math.round((orders[i].totalPriceSet.amount - orderTotal + Number.EPSILON) * 100) / 100);
}
}
}
}
const monthlyListArray = [];
const years = Object.keys(monthlyList);
for (let i = 0; i < years.length; i++) {
const months = Object.keys(monthlyList[years[i]]);
for (let j = 0; j < months.length; j++) {
const days = Object.keys(monthlyList[years[i]][months[j]]);
for (let k = 0; k < days.length; k++) {
const aliquote = Object.keys(monthlyList[years[i]][months[j]][days[k]]);
for (let x = 0; x < aliquote.length; x++) {
const { amount } = monthlyList[years[i]][months[j]][days[k]][aliquote[x]];
const tax = await getTaxIdFromTaxClass(aliquote[x], req.params.channelId);
const taxRate = await getTaxRate(tax);
monthlyListArray.push({
year: years[i],
month: months[j],
day: days[k],
tax: aliquote[x],
netAmount: amount / (1 + taxRate),
taxAmount: amount - (amount / (1 + taxRate)),
});
}
}
}
}
return res.status(200).json({ success: true, data: monthlyListArray });
} catch (error) {
console.log(error.message);
return res.status(400).send({ success: false, message: 'Error reading orders for the period', error: error.message });
}
});
router.get('/summary/:partnerId/:channelId', async (req, res) => {
try {
const soldProducts = [];
const orders = await orderModel.find();
for (let i = 0; i < orders.length; i++) {
for (let j = 0; j < orders[i].items.length; j++) {
const product = await productModel.findOne({ sku: orders[i].items[j].sku });
if (product && product.partnerId.equals(req.params.partnerId)) {
soldProducts.push({
product, quantity: orders[i].items[j].quantity, createdAt: orders[i].createdAt, totalPrice: orders[i].items[j].totalPriceSet.amount, totalPriceCurrency: orders[i].items[j].totalPriceSet.currencyCode,
});
}
}
}
return res.status(200).json({ success: true, data: soldProducts });
} catch (error) {
console.log(error.message);
return res.status(400).send({ success: false, message: 'Error reading attribute sets', error: error.message });
}
});
router.get('/summary/:partnerId/:channelId/:year/:month/:day', async (req, res) => {
try {
const soldProducts = [];
const orders = await orderModel.find({
createdAt: {
$gte: new Date(req.params.year, req.params.month - 1, 1),
$lt: new Date(req.params.year, req.params.month - 1, 31),
},
});
for (let i = 0; i < orders.length; i++) {
for (let j = 0; j < orders[i].items.length; j++) {
const product = await productModel.findOne({ sku: orders[i].items[j].sku });
if (product && product.partnerId.equals(req.params.partnerId)) {
soldProducts.push({
product, quantity: orders[i].items[j].quantity, createdAt: orders[i].createdAt, totalPrice: orders[i].items[j].totalPriceSet.amount, totalPriceCurrency: orders[i].items[j].totalPriceSet.currencyCode,
});
}
}
}
return res.status(200).json({ success: true, data: soldProducts });
} catch (error) {
console.log(error.message);
return res.status(400).send({ success: false, message: 'Error reading attribute sets', error: error.message });
}
});
// class SalesEntry {
// id = "";
// customer,
// customerEmail,
// itemName,
// quantity,
// price,
// priceCurrency,
// value,
// valueCurrency,
// totalPartnerCost,
// //subtotal
// boxes,
// refrigeratedWeight,
// totalItems,
// bottles,
// fragile,
// totalRevenue,
// totalCosts,
// }
// TODO: ADMIN?
router.get('/summary/details/admin/:partnerId/:channelId/:year/:month/:day', async (req, res) => {
try {
const rows = [];
const orders = await orderModel.find({
partnerId: req.params.partnerId,
createdAt: {
$gte: new Date(req.params.year, req.params.month - 1, 1),
$lt: new Date(req.params.year, req.params.month - 1, 31),
},
});
for (let i = 0; i < orders.length; i++) {
// total cost calculation
const boxes = 1;
const boxCost = 2.9;
const firstRowRate = 1.15;
const subsequentRowsRate = 0.35;
const fragileRate = 0.12;
const bottleRate = 1.23;
// retrieving data contained in items, needed before looping them
const metadata = await getItemsMetaData(orders[i].items);
const refrigeratedRate = 1.55;
const totalValue = orders[i].totalPriceSet.amount;
const shipmentPercentage = 0.125;
// set 25 to totalvalue if order has no shipment (Da adattare sulla base della tabella prezzi);
const shipmentFraction = metadata.itemTotal === totalValue ? getShipmentValueFromTable(orders[i]) * shipmentPercentage : 0;
const totalCost = (boxes * boxCost) + (refrigeratedRate * (metadata.refrigeratedWeight / 1000)) + firstRowRate + (subsequentRowsRate * (orders[i].items.length - 1)) + shipmentFraction;
console.log(`Total cost: ${boxes}*${boxCost} + ${refrigeratedRate}*${metadata.refrigeratedCount} + ${firstRowRate} + ${subsequentRowsRate}*${orders[i].items.length - 1} + ${shipmentFraction}`);
for (let j = 0; j < orders[i].items.length; j++) {
const row = {};
row.id = orders[i].omsgid;
row.customer = orders[i].customer.displayName;
row.customerEmail = orders[i].customer.email;
row.createdAt = new Date(orders[i].createdAt);
const item = orders[i].items[j];
row.itemName = item.name;
const product = await productModel.findOne({ sku: item.sku });
if (product) {
const tax = await getTaxCode(product.imsTaxCode, req.params.channelId);
const taxRate = await getTaxRate(product.imsTaxCode);
const partner = await partnerModel.findOne({ _id: product.partnerId });
if (partner) {
row.partner = partner.companyName;
}
row.sku = item.sku;
row.quantity = item.quantity;
row.price = item.unitPriceSet.amount;
row.priceCurrency = item.unitPriceSet.currencyCode;
row.netValue = item.totalPriceSet.amount / (1 + taxRate);
row.valueCurrency = item.totalPriceSet.currencyCode;
row.taxValue = item.totalPriceSet.amount - row.netValue;
row.productTax = tax;
row.fragileRate = product.fragile ? fragileRate * item.quantity : 0;
row.bottleRate = product.bottle ? bottleRate * item.quantity : 0;
row.refrigeratedRate = product.refrigerated ? refrigeratedRate * (item.quantity * (item.weight / 1000)) : 0;
row.shipmentFraction = shipmentFraction * (item.totalPriceSet.amount / metadata.itemTotal);
console.log(`shipmentFraction = ${shipmentFraction}*(${item.totalPriceSet.amount / metadata.itemTotal})`);
// row.totalRowCost = totalCost * ((row.netValue + row.taxValue + row.shipmentFraction) / totalValue);
const paidShipment = shipmentFraction === 0 ? orders[i].totalPriceSet.amount - metadata.itemTotal : 0;
row.totalRowCost = totalCost * ((row.netValue + row.taxValue) / (totalValue - paidShipment));
row.totalPartnerCost = row.totalRowCost + row.fragileRate + row.bottleRate;
}
rows.push(row);
}
// Riga relativa alla spedizione
const shipmentRow = {};
shipmentRow.id = orders[i].omsgid;
shipmentRow.createdAt = new Date(orders[i].createdAt);
shipmentRow.itemName = 'Spedizione';
shipmentRow.customer = orders[i].customer.displayName;
shipmentRow.customerEmail = orders[i].customer.email;
shipmentRow.totalValue = orders[i].totalPriceSet.amount - metadata.itemTotal;
rows.push(shipmentRow);
const recapRow = {};
recapRow.id = orders[i].omsgid;
recapRow.createdAt = new Date(orders[i].createdAt);
recapRow.boxes = boxes;
recapRow.itemName = 'Riepilogo';
// recapRow.netValue = totalValue - metadata.itemTotal;
recapRow.refrigeratedWeight = metadata.refrigeratedWeight;
recapRow.items = metadata.totalQuantity;
recapRow.totalValue = totalValue;
recapRow.totalCost = totalCost;
rows.push(recapRow);
}
return res.status(200).json({ success: true, data: rows });
} catch (error) {
console.log(error.message);
return res.status(400).send({ success: false, message: 'Error reading orders for the period', error: error.message });
}
});
// updating vendor's orders setting proper status
router.get('/update/:partnerId/', async (req, res) => {
try {
console.log('update orders');
const omsorders = await oms.fetchOrdersRest()
.catch((error) => {
throw Error(error);
});
const orders = await orderModel.find({ partnerId: req.params.partnerId });
console.log(`found ${orders.length} orders...`);
for (let i = 0; i < orders.length; i++) {
const order = orders[i];
for (let j = 0; j < omsorders.length; j++) {
if (order.omsgid === omsorders[j].omsgid) {
console.log(`${order.omsgid} - ${omsorders[j].omsgid}`);
console.log(`${order.status} - ${omsorders[j].status}`);
if (order.status !== omsorders[j].status) {
console.log(`Set status ${omsorders[j].status} over ${order.status} of order ${order.omsgid}`);
order.status = omsorders[j].status;
order.save();
}
}
}
}
return res.status(200).json({ success: true, data: orders });
} catch (error) {
console.log(error.message);
return res.status(400).send({ success: false, message: 'Error updating order', error: error.message });
}
});
// updating vendor's orders setting proper status
router.get('/all/:partnerId/', async (req, res) => {
console.log('get all orders');
try {
const orders = await orderModel.find({
partnerId: req.params.partnerId,
});
return res.status(200).json({ success: true, data: orders });
} catch (error) {
console.log(error.message);
return res.status(400).send({ success: false, message: 'Error reading orders', error: error.message });
}
});
// updating vendor's orders setting proper status
router.get('/open/:partnerId/', async (req, res) => {
try {
const orders = await orderModel.find({
partnerId: req.params.partnerId,
fulfilled: false,
});
return res.status(200).json({ success: true, data: orders });
} catch (error) {
console.log(error.message);
return res.status(400).send({ success: false, message: 'Error reading open orders', error: error.message });
}
});
// updating vendor's orders setting proper status
router.post('/retry', async (req, res) => {
try {
const order = req.body;
const persistentOrder = await orderModel.findOne({ omsgid: order.omsgid, instanceId: order.instanceId, storeName: order.storeName });
await oms.checkOrder(persistentOrder, persistentOrder.instanceId, persistentOrder.storeName);
return res.status(200).json({ success: true });
} catch (error) {
console.log(error.message);
return res.status(400).send({ success: false, message: 'Error reading attribute sets', error: error.message });
}
});
async function getItemsMetaData(items) {
let refrigeratedCount = 0;
let refrigeratedWeight = 0.0;
let itemTotal = 0.0;
let totalQuantity = 0;
for (let i = 0; i < items.length; i++) {
totalQuantity += items[i].quantity;
const product = await productModel.findOne({ sku: items[i].sku });
if (product) {
if (product.refrigerated) {
refrigeratedCount++;
refrigeratedWeight += items[i].quantity * items[i].weight;
}
itemTotal += items[i].totalPriceSet.amount;
}
}
return {
refrigeratedCount, refrigeratedWeight, totalQuantity, itemTotal,
};
}
async function getTaxCode(productTaxCode, channelId) {
const taxes = await taxQuery.readMany('all', channelId);
for (let i = 0; i < taxes.items.length; i++) {
if (taxes.items[i].class_id.toString() === productTaxCode.toString() && taxes.items[i].class_type === 'PRODUCT') {
return taxes.items[i].class_name;
}
}
return '';
}
async function getTaxIdFromTaxClass(taxClass, channelId) {
const taxes = await taxQuery.readMany('all', channelId);
for (let i = 0; i < taxes.items.length; i++) {
if (taxes.items[i].class_name.toString() === taxClass && taxes.items[i].class_type === 'PRODUCT') {
return taxes.items[i].class_id.toString();
}
}
}
async function getTaxRate(tax) {
switch (tax) {
case '2':
return 0.22;
case '4':
return 0.10;
case '5':
return 0.04;
default:
console.log('IVA default');
return 0.22;
}
}
function getShipmentValueFromTable(order) {
return 25;
}
module.exports = router;