sagas/coupons.js

/* eslint-disable sonarjs/cognitive-complexity */
import { takeLatest, put, call, select } from 'redux-saga/effects';
import { MODALS, API_URLS, SUCCESS_MODALS, SETTLED_COUPON_PAID_STATUS, BET_STATUS } from '../constants';

import { requestGet, requestPost } from '../utils/request';
import {
  getLastCouponId,
  getLastPlacedDate,
  getPlacedCoupons,
  getPlacedCouponsShop,
  getSettledCoupons,
  getSettledCouponsShop,
  getTurboLastCouponId,
  getTurboLastPlacedDate,
} from '../selectors/coupons';
import { aSetHasRecord, aSetIsFetched, aSetLastRecord, aSetOpenModal } from '../reducers/common';
import {
  aGetPlacedCouponsShopSuccess,
  aGetPlacedCouponsSuccess,
  aGetSettledCouponsShopSuccess,
  aGetSettledCouponsSuccess,
  aGetUpdatedSettledCouponsSuccess,
  aSetIsLoadingCoupons,
} from '../reducers/coupons';
import {
  aGetPlacedCoupons,
  aGetPlacedCouponsShop,
  aGetSettledCoupons,
  aGetSettledCouponsShop,
  aSetCouponToWontpayRequest,
  aUpdateSettledCoupons,
  aVoidCouponRequest,
} from '../reducers/actions';
import { aSetLastFilterData } from '../reducers/exporter';

/**
 * @namespace sagas/coupons
 */
/**
 * @memberof sagas/coupons
 * @typedef Coupon
 * @type {object}
 * @property {number} id
 * @property {number} clientId
 * @property {number} agentId
 * @property {string} placedDate
 * @property {number} roundId
 * @property {number} stake
 * @property {boolean} bonus
 * @property {number} status
 * @property {number} wonAmount
 * @property {string} settlementDate
 * @property {number} paid
 * @property {string} paidDate
 * @property {string} betDetails
 */

/**
 * @memberof sagas/coupons
 * @typedef "getCoupons/response.data"
 * @type {object}
 * @property {Array<Coupon>} coupons
 * @property {number} totalPage
 */
/**
 * Get coupons list
 *
 * @memberof sagas/coupons
 * @async
 * @param {object} action Filtering data
 */
function* getPlacedCouponsSaga(action) {
  let response;
  try {
    if (action.payload) {
      const lastCouponId = yield select(getLastCouponId);
      const lastPlacedDate = yield select(getLastPlacedDate);
      const turboLastCouponId = yield select(getTurboLastCouponId);
      const turboLastPlacedDate = yield select(getTurboLastPlacedDate);
      const filters = {
        ...action.payload,
        lastCouponId,
        lastPlacedDate,
        turboLastCouponId,
        turboLastPlacedDate,
      };
      const params = `?${new URLSearchParams(filters).toString()}`;

      yield put(aSetIsFetched({ isFetched: false }));
      response = yield call(requestGet, API_URLS.PLACED_COUPONS + params, true);

      if (response.status === -1) {
        const e = new Error(response.error.message);
        e.modal = MODALS.ERROR;
        throw e;
      } else {
        const coupons = yield select(getPlacedCoupons);
        yield put(
          aGetPlacedCouponsSuccess({
            coupons: [...coupons, ...response.data.coupons],
            lastCouponId: response.data.lastCouponId,
            lastPlacedDate: response.data.lastPlacedDate,
            turboLastCouponId: response.data.turboLastCouponId,
            turboLastPlacedDate: response.data.turboLastPlacedDate,
          })
        );
        if (!response.data.lastCouponId && !response.data.turboLastCouponId) {
          yield put(aSetLastRecord(true));
        }
        yield put({
          type: aSetHasRecord.type,
          payload: {
            hasRecord: response.data.coupons.length > 0,
          },
        });
      }
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}
/**
 * @memberof sagas/coupons
 * @typedef "getCoupons/response.data"
 * @type {object}
 * @property {Array<Coupon>} coupons
 * @property {number} totalPage
 */
/**
 * Get coupons list SHOP
 *
 * @memberof sagas/coupons
 * @async
 * @param {object} action Filtering data
 */
function* getPlacedCouponsShopSaga(action) {
  let response;
  try {
    if (action.payload) {
      const lastCouponId = yield select(getLastCouponId);
      const lastPlacedDate = yield select(getLastPlacedDate);
      const turboLastCouponId = yield select(getTurboLastCouponId);
      const turboLastPlacedDate = yield select(getTurboLastPlacedDate);
      const filters = {
        ...action.payload,
        lastCouponId,
        lastPlacedDate,
        turboLastCouponId,
        turboLastPlacedDate,
      };
      const params = `?${new URLSearchParams(filters).toString()}`;

      yield put(aSetIsFetched({ isFetched: false }));
      response = yield call(requestGet, API_URLS.PLACED_COUPONS_SHOP + params, true);

      if (response.status === -1) {
        const e = new Error(response.error.message);
        e.modal = MODALS.ERROR;
        throw e;
      } else {
        const coupons = yield select(getPlacedCouponsShop);
        yield put(
          aGetPlacedCouponsShopSuccess({
            coupons: [...coupons, ...response.data.coupons],
            lastCouponId: response.data.lastCouponId,
            lastPlacedDate: response.data.lastPlacedDate,
            turboLastCouponId: response.data.turboLastCouponId,
            turboLastPlacedDate: response.data.turboLastPlacedDate,
          })
        );
        if (!response.data.lastCouponId && !response.data.turboLastCouponId) {
          yield put(aSetLastRecord(true));
        }
        yield put({
          type: aSetHasRecord.type,
          payload: {
            hasRecord: response.data.coupons.length > 0,
          },
        });
      }
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}
/**
 * Get settled coupon list
 *
 * @memberof sagas/coupons
 * @async
 * @param {object} action Filtering data
 */
function* getSettledCouponsSaga(action) {
  let response;
  const { sort, ...payloads } = action.payload;
  try {
    if (action.payload) {
      const lastCouponId = yield select(getLastCouponId);
      const lastPlacedDate = yield select(getLastPlacedDate);
      const turboLastCouponId = yield select(getTurboLastCouponId);
      const turboLastPlacedDate = yield select(getTurboLastPlacedDate);
      const filters = {
        ...payloads,
        lastCouponId,
        lastPlacedDate,
        turboLastCouponId,
        turboLastPlacedDate,
      };

      const params = `?${new URLSearchParams(filters).toString()}`;
      yield put(aSetIsLoadingCoupons({ isLoadingCoupons: true }));

      response = yield call(requestGet, API_URLS.PLACED_COUPONS + params, true);

      if (response.status === -1) {
        const e = new Error(response.error.message);
        e.modal = MODALS.ERROR;
        throw e;
      } else {
        // initial fetch, keep the filter for export feature
        if (filters.lastCouponId === '') {
          yield put(
            aSetLastFilterData({
              filters,
              totalRows: response.data.totalAmountOfCoupons,
              firstBatchOfCoupons: response.data.coupons,
            })
          );
        }
        const coupons = yield select(getSettledCoupons);
        yield put(
          aGetSettledCouponsSuccess({
            coupons: [...coupons, ...response.data.coupons],
            lastCouponId: response.data.lastCouponId,
            lastPlacedDate: response.data.lastPlacedDate,
            turboLastCouponId: response.data.turboLastCouponId,
            turboLastPlacedDate: response.data.turboLastPlacedDate,
            sort,
          })
        );
        if ((!response.data.lastCouponId && !response.data.turboLastCouponId) || response.data.coupons.length === 0) {
          yield put(aSetLastRecord(true));
        }
        yield put({
          type: aSetHasRecord.type,
          payload: {
            hasRecord: response.data.coupons.length > 0,
          },
        });
        yield put(aSetIsLoadingCoupons({ isLoadingCoupons: false }));
      }
    }
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
    yield put(aSetIsLoadingCoupons({ isLoadingCoupons: false }));
  }
}

/**
 * Get settled coupon list SHOP
 *
 * @memberof sagas/coupons
 * @async
 * @param {object} action Filtering data
 */
function* getSettledCouponsShopSaga(action) {
  let response;
  const { sort, ...payloads } = action.payload;
  try {
    if (action.payload) {
      const lastCouponId = yield select(getLastCouponId);
      const lastPlacedDate = yield select(getLastPlacedDate);
      const turboLastCouponId = yield select(getTurboLastCouponId);
      const turboLastPlacedDate = yield select(getTurboLastPlacedDate);
      const filters = {
        ...payloads,
        lastCouponId,
        lastPlacedDate,
        turboLastCouponId,
        turboLastPlacedDate,
      };
      const params = `?${new URLSearchParams(filters).toString()}`;

      yield put(aSetIsFetched({ isFetched: false }));
      response = yield call(requestGet, API_URLS.PLACED_COUPONS_SHOP + params, true);

      if (response.status === -1) {
        const e = new Error(response.error.message);
        e.modal = MODALS.ERROR;
        throw e;
      } else {
        const coupons = yield select(getSettledCouponsShop);
        yield put(
          aGetSettledCouponsShopSuccess({
            coupons: [...coupons, ...response.data.coupons],
            lastCouponId: response.data.lastCouponId,
            lastPlacedDate: response.data.lastPlacedDate,
            turboLastCouponId: response.data.turboLastCouponId,
            turboLastPlacedDate: response.data.turboLastPlacedDate,
            sort,
            isShop: true,
          })
        );

        if ((!response.data.lastCouponId && !response.data.turboLastCouponId) || response.data.coupons.length === 0) {
          yield put(aSetLastRecord(true));
        }

        yield put({
          type: aSetHasRecord.type,
          payload: {
            hasRecord: response.data.coupons.length > 0,
          },
        });
      }
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * Void Coupon
 *
 * @param {object} action
 */
function* voidCouponSaga(action) {
  let response;
  try {
    const body = {
      couponId: action.payload.couponId,
    };

    yield put(aSetIsFetched({ isFetched: false }));

    const endPoint = action.payload.hasVoidCouponPermission
      ? API_URLS.VOID_COUPON
      : action.payload.hasVoidLosingCouponPermission
      ? API_URLS.VOID_LOSING_COUPON
      : '';

    response = yield call(requestPost, endPoint, body, true);

    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      const coupons = [...(yield select(getSettledCoupons))];
      const updatedCouponIndex = coupons.findIndex((coupon) => coupon?.id === body.couponId);

      coupons[updatedCouponIndex] = {
        ...coupons[updatedCouponIndex],
        status: BET_STATUS.VOID_REQUESTED,
      };
      yield put(
        aGetUpdatedSettledCouponsSuccess({
          coupons,
        })
      );
      yield put(
        aSetOpenModal({
          modal: MODALS.SUCCESS,
          modalData: {
            message: SUCCESS_MODALS.REQUEST_SUBMITTED,
            additionalMessage: '',
          },
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * Set coupon as Won't Pay
 *
 * @param {object} action
 */
function* setPaidStatusToWontPay(action) {
  try {
    const body = {
      couponId: action.payload.couponId,
    };

    yield put(aSetIsFetched({ isFetched: false }));

    const response = yield call(requestPost, API_URLS.SET_COUPON_TO_WONTPAY, body, true);
    if (response.status === -1) {
      const e = new Error(response.error.message);
      e.modal = MODALS.ERROR;
      throw e;
    } else {
      const coupons = [...(yield select(getSettledCoupons))];
      const updatedCouponIndex = coupons.findIndex((coupon) => coupon?.id === body.couponId);

      coupons[updatedCouponIndex] = {
        ...coupons[updatedCouponIndex],
        paid: SETTLED_COUPON_PAID_STATUS.WONT_PAY,
      };
      yield put(
        aGetUpdatedSettledCouponsSuccess({
          coupons,
        })
      );
      yield put(
        aSetOpenModal({
          modal: MODALS.SUCCESS,
          modalData: {
            message: SUCCESS_MODALS.UPDATED_COUPONS_STATUS_SUCCESS,
            additionalMessage: '',
          },
        })
      );
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}
/**
 * update settled coupon list
 *
 * @param {object} action
 */
function* updateSettledCouponsSaga(action) {
  let response;
  try {
    if (action.payload) {
      const filters = {
        ...action.payload,
      };
      const params = `?${new URLSearchParams(filters).toString()}`;

      yield put(aSetIsFetched({ isFetched: false }));

      response = yield call(requestGet, API_URLS.PLACED_COUPONS + params, true);
      if (response.status === -1) {
        const e = new Error(response.error.message);
        e.modal = MODALS.ERROR;
        throw e;
      } else {
        const updatedCoupon = response?.data?.coupons?.[0];
        const coupons = [...(yield select(getSettledCoupons))];
        const updatedCouponIndex = coupons.findIndex((coupon) => coupon?.id === updatedCoupon?.id);
        coupons[updatedCouponIndex] = updatedCoupon;
        yield put(
          aGetUpdatedSettledCouponsSuccess({
            coupons,
          })
        );
      }
    }
    yield put(aSetIsFetched({ isFetched: true }));
  } catch (error) {
    yield put(
      aSetOpenModal({
        modal: error.modal || MODALS.GENERAL_ERROR,
        errorMessage: error.modal ? error.message : MODALS.GENERAL_ERROR,
      })
    );
  }
}

/**
 * @memberof sagas/coupons
 * @async
 * @returns {void}
 */
export default function* couponsSaga() {
  yield takeLatest(aGetPlacedCoupons, getPlacedCouponsSaga);
  yield takeLatest(aGetPlacedCouponsShop, getPlacedCouponsShopSaga);
  yield takeLatest(aGetSettledCoupons, getSettledCouponsSaga);
  yield takeLatest(aGetSettledCouponsShop, getSettledCouponsShopSaga);
  yield takeLatest(aVoidCouponRequest, voidCouponSaga);
  yield takeLatest(aSetCouponToWontpayRequest, setPaidStatusToWontPay);
  yield takeLatest(aUpdateSettledCoupons, updateSettledCouponsSaga);
}