Files
address-verification-app/src/components/utlis/apiHelper.ts
Aman Singh ec07eca1f1 TP-82644 | Tele master hard release (#967)
Co-authored-by: Aman Chaturvedi <aman.chaturvedi@navi.com>
Co-authored-by: yashmantri <mantri.ramkishor@navi.com>
Co-authored-by: Varnit Goyal <varnit.goyal@navi.com>
Co-authored-by: github-cicd <github.cicd@navi.com>
Co-authored-by: Ashish Deo <ashish.deo@navi.com>
2024-10-08 17:34:39 +05:30

372 lines
16 KiB
TypeScript

import axios from 'axios';
import { Dispatch } from '@reduxjs/toolkit';
import { toast } from '../../../RN-UI-LIB/src/components/toast';
import { getCurrentScreen } from './navigationUtlis';
import { GLOBAL } from '../../constants/Global';
import { _map, compareUrl } from '../../../RN-UI-LIB/src/utlis/common';
import { BASE_AV_APP_URL } from '../../constants/config';
import { logError } from './errorUtils';
import { sendApiToClickstreamEvent } from '../../services/clickstreamEventService';
import { handleLogout } from '../../action/authActions';
import {
API_ERROR_MESSAGE,
REQUEST_TO_UNBLOCK_FOR_IMPERSONATION,
REQUEST_TYPE_TO_BLOCK_FOR_IMPERSONATION,
} from '../../common/Constants';
import { ToastMessages } from '../../screens/allCases/constants';
import { alfredHandleSWWEvent } from './DeviceUtils';
export enum ApiKeys {
GENERATE_OTP = 'GENERATE_OTP',
VERIFY_OTP = 'VERIFY_OTP',
ALL_CASES = 'ALL_CASES',
CASE_DETAIL = 'CASE_DETAIL',
PINNED_CASES = 'PINNED_CASES',
LOGOUT = 'LOGOUT',
FEEDBACK = 'FEEDBACK',
FILTERS = 'FILTERS',
JANUS = 'JANUS',
GENERATE_PAYMENT_LINK = 'GENERATE_PAYMENT_LINK',
GENERATE_PAYMENT_LINK_V2 = 'GENERATE_PAYMENT_LINK_V2',
ADDRESSES_GEOLOCATION = 'ADDRESSES_GEOLOCATION',
NEW_ADDRESS = 'NEW_ADDRESS',
GET_SIGNED_URL = 'GET_SIGNED_URL',
CASE_UNIFIED_DETAILS = 'CASE_UNIFIED_DETAILS',
CASE_UNIFIED_DETAILS_V4 = 'CASE_UNIFIED_DETAILS_V4',
UNGROUPED_ADDRESSES = 'UNGROUPED_ADDRESSES',
PAST_FEEDBACK = 'PAST_FEEDBACK',
PAST_FEEDBACK_ON_ADDRESSES = 'PAST_FEEDBACK_ON_ADDRESSES',
NOTIFICATIONS = 'NOTIFICATIONS',
NOTIFICATION_ACTION = 'NOTIFICATION_ACTION',
NOTIFICATION_DELIVERED = 'NOTIFICATION_DELIVERED',
SEND_LOCATION = 'SEND_LOCATION',
VERIFY_GOOGLE_SIGN_IN = 'VERIFY_GOOGLE_SIGN_IN',
SYNC_TIME = 'SYNC_TIME',
IS_DATA_SYNC_REQUIRED = 'IS_DATA_SYNC_REQUIRED',
GET_PRE_SIGNED_URL_DATA_SYNC = 'GET_PRE_SIGNED_URL_DATA_SYNC',
DATA_SYNC_UPLOAD_COMPLETED = 'DATA_SYNC_UPLOAD_COMPLETED',
IMPERSONATION = 'IMPERSONATION',
TELEPHONES = 'TELEPHONES',
CASES_SYNC_STATUS = 'CASES_SYNC_STATUS',
CASES_SEND_ID = 'CASES_SEND_ID',
FETCH_CASES = 'FETCH_CASES',
GET_FORECLOSURE_AMOUNT = 'GET_FORECLOSURE_AMOUNT',
UPLOAD_FEEDBACK_IMAGES = 'UPLOAD_FEEDBACK_IMAGES',
ORIGINAL_IMAGES = 'ORIGINAL_IMAGES',
GLOBAL_CONFIG = 'GLOBAL_CONFIG',
UPLOAD_IMAGE_ID = 'UPLOAD_IMAGE_ID',
GET_DOCUMENTS = 'GET_DOCUMENTS',
REPORTEES = 'REPORTEES',
GET_AGENT_DETAIL = 'GET_AGENT_DETAIL',
GET_SIGNED_URL_FOR_REPORTEE = 'GET_SIGNED_URL_FOR_REPORTEE',
GET_PERFORMANCE_METRICS = 'GET_PERFORMANCE_METRICS',
GET_CASH_COLLECTED = 'GET_CASH_COLLECTED',
GET_TELEPHONE_NUMBERS = 'GET_TELEPHONE_NUMBERS',
GET_TELEPHONE_NUMBERS_V2 = 'GET_TELEPHONE_NUMBERS_V2',
FIRESTORE_INCONSISTENCY_INFO = 'FIRESTORE_INCONSISTENCY_INFO',
FIRESTORE_INCONSISTENCY_INFO_V2 = 'FIRESTORE_INCONSISTENCY_INFO_V2',
GET_CASE_DETAILS_FROM_API = 'GET_CASE_DETAILS_FROM_API',
GET_CASE_DETAILS_FROM_API_V2 = 'GET_CASE_DETAILS_FROM_API_V2',
DAILY_COMMITMENT = 'DAILY_COMMITMENT',
GET_PTP_AMOUNT = 'GET_PTP_AMOUNT',
GET_VISIBILITY_STATUS = 'GET_VISIBILITY_STATUS',
GET_CSA_TICKETS = 'GET_CSA_TICKETS',
GET_CSA_SINGLE_TICKET = 'GET_CSA_SINGLE_TICKET',
CREATE_TICKET = 'CREATE_TICKET',
ACKNOWLEDGE_TICKET = 'ACKNOWLEDGE_TICKET',
ADD_COMMENT = 'ADD_COMMENT',
UPDATE_TICKET_STATUS = 'UPDATE_TICKET_STATUS',
GET_CSA_FILTERS = 'GET_CSA_FILTERS',
GET_FORM_OPTIONS = 'GET_FORM_OPTIONS',
GET_UPDATE_COUNT = 'GET_UPDATE_COUNT',
SIMILAR_GEOLOCATION_TIMESTAMPS = 'SIMILAR_GEOLOCATION_TIMESTAMPS',
GET_PRE_SIGNED_URL = 'GET_PRE_SIGNED_URL',
SEND_UPLOAD_ACK = 'SEND_UPLOAD_ACK',
DUE_AMOUNT_SUMMARY = 'DUE_AMOUNT_SUMMARY',
FEE_WAIVER_HISTORY = 'FEE_WAIVER_HISTORY',
FEE_WAIVER_V2 = 'FEE_WAIVER_V2',
GET_PIN_CODES_DETAILS = 'GET_PIN_CODES_DETAILS',
SYNC_COSMOS_TO_LONGHORN = 'SYNC_COSMOS_TO_LONGHORN',
CALL_CUSTOMER = 'CALL_CUSTOMER',
SYNC_ACTIVE_CALL_DETAILS = 'SYNC_ACTIVE_CALL_DETAILS',
GET_CALL_HISTORY = 'GET_CALL_HISTORY',
FETCH_CUSTOMER_DOCUMENTS = 'FETCH_CUSTOMER_DOCUMENTS',
FETCH_AGENT_DOCUMENTS = 'FETCH_AGENT_DOCUMENTS',
FETCH_DOCUMENT_SPECIFIC_LANGUAGE = 'FETCH_DOCUMENT_SPECIFIC_LANGUAGE',
SEND_COMMUNICATION_NAVI_ACCOUNT = 'SEND_COMMUNICATION_NAVI_ACCOUNT',
SYNC_CALL_FEEDBACK_NUDGE_DETAILS = 'SYNC_CALL_FEEDBACK_NUDGE_DETAILS',
GENERATE_DYNAMIC_DOCUMENT = 'GENERATE_DYNAMIC_DOCUMENT',
DOWNLOAD_LATEST_APP = 'DOWNLOAD_LATEST_APP',
GET_SIGNED_URL_V2 = 'GET_SIGNED_URL_V2',
GET_SIGNED_URL_FOR_REPORTEE_V2 = 'GET_SIGNED_URL_FOR_REPORTEE_V2'
}
export const API_URLS: Record<ApiKeys, string> = {} as Record<ApiKeys, string>;
API_URLS[ApiKeys.GENERATE_OTP] = '/auth/request-otp';
API_URLS[ApiKeys.VERIFY_OTP] = '/auth/otp/verify';
API_URLS[ApiKeys.ALL_CASES] = '/cases/all-cases';
API_URLS[ApiKeys.CASE_DETAIL] = '/cases/get-cases';
API_URLS[ApiKeys.PINNED_CASES] = '/cases/pin';
API_URLS[ApiKeys.LOGOUT] = '/auth/logout';
API_URLS[ApiKeys.FEEDBACK] = '/cases/feedback';
API_URLS[ApiKeys.FILTERS] = '/cases/filters';
API_URLS[ApiKeys.JANUS] = '/events/json';
API_URLS[ApiKeys.GENERATE_PAYMENT_LINK] = '/payments/send-payment-link';
API_URLS[ApiKeys.GENERATE_PAYMENT_LINK_V2] = '/payments/v2/send-payment-link';
API_URLS[ApiKeys.ADDRESSES_GEOLOCATION] = '/addresses-geolocations';
API_URLS[ApiKeys.NEW_ADDRESS] = '/addresses';
API_URLS[ApiKeys.GET_SIGNED_URL] = '/cases/get-signed-urls';
API_URLS[ApiKeys.GET_SIGNED_URL_V2] = '/cases/v2/get-signed-urls';
API_URLS[ApiKeys.GET_SIGNED_URL_FOR_REPORTEE] = '/cases/get-signed-urls-for-reportee';
API_URLS[ApiKeys.GET_SIGNED_URL_FOR_REPORTEE_V2] = '/cases/v2/get-signed-urls-for-reportee';
API_URLS[ApiKeys.CASE_UNIFIED_DETAILS] = '/v3/collection-cases/unified-details/{loanAccountNumber}';
API_URLS[ApiKeys.CASE_UNIFIED_DETAILS_V4] =
'/v5/collection-cases/unified-details/{loanAccountNumber}';
API_URLS[ApiKeys.UNGROUPED_ADDRESSES] = '/addresses/ungrouped-v2/{loanAccountNumber}';
API_URLS[ApiKeys.PAST_FEEDBACK] = '/feedback/filters';
API_URLS[ApiKeys.PAST_FEEDBACK_ON_ADDRESSES] = '/feedback/v2';
API_URLS[ApiKeys.NOTIFICATIONS] = '/notification/fetch';
API_URLS[ApiKeys.NOTIFICATION_ACTION] = '/notification/action';
API_URLS[ApiKeys.NOTIFICATION_DELIVERED] = '/notification/delivered';
API_URLS[ApiKeys.SEND_LOCATION] = '/geolocations/agents';
API_URLS[ApiKeys.VERIFY_GOOGLE_SIGN_IN] = '/auth/session/internal/exchange/v2';
API_URLS[ApiKeys.SYNC_TIME] = '/sync/server-timestamp';
API_URLS[ApiKeys.IS_DATA_SYNC_REQUIRED] = '/sync-data/is-sync-required';
API_URLS[ApiKeys.GET_PRE_SIGNED_URL_DATA_SYNC] = '/sync-data/get-pre-signed-url';
API_URLS[ApiKeys.DATA_SYNC_UPLOAD_COMPLETED] = '/sync-data/upload-completed';
API_URLS[ApiKeys.IMPERSONATION] = '/auth/impersonation';
API_URLS[ApiKeys.TELEPHONES] = '/telephones';
API_URLS[ApiKeys.CASES_SYNC_STATUS] = '/cases/agents/sync-status';
API_URLS[ApiKeys.CASES_SEND_ID] = '/cases/sync';
API_URLS[ApiKeys.FETCH_CASES] = '/cases/agents/{agentReferenceId}';
API_URLS[ApiKeys.GET_FORECLOSURE_AMOUNT] = '/{loanAccountNumber}/pre-closure-amount/v2';
API_URLS[ApiKeys.UPLOAD_FEEDBACK_IMAGES] = '/feedback/persist-original-images';
API_URLS[ApiKeys.GLOBAL_CONFIG] = '/global-config';
API_URLS[ApiKeys.UPLOAD_IMAGE_ID] = '/user/documents/selfie';
API_URLS[ApiKeys.GET_DOCUMENTS] = '/user/documents';
API_URLS[ApiKeys.REPORTEES] = '/user/all-field-reportees';
API_URLS[ApiKeys.GET_AGENT_DETAIL] = '/user/role-info';
API_URLS[ApiKeys.GET_PERFORMANCE_METRICS] = '/allocation-cycle/agent-performance';
API_URLS[ApiKeys.GET_CASH_COLLECTED] = '/allocation-cycle/cash-collected-split';
API_URLS[ApiKeys.GET_TELEPHONE_NUMBERS] =
'/v2/collection-cases/telephones-view/{loanAccountNumber}';
API_URLS[ApiKeys.GET_TELEPHONE_NUMBERS_V2] =
'/collections/{loanAccountNumber}/telephones-agent-call-activity-view';
API_URLS[ApiKeys.FIRESTORE_INCONSISTENCY_INFO] = '/cases/sync-status';
API_URLS[ApiKeys.FIRESTORE_INCONSISTENCY_INFO_V2] = '/cases/v2/sync-status';
API_URLS[ApiKeys.GET_CASE_DETAILS_FROM_API] =
'/collection-cases/minimal-collection-case-view/{caseId}';
API_URLS[ApiKeys.GET_CASE_DETAILS_FROM_API_V2] =
'/v2/collection-cases/minimal-collection-case-view/{caseId}';
API_URLS[ApiKeys.DAILY_COMMITMENT] = '/daily-commitment';
API_URLS[ApiKeys.GET_PTP_AMOUNT] = '/ptps-due-view/agent-detail';
API_URLS[ApiKeys.GET_VISIBILITY_STATUS] = '/daily-commitment/visibility';
API_URLS[ApiKeys.SIMILAR_GEOLOCATION_TIMESTAMPS] =
'/v1/geolocation-cluster/{clusterId}/similar-locations-info';
API_URLS[
ApiKeys.GET_PRE_SIGNED_URL
] = `/agent-data-sync/presigned-url?userReferenceId={agentID}&deviceReferenceId={deviceID}&dataSyncType={dataSyncType}`;
API_URLS[ApiKeys.SEND_UPLOAD_ACK] = '/agent-data-sync/{requestId}';
API_URLS[ApiKeys.GET_CSA_TICKETS] = '/support-requests/fetch-all';
API_URLS[ApiKeys.GET_CSA_SINGLE_TICKET] = '/support-requests/{ticketReferenceId}';
API_URLS[ApiKeys.CREATE_TICKET] = '/support-requests';
API_URLS[ApiKeys.ACKNOWLEDGE_TICKET] =
'/support-requests/{ticketReferenceId}/acknowledge?supportRequestUserType=FE';
API_URLS[ApiKeys.ADD_COMMENT] = '/support-requests/{ticketReferenceId}/comments';
API_URLS[ApiKeys.UPDATE_TICKET_STATUS] = '/support-requests/{ticketReferenceId}';
API_URLS[ApiKeys.GET_CSA_FILTERS] = '/support-requests/filters';
API_URLS[ApiKeys.GET_FORM_OPTIONS] = '/support-requests/form';
API_URLS[ApiKeys.GET_UPDATE_COUNT] = '/support-requests/summary';
API_URLS[ApiKeys.DUE_AMOUNT_SUMMARY] = '/collection-cases/{loanAccountNumber}/amount-summary';
API_URLS[ApiKeys.FEE_WAIVER_HISTORY] = '/collection-cases/{loanAccountNumber}/waiver-history';
API_URLS[ApiKeys.FEE_WAIVER_V2] = '/loan/request/{loanAccountNumber}/adjust-component/v2';
API_URLS[ApiKeys.GET_PIN_CODES_DETAILS] = '/api/v1/pincodes/{pinCode}';
API_URLS[ApiKeys.SYNC_COSMOS_TO_LONGHORN] = '/sync/tele-cosmos-sync';
API_URLS[ApiKeys.CALL_CUSTOMER] = '/call-recording/call-request/{loanAccountNumber}/{telephoneReferenceId}';
API_URLS[ApiKeys.SYNC_ACTIVE_CALL_DETAILS] = '/call-recording/call-status';
API_URLS[ApiKeys.GET_CALL_HISTORY] = '/call-recording/call-history/{loanAccountNumber}';
API_URLS[ApiKeys.SYNC_CALL_FEEDBACK_NUDGE_DETAILS] =
'/call-recording/acknowledge-feedback-nudge/{callId}';
API_URLS[ApiKeys.FETCH_CUSTOMER_DOCUMENTS] = '/documents/{loanAccountNumber}';
API_URLS[ApiKeys.FETCH_AGENT_DOCUMENTS] = '/documents/agent';
API_URLS[ApiKeys.FETCH_DOCUMENT_SPECIFIC_LANGUAGE] = '/documents/language/{loanAccountNumber}';
API_URLS[ApiKeys.SEND_COMMUNICATION_NAVI_ACCOUNT] = '/navi-communications/{loanAccountNumber}';
API_URLS[ApiKeys.GENERATE_DYNAMIC_DOCUMENT] = '/documents/generate/{loanAccountNumber}';
API_URLS[ApiKeys.DOWNLOAD_LATEST_APP] = 'https://longhorn.navi.com/api/app/download';
export const API_STATUS_CODE = {
OK: 200,
CREATED: 201,
BAD_REQUEST: 400,
UNAUTHORIZED: 401,
FORBIDDEN: 403,
NOT_FOUND: 404,
UNPROCESSABLE_CONTENT: 422,
INTERNAL_SERVER_ERROR: 500,
TOO_MANY_REQUESTS: 429,
};
const API_TIMEOUT_INTERVAL = 2e4; // 20s
let dispatch: Dispatch<any>;
export const getErrorMessage = (err: any) => {
if (err?.response?.data?.title) {
return err?.response?.data?.title;
}
const errorContent = err?.response?.data?.message ? JSON.parse(err?.response?.data?.message) : '';
return errorContent?.detail || errorContent?.message || errorContent || err;
};
export function getApiUrl(
apiKey: ApiKeys,
params?: Record<string, string | number>,
queryParams?: Record<string, string | number | boolean>
) {
let apiUrl = API_URLS[apiKey];
// replace all {placeholders} with their values in params
if (params) {
Object.keys(params).forEach((paramKey) => {
apiUrl = apiUrl.split(`{${paramKey}}`).join(`${params[paramKey]}`);
// apiUrl = apiUrl.replaceAll(`{${paramKey}}`, `${params[paramKey]}`);
});
}
if (queryParams) {
apiUrl += '?' + _map(queryParams, (key) => `${key}=${queryParams[key]}`).join('&');
}
return `${apiUrl}`;
}
// status code to be retried on
const errorsToRetry = [500, 503];
const axiosInstance = axios.create({ timeout: API_TIMEOUT_INTERVAL });
axiosInstance.interceptors.request.use((request) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
request.retry = request?.retry < 4 ? request.retry : 3;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
request.headers['X-Auth-Source'] = 'mjolnir';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
request.retry = request?.retry < 4 ? request.retry : 3;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
request.headers['request-start-time'] = Date.now();
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
request.headers['X-Session-Token'] = GLOBAL.SESSION_TOKEN || '';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
request.headers['X-Device-Id'] = GLOBAL.DEVICE_ID || '';
const abortController = new AbortController();
if (GLOBAL.IS_IMPERSONATED) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
request.headers['X-Impersonation-Session-Id'] = GLOBAL.SESSION_TOKEN || '';
const requestType = request?.method ?? '';
if (REQUEST_TYPE_TO_BLOCK_FOR_IMPERSONATION.includes(requestType)) {
const url = request?.url ?? '';
let isUrlUnBlocked = false;
REQUEST_TO_UNBLOCK_FOR_IMPERSONATION.forEach((requestPattern) => {
if (compareUrl(url, requestPattern)) {
isUrlUnBlocked = true;
}
});
if (!isUrlUnBlocked) {
request.headers['donotHandleError'] = true;
abortController.abort();
}
}
}
return {
...request,
signal: abortController.signal,
};
});
axiosInstance.interceptors.response.use(
(response) => {
if (response.config.headers) {
const start = response.config.headers['request-start-time'];
const end = Date.now();
const milliseconds = end - Number(start);
response.headers['request-duration'] = String(milliseconds);
sendApiToClickstreamEvent(response, milliseconds, true);
}
return response;
},
(error) => {
if (axios.isCancel(error) && GLOBAL.IS_IMPERSONATED) {
toast({
type: 'error',
text1: ToastMessages.NOT_ALLOWED_ERROR,
});
}
const { config, response } = error;
if (response?.status === 400) {
alfredHandleSWWEvent(new Error('API Error occured'));
}
logError(error as Error, config?.baseURL + config?.url);
const start = response?.config?.headers['request-start-time'];
const end = Date.now();
const milliseconds = end - Number(start);
sendApiToClickstreamEvent(response, milliseconds, false);
const donotHandleErrorOnStatusCode = (config.headers.donotHandleErrorOnStatusCode || []).map(
Number
);
if (
config?.headers?.donotHandleError ||
donotHandleErrorOnStatusCode.includes(error.response.status)
) {
return Promise.reject(error);
}
if (!config || config.retry <= 1 || !errorsToRetry.includes(error.response.status)) {
const errorString = getErrorMessage(error);
if (
!config.headers.donotHandleError &&
(config.headers?.showInSpecificComponents
? config.headers.showInSpecificComponents?.includes(getCurrentScreen().name)
: true)
) {
toast({
type: 'error',
text1: typeof errorString === 'string' ? errorString : API_ERROR_MESSAGE,
});
}
if ([API_STATUS_CODE.UNAUTHORIZED, API_STATUS_CODE.FORBIDDEN].includes(response.status)) {
// Reset user info
dispatch(handleLogout());
}
return Promise.reject(error);
}
config.retry -= 1;
const delayRetryRequest = new Promise<void>((resolve) => {
setTimeout(() => {
resolve();
}, 500);
});
return delayRetryRequest.then(() => axiosInstance(config));
}
);
axiosInstance.defaults.headers.common['Content-Type'] = 'application/json';
axiosInstance.defaults.baseURL = BASE_AV_APP_URL;
// TODO:: Ideally should happen through middlewares.
export const registerNavigateAndDispatch = (dispatchParam: Dispatch<any>) =>
(dispatch = dispatchParam);
export const isAxiosError = (err: Error) => {
return axios.isAxiosError(err);
};
export default axiosInstance;