Improve numerous conditions

I am currently working on a project that involves Angular and Node. In this project, I have written a function with multiple if and else if statements containing various conditions. The code looks complex and lengthy, and I want to refactor it to make it more concise and clean. Although I tried using a switch statement, I haven't found a satisfactory solution yet.

if (
      (
        !orderRequest.paymentProvider
        || orderRequest.paymentProvider === OrderRequestV2.PaymentProviderEnum.ADYEN
      )
      && orderRequest.paymentMethod === OrderRequestV2.PaymentMethodEnum.CREDITCARD
    ) {
      const mainPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.CREDIT_CARD, true);
      const giftCardPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.GIFT_CERTIFICATE);

      const mainPayment = {
        paymentInstrument: mainPaymentInstruments[0],
        paymentMethod: this.AdyenCreditCardPaymentMethodService
      };

      const giftCardsPayments = this.getGiftCardsPayments(giftCardPaymentInstruments);

      return [
        mainPayment,
        ...giftCardsPayments
      ];
    } else if (
      orderRequest.paymentProvider === OrderRequestV2.PaymentProviderEnum.ADYEN
      && orderRequest.paymentMethod === OrderRequestV2.PaymentMethodEnum.PAYPAL
    ) {
      const mainPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.ADYEN_PAYPAL, true);
      const giftCardPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.GIFT_CERTIFICATE);

      const mainPayment = {
        paymentInstrument: mainPaymentInstruments[0],
        paymentMethod: this.adyenPayPalPaymentMethodService
      };

      const giftCardsPayments = this.getGiftCardsPayments(giftCardPaymentInstruments);

      return [
        mainPayment,
        ...giftCardsPayments
      ];
    } else if (
      (
        !orderRequest.paymentProvider
        || orderRequest.paymentProvider === OrderRequestV2.PaymentProviderEnum.ADYEN
      )
      && orderRequest.paymentMethod === OrderRequestV2.PaymentMethodEnum.INVOICE
    ) {
      const mainPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.INVOICE, true);
      const giftCardPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.GIFT_CERTIFICATE);

      const mainPayment = {
        paymentInstrument: mainPaymentInstruments[0],
        paymentMethod: this.AdyenInvoicePaymentMethodService
      };

      const giftCardsPayments = this.getGiftCardsPayments(giftCardPaymentInstruments);

      return [
        mainPayment,
        ...giftCardsPayments
      ];
    } else if (
      orderRequest.paymentProvider === OrderRequestV2.PaymentProviderEnum.GMO
      && orderRequest.paymentMethod === OrderRequestV2.PaymentMethodEnum.CREDITCARD
    ) {
      const mainPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.CREDIT_CARD, true);
      const mainPayment = {
        paymentInstrument: mainPaymentInstruments[0],
        paymentMethod: this.GMOCreditCardPaymentMethodService
      };
      return [mainPayment];
    } else if (
      orderRequest.paymentProvider === OrderRequestV2.PaymentProviderEnum.COD
      && orderRequest.paymentMethod === OrderRequestV2.PaymentMethodEnum.COD
    ) {
      const mainPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.CASH_ON_DELIVERY, true);
      const mainPayment = {
        paymentInstrument: mainPaymentInstruments[0],
        paymentMethod: this.CashOnDeliveryPaymentService
      };
      return [mainPayment];
    } else if (
      (
        !orderRequest.paymentProvider
        || orderRequest.paymentProvider === OrderRequestV2.PaymentProviderEnum.ADYEN
      )
      && orderRequest.paymentMethod === OrderRequestV2.PaymentMethodEnum.GIFTCERTIFICATE
    ) {
      const giftCardPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.GIFT_CERTIFICATE, true);
      return this.getGiftCardsPayments(giftCardPaymentInstruments);
    } else if (
      (
        !orderRequest.paymentProvider
        || orderRequest.paymentProvider === OrderRequestV2.PaymentProviderEnum.ADYEN
      )
      && orderRequest.paymentMethod === OrderRequestV2.PaymentMethodEnum.APPLEPAY
    ) {
      const mainPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.APPLE_PAY, true);
      const mainPayment = {
        paymentInstrument: mainPaymentInstruments[0],
        paymentMethod: this.AdyenApplePayPaymentService
      };
      return [mainPayment];
    } 
    throw new BadRequestError(`${ERRORS.PLACE_ORDER_V2_PREFIX} Please verify your request`);
  }

Answer №1

Consider enabling different payment providers and their respective payment methods individually. Since each provider has its own unique requirements, avoid creating a generic function to handle all cases.

const {
  ADYEN,
  COD: COD_PROVIDER,
  GMO
} = OrderRequestV2.PaymentProviderEnum;

const {
  APPLEPAY,
  COD: COD_METHOD,
  CREDITCARD,
  GIFTCERTIFICATE,
  INVOICE,
  PAYPAL
} = OrderRequestV2.PaymentMethodEnum;

const getPaymentMethods = async (orderRequest) => {
  switch (orderRequest.paymentProvider) {
    case ADYEN:
      {
        switch (orderRequest.paymentMethod) {
          case CREDITCARD:
            {
              const mainPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.CREDIT_CARD, true);
              const giftCardPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.GIFT_CERTIFICATE);
              const mainPayment = {
                paymentInstrument: mainPaymentInstruments[0],
                paymentMethod: this.AdyenCreditCardPaymentMethodService
              };
              const giftCardsPayments = this.getGiftCardsPayments(giftCardPaymentInstruments);
              return [mainPayment, ...giftCardsPayments];
            }
          case PAYPAL:
            {
              const mainPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.ADYEN_PAYPAL, true);
              const giftCardPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.GIFT_CERTIFICATE);
              const mainPayment = {
                paymentInstrument: mainPaymentInstruments[0],
                paymentMethod: this.adyenPayPalPaymentMethodService
              };
              const giftCardsPayments = this.getGiftCardsPayments(giftCardPaymentInstruments);
              return [mainPayment, ...giftCardsPayments];
            }
          case INVOICE:
            {
              const mainPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.INVOICE, true);
              const giftCardPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.GIFT_CERTIFICATE);
              const mainPayment = {
                paymentInstrument: mainPaymentInstruments[0],
                paymentMethod: this.AdyenInvoicePaymentMethodService
              };
              const giftCardsPayments = this.getGiftCardsPayments(giftCardPaymentInstruments);
              return [mainPayment, ...giftCardsPayments];
            }
          case GIFTCERTIFICATE:
            {
              const giftCardPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.GIFT_CERTIFICATE, true);
              return this.getGiftCardsPayments(giftCardPaymentInstruments);
            }
          case APPLEPAY:
            {
              const mainPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.APPLE_PAY, true);
              const mainPayment = {
                paymentInstrument: mainPaymentInstruments[0],
                paymentMethod: this.AdyenApplePayPaymentService
              };
              return [mainPayment];
            }
        }
        break;
      }
    case COD_PROVIDER:
      {
        switch (orderRequest.paymentMethod) {
          case COD_METHOD:
            {
              const mainPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.CASH_ON_DELIVERY, true);
              const mainPayment = {
                paymentInstrument: mainPaymentInstruments[0],
                paymentMethod: this.CashOnDeliveryPaymentService
              };
              return [mainPayment];
            }
        }
        break;
      }
    case GMO:
      {
        switch (orderRequest.paymentMethod) {
          case CREDITCARD:
            {
              const mainPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.CREDIT_CARD, true);
              const mainPayment = {
                paymentInstrument: mainPaymentInstruments[0],
                paymentMethod: this.GMOCreditCardPaymentMethodService
              };
              return [mainPayment];
            }
        }
        break;
      }
  }
  throw new BadRequestError(`${ERRORS.PLACE_ORDER_V2_PREFIX} Please verify your request`);
};

To simplify the logic, you may create separate functions:

const {
  ADYEN,
  COD: COD_PROVIDER,
  GMO
} = OrderRequestV2.PaymentProviderEnum;

const {
  APPLEPAY,
  COD: COD_METHOD,
  CREDITCARD,
  GIFTCERTIFICATE,
  INVOICE,
  PAYPAL
} = OrderRequestV2.PaymentMethodEnum;

async function getPaymentMethods(orderRequest) {
  switch (orderRequest.paymentProvider) {
    case ADYEN:
      {
        switch (orderRequest.paymentMethod) {
          case CREDITCARD:
            return this.paymentWithGiftCards(this.AdyenCreditCardPaymentMethodService);
          case PAYPAL:
            return this.paymentWithGiftCards(this.adyenPayPalPaymentMethodService);
          case INVOICE:
            return this.paymentWithGiftCards(this.AdyenInvoicePaymentMethodService);
          case GIFTCERTIFICATE:
            return giftPaymentOnly();
          case APPLEPAY:
            return this.simplePayment(this.AdyenApplePayPaymentService);
        }
        break;
      }
    case COD_PROVIDER:
      {
        switch (orderRequest.paymentMethod) {
          case COD_METHOD:
            return this.simplePayment(this.CashOnDeliveryPaymentService);
        }
        break;
      }
    case GMO:
      {
        switch (orderRequest.paymentMethod) {
          case CREDITCARD:
            return this.simplePayment(this.GMOCreditCardPaymentMethodService);
        }
        break;
      }
  }
  throw new BadRequestError(`${ERRORS.PLACE_ORDER_V2_PREFIX} Please verify your request`);
};

async function paymentWithGiftCards(paymentMethod) {
  const mainPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.CREDIT_CARD, true);
  const giftCardPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.GIFT_CERTIFICATE);
  const mainPayment = {
    paymentInstrument: mainPaymentInstruments[0],
    paymentMethod
  };
  const giftCardsPayments = this.getGiftCardsPayments(giftCardPaymentInstruments);
  return [mainPayment, ...giftCardsPayments];
}

async function simplePayment(paymentMethod) {
  const mainPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.APPLE_PAY, true);
  const mainPayment = {
    paymentInstrument: mainPaymentInstruments[0],
    paymentMethod: paymentMethod;
  };
  return [mainPayment];
}

async function giftPaymentOnly(paymentMethod) {
  const giftCardPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.GIFT_CERTIFICATE, true);
  return this.getGiftCardsPayments(giftCardPaymentInstruments);
}

To avoid nested switch statements, delegate each payment provider's call to specific functions:

const {
  ADYEN,
  COD: COD_PROVIDER,
  GMO
} = OrderRequestV2.PaymentProviderEnum;

const {
  APPLEPAY,
  COD: COD_METHOD,
  CREDITCARD,
  GIFTCERTIFICATE,
  INVOICE,
  PAYPAL
} = OrderRequestV2.PaymentMethodEnum;

async function getPaymentMethods(orderRequest) {
  switch (orderRequest.paymentProvider) {
    case ADYEN:
      return getAdyenPaymentMethods(orderRequest);
    case COD_PROVIDER:
      return getCodPaymentMethods(orderRequest);
    case GMO:
      return getGmoPaymentMethods(orderRequest);
  }
  throw new BadRequestError(`${ERRORS.PLACE_ORDER_V2_PREFIX} Please verify your request`);
};

async function getAdyenPaymentMethods(orderRequest) {
  switch (orderRequest.paymentMethod) {
    case CREDITCARD:
      return this.paymentWithGiftCards(this.AdyenCreditCardPaymentMethodService);
    case PAYPAL:
      return this.paymentWithGiftCards(this.adyenPayPalPaymentMethodService);
    case INVOICE:
      return this.paymentWithGiftCards(this.AdyenInvoicePaymentMethodService);
    case GIFTCERTIFICATE:
      return giftPaymentOnly();
    case APPLEPAY:
      return this.simplePayment(this.AdyenApplePayPaymentService);
  }
  throw new BadRequestError(`${ERRORS.PLACE_ORDER_V2_PREFIX} Please verify your request`);
}

async function getCodPaymentMethods(orderRequest) {
  switch (orderRequest.paymentMethod) {
    case COD_METHOD:
      return this.simplePayment(this.CashOnDeliveryPaymentService);
  }
  throw new BadRequestError(`${ERRORS.PLACE_ORDER_V2_PREFIX} Please verify your request`);
}

async function getGmoPaymentMethods(orderRequest) {
  switch (orderRequest.paymentMethod) {
    case CREDITCARD:
      return this.simplePayment(this.GMOCreditCardPaymentMethodService);
  }
  throw new BadRequestError(`${ERRORS.PLACE_ORDER_V2_PREFIX} Please verify your request`);
}

async function paymentWithGiftCards(paymentMethod) {
  const mainPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.CREDIT_CARD, true);
  const giftCardPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.GIFT_CERTIFICATE);
  const mainPayment = {
    paymentInstrument: mainPaymentInstruments[0],
    paymentMethod
  };
  const giftCardsPayments = this.getGiftCardsPayments(giftCardPaymentInstruments);
  return [mainPayment, ...giftCardsPayments];
}

async function simplePayment(paymentMethod) {
  const mainPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.APPLE_PAY, true);
  const mainPayment = {
    paymentInstrument: mainPaymentInstruments[0],
    paymentMethod: paymentMethod;
  };
  return [mainPayment];
}

async function giftPaymentOnly(paymentMethod) {
  const giftCardPaymentInstruments = await this.pickPaymentInstruments(basket, constants.PAYMENT_METHODS.GIFT_CERTIFICATE, true);
  return this.getGiftCardsPayments(giftCardPaymentInstruments);
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Troubleshooting React on an Apache Server: A Comprehensive Guide

An interactive React application utilizing React Router has been successfully deployed on an Apache server. After making modifications to the .htaccess file, most of the routes function correctly as intended. Some specific routes within the app rely on us ...

Combine multiple arrays in JavaScript into a single array

Here is the array I am working with: array = ['bla', ['ble', 'bli'], 'blo', ['blu']] I need to transform it into this format: array = ['bla', 'ble', 'bli', 'blo', &a ...

Reaching out to the Edge: Enhancing the jQuery Slider Experience

Alright, I'm really excited about using this amazing slider. What I love most is the "free mode" feature that creates this stunning sliding effect. The size and number of slides are absolutely perfect for me. But there's just one small adjustment ...

React modal not triggered on click event

As a newcomer to react, I am exploring a modal component import React, { useState, useEffect } from 'react'; import { Modal, Button } from "react-bootstrap"; function TaskModal(props) { return ( <Modal show={pro ...

Creating an HTML layout or template directly within a JavaScript bookmarklet

Currently, I am using a bookmarklet that generates a user interface for interaction. The method I have been using involves creating elements using $('<element>').addClass().css({..});, but this approach is proving to be difficult to maintai ...

Tips for implementing a search function with DynamoDB using the "contains" operator

I'm currently working on implementing a search function in my React application. Here is the structure of my DynamoDB table: --------------------- movie_id | movie_name --------------------- 1 | name a --------------------- 2 | name b ...

Struggling with sending intricate model to controller via ajax request

I've encountered an issue where my model is not updating properly when I click a button. Despite logging the data in the razor file and confirming that it's correct, the controller method receives an empty model. Below is the onclick method bein ...

Transforming the output of a PHP script from an HTML table into an ion-list format tailored for the Ionic framework

Currently I am working on an application built with the Ionic framework. I have developed a PHP file to retrieve 'Users' data from my database and it is currently being displayed in an HTML table format. In the services section of the framework, ...

Adding Bootstrap component via ajax request

I'm facing an issue with injecting a Bootstrap component using ajax. I usually include a select element like this: <select class="selectpicker" data-width="75%"> Most of the HTML code is generated dynamically through javascript, which you can ...

"The issue with ExpressJS deleteRoute is that it is not properly refreshing user

I have a specific issue with my express controller for deleting user posts. The problem is that while the post is being removed from the page successfully, it is not getting deleted from the User.posts data as expected. function deleteRoute(req, res) { ...

Switch from using `widthWidth` to `useWidth` in MUI v5 ReactJS

Currently, I am in the process of updating a project that utilizes MUI as the UI Library for my React application. I have started migrating to version 5 today, and one issue I've encountered is related to all functional components wrapped by withWidth ...

Unveil the socket connection using web sockets

My current setup involves a server generating a socket on port 8181. I am interested in accessing this socket from a web page viewed in Google Chrome version 14. It seems that direct access may not be feasible, as Chrome only supports Web Sockets and not s ...

Choosing the perfect gradient shade for a progress bar canvas illustration: Tips and tricks

I am trying to customize the appearance of the usage bar in my Google Chrome extension by utilizing the features of the HTML5 canvas. Currently, the bar consists of a basic DIV element: <div id="idUsgBar"></div> accompanied by this CSS stylin ...

How can JavaScript be used to parse an XML file? Should we consider using SAX for handling large XML files

Hello everyone, I am feeling very frustrated and overwhelmed with my current situation. I have been searching everywhere for a solution but seem to be going in circles. This will be my first attempt at working with xml and it's quite daunting, espec ...

What steps can you take to address Git conflicts within the yarn.lock file?

When numerous branches in a Git project make changes to dependencies and use Yarn, conflicts may arise in the yarn.lock file. Instead of deleting and recreating the yarn.lock file, which could lead to unintended package upgrades, what is the most efficie ...

Troubleshooting: Issues with jQuery.on method functionality

I'm currently using jQuery version 1.9.1 and I have a situation where I need to perform an action on a dynamically added td element. I attempted to utilize the jQuery.on function, however my code is not being triggered. Can someone please provide some ...

Preparing JSON data for creating a wind map with Leaflet

I am currently working on converting netCDF data to JSON in order to use it with leaflet-velocity. This tool follows the same format as the output of grib2json used by cambecc in earth. An example of sample JSON data can be found at wind-global.json. By u ...

Tips for implementing AngularJS on a webpage transfer

I am a beginner in learning AngularJS. I have gone through the basic tips on W3Schools, but now I am stuck on implementing the login function. When I click the "sign in" button, the webpage should redirect to the login page of the website. However, I am ...

Struggling to link variables and functions to an angularJS controller

When using the $scope object to bind functions and variables, and making changes accordingly in HTML, the code works fine. But when using a different object, it doesn't work as expected. Here is an example of a working code snippet: ...

When Vue.js is compiled, it removes a script tag

I'm currently learning Vue.js and encountering an issue that I can't seem to resolve. My project is utilizing Vue CLI 3, and within my code I am inserting a custom tag (not a component) in my template with a script tag inside it. <ra type="ou ...