Your IP : 216.73.216.220


Current Path : /home/deltalab/PMS/ims-connector/logic/shopify/
Upload File :
Current File : //home/deltalab/PMS/ims-connector/logic/shopify/order.js

/* eslint-disable new-cap */
/* eslint-disable no-param-reassign */
const axios = require('axios');

const { orderAddressModel } = require('../../models/mongoose/order');
const { orderBaseModel } = require('../../models/mongoose/order');
const { orderCustomerModel } = require('../../models/mongoose/order');
const { orderItemModel } = require('../../models/mongoose/order');
const { orderMoneyModel } = require('../../models/mongoose/order');

// Headers ===============================================
const shopifyHeaders = {
  'Content-Type': 'application/json',
  Accept: 'application/json',
  'X-Shopify-Access-Token': process.env.SHOPIFY_PASSWORD,
};

// Queries ================================================

/**
 * String representation of a shopify order
 */
const shopifyOrderType = `
  id,
  name,
  closed,
  customer {
    displayName,
    email,
    phone
  },
  shippingAddress {
    name,
    latitude,
    longitude,
    company,
    address1,
    address2,
    phone,
    city,
    province,
    zip,
    country
  },
  fullyPaid,
  fulfillable,
  fulfillments {
    displayStatus
  },
  lineItems (first: 10) {
    edges {
      node {
        product {
          id
        },
        name,
        sku,
        title,
        quantity,
        discountedTotalSet {
          shopMoney {
            amount,
            currencyCode
          }
        },
        discountedUnitPriceSet {
          shopMoney {
            amount,
            currencyCode
          }
        }
      }
    }
  },
  totalPriceSet {
    shopMoney {
      amount,
      currencyCode
    }
  },
  createdAt
`;

/**
 * Retrieve the details of the order with the given id
 */
const shopifyOrderByIdQuery = `
query ($orderId: ID!){
  order (id: $orderId) {
    ${shopifyOrderType}
  }
}
`;

/**
 * This is the query data to retrieve the orders from Shopify
 * Beware the orders retrieved don't have the items populated to limit the query size
 * @param {*} first
 * @param {*} last
 * @param {*} after
 * @param {*} before
 * @param {*} search
 */
const shopifyOrdersQuery = `query getOrders ($first: Int!, $after: String) {
  orders (first: $first, after: $after, query: "status:open") {
    pageInfo {                # Returns details about the current page of results
      hasNextPage,            # Whether there are more results after this page
      hasPreviousPage,        # Whether there are more results before this page
    },
    edges {
      cursor,                 # Marker for absolute edge position in the connection
      node {
        ${shopifyOrderType}   # Object to be returned
      }
    }
  }
}`;

// Functions ==============================================

/**
 * Get a single order from shopify
 * @param {String} orderId
 * @returns
 */
async function getOrder(orderId) {
  console.log(`get order ${orderId} data from  ${process.env.SHOPIFY_STORE_URL}`);
  const result = await axios({
    url: process.env.SHOPIFY_STORE_URL,
    method: 'post',
    data: {
      query: shopifyOrderByIdQuery,
      variables: {
        orderId,
      },
    },
    headers: shopifyHeaders,
  });

  const order = new orderBaseModel();
  populateOrder(order, result.data.data.order);
  return order;
}

/**
 * Get a list of orders directly from shopify
 * @param {Int} first number of items to fetch
 * @param {String} after cursor ID after which fetch items
 * @returns
 */
async function getOrders(first = 10, after = null) {
  console.log(`getting ${first} orders after ${after} from ${process.env.SHOPIFY_STORE_URL}`);
  const orders = [];
  let lastCursor;
  let pageInfo;
  await axios({
    url: process.env.SHOPIFY_STORE_URL,
    method: 'post',
    data: {
      query: shopifyOrdersQuery,
      variables: {
        first,
        after,
      },
    },
    headers: shopifyHeaders,
  }).then((result) => {
    // check errors
    if (result.data.errors) {
      throw Error(result.data.errors[0].message);
    }
    // pagination check
    pageInfo = result.data.data.orders.pageInfo;
    const edges = result.data.data.orders.edges;
    edges.forEach((edge) => {
      lastCursor = edge.cursor;
      const order = new orderBaseModel();
      populateOrder(order, edge.node);
      orders.push(order);
    });
  }).catch((error) => {
    console.log(error);
  });

  // Iteration -------------------------------------
  if (pageInfo && pageInfo.hasNextPage) {
    // Keep requesting orders until there is a nextPage
    const _orders = await getOrders(first, lastCursor);
    console.log(`retrieved orders ${_orders.length}`);
    _orders.forEach((order) => {
      orders.push(order);
    });
  }
  console.log(`finished with orders ${orders.length}`);
  return orders;
}

/**
 * Retrieve an Order object from the response node
 * @param {orderBaseModel} order the order to populate
 * @param {*} node data collected from oms
 * @return the standard order model representation
 */
function populateOrder(order, node) {
  // mapping shopify shit into our data structure
  order.omsgid = node.id;
  order.name = node.name;
  order.createdAt = node.createdAt;
  order.fullyPaid = node.fullyPaid;

  order.customer = new orderCustomerModel();
  // Sanity check
  if (node.customer) {
    order.customer.displayName = node.customer.displayName;
    order.customer.email = node.customer.email;
    order.customer.phone = node.customer.phone;
  }

  order.status = node.fulfillable ? 'Processing' : 'Fulfilled';

  order.shippingAddress = new orderAddressModel();
  // Sanity check
  if (node.shippingAddress) {
    order.shippingAddress.name = node.shippingAddress.name;
    // latitude, longitude??
    order.shippingAddress.company = node.shippingAddress.company;
    order.shippingAddress.address1 = node.shippingAddress.address1;
    order.shippingAddress.address2 = node.shippingAddress.address2;
    order.shippingAddress.phone = node.shippingAddress.phone;
    order.shippingAddress.city = node.shippingAddress.city;
    order.shippingAddress.province = node.shippingAddress.province;
    order.shippingAddress.zip = node.shippingAddress.zip;
    order.shippingAddress.country = node.shippingAddress.country;
  }

  order.totalPriceSet = new orderMoneyModel();
  order.totalPriceSet.amount = node.totalPriceSet.shopMoney.amount;
  order.totalPriceSet.currencyCode = node.totalPriceSet.shopMoney.currencyCode;

  // populate the order items iterating over the line items
  order.items = [];
  const lineItems = node.lineItems.edges;
  for (const lineItemEdge of lineItems) {
    const lineItem = lineItemEdge.node;
    // A little sanity check
    if (lineItem.product == null) continue;
    const item = new orderItemModel();
    item.imsgid = lineItem.product.id;
    item.name = lineItem.name;
    item.sku = lineItem.sku;
    item.title = lineItem.title;
    item.quantity = lineItem.quantity;

    item.totalPriceSet = new orderMoneyModel();
    item.totalPriceSet.amount = lineItem.discountedTotalSet.shopMoney.amount;
    item.totalPriceSet.currencyCode = lineItem.discountedTotalSet.shopMoney.currencyCode;

    item.unitPriceSet = new orderMoneyModel();
    item.unitPriceSet.amount = lineItem.discountedUnitPriceSet.shopMoney.amount;
    item.unitPriceSet.currencyCode = lineItem.discountedUnitPriceSet.shopMoney.currencyCode;

    order.items.push(item);
  }

  return order;
}

// EXPORTS =======================================================
module.exports = {
  getOrder,
  getOrders,
};