Your IP : 216.73.216.43


Current Path : /proc/thread-self/root/home/deltalab/PMS/partner-manager-backend/services/
Upload File :
Current File : //proc/thread-self/root/home/deltalab/PMS/partner-manager-backend/services/mail.js

/* eslint-disable no-use-before-define */
/* eslint-disable no-continue */
/* eslint-disable no-await-in-loop */
/* eslint-disable max-len */
/* eslint-disable no-restricted-syntax */
require('dotenv').config();
const nodemailer = require('nodemailer');
const pdf = require('./pdf');
const { partnerModel } = require('../models/mongoose/partner');
const { productModel } = require('../models/mongoose/product');

function generatePickingMailText(order, parcels, labelUrls, pickupDate) {
  console.log('PICKING TEXT');
  console.log(labelUrls);
  let text = 'Si segnala l\'inserimento di un nuovo ordine e-commerce \n';
  text += `Nuovo ordine n. ${order.name} da ${order.customer.displayName}\n`;
  text += '\n\n';
  text += `Venditore: ${order.partner.companyName} (${order.partner.vatNumber})\n`;
  text += '\n\n';
  text += 'I seguenti prodotti sono da prelevare e preparare con l\'imballo di seguito specificato \n';
  text += '\n\n';
  text += 'Prodotti:\n';
  for (const item of order.items) {
    text += `${item.quantity}x ${item.name} - SKU: ${item.sku}\n`;
  }
  text += '\n\n';
  text += 'NOTA: provvedere all\'imballo avendo cura di garantire la conservazione dei prodotti dagli urti e dagli sbalzi di temperatura. \n';
  text += 'Inserire nel pacco la PACKING SLIP \n';
  text += 'IMPORTANTE: Rispettare il numero di colli indicato qui sotto. Qualora non fosse abbastanza grande l’imballo indicato, utilizzare un imballo più capiente';
  text += '\n\n';
  text += 'Colli:\n';
  let i = 0;
  for (const parcel of parcels) {
    const parcelSizeStr = `${parcel.length}x${parcel.width}x${parcel.height}`;
    text += `${++i}) ${parcelSizeStr} (${parcel.weight}g)\n`;
  }

  for (let j = 0; j < labelUrls.length; j++) {
    text += '\n\n';
    text += `Etichetta spedizione: ${labelUrls[j]}\n`;
    text += '\n\n';
  }
  // text += 'É STATO PRENOTATO IL RITIRO DA PARTE DEL CORRIERE IN DATA E ORA \n';
  // text += pickupDate;
  // text += '\n\n';
  text += 'In caso di problemi che impediscano la spedizione si prega di contattare \n';
  text += 'sara Malpaga';
  text += '\n\n';
  text += '- INDACO -';
  return text;
}

function generateNewUserMailText(userName) {
  let text = `É stato creato un nuovo utente ${userName} su INDACO PMS utilizzando questo indirizzo e-mail. \n`;
  text += 'É possibile effettuare l\'accesso utilizzando le credenziali create, dalla pagina di login del PMS. \n';
  text += '\n\n';
  text += 'Se la creazione di questo utente non è autorizzata, contattare l\'email info@indacotrentino.com';
  text += '\n\n';
  text += '\n\n';
  text += '- INDACO -';
  return text;
}

function generateNewTransferMailText(warehouseTo, product, quantity) {
  let text = `É stato richiesto un trasferimento da questo magazzino verso ${warehouseTo.name} per l'evasione di un ordine. \n`;
  text += 'Si prega di organizzare la spedizione di  \n';
  text += `${product.title} - ${product.sku} - Quantità: ${quantity} \n\n`;
  text += '\n\n';
  text += ' La spedizione dovrà essere effettuata verso: \n\n';
  text += `${warehouseTo.address.name}`;
  text += `${warehouseTo.address.street1}`;
  text += `${warehouseTo.address.street2}`;
  text += `${warehouseTo.address.city}`;
  text += `${warehouseTo.address.zip}`;
  text += `${warehouseTo.address.country}`;
  text += `${warehouseTo.address.phone}`;
  text += `${warehouseTo.address.email}`;
  text += '\n\n';
  text += '\n\n';
  text += 'Si prega di provvedere alla spedizione nel più breve tempo possibile, per permettere l\'evasione dell\'intero ordine.';
  text += '\n\n';
  text += '\n\n';
  text += '- INDACO -';
  return text;
}

async function generatePartnerRecapText(companyName, partnerObject) {
  const productsMap = new Map();
  let text = `Gentile ${companyName}, \n`;
  // let text = 'Buongiorno, \n';
  text += 'inviamo per conoscenza il riepilogo degli ordini ricevuti nella giornata di ieri con dettaglio prodotti totali venduti divisi per referenza. \n';
  text += 'Ricordiamo che il documento è condiviso per permettere di tenere monitorato l\'andamento delle vendite online, ma non prevede alcuna azione da parte vostra. \n';
  text += '\n\n';
  text += '\n\n';
  const orders = Object.keys(partnerObject);
  for (let i = 0; i < orders.length; i++) {
    text += `Ordine n. ${orders[i]} \n`;
    const items = Object.keys(partnerObject[orders[i]]);
    for (let j = 0; j < items.length; j++) {
      const product = await productModel.findOne({ 'offers.sku': items[j] });
      if (!product) {
        continue;
      }
      text += `- ${product.title} (${items[j]}): ${partnerObject[orders[i]][items[j]].quantity} \n`;
      const previousValue = productsMap.get(`${product.title} (${items[j]})`);
      productsMap.set(`${product.title} (${items[j]})`, previousValue ? previousValue + partnerObject[orders[i]][items[j]].quantity : partnerObject[orders[i]][items[j]].quantity);
    }
    text += '\n';
  }
  text += 'TOTALE PRODOTTI ACQUISTATI: \n';
  for (const [key, value] of productsMap) {
    text += `- ${key}: ${value} \n`;
  }
  text += '\n\n';
  text += 'Ci sentiamo nei primi giorni della prossima settimana per organizzare il conferimento dei prodotti presso il nostro magazzino: \n\n';
  text += 'Delivery Srl \n';
  text += 'Via Innsbruck 20 – lotto n. 8 \n';
  text += 'Trento (TN) \n\n';
  text += 'Rimaniamo a disposizione,\n';
  text += 'Un saluto\n\n';
  text += 'Sara Malpaga \n';
  text += 'tel: +39 3486695292 \n';
  text += 'email: sara.malpaga@ftcoop.it \n';
  text += '\n\n';
  text += '- INDACO -';
  return text;
}

async function generateAnomaliesRecapText(anomalies) {
  let html = 'Nel corso dell\'ultimo controllo automatico è stata riscontrata un\'anomalia tra gli ordini creati sull\'e-commerce e quelli registrati sul PMS. \n\n';
  html += 'Si prega di controllare la lista qui sotto e verificare le anomalie nel più breve tempo possibile:  \n\n';
  for (let i = 0; i < anomalies.length; i++) {
    html += `Ordine ${anomalies[i].order} - ${anomalies[i].channel} \n\n`;
  }
  html += '\n\n';
  html += '<br><br>';
  html += '- INDACO -';
  return html;
}

// =================================================== HTML =====================================================================

function generatePickingMailHTML(order, parcels, labelUrls, pickupDate) {
  console.log('PICKING HTML');
  console.log(labelUrls);
  let html = 'Si segnala l\'inserimento di un nuovo ordine e-commerce <br>';
  html += `<strong> Nuovo ordine n. ${order.name} da ${order.customer.displayName}</strong> <br>`;
  html += '<br><br>';
  html += `Venditore: ${order.partner.companyName} (${order.partner.vatNumber})<br>`;
  html += '<br><br>';
  html += 'I seguenti prodotti sono da prelevare e preparare con l\'imballo di seguito specificato <br>';
  html += '<br><br>';
  html += 'Prodotti:<br>';
  for (const item of order.items) {
    html += ` - ${item.quantity}x ${item.name} - SKU: ${item.sku} <br>`;
  }
  html += '<br><br>';
  html += 'NOTA: provvedere all\'imballo avendo cura di garantire la conservazione dei prodotti dagli urti e dagli sbalzi di temperatura. <br>';
  html += 'Inserire nel pacco la PACKING SLIP <br>';
  html += 'IMPORTANTE: Rispettare il numero di colli indicato qui sotto. Qualora non fosse abbastanza grande l’imballo indicato, utilizzare un imballo più capiente';
  html += '<br><br>';
  html += 'Colli:<br>';
  let i = 0;
  for (const parcel of parcels) {
    const parcelSizeStr = `${parcel.length}x${parcel.width}x${parcel.height}`;
    html += `${++i}) ${parcelSizeStr} (${parcel.weight}g)<br>`;
  }
  for (let j = 0; j < labelUrls.length; j++) {
    html += '<br><br>';
    html += `Etichetta spedizione: <a href="${labelUrls[j]}">scarica qui</a><br>`;
    html += '<br><br>';
  }
  // html += 'É STATO PRENOTATO IL RITIRO DA PARTE DEL CORRIERE IN DATA E ORA <br>';
  // html += pickupDate;
  // html += '<br><br>';
  html += 'In caso di problemi che impediscano la spedizione si prega di contattare <br>';
  html += 'Sara Malpaga';
  html += '<br><br>';
  html += '- INDACO -';
  return html;
}

function generateNewUserMailHTML(userName) {
  let html = `É stato creato un nuovo utente ${userName} su INDACO PMS utilizzando questo indirizzo e-mail. <br>`;
  html += 'É possibile effettuare l\'accesso utilizzando le credenziali create, dalla pagina di login del PMS. <br>';
  html += '<br><br>';
  html += 'Se la creazione di questo utente non è autorizzata, contattare l\'email info@indacotrentino.com';
  html += '<br><br>';
  html += '<br><br>';
  html += '- INDACO -';
  return html;
}

function generateNewTransferMailHTML(warehouse, product, quantity) {
  let html = `É stato richiesto un trasferimento da questo magazzino verso ${warehouse.name} per l'evasione di un ordine. <br>`;
  html += 'Si prega di organizzare la spedizione di  <br>';
  html += `${product.title} - Quantità: ${quantity} <br><br>`;
  html += '<br><br>';
  html += ' La spedizione dovrà essere effettuata verso: <br><br>';
  html += `${warehouse.address.name} <br>`;
  html += `${warehouse.address.street1} <br>`;
  html += `${warehouse.address.street2} <br>`;
  html += `${warehouse.address.city} <br>`;
  html += `${warehouse.address.zip} <br>`;
  html += `${warehouse.address.country} <br>`;
  html += `${warehouse.address.phone} <br>`;
  html += `${warehouse.address.email} <br>`;
  html += '<br><br>';
  html += '<br><br>';
  html += 'Si prega di provvedere alla spedizione nel più breve tempo possibile, per permettere l\'evasione dell\'intero ordine.';
  html += '<br><br>';
  html += '<br><br>';
  html += '- INDACO -';
  return html;
}

async function generatePartnerRecapHtml(companyName, partnerObject) {
  const productsMap = new Map();

  let html = `Gentile ${companyName}, <br>`;
  // let html = 'Buongiorno, <br>';
  html += 'inviamo per conoscenza il riepilogo degli ordini ricevuti nella giornata di ieri con dettaglio prodotti totali venduti divisi per referenza. <br>';
  html += 'Ricordiamo che il documento è condiviso per permettere di tenere monitorato l\'andamento delle vendite online, ma non prevede alcuna azione da parte vostra. <br>';
  html += '<br><br>';
  html += '<br><br>';
  const orders = Object.keys(partnerObject);
  for (let i = 0; i < orders.length; i++) {
    html += `<b> Ordine n. ${orders[i]} </b><br>`;
    const items = Object.keys(partnerObject[orders[i]]);
    for (let j = 0; j < items.length; j++) {
      console.log(`trying to find product with sku ${items[j]}`);
      const product = await productModel.findOne({ 'offers.sku': items[j] });
      if (!product) {
        console.log('PRODOTTO NON TROVATO');
        continue;
      }
      html += `- ${product.title} (${items[j]}): ${partnerObject[orders[i]][items[j]].quantity} <br>`;
      const previousValue = productsMap.get(`${product.title} (${items[j]})`);
      productsMap.set(`${product.title} (${items[j]})`, previousValue ? previousValue + partnerObject[orders[i]][items[j]].quantity : partnerObject[orders[i]][items[j]].quantity);
    }
    html += '<br>';
  }
  html += '<b>TOTALE PRODOTTI ACQUISTATI:</b><br>';
  for (const [key, value] of productsMap) {
    html += `- ${key}: ${value} <br>`;
  }
  html += '<br><br>';
  html += 'Ci sentiamo nei primi giorni della prossima settimana per organizzare il conferimento dei prodotti presso il nostro magazzino: <br><br>';
  html += 'Delivery Srl <br>';
  html += 'Via Innsbruck 20 – lotto n. 8 <br>';
  html += 'Trento (TN) <br><br>';
  html += 'Rimaniamo a disposizione,<br>';
  html += 'Un saluto<br><br>';
  html += 'Sara Malpaga <br>';
  html += 'tel: +39 3486695292 <br>';
  html += 'email: sara.malpaga@ftcoop.it <br>';
  html += '<br><br>';
  html += '- INDACO -';
  return html;
}

async function generateAnomaliesRecapHtml(anomalies) {
  let html = 'Nel corso dell\'ultimo controllo automatico è stata riscontrata un\'anomalia tra gli ordini creati sull\'e-commerce e quelli registrati sul PMS. <br>';
  html += 'Si prega di controllare la lista qui sotto e verificare le anomalie nel più breve tempo possibile:  <br>';
  for (let i = 0; i < anomalies.length; i++) {
    html += `Ordine ${anomalies[i].order} - ${anomalies[i].channel} <br><br>`;
  }
  html += '<br><br>';
  html += '- INDACO -';
  return html;
}

// =================================================== UTILITIES =====================================================================

function generatePickingListAttachment(order, parcels, labelUrls) {
  // generate picking list
  let attachment = null;
  const pickingListPdf = pdf.generatePickingListPdf(order, parcels, labelUrls);
  // check if file exists
  attachment = [{
    filename: `${order.name.replace('#', '')}-pickingList.pdf`,
    content: pickingListPdf,
  }];
  return attachment;
}

/**
 * Low level, sends the mail data to the given sender
 * @param {*} sender
 * @param {*} mailData
 * @param {*} attachmentData
 */
async function sendMail(sender, mailData, attachmentData) {
  if (!mailData.to) {
    console.log('E-mail not sent, recipient not specified');
    return;
  }

  // create reusable transporter object using the default SMTP transport
  const senderData = {
    host: sender != null ? sender.host : process.env.MAIL_HOST, // "smtp.ethereal.email",
    port: sender != null ? sender.port : process.env.MAIL_PORT, // 587,
    // secure: true, //false, // true for 465, false for other ports
    auth: {
      user: sender != null ? sender.user : process.env.MAIL_USER, // testAccount.user, // generated ethereal user
      pass: sender != null ? sender.host : process.env.MAIL_PASSWORD, // testAccount.pass, // generated ethereal password
    },
    secure: sender != null ? sender.host : process.env.MAIL_SECURE,
  };

  const transporter = nodemailer.createTransport(senderData);

  // send mail with defined transport object
  const messageInfo = await transporter.sendMail({
    from: sender != null ? sender.address : process.env.MAIL_ADDRESS, // '"Fred Foo 👻" <foo@example.com>', // sender address
    to: mailData.to, // "bar@example.com, baz@example.com", // list of receivers
    subject: mailData.subject, // "Hello ✔", // Subject line
    text: mailData.text, // "Hello world?", // plain text body
    html: mailData.html, // "<b>Hello world?</b>", // html body
    attachments: attachmentData || null,
  });
}

/**
 * Sends a picking email to the given warehouse for the order and parcels specified.
 * @param {*} warehouseAddress
 * @param {*} order
 * @param {*} parcels
 * @returns false if something goes wrong
 */
function sendPickingEmail(emails, order, parcels, labelUrls, pickupDate) {
  if (!emails) return false;
  sendMail(null, {
    to: emails,
    subject: `INDACO Instant - Ordine n. ${order.name} in entrata`,
    text: generatePickingMailText(order, parcels, labelUrls, pickupDate),
    html: generatePickingMailHTML(order, parcels, labelUrls, pickupDate),
  }, generatePickingListAttachment(order, parcels, labelUrls));
  return true;
}

function sendNewUserEmail(emails, userName) {
  if (!emails) return false;
  sendMail(null, {
    to: emails,
    subject: `INDACO PMS - Creato utente ${userName}`,
    text: generateNewUserMailText(userName),
    html: generateNewUserMailHTML(userName),
  }, null);
  return true;
}

function sendWarehouseTransferEmail(warehouseFrom, warehouseTo, product, quantity) {
  const emails = warehouseFrom.email;
  let emailAddresses = '';
  emails.forEach((email) => {
    emailAddresses += email;
    emailAddresses += ';';
  });

  sendMail(null, {
    to: emailAddresses,
    subject: 'INDACO PMS - Richiesta Trasferimento Merce',
    text: generateNewTransferMailText(warehouseTo, product, quantity),
    html: generateNewTransferMailHTML(warehouseTo, product, quantity),
  }, null);
  return true;
}

async function sendMailToPartners(orderObject) {
  const partners = Object.keys(orderObject);
  for (let i = 0; i < partners.length; i++) {
    const partner = await partnerModel.findById(partners[i]);
    if (!partner) {
      continue;
    }
    console.log(orderObject[partners[i]]);
    const htmlRecap = await generatePartnerRecapHtml(partner.companyName, orderObject[partners[i]]);
    const textRecap = await generatePartnerRecapText(partner.companyName, orderObject[partners[i]]);

    sendPartnerRecapEmail(partner.email, htmlRecap, textRecap);
  }
}

async function sendAnomaliesEmail(anomalies) {
  const htmlRecap = await generateAnomaliesRecapHtml(anomalies);
  const textRecap = await generateAnomaliesRecapText(anomalies);

  sendOrderAnomaliesEmail(null, htmlRecap, textRecap);
}

function sendPartnerRecapEmail(partnerEmails, htmlRecap, textRecap) {
  const email = 'andrea.gottardi@deltainformatica.eu;sara.malpaga@ftcoop.it'; // partnerEmails
  sendMail(null, {
    to: email,
    subject: 'Riepilogo vendite giornaliere AUTUMNUS - By INDACO Srl',
    text: textRecap,
    html: htmlRecap,
  }, null);
  return true;
}

function sendOrderAnomaliesEmail(partnerEmails, htmlAnomalies, textAnomalies) {
  const email = 'andrea.gottardi@deltainformatica.eu'; // partnerEmails
  sendMail(null, {
    to: email,
    subject: 'Riscontrata anomalia sugli ordini INDACO - Verificare la correttezza dei dati',
    text: textAnomalies,
    html: htmlAnomalies,
  }, null);
  return true;
}

module.exports = {
  sendPickingEmail,
  sendNewUserEmail,
  sendWarehouseTransferEmail,
  sendMailToPartners,
  sendAnomaliesEmail,
};