Activate Currencies in Bulk in the Zuora Product Catalog

Edited

This code is designed to perform database queries and make API calls to Zuora to activate currencies on rate plans. We have provided the Javascript written to run in a Node.js environment.

// Import necessary modules
const { Client } = require('pg'); // PostgreSQL client
const axios = require('axios');

// Database connection configuration
const client = new Client({
  user: 'your_db_username',
  host: 'your_db_host',
  database: 'your_db_name',
  password: 'your_db_password',
  port: 5432, // default PostgreSQL port
});

// Zuora API configuration
const zuoraApi = axios.create({
  baseURL: 'https://rest.zuora.com',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer YOUR_ZUORA_ACCESS_TOKEN', // Replace with your Zuora access token
  },
});

async function activateCurrenciesOnRatePlans() {
  try {
    await client.connect();

    // Fetch extracts from the database
    const extractResult = await client.query(
      `SELECT * FROM extracts WHERE process = 'product-migration' AND name = 'product-catalog'`
    );
    const extractRows = extractResult.rows;

    for (const row of extractRows) {
      // Parse JSON data
      const rp = JSON.parse(row.data);

      for (const plan of rp.productRatePlans) {
        let currencies = [];

        for (const charge of plan.productRatePlanCharges) {
          for (const price of charge.pricing) {
            currencies.push(price.currency);
          }
        }

        if (currencies.length > 0) {
          if (!currencies.includes('USD')) {
            currencies.push('USD');
          }
          const payload = { ActiveCurrencies: currencies.join(',') };
          console.log(`Activate currencies on plan ${plan.id} -> ${payload.ActiveCurrencies}`);

          // Fetch new_id from the conversions table
          const conversionResult = await client.query(
            `SELECT new_id FROM conversions WHERE process = 'lumivero-migration' AND table_name = 'productRatePlan' AND old_id = $1`,
            [plan.id]
          );
          const c = conversionResult.rows[0];

          if (!c) {
            throw new Error(`Could not find conversion row for ${plan.id}`);
          }

          // Make API call to Zuora
          const zuoraResponse = await zuoraApi.put(`/v1/object/product-rate-plan/${c.new_id}`, payload);
          const results = zuoraResponse.data;

          if (!results.Success) {
            throw new Error(`Zuora Update Error: ${JSON.stringify(results)}`);
          }
        }
      }
    }
  } catch (error) {
    console.error('Error activating currencies:', error);
  } finally {
    await client.end();
  }
}

// Run the function
activateCurrenciesOnRatePlans();

Explanation:

  • Database Connection: We use the pg library to connect to a PostgreSQL database. Replace the connection configuration with your actual database credentials.

  • Zuora API Calls: We use axios to make HTTP requests to the Zuora API. Make sure to replace 'YOUR_ZUORA_ACCESS_TOKEN' with your actual Zuora access token.

  • Data Processing: The script queries the extracts table, parses the JSON data, collects currencies, ensures 'USD' is included, and constructs the payload.

  • Error Handling: The script includes try-catch blocks to handle errors gracefully.

Notes:

  • Server-Side Execution: This script is intended to run on the server side using Node.js. It's not suitable for running in a React front-end application due to security and architectural reasons.

  • Security: Never expose database credentials or API tokens in a client-side application.

  • Dependencies: Install the required packages using:

    npm install pg axios

If you need to trigger this script from a React application, you should create an API endpoint on your server that the React app can call. The server can then execute this script. Here's a brief example:

// In your server (e.g., using Express.js)
const express = require('express');
const app = express();

app.post('/activate-currencies', async (req, res) => {
  try {
    await activateCurrenciesOnRatePlans();
    res.status(200).send('Currencies activated successfully.');
  } catch (error) {
    res.status(500).send(`Error: ${error.message}`);
  }
});

// Start the server
app.listen(3000, () => console.log('Server running on port 3000'));

Then, in your React application, you can make a POST request to /activate-currencies when needed.

Remember: Always ensure that sensitive operations are handled securely and that your APIs are protected with proper authentication and authorization mechanisms.