Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
/* eslint-disable brace-style */
import { isSafe, isObj, toBoolean, isArray } from 'exotic'
import { cloneJSON } from 'chain-able'
import { getTyped, getFloat } from '@skava/modules/___dist/composition'

// console.dev('@todo availability giftitem [isgiftcard]=true != "true" flags[returnable]')

const toFloat = x => {
  if (!isNaN(x)) {
    return parseFloat(x, 10).toFixed(2)
  }
  return x
}
const tranformWorkingHour = data => {
  const { string } = getTyped(data)
  return {
    weekday: string('weekday'),
    weekend: string('weekend'),
  }
}

const tranformContactUs = data => {
  const { obj, string } = getTyped(data)
  return {
    description: string('description'),
    number: string('number'),
    workinghour: tranformWorkingHour(obj('workinghour')),
  }
}

/**
 * @todo @invalid @fixme @autofix no === 'true'
 * @return {Address | Object}
 */
const getShippingMethod = address => {
  if (isSafe(address) === false) {
    return {}
  }
  else if (address.selected === 'true') {
    return address
  }
  else {
    return {}
  }
}

const transformPromoDetail = promo => {
  const { obj, string, array } = getTyped(promo)

  return {
    identifier: string('identifier'),
    skuId: string('properties.iteminfo.sku'),
    name: string('properties.promocodeinfo.promos[0].name'),
    errorcode: string('properties.state.errorcode'),
    errormessage: string('properties.state.errormessage'),
  }
}


/**
 * @param {Object} product
 * @return {ProductPromotion | Boolean}
 */
const getPromoMethod = product => {
  // console.log('test prodcuct', product)

  if (isSafe(product) === false) {
    return false
  }
  else if (product.label === 'discounts') {
    // console.log('test this product', product)
    return product
  }
  else {
    return false
  }
}

// ============ product options =========

/**
 * @see __product/OneThing
 */
const toProductOptionItem = (type, value) => {
  return {
    type,
    value,
  }
}
const renameOptionKey = (key) => {
  switch (key) {
    case 'size1': return 'size'
    case 'fit': return 'style'
    case 'colors': return 'color'
    default: return key
  }
}
/**
 * @example skuinfo
 *   {
 *      color: { identifier: 'Red',
 *      image: 'undefined?ch=150&cw=190&cx=center&cy=center' },
 *      size1: { identifier: '10 D' }
 *   }
 *
 * @example
 *   productOptions: [
 *     {
 *       type: 'color',
 *       value: 'Red',
 *     },
 *     {
 *       type: 'size',
 *       value: 'XL',
 *     }
 *   ],
 */
const fromSkuInfoToProductOptions = skuinfo => {
  // console.log('fromSkuInfoToProductOptions__pre', skuinfo, Object.keys(skuinfo))
  const productOptions = []

  Object.keys(skuinfo).forEach(key => {
    const option = skuinfo[key]
    const value = isObj(option) ? option.identifier : undefined
    const renamed = renameOptionKey(key)
    const optionItem = toProductOptionItem(renamed, value)
    productOptions.push(optionItem)
  })

  // console.log('fromSkuInfoToProductOptions__post', productOptions)
  if (productOptions.length === 0) {
    // always want to send this now with gql
    return productOptions
    // return undefined
  }
  return productOptions
}

const transformSkuDetail = product => {
  const { obj, string, number, array, float } = getTyped(product)
  const skuinfo = obj('properties.skuinfo')
  const productOptions = fromSkuInfoToProductOptions(skuinfo)
  const quantity = number('properties.cartinfo.quantity')

  const commonSkuDetail = {
    quantity,
    identifier: string('identifier'),
    skuId: string('properties.iteminfo.sku'),
    image: string('image'),
    name: string('name'),
    type: string('type'),
    price: float('properties.buyinfo.pricing.prices[0].value'),
    preOrder: string('properties.buyinfo.preorderdate'),
    // style: string('properties.skuinfo.fit.identifier'),
    // color: string('properties.skuinfo.color.identifier'),
    // size: string('properties.skuinfo.size1.identifier'),
    giftItem: string('properties.cartinfo.giftitem'),
    shippingmethod: array('properties.cartinfo.shippingmethods[0].shippingmethods'),
    shippingAddress: obj('properties.userinfo[0]'),
    cards: array('properties.creditcardinfo.cards'),
  }

  return {
    ...commonSkuDetail,
    productId: string('properties.iteminfo.itemid'),
    flags: array('properties.iteminfo.flags'),
    productOptions,
    promoMessage: array('properties.cartinfo.discount').find(getPromoMethod),

    shippingmethodType: string('properties.cartinfo.shippingmethods[0].type'),

    iteminfo: obj('properties.iteminfo'),
    cartinfo: obj('properties.cartinfo'),
  }
}
const typeIsPromoCode = sku => sku.type === 'promoCode'
const typeIsSkuOrGift = sku => sku.type === 'sku' || sku.type === 'gift' || sku.type === 'bundle'
const typeIsGift = sku => sku.type === 'gift'
const isTypePayment = sku => sku.type === 'payment'

const transformMath = maths => {
  const { string, number, float } = getTyped(maths || {})

  return {
    totalBagCount: number('totalBagCount'),
    estTotalTax: float('estTotalTax'),
    totalGiftWrapPrice: float('totalGiftWrapPrice'),
    totalGiftWrapCost: float('totalGiftWrapCost'),
    grandTotal: float('grandTotal'),
    grandTotalTax: float('grandTotalTax'),
    totalGiftWrapTax: float('totalGiftWrapTax'),
    totalGiftWrapDiscount: float('totalGiftWrapDiscount'),
    maxBagCount: float('maxBagCount'),
    totalDiscount: float('totalDiscount'),
    estTotalShippingTax: float('estTotalShippingTax'),
    estTotalShippingDiscount: float('estTotalShippingDiscount'),
    estTotalShippingPrice: float('estTotalShippingPrice'),
    totalSale: float('totalSale'),
    totalCost: float('totalCost'),
    totalBagCountWithErrors: float('totalBagCountWithErrors'),
    currency: string('currency'),
  }
}

const transformCartInfo = cartinfoUnsafe => {
  const cartinfo = cloneJSON(cartinfoUnsafe || {})

  const { boolean, float, number, array } = getTyped(cartinfo)

  return {
    ...cartinfo,
    quantity: number('quantity'),
    totaltax: float('totaltax'),
    total: float('total'),
    subtotal: float('subtotal'),
    estsubtotal: float('subtotal'),
    discounttotal: float('discounttotal'),
    iseligible: boolean('iseligible'),
    shippingmethods: array('shippingmethods').map(shippingmethod => {
      const reallyDeeplyNestedShippingMethods = getTyped(shippingmethod).array('shippingmethods')
      
      return reallyDeeplyNestedShippingMethods.map(method => {
        const priceList = getTyped(method).array('prices')

        const prices = priceList.map(price => {
          return {
            ...price,
            value: getFloat(price, 'value'),
          }
        })

        return {
          ...method,
          prices,
          selected: boolean('selected'),
        }
      })
    }),

    // here
    discount: array('discount').map(discount => {
      return {
        ...discount,
        value: getFloat(discount, 'value'),
      }
    }),
    giftwrap: toBoolean(cartinfo.giftwrap),
  }
}

// because one sku uses the deeply nested ones
function transformOneSkuCompatible(sku) {
  const { obj } = getTyped(sku)
  const skuinfo = obj('properties.skuinfo')
  const productOptions = fromSkuInfoToProductOptions(skuinfo)

  return {
    ...sku,
    productOptions,
  }
}

// @todo @fixme
// eslint-disable-next-line
const transformCart = unsafeResponse => {
  // graphql is messing this up
  const response = cloneJSON(unsafeResponse || {})
  const { any, array, obj, float, string } = getTyped(response)

  const commonResponse = {
    products: array('children.products').filter(typeIsSkuOrGift).map(transformOneSkuCompatible),
    type: any('type'),
    shippingmethods: array('properties.cartinfo.shippingmethods[0].shippingmethods'),
    iteminfo: obj('properties.iteminfo'),

    // @todo - should not have userinfo on cart
    userinfo: array('properties.userinfo'),
  }

  const cartinfo = obj('properties.cartinfo')
  const contactus = obj('properties.contactus')
  const maths = obj('properties.math')
  const math = transformMath(maths)
  const adjustedamount = float('properties.paymentcardinfo.adjustedamount')
  math.adjustedamount = adjustedamount

  // userinfo: array('properties.userinfo'),
  const cartResponse = {
    ...commonResponse,
    // drop
    // items: array('children.products'),
    giftproducts: array('children.products').filter(typeIsGift).map(transformSkuDetail),
    promocodes: array('children.products').filter(typeIsPromoCode).map(transformPromoDetail),
    shippingmethodtype: string('properties.cartinfo.shippingmethods[0].type'),
    state: obj('properties.state'),
    status: string('properties.state.status'),
    contactus: tranformContactUs(contactus),
    creditcard: array('children.products').filter(isTypePayment).map(transformSkuDetail),
    buyinfo: obj('properties.buyinfo'),
    cartinfo: transformCartInfo(cartinfo),
    properties: obj('properties'),
    math,
  }

  return cartResponse
}

const getMatchedData = (addressData, addressTypeToCheck) => {
  // isn't safe?
  return addressData.types.includes(addressTypeToCheck)
}

const transformGeoCodeData = response => {
  if (!(response.results && response.results.length)) {
    return {}
  }
  const addressDataFromResponse = response.results[0].address_components

  const getAddressData = addressTypeToCheck => {
    const matchedAddressData = addressDataFromResponse
      .find(addressData => getMatchedData(addressData, addressTypeToCheck)) || {}
    return matchedAddressData.short_name || ''
  }

  return {
    postalCode: getAddressData('postal_code'),
    state: getAddressData('administrative_area_level_1'),
    country: getAddressData('country'),
    city: getAddressData('locality'),
    county: getAddressData('administrative_area_level_2'),
  }
}

const transformAddPayment = response => {
  const { any, array, obj, float, string } = getTyped(response)
  return {
    ...response,
    identifier: string('children.products.0.identifier'),
  }
}

export { transformCart, transformGeoCodeData, transformAddPayment }
export default transformCart