payments/src/lib/actions/deny.ts

import { Payment, PaymentStatus, PaymentProcessingState } from '../types';
import { tracer } from '@capchase/tracer';
import { create } from './create';
import { getLastPayment } from './getters';
import { callLog } from '../call_log';

const internalDenyPayment = async (
  paymentKey: string,
  reason: string,
  actionBy: string
): Promise<Payment> => {
  await callLog({
    callName: 'denyPayment',
    actionBy,
    args: [paymentKey, reason, actionBy],
  });

  const span = tracer?.scope()?.active();

  span?.addTags({
    payment_key: paymentKey,
    reason,
    action_by: actionBy,
  });

  // TODO(SHI-1454): Validate actual user permissions
  if (actionBy.length === 0) {
    throw new Error('Action by should be set');
  }

  if (reason.length === 0) {
    throw new Error('Reason for denial should be set');
  }

  const payment = await getLastPayment(paymentKey, actionBy);

  // Avoid duplicated denies
  if (payment.status === PaymentStatus.DENIED) {
    return payment;
  }

  const createdPayment = await create({
    ...payment,
    status: PaymentStatus.DENIED,
    reason,
    actionBy,
    processingState: PaymentProcessingState.UNPROCESSED,
  });

  return createdPayment;
};

/**
 * Denies a payment.
 *
 * @param {string} paymentKey Payment key
 * @param {string} reason Reason fo denial
 * @param {string} actionBy Action executor
 * @return {Promise<Payment>} The last payment for the given key
 *
 * @throws {Error} If no payment for the given key are found
 * @throws {Error} If reason is empty
 *
 * @async
 * @function
 * @memberOf module:payments/actions
 * @access public
 */
const denyPayment =
  tracer?.wrap('payments.denyPayment', internalDenyPayment) ||
  internalDenyPayment;

export { denyPayment };