Your IP : 216.73.216.220


Current Path : /home/deltalab/PMS/partner-manager-backend/services/
Upload File :
Current File : //home/deltalab/PMS/partner-manager-backend/services/cron.js

/* eslint-disable no-continue */
/* eslint-disable guard-for-in */
/* eslint-disable no-restricted-syntax */
const cron = require('node-cron');
const axios = require('axios');
const { productModel } = require('../models/mongoose/product');
const { orderModel } = require('../models/mongoose/order');
const { channelModel } = require('../models/mongoose/channel');
const { userBasedRecommendationModel } = require('../models/mongoose/recommendation');

const ims = require('./ims');
const oms = require('./oms');
const mail = require('./mail');

const { MARKETPLACE_ID } = process.env;
const { MARKETPLACE_URL } = process.env;
const { MARKETPLACE_AUTH } = process.env;

function orderProducts(products, permutations) {
  const newProducts = products.slice();
  const productsOrdered = [];
  for (let i = 0; i < permutations.length; i++) {
    productsOrdered.push(products[permutations[i]]);
  }
  for (let i = 0; i < newProducts.length; i++) {
    if (!permutations.includes(i)) {
      productsOrdered.push(newProducts[i]);
    }
  }
  return productsOrdered;
}

function getMarketplaceOfferFromReference(reference) {
  for (const offer of reference.offers) {
    if (offer.channelId.toString() === MARKETPLACE_ID) {
      return offer.sku;
    }
  }
  return undefined;
}

async function cronUpdateProducts() {
  console.log('[CRON] Schedule updating products for related items...');
  cron.schedule('0 3 * * *', async () => { // runs every day at 3:00 AM
    console.log('[CRON] Updating products for related items...');

    console.log('leggo raccomandazioni');
    // TODO: load data from DB
    const recommendations = await userBasedRecommendationModel.find({});

    console.log('[RECOMMENDATIONS] length');
    console.log(recommendations.length);

    // order all reccommendation and update linked products
    for (let i = 0; i < recommendations.length; i++) {
      const users = recommendations[i].linkedProducts_permutations;
      // for (const user in users) {
      //   if (user === 'generic_user') {
      //     recommendations[i].all_linkedProducts = orderProducts(recommendations[i].all_linkedProducts, users[user].product_permutation);
      //   }
      // }
      // update linked products
      const reference = await productModel.findById(recommendations[i].product_id);
      reference.linkedProducts = recommendations[i].all_linkedProducts;
      try {
        console.log('[REFERENCE] offerte e lunghezza');
        await ims.referenceUpdate(reference, reference.sku);
        console.log(`[CRON] Updated product ${reference.sku}`);
      } catch (error) {
        console.log(error);
        console.log(`[CRON] Error updating the product ${reference.sku}`);
      }
    }

    for (let i = 0; i < recommendations.length; i++) {
      const permutations = [];
      const explanations = [];
      const users = recommendations[i].linkedProducts_permutations;
      // get Marketplace offer from the reference
      const reference = await productModel.findById(recommendations[i].product_id);
      const offerSku = getMarketplaceOfferFromReference(reference);
      if (!offerSku) continue;
      for (const user in users) {
        const linkedProducts = users[user].product_permutation;
        for (let j = 0; j < linkedProducts.length; j++) {
          const related = await productModel.findById(recommendations[i].all_linkedProducts[linkedProducts[j]]);
          // select only the offer from the marketplace
          const linkedOfferSku = getMarketplaceOfferFromReference(related);
          // permutations
          permutations.push({
            sku: offerSku, // push offer sku
            user,
            position: j,
            related: linkedOfferSku, // push offer sku
          });
        }
        // select only the offer from the marketplace
        // explanations
        explanations.push({
          sku: offerSku, // push offer sku
          user,
          title: users[user].explaination,
        });
      }
      // send request directly to marketplace
      const config = {
        headers: {
          Authorization: MARKETPLACE_AUTH, // the token is a variable which holds the token
        },
      };
      try {
        const responseLinkedProducts = await axios.post(`${MARKETPLACE_URL}/insertRelatedSku`, permutations, config);
      } catch (error) {
        console.log(error);
        console.log('[CRON] Error during insertRelatedSku');
      }
      try {
        const responseExplanation = await axios.post(`${MARKETPLACE_URL}/insertRelatedTitle`, explanations, config);
      } catch (error) {
        console.log(error);
        console.log('[CRON] Error during insertRelatedTitle');
      }
    }
  });
}

async function cronCheckOrderNumbers() {
  console.log('[CRON] Schedule product checks...');
  cron.schedule('0 6 * * *', async () => { // runs every day at 6:00 AM
    console.log('[CRON] Starting order check...');
    const pmsOrders = await orderModel.find();

    const today = new Date();

    const orderIds = [];
    for (let i = 0; i < pmsOrders.length; i++) {
      orderIds.push(pmsOrders[i].omsgid);
    }

    console.log(orderIds);

    const channels = await channelModel.find();

    const anomalies = new Set();

    for (let i = 0; i < channels.length; i++) {
      console.log(`[CRON] Order check in channel ${channels[i].storeName}`);
      const orders = await oms.getOrdersByChannel(channels[i]);
      for (let j = 0; j < orders.length; j++) {
        const orderTime = new Date(orders[j].createdAt).getTime();
        const todayTime = today.getTime();
        const dayDifference = ((todayTime - orderTime) / (1000 * 60 * 60 * 24.0));
        console.log(`${orders[j].omsgid} - ${orderTime} - ${todayTime} - ${dayDifference}`);
        if (dayDifference > 60) {
          continue;
        }
        if (!orderIds.includes(orders[j].omsgid)) {
          anomalies.add({ order: orders[j].omsgid });
          console.log(`[CRON] There is an anomaly... Order ${orders[j].omsgid} from channel ${channels[i].storeName} not found on PMS`);
        }
      }
    }
    console.log(`[CRON] Total anomalies found: ${anomalies.length}`);
    if (anomalies.length > 0) {
      console.log('[CRON] Sending email...');
      await mail.sendAnomaliesEmail(Array.from(anomalies));
    }
    console.log('[CRON] Order check completed!');
  });
}

async function cronCheckOrderNumbersOnce() {
  console.log('[CRON] Starting order check...');
  const pmsOrders = await orderModel.find();

  const today = new Date();

  const orderIds = [];
  for (let i = 0; i < pmsOrders.length; i++) {
    orderIds.push(pmsOrders[i].omsgid);
  }

  console.log(orderIds);

  const channels = await channelModel.find();

  const anomalies = [];

  for (let i = 0; i < channels.length; i++) {
    console.log(`[CRON] Order check in channel ${channels[i].storeName}`);
    const orders = await oms.getOrdersByChannel(channels[i]);
    for (let j = 0; j < orders.length; j++) {
      const orderTime = new Date(orders[j].createdAt).getTime();
      const todayTime = today.getTime();
      const dayDifference = ((todayTime - orderTime) / (1000 * 60 * 60 * 24.0));
      console.log(`${orders[j].omsgid} - ${orderTime} - ${todayTime} - ${dayDifference}`);
      if (dayDifference > 60) {
        continue;
      }
      if (!orderIds.includes(orders[j].omsgid)) {
        anomalies.push({ order: orders[j].omsgid, channel: channels[i].storeName });
        console.log(`[CRON] There is an anomaly... Order ${orders[j].omsgid} from channel ${channels[i].storeName} not found on PMS`);
      }
    }
  }
  console.log(`[CRON] Total anomalies found: ${anomalies.length}`);
  if (anomalies.length > 0) {
    console.log('[CRON] Sending email...');
    // await mail.sendAnomaliesEmail(anomalies);
  }
  console.log('[CRON] Order check completed!');
}

async function cronUpdateProductsOnce() {
  console.log('[CRON] Updating products for related items...');

  // console.log('leggo raccomandazioni');
  // // TODO: load data from DB
  const recommendations = await userBasedRecommendationModel.find({});

  console.log('[RECOMMENDATIONS] length');
  console.log(recommendations.length);

  // order all reccommendation and update linked products
  for (let i = 0; i < recommendations.length; i++) {
    const users = recommendations[i].linkedProducts_permutations;
    // for (const user in users) {
    //   if (user === 'generic_user') {
    //     recommendations[i].all_linkedProducts = orderProducts(recommendations[i].all_linkedProducts, users[user].product_permutation);
    //   }
    // }
    // update linked products
    const reference = await productModel.findById(recommendations[i].product_id);
    reference.linkedProducts = recommendations[i].all_linkedProducts;
    try {
      console.log('[REFERENCE] offerte e lunghezza');
      await ims.referenceUpdate(reference, reference.sku);
      console.log(`[CRON] Updated product ${reference.sku}`);
    } catch (error) {
      console.log(error);
      console.log(`[CRON] Error updating the product ${reference.sku}`);
    }
  }

  for (let i = 0; i < recommendations.length; i++) {
    const permutations = [];
    const explanations = [];
    const users = recommendations[i].linkedProducts_permutations;
    // get Marketplace offer from the reference
    const reference = await productModel.findById(recommendations[i].product_id);
    const offerSku = getMarketplaceOfferFromReference(reference);
    if (!offerSku) continue;
    for (const user in users) {
      const linkedProducts = users[user].product_permutation;
      for (let j = 0; j < linkedProducts.length; j++) {
        const related = await productModel.findById(recommendations[i].all_linkedProducts[linkedProducts[j]]);
        // select only the offer from the marketplace
        const linkedOfferSku = getMarketplaceOfferFromReference(related);
        // permutations
        permutations.push({
          sku: offerSku, // push offer sku
          user,
          position: j,
          related: linkedOfferSku, // push offer sku
        });
      }
      // select only the offer from the marketplace
      // explanations
      explanations.push({
        sku: offerSku, // push offer sku
        user,
        title: users[user].explaination,
      });
    }
    // send request directly to marketplace
    const config = {
      headers: {
        Authorization: MARKETPLACE_AUTH, // the token is a variable which holds the token
      },
    };
    try {
      const responseLinkedProducts = await axios.post(`${MARKETPLACE_URL}/insertRelatedSku`, permutations, config);
    } catch (error) {
      console.log(error);
      console.log('[CRON] Error during insertRelatedSku');
    }
    try {
      const responseExplanation = await axios.post(`${MARKETPLACE_URL}/insertRelatedTitle`, explanations, config);
      console.log(`[EXPLANATION] ${responseExplanation.data.message}`);
    } catch (error) {
      console.log(error);
      console.log('[CRON] Error during insertRelatedTitle');
    }
  }
}

module.exports = {
  cronUpdateProducts,
  cronUpdateProductsOnce,
  cronCheckOrderNumbers,
  cronCheckOrderNumbersOnce,
};