makeomatic/ms-payments

View on GitHub
src/actions/plan/state.js

Summary

Maintainability
A
0 mins
Test Coverage
const { ActionTransport } = require('@microfleet/core');
const Promise = require('bluebird');
const uniq = require('lodash/uniq');
const compact = require('lodash/compact');

// helpers
const key = require('../../redis-key');
const { PLANS_DATA, PLAN_ALIAS_FIELD } = require('../../constants');
const { serialize, handlePipeline } = require('../../utils/redis');
const { plan: { update } } = require('../../utils/paypal');

function isAlreadyInState(err) {
  return err.httpStatusCode === 400
    && err.response
    && err.response.name === 'BUSINESS_VALIDATION_ERROR'
    && err.response.details
    && err.response.details.find((el) => (
      el.issue === 'Plan already in same state.'
    ));
}

/**
 * @api {amqp, internal} <prefix>.plan.state Change plan state
 * @apiVersion 1.0.0
 * @apiName planState
 * @apiGroup Plan
 *
 * @apiDescription Changes plan state
 *
 * @apiSchema {jsonschema=plan/state.json} apiRequest
 * @apiSchema {jsonschema=response/plan/state.json} apiResponse
 */
async function planState({ log, params: message }) {
  const { config, redis } = this;
  const { id, state } = message;
  const { paypal: paypalConfig } = config;

  const possibleAlias = await redis.hget(key(PLANS_DATA, id), PLAN_ALIAS_FIELD);
  const alias = possibleAlias && possibleAlias.length > 0 && JSON.parse(possibleAlias);
  const request = [{
    op: 'replace',
    path: '/',
    value: { state },
  }];

  const partialIds = id.split('|');
  const requests = [];
  for (const planId of partialIds) {
    requests.push(
      update(planId, request, paypalConfig).catchReturn(isAlreadyInState, 'OK')
    );
  }

  await Promise.all(requests);

  const ids = compact(uniq(partialIds.concat([id, alias])));
  const serializedState = serialize({ state });

  const pipeline = redis.pipeline(ids.map((planId) => [
    'hmset', key(PLANS_DATA, planId), serializedState,
  ]));

  log.debug({ state, ids }, 'updating state for ids %s to %s', ids.join(', '), state);

  return handlePipeline(await pipeline.exec());
}

planState.transports = [ActionTransport.amqp, ActionTransport.internal];

module.exports = planState;