NTP-39292 | Added limit on PTP amount (#1118)
This commit is contained in:
committed by
GitHub
parent
31b7f6fc61
commit
e369714128
@@ -113,8 +113,8 @@ def jscFlavor = 'org.webkit:android-jsc:+'
|
||||
def enableHermes = project.ext.react.get("enableHermes", false);
|
||||
|
||||
|
||||
def VERSION_CODE = 249
|
||||
def VERSION_NAME = "2.18.6"
|
||||
def VERSION_CODE = 250
|
||||
def VERSION_NAME = "2.18.7"
|
||||
|
||||
android {
|
||||
namespace "com.avapp"
|
||||
|
||||
@@ -1 +1 @@
|
||||
249
|
||||
250
|
||||
@@ -1 +1 @@
|
||||
2.18.6
|
||||
2.18.7
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "AV_APP",
|
||||
"version": "2.18.6",
|
||||
"buildNumber": "249",
|
||||
"version": "2.18.7",
|
||||
"buildNumber": "250",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"android:dev": "yarn move:dev && react-native run-android",
|
||||
|
||||
@@ -2,6 +2,7 @@ import { AppDispatch } from '@store';
|
||||
import axiosInstance, { ApiKeys, getApiUrl } from '../components/utlis/apiHelper';
|
||||
import { logError } from '../components/utlis/errorUtils';
|
||||
import { setTopFeedbacks, setTopFeedbacksLoading } from '@reducers/topFeedbacksSlice';
|
||||
import { setForeclosureAmount } from '@reducers/feedbackFormSlice';
|
||||
|
||||
interface IPastFeedbacksPayload {
|
||||
loan_account_number: string;
|
||||
@@ -97,3 +98,26 @@ export const getTopFeedbacks = (caseId: string) => (dispatch: AppDispatch) => {
|
||||
})
|
||||
.finally(() => dispatch(setTopFeedbacksLoading({ caseId, isLoading: false })));
|
||||
};
|
||||
|
||||
export const getForeclosureAmount =
|
||||
(caseId: string, loanAccountNumber: string, preclosureDate: string) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
const url = getApiUrl(
|
||||
ApiKeys.GET_FORECLOSURE_AMOUNT,
|
||||
{ loanAccountNumber },
|
||||
{ preclosureDate }
|
||||
);
|
||||
return axiosInstance
|
||||
.get(url)
|
||||
.then((response) => {
|
||||
dispatch(
|
||||
setForeclosureAmount({
|
||||
caseId,
|
||||
foreclosureAmount: response?.data,
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
logError(err);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -12,6 +12,7 @@ import { addClickstreamEvent } from '../../../services/clickstreamEventService';
|
||||
import { CLICKSTREAM_EVENT_NAMES } from '../../../common/Constants';
|
||||
import { isQuestionMandatory, validateInput } from '../services/validation.service';
|
||||
import { CaseAllocationType } from '../../../screens/allCases/interface';
|
||||
import { validateInputValue } from '../utils';
|
||||
|
||||
interface ITextInput {
|
||||
questionType: string;
|
||||
@@ -26,7 +27,12 @@ interface ITextInput {
|
||||
|
||||
const TextInput: React.FC<ITextInput> = (props) => {
|
||||
const { questionId, error, sectionId, widgetId, caseId, questionType } = props;
|
||||
const template = useAppSelector((state) => state?.case?.templateData[CaseAllocationType.COLLECTION_CASE]);
|
||||
const template = useAppSelector(
|
||||
(state) => state?.case?.templateData[CaseAllocationType.COLLECTION_CASE]
|
||||
);
|
||||
const foreclosureAmount = useAppSelector(
|
||||
(state) => state?.feedbackForm?.foreclosureAmount?.[caseId]
|
||||
);
|
||||
const question = template.questions[questionId as keyof typeof template.questions];
|
||||
if (!question) {
|
||||
return null;
|
||||
@@ -69,7 +75,15 @@ const TextInput: React.FC<ITextInput> = (props) => {
|
||||
</Text>
|
||||
<Controller
|
||||
control={props.control}
|
||||
rules={{ validate: (data) => validateInput(data, question.metadata.validators) }}
|
||||
rules={{
|
||||
validate: (data) =>
|
||||
validateInput(
|
||||
data,
|
||||
question.metadata.validators,
|
||||
() => validateInputValue(data, foreclosureAmount),
|
||||
question?.tag
|
||||
),
|
||||
}}
|
||||
render={({ field: { onChange, onBlur, value } }) => (
|
||||
<RNTextInput
|
||||
maskType={question.metadata.maskType || null}
|
||||
|
||||
@@ -13,3 +13,5 @@ export const NUDGE_BOTTOM_SHEET_DEFAULT_STATE = {
|
||||
showNudgeBottomSheet: false,
|
||||
suspiciousFeedbackMessage: '',
|
||||
};
|
||||
|
||||
export const AMOUNT_PROMISED = 'AMOUNT_PROMISED';
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { isFunction } from '@components/utlis/commonFunctions';
|
||||
import { QuestionV1 } from '../../../types/template.types';
|
||||
import { AMOUNT_PROMISED } from '../constants';
|
||||
|
||||
export function isQuestionMandatory(question: QuestionV1): boolean {
|
||||
return !!question.metadata?.validators?.['required']?.value;
|
||||
@@ -6,7 +8,15 @@ export function isQuestionMandatory(question: QuestionV1): boolean {
|
||||
|
||||
const DEFAULT_ERROR_MESSAGE = 'This is a mandatory question';
|
||||
|
||||
export function validateInput(data: { answer: any; type: string }, allRules: any): boolean {
|
||||
export function validateInput(
|
||||
data: { answer: any; type: string },
|
||||
allRules: any,
|
||||
validateFieldValue?: () => {
|
||||
showValidationError: boolean;
|
||||
errMessage: string;
|
||||
},
|
||||
questionTag?: string,
|
||||
): boolean {
|
||||
let result = true;
|
||||
const currentDate = new Date();
|
||||
const endOfDayDate = new Date(
|
||||
@@ -62,6 +72,14 @@ export function validateInput(data: { answer: any; type: string }, allRules: any
|
||||
result = rule.message;
|
||||
break;
|
||||
}
|
||||
} else if (ruleName === Validators.MAX_AMOUNT && rule.value) {
|
||||
if (questionTag === AMOUNT_PROMISED && isFunction(validateFieldValue)) {
|
||||
const { showValidationError, errMessage } = validateFieldValue();
|
||||
if (showValidationError) {
|
||||
result = errMessage || rule.message;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,4 +92,5 @@ export enum Validators {
|
||||
MIN_TODAY = 'minToday',
|
||||
MAX_DATE = 'maxDate',
|
||||
PHONE_NUMBER = 'phoneNumber',
|
||||
MAX_AMOUNT = 'maxAmount',
|
||||
}
|
||||
|
||||
14
src/components/form/utils.ts
Normal file
14
src/components/form/utils.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { formatAmount } from '@rn-ui-lib/utils/amount';
|
||||
|
||||
export const validateInputValue = (
|
||||
data: { answer: any; type: string },
|
||||
foreclosureAmount: number
|
||||
) => {
|
||||
if (!foreclosureAmount) {
|
||||
return { showValidationError: false, errMessage: '' };
|
||||
}
|
||||
return {
|
||||
showValidationError: data?.answer > foreclosureAmount,
|
||||
errMessage: `PTP cannot exceed foreclosure (${formatAmount(foreclosureAmount)})`,
|
||||
};
|
||||
};
|
||||
24
src/reducer/feedbackFormSlice.ts
Normal file
24
src/reducer/feedbackFormSlice.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
interface IFeedbackFormState {
|
||||
foreclosureAmount: Record<string, number>;
|
||||
}
|
||||
|
||||
const initialState: IFeedbackFormState = {
|
||||
foreclosureAmount: {},
|
||||
};
|
||||
|
||||
const FeedbackFormSlice = createSlice({
|
||||
name: 'feedbackForm',
|
||||
initialState,
|
||||
reducers: {
|
||||
setForeclosureAmount: (state, action) => {
|
||||
const { caseId, foreclosureAmount } = action.payload;
|
||||
state.foreclosureAmount[caseId] = foreclosureAmount?.totalAmount;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { setForeclosureAmount } = FeedbackFormSlice.actions;
|
||||
|
||||
export default FeedbackFormSlice.reducer;
|
||||
@@ -24,9 +24,10 @@ import { getSkipTracingAddress, getUngroupedAddress } from '@actions/addressGeol
|
||||
import EscalationsSection from '@screens/escalations/EscalationsSection';
|
||||
import TopFeedbacks from './feedback/TopFeedbacks';
|
||||
import { CaseStatuses } from '@screens/allCases/interface';
|
||||
import { BUSINESS_DATE_FORMAT, ISO_DATE_FORMAT } from '@rn-ui-lib/utils/dates';
|
||||
import { BUSINESS_DATE_FORMAT, dateFormat, ISO_DATE_FORMAT } from '@rn-ui-lib/utils/dates';
|
||||
import dayjs from 'dayjs';
|
||||
import CaseDetailPausedNudge from './CaseDetailPausedNudge';
|
||||
import { getForeclosureAmount } from '@actions/feedbackActions';
|
||||
|
||||
interface ICaseDetails {
|
||||
route: {
|
||||
@@ -91,6 +92,7 @@ const CollectionCaseDetails: React.FC<ICaseDetails> = (props) => {
|
||||
lan: loanAccountNumber,
|
||||
currentTask: caseDetail?.currentTask?.taskType,
|
||||
});
|
||||
dispatch(getForeclosureAmount(caseId, loanAccountNumber, dateFormat(new Date(), ISO_DATE_FORMAT)));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -38,6 +38,7 @@ import escalationSlice from '@reducers/escalationSlice';
|
||||
import postOperationalHourRestrictionsSlice from '@reducers/postOperationalHourRestrictionsSlice';
|
||||
import skipTracingAddressesSlice from '@reducers/skipTracingAddressesSlice';
|
||||
import trainingMaterialSlice from '@reducers/trainingMaterialSlice';
|
||||
import feedbackFormSlice from '@reducers/feedbackFormSlice';
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
case: caseReducer,
|
||||
@@ -76,6 +77,7 @@ const rootReducer = combineReducers({
|
||||
escalationSlice: escalationSlice,
|
||||
postOperationalHourRestrictionsSlice: postOperationalHourRestrictionsSlice,
|
||||
trainingMaterial: trainingMaterialSlice,
|
||||
feedbackForm: feedbackFormSlice,
|
||||
});
|
||||
|
||||
const persistConfig = {
|
||||
|
||||
Reference in New Issue
Block a user