zuora to eloqua | test eloqua import service | zuora eloqua mapper test | Search

This code processes subscription data by categorizing rate plans into product types and extracting account-specific information, including the latest charges and contact details.

Run example

npm run import -- "zuora eloqua mapper"

zuora eloqua mapper

var moment = require('moment');
var _ = require('lodash');
var chrono = require('chrono-node');

function mapRatePlanToProduct(description) {
    description = description.toLowerCase();
    if(description.includes('trial'))
        return 'trial';
    else if (description.includes('volume') || description.includes('discount'))
        return 'discount';
    else if (description.includes('cloud') && !description.includes('trial'))
        return 'actpremiumcloud';
    else if (description.includes('premium') && !description.includes('cloud')
             && !description.includes('trial') && !description.includes('support'))
        return 'actpremium';
    else if (description.includes('pro')  && !description.includes('support'))
        return 'actpro';
    else if (description.includes('support'))
        return 'support';
    else if (description.includes('handheld') || description.includes('contact'))
        return 'handheld';
    else if (description.includes('aem'))
        return 'aem';
    else if (description.includes('password'))
        return 'password';
    else if (description.includes('training'))
        return 'training';
    else throw new Error('product not recognized ' + description);
}

function mapDataToFields(records) {
    var uniqueIds = _.groupBy(records, r => r['Account.Id']);
    return Object.keys(uniqueIds).map(k => {
        const rpcs = _.groupBy(uniqueIds[k], r => r['RatePlanCharge.Id']);
        const charges = Object.keys(rpcs).map(k => _.sortBy(rpcs[k], r => r['RatePlanCharge.Version']).pop());
        const record = {};
        charges.sort((a, b) =>
                          chrono.parseDate(b['Subscription.TermEndDate']).getTime()
                          - chrono.parseDate(a['Subscription.TermEndDate']).getTime());
        // contact information
        const contact = charges.filter(charge => charge['SoldToContact.WorkEmail'] || charge['BillToContact.WorkEmail'])[0]
        if(typeof contact === 'undefined') {
            console.log('No contact information for ' + JSON.stringify(charges));
            return;
        }
        record['EmailAddress'] = contact['SoldToContact.WorkEmail'] || contact['BillToContact.WorkEmail'];
        record['State'] = contact['SoldToContact.State'];
        record['Country'] = contact['SoldToContact.Country'];
        record['Currency'] = contact['Account.Currency'];

        // primary product
        const actProduct = charges.filter(p => {
            const pname = mapRatePlanToProduct(p['ProductRatePlan.Name']);
            return pname === 'actpremiumcloud' || pname === 'actpremium' || pname === 'actpro' || pname === 'trial'
        })[0];
        
        if(typeof actProduct !== 'undefined') {
            record['ActProduct'] = mapRatePlanToProduct(actProduct['ProductRatePlan.Name']);
            record['Quantity'] = actProduct['RatePlanCharge.Quantity'];
        } else {
            record['ActProduct'] = 'Unknown';
            record['Quantity'] = 0;
        }
        
        // discounts!
        const discount = charges.filter(p => {
            const pname = mapRatePlanToProduct(p['ProductRatePlan.Name']);
            return pname === 'discount'
        })[0];
        if(typeof discount !== 'undefined') {
            record['Discount'] = discount['ProductRatePlan.Name'];
        } else {
            record['Discount'] = '';
        }
        
        // support
        const support = charges.filter(charge => {
            return mapRatePlanToProduct(charge['ProductRatePlan.Name']) === 'support'
        })[0];
        if(typeof support !== 'undefined') {
            record['Support'] = support['ProductRatePlan.Name'];
            record['SupportQuantity'] = support['RatePlanCharge.Quantity'];
        } else {
            record['Support'] = 'Unknown';
            record['SupportQuantity'] = 0;
        }
        
        // subscription
        const renewal = chrono.parseDate(charges[0]['Subscription.TermEndDate']);
        record['RenewalsStatus'] = charges[0]['Subscription.Status'];
        record['RenewalDate'] = moment(renewal).format('YYYY-MM-DD');
        
        // card expiration
        const expiration = new Date();
        expiration.setDate(1);
        expiration.setMonth(parseInt(charges[0]['DefaultPaymentMethod.CreditCardExpirationMonth']) - 1);
        expiration.setYear(parseInt(charges[0]['DefaultPaymentMethod.CreditCardExpirationYear']));
        record['CardExpiration'] = moment(expiration).format('YYYY-MM-DD');
        //record['Last4DigitsOfCard'] = ((/([0-9]+)/ig).exec(charges[0]['DefaultPaymentMethod.CreditCardMaskNumber']) || [])[1];
        
        // account data
        record['RepName'] = charges[0]['Account.renewalRep__c'];
        record['RORName'] = charges[0]['Account.resellerofRecord__c'];
        record['RORNumber'] = ((/([0-9]+)/ig).exec(charges[0]['Account.resellerofRecord__c']) || [])[1];
        record['AccountId'] = charges[0]['Account.Id'];

        return record;
    }).filter(r => typeof r !== 'undefined');
}
module.exports = {
    mapDataToFields,
    mapRatePlanToProduct
};

What the code could have been:

const moment = require('moment');
const _ = require('lodash');
const chrono = require('chrono-node');

/**
 * Maps a rate plan description to a product type.
 *
 * @param {string} description - The rate plan description to map.
 * @returns {string} The product type (e.g. 'trial', 'discount', etc.).
 */
function mapRatePlanToProduct(description) {
    description = description.toLowerCase();
    const typeMap = {
        'trial': (d) => d.includes('trial'),
        'discount': (d) => d.includes('volume') || d.includes('discount'),
        'actpremiumcloud': (d) => d.includes('cloud') &&!d.includes('trial'),
        'actpremium': (d) => d.includes('premium') &&!d.includes('cloud') &&!d.includes('trial') &&!d.includes('support'),
        'actpro': (d) => d.includes('pro') &&!d.includes('support'),
       'support': (d) => d.includes('support'),
        'handheld': (d) => d.includes('handheld') || d.includes('contact'),
        'aem': (d) => d.includes('aem'),
        'password': (d) => d.includes('password'),
        'training': (d) => d.includes('training'),
    };
    for (const [key, f] of Object.entries(typeMap)) {
        if (f(description)) return key;
    }
    throw new Error(`Product not recognized: ${description}`);
}

/**
 * Maps data to fields for a list of records.
 *
 * @param {object[]} records - The list of records to map.
 * @returns {object[]} The mapped records.
 */
function mapDataToFields(records) {
    const uniqueIds = _.groupBy(records, 'Account.Id');
    return Object.keys(uniqueIds)
       .map((k) => {
            const rpcs = _.groupBy(uniqueIds[k], 'RatePlanCharge.Id');
            const charges = Object.keys(rpcs)
               .map((k) => _.sortBy(rpcs[k], (r) => r['RatePlanCharge.Version']).pop());
            const record = {};

            // Sort by expiration date
            charges.sort((a, b) =>
                chrono.parseDate(b['Subscription.TermEndDate']).getTime()
                - chrono.parseDate(a['Subscription.TermEndDate']).getTime()
            );

            // Contact information
            const contact = charges
               .filter((charge) => charge['SoldToContact.WorkEmail'] || charge['BillToContact.WorkEmail'])
               .shift();
            if (!contact) {
                console.log('No contact information for:', JSON.stringify(charges));
                return;
            }
            record['EmailAddress'] = contact['SoldToContact.WorkEmail'] || contact['BillToContact.WorkEmail'];
            record['State'] = contact['SoldToContact.State'];
            record['Country'] = contact['SoldToContact.Country'];
            record['Currency'] = contact['Account.Currency'];

            // Primary product
            const actProduct = charges.find((p) => [
                'actpremiumcloud',
                'actpremium',
                'actpro',
                'trial',
            ].includes(mapRatePlanToProduct(p['ProductRatePlan.Name'])));
            if (actProduct) {
                record['ActProduct'] = mapRatePlanToProduct(actProduct['ProductRatePlan.Name']);
                record['Quantity'] = actProduct['RatePlanCharge.Quantity'];
            } else {
                record['ActProduct'] = 'Unknown';
                record['Quantity'] = 0;
            }

            // Discounts
            const discount = charges.find((p) => mapRatePlanToProduct(p['ProductRatePlan.Name']) === 'discount');
            if (discount) {
                record['Discount'] = discount['ProductRatePlan.Name'];
            } else {
                record['Discount'] = '';
            }

            // Support
            const support = charges.find((charge) => mapRatePlanToProduct(charge['ProductRatePlan.Name']) ==='support');
            if (support) {
                record['Support'] = support['ProductRatePlan.Name'];
                record['SupportQuantity'] = support['RatePlanCharge.Quantity'];
            } else {
                record['Support'] = 'Unknown';
                record['SupportQuantity'] = 0;
            }

            // Subscription
            const renewal = chrono.parseDate(charges[0]['Subscription.TermEndDate']);
            record['RenewalsStatus'] = charges[0]['Subscription.Status'];
            record['RenewalDate'] = moment(renewal).format('YYYY-MM-DD');

            // Card expiration
            const expiration = new Date();
            expiration.setDate(1);
            expiration.setMonth(parseInt(charges[0]['DefaultPaymentMethod.CreditCardExpirationMonth']) - 1);
            expiration.setYear(parseInt(charges[0]['DefaultPaymentMethod.CreditCardExpirationYear']));
            record['CardExpiration'] = moment(expiration).format('YYYY-MM-DD');

            // Account data
            record['RepName'] = charges[0]['Account.renewalRep__c'];
            record['RORName'] = charges[0]['Account.resellerofRecord__c'];
            record['RORNumber'] = ((/([0-9]+)/ig).exec(charges[0]['Account.resellerofRecord__c']) || [])[1];
            record['AccountId'] = charges[0]['Account.Id'];

            return record;
        })
       .filter((r) =>!_.isNil(r));
}

module.exports = {
    mapDataToFields,
    mapRatePlanToProduct,
};

This code snippet defines two functions for processing data likely retrieved from a database, possibly related to subscriptions or billing.

1. mapRatePlanToProduct(description):

2. mapDataToFields(records):

In essence:

This code snippet processes subscription data, categorizes rate plans into product types, and extracts relevant information for each account, including the latest charges and contact details.