Skip to content

Commit

Permalink
feat: addition check for negative case fulfillment an ditem
Browse files Browse the repository at this point in the history
  • Loading branch information
sharique827 committed Nov 22, 2024
1 parent 4a45b2b commit 31fcd83
Show file tree
Hide file tree
Showing 13 changed files with 184 additions and 129 deletions.
2 changes: 1 addition & 1 deletion shared/Actions/metroActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export function validateLogsForMetro(data: any, flowName: string) {
}

if (data[metroSequence.ON_INIT]) {
const searchResp = checkOnInit(data[metroSequence.ON_INIT], msgIdSet)
const searchResp = checkOnInit(data[metroSequence.ON_INIT], msgIdSet, flow)
if (!_.isEmpty(searchResp)) {
logReport = { ...logReport, [metroSequence.ON_INIT]: searchResp }
}
Expand Down
2 changes: 1 addition & 1 deletion utils/metro/cancel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const checkCancelPayload = (data: any, msgIdSet: any, cancelType: boolean
const contextRes: any = validateContext(
context,
msgIdSet,
cancelType ? metroSequence?.SOFT_CANCEL : constants.ON_CONFIRM,
cancelType ? metroSequence?.SOFT_ON_CANCEL : constants.ON_CONFIRM,
cancelType ? metroSequence?.CONFIRM_CANCEL : metroSequence?.SOFT_CANCEL,
)
setValue(`${constants.CANCEL}_message`, message)
Expand Down
24 changes: 14 additions & 10 deletions utils/metro/metroChecks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface Stop {
parent_stop_id: string
}

export const validateContext = (context: any, msgIdSet: any, pastCall: any, curentCall: any) => {
export const validateContext = (context: any, msgIdSet: any, pastCall: any, curentCall: any, searchType?: boolean) => {
const errorObj: any = {}

const contextRes: any = checkMetroContext(context, curentCall)
Expand Down Expand Up @@ -65,13 +65,17 @@ export const validateContext = (context: any, msgIdSet: any, pastCall: any, cure
}

if (prevContext) {
if (pastCall !== 'search') {
if (!_.isEqual(prevContext.bpp_id, context.bpp_id)) {
if (context?.action !== 'search' || (context?.action === 'search' && searchType)) {
if (!context?.bpp_id) {
errorObj.bppId = 'context/bpp_id is missing'
} else if (prevContext.bpp_id && !_.isEqual(prevContext.bpp_id, context.bpp_id)) {
errorObj.bppIdContextMismatch = `BPP Id mismatch in /${pastCall} and /${curentCall}`
}

if (!_.isEqual(prevContext.bpp_uri, context.bpp_uri)) {
errorObj.bppUriContextMismatch = `BPP URI mismatch in /${pastCall} and /${curentCall}`
if (!context?.bpp_uri) {
errorObj.bppUri = 'context/bpp_uri is missing'
} else if (prevContext.bpp_uri && !_.isEqual(prevContext.bpp_uri, context.bpp_uri)) {
errorObj.bppUriContextMismatch = `BPP URL mismatch in /${pastCall} and /${curentCall}`
}
}

Expand Down Expand Up @@ -121,19 +125,19 @@ export const validateContext = (context: any, msgIdSet: any, pastCall: any, cure

try {
logger.info(`Comparing Message Ids of /${pastCall} and /${curentCall}`)
if (curentCall.startsWith('on_')) {
if (curentCall.startsWith('on_') || curentCall === 'soft_on_cancel' || curentCall === 'confirm_on_cancel') {
logger.info(`Comparing Message Ids of /${pastCall} and /${curentCall}`)
if (!_.isEqual(prevContext.message_id, context.message_id)) {
errorObj.message_id = `Message Id for /${pastCall} and /${curentCall} api should be same`
errorObj.message_id = `Message Id for /${pastCall} and /${curentCall} api should be same.`
}
} else {
logger.info(`Checking if Message Ids are different for /${pastCall} and /${curentCall}`)
if (
pastCall !== 'on_confirm' &&
curentCall !== 'cancel' &&
pastCall === 'on_confirm' &&
curentCall === 'soft_cancel' &&
_.isEqual(prevContext.message_id, context.message_id)
) {
errorObj.message_id = `Message Id for /${pastCall} and /${curentCall} api should be different`
errorObj.message_id = `Message Id for /${pastCall} and /${curentCall} api should be different.`
}
}
} catch (error: any) {
Expand Down
22 changes: 16 additions & 6 deletions utils/metro/mobilityChecks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ import { getValue, setValue } from '../../shared/dao'
import { checkGpsPrecision, checkIdAndUri, checkMobilityContext, timestampCheck } from '../../utils'
import _, { isNil } from 'lodash'

export const validateContext = (context: any, msgIdSet: any, pastCall: any, curentCall: any, toCheck?: boolean) => {
export const validateContext = (
context: any,
msgIdSet: any,
pastCall: any,
curentCall: any,
toCheck?: boolean,
searchType?: boolean,
) => {
const errorObj: any = {}

const contextRes: any = checkMobilityContext(context, curentCall)
Expand Down Expand Up @@ -31,8 +38,7 @@ export const validateContext = (context: any, msgIdSet: any, pastCall: any, cure
logger.info(`Comparing BAP and BPP in /${curentCall}`)

let bppValidationResult
if(toCheck || isNil(toCheck))
bppValidationResult = checkIdAndUri(context?.bpp_id, context?.bpp_uri, 'bpp')
if (toCheck || isNil(toCheck)) bppValidationResult = checkIdAndUri(context?.bpp_id, context?.bpp_uri, 'bpp')

const bapValidationResult = checkIdAndUri(context?.bap_id, context?.bap_uri, 'bap')

Expand All @@ -45,12 +51,16 @@ export const validateContext = (context: any, msgIdSet: any, pastCall: any, cure
}

if (prevContext) {
if (pastCall !== 'search') {
if (!_.isEqual(prevContext.bpp_id, context.bpp_id)) {
if (context?.action !== 'search' || (context?.action === 'search' && searchType)) {
if (!context?.bpp_id) {
errorObj.bppId = 'context/bpp_id is missing'
} else if (prevContext.bpp_id && !_.isEqual(prevContext.bpp_id, context.bpp_id)) {
errorObj.bppIdContextMismatch = `BPP Id mismatch in /${pastCall} and /${curentCall}`
}

if (!_.isEqual(prevContext.bpp_uri, context.bpp_uri)) {
if (!context?.bpp_uri) {
errorObj.bppUri = 'context/bpp_uri is missing'
} else if (prevContext.bpp_uri && !_.isEqual(prevContext.bpp_uri, context.bpp_uri)) {
errorObj.bppUriContextMismatch = `BPP URL mismatch in /${pastCall} and /${curentCall}`
}
}
Expand Down
2 changes: 1 addition & 1 deletion utils/metro/onCancel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const checkOnCancelPayload = (
const contextRes: any = validateContext(
context,
msgIdSet,
cancelType ? metroSequence?.SOFT_ON_CANCEL : metroSequence?.CONFIRM_CANCEL,
cancelType ? metroSequence?.CONFIRM_CANCEL : metroSequence?.SOFT_CANCEL,
cancelType ? metroSequence?.CONFIRM_ON_CANCEL : metroSequence?.SOFT_ON_CANCEL,
)
setValue(`${constants.ON_CANCEL}_message`, message)
Expand Down
56 changes: 37 additions & 19 deletions utils/metro/onConfirm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import {
validateStops,
validateCancellationTerms,
} from './metroChecks'
import { validatePaymentTags, validateRouteInfoTags } from './tags'
import { validatePaymentTags, validateRouteInfoTags, validateTags } from './tags'
import { isNil } from 'lodash'

const VALID_VEHICLE_CATEGORIES = ['AUTO_RICKSHAW', 'CAB', 'METRO', 'BUS', 'AIRLINE']
// const VALID_VEHICLE_CATEGORIES = ['AUTO_RICKSHAW', 'CAB', 'METRO', 'BUS', 'AIRLINE']
const VALID_DESCRIPTOR_CODES = ['RIDE', 'SJT', 'SESJT', 'RUT', 'PASS', 'SEAT', 'NON STOP', 'CONNECT']

export const checkOnConfirm = (data: any, msgIdSet: any, flow: { flow: string; flowSet: string }) => {
Expand Down Expand Up @@ -89,7 +90,7 @@ export const checkOnConfirm = (data: any, msgIdSet: any, flow: { flow: string; f
logger.info(`Validating fulfillments object for /${constants.ON_CONFIRM}`)
let FULFILLMENT: string[] = []
on_confirm.fulfillments.forEach((fulfillment: any, index: number) => {
FULFILLMENT=[...FULFILLMENT, fulfillment?.id]
FULFILLMENT = [...FULFILLMENT, fulfillment?.id]
const fulfillmentKey = `fulfillments[${index}]`

if (!storedFull.includes(fulfillment?.id)) {
Expand All @@ -101,11 +102,11 @@ export const checkOnConfirm = (data: any, msgIdSet: any, flow: { flow: string; f

if (!fulfillment?.vehicle) {
errorObj['Vehicle'] = 'Vehicle Object Is Missing'
} else {
if (!VALID_VEHICLE_CATEGORIES.includes(fulfillment.vehicle.category)) {
errorObj[`${fulfillmentKey}.vehicleCategory`] =
`Vehicle category should be one of ${VALID_VEHICLE_CATEGORIES}`
}
} else if (
fulfillment?.vehicle?.category !== (String(flow?.flow).toUpperCase() !== 'METRO' ? 'BUS' : 'METRO')
) {
errorObj[`${fulfillmentKey}.vehicleCategory`] =
`Vehicle category should be ${String(flow?.flow).toUpperCase() !== 'METRO' ? 'BUS' : 'METRO'} in Fulfillment.`
}

if (fulfillment.type !== 'TRIP') {
Expand All @@ -119,18 +120,20 @@ export const checkOnConfirm = (data: any, msgIdSet: any, flow: { flow: string; f
if (Object.keys(getStopsError).length > 0 && Object.keys(errorValue)?.length)
Object.assign(errorObj, getStopsError)

if (fulfillment.tags) {
// Validate route info tags
if (String(flow.flow.toUpperCase()).includes('INTRACITY')) {
const tagsValidation = validateRouteInfoTags(fulfillment.tags)
if (String(flow?.flow).toUpperCase() !== 'METRO') {
if (!fulfillment?.tags)
errorObj[`ulfillment_${index}_tags`] = `Tags should be present in Fulfillment in case of Intracity.`
else {
// Validate route info tags
const tagsValidation = validateRouteInfoTags(fulfillment?.tags)
if (!tagsValidation.isValid) {
Object.assign(errorObj, { tags: tagsValidation.errors })
}
}
}
})

setValue(`${metroSequence.ON_CONFIRM}_storedFulfillments`, FULFILLMENT || [])
setValue(`${metroSequence.ON_CONFIRM}_storedFulfillments`, FULFILLMENT || [])
} catch (error: any) {
logger.error(`!!Error occcurred while checking fulfillments info in /${constants.ON_INIT}, ${error.message}`)
return { error: error.message }
Expand Down Expand Up @@ -162,8 +165,8 @@ export const checkOnConfirm = (data: any, msgIdSet: any, flow: { flow: string; f
errorObj[key] = `Price is incomplete in /items[${index}]`
}

item.fulfillment_ids &&
item.fulfillment_ids.forEach((fulfillmentId: string) => {
item?.fulfillment_ids &&
item?.fulfillment_ids?.forEach((fulfillmentId: string) => {
if (!fulfillmentIdsSet.has(fulfillmentId)) {
errorObj[`invalidFulfillmentId_${index}`] =
`Fulfillment ID should be one of the fulfillment id '${fulfillmentId}' at index ${index} in /${constants.ON_CONFIRM} is not valid`
Expand Down Expand Up @@ -218,7 +221,8 @@ export const checkOnConfirm = (data: any, msgIdSet: any, flow: { flow: string; f
const { amount, currency, transaction_id } = params

if (!amount) {
errorObj[`payments[${i}]_params_amount`] = `payments.params.amount must be present in ${constants.ON_CONFIRM}`
errorObj[`payments[${i}]_params_amount`] =
`payments.params.amount must be present in ${constants.ON_CONFIRM}`
} else if (amount !== paymentAmount) {
errorObj[`payments[${i}]_params_amount`] =
`payments.params.amount must match with the ${paymentAmount} in ${constants.ON_CONFIRM}`
Expand All @@ -228,7 +232,8 @@ export const checkOnConfirm = (data: any, msgIdSet: any, flow: { flow: string; f
errorObj[`payments[${i}]_params_currency`] =
`payments.params.currency must be present in ${constants.CONFIRM}`
} else if (currency !== 'INR') {
errorObj[`payments[${i}]_params_currency`] = `payments.params.currency must be INR in ${constants.ON_CONFIRM}`
errorObj[`payments[${i}]_params_currency`] =
`payments.params.currency must be INR in ${constants.ON_CONFIRM}`
}

if (!transaction_id) {
Expand Down Expand Up @@ -282,8 +287,16 @@ export const checkOnConfirm = (data: any, msgIdSet: any, flow: { flow: string; f

try {
logger.info(`Checking cancellation terms in /${constants.ON_CONFIRM}`)
const cancellationErrors = validateCancellationTerms(on_confirm.cancellation_terms, constants.ON_CONFIRM)
Object.assign(errorObj, cancellationErrors)
if (String(flow?.flow)?.toUpperCase() === 'METRO') {
if (!on_confirm?.cancellation_terms)
errorObj.cancellation_terms = `cancellation_terms missing in /${constants.ON_CONFIRM}`
else {
logger.info(`Checking cancellation terms in /${constants.ON_CONFIRM}`)

const cancellationErrors = validateCancellationTerms(on_confirm?.cancellation_terms, constants.ON_CONFIRM)
if (!isNil(cancellationErrors)) Object.assign(errorObj, cancellationErrors)
}
}
} catch (error: any) {
logger.error(`!!Error while checking cancellation_terms in /${constants.ON_CONFIRM}, ${error.stack}`)
}
Expand All @@ -298,6 +311,11 @@ export const checkOnConfirm = (data: any, msgIdSet: any, flow: { flow: string; f
logger.error(`!!Error while checking status in message.order object /${constants.ON_CONFIRM}, ${error.stack}`)
}

if (String(flow?.flow)?.toUpperCase() === 'METRO' && on_confirm?.tags) {
const tagsValidation: { [key: string]: any } | null = validateTags(on_confirm?.tags ?? [], 0)
if (!isNil(tagsValidation)) Object.assign(errorObj, tagsValidation)
}

if (!on_confirm?.created_at) errorObj.created_at = `created_at is missing in /${constants.ON_CONFIRM}`
else if (on_confirm?.created_at !== context?.timestamp)
errorObj.created_at = `created_at must match with context.timestamp in /${constants.ON_CONFIRM}`
Expand Down
23 changes: 12 additions & 11 deletions utils/metro/onInit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { checkItemTime, checkProviderTime } from './validate/helper'
import { isNil } from 'lodash'

const VALID_DESCRIPTOR_CODES = ['SJT', 'SFSJT', 'RJT', 'PASS']
const VALID_VEHICLE_CATEGORIES = ['METRO']
export const checkOnInit = (data: any, msgIdSet: any, flow: { flow: string; flowSet: string }) => {
try {
const errorObj: any = {}
Expand Down Expand Up @@ -129,9 +128,9 @@ export const checkOnInit = (data: any, msgIdSet: any, flow: { flow: string; flow
errorObj[`Fulfillment[${index}].id`] = `fulfillment.id missing in /${constants.ON_INIT}`
}

if (!VALID_VEHICLE_CATEGORIES.includes(fulfillment.vehicle.category)) {
if (fulfillment?.vehicle?.category !== (String(flow?.flow).toUpperCase() !== 'METRO' ? 'BUS' : 'METRO')) {
errorObj[`${fulfillmentKey}.vehicleCategory`] =
`Vehicle category should be one of ${VALID_VEHICLE_CATEGORIES}`
`Vehicle category should be ${String(flow?.flow).toUpperCase() !== 'METRO' ? 'BUS' : 'METRO'} in Fulfillment.`
}

if (fulfillment.type !== 'TRIP') {
Expand Down Expand Up @@ -171,7 +170,7 @@ export const checkOnInit = (data: any, msgIdSet: any, flow: { flow: string; flow
//items null check
if (!on_init?.items) errorObj.items = `Items missing in /${constants.ON_INIT}`
else {
on_init.items.forEach((item: any, index: number) => {
on_init?.items?.forEach((item: any, index: number) => {
//handle id non-existant check
if (!item.id) errorObj[`item[${index}].id`] = `Item id missing in /${constants.ON_INIT}`
else if (!newItemIDSValue.includes(item.id)) {
Expand Down Expand Up @@ -239,13 +238,15 @@ export const checkOnInit = (data: any, msgIdSet: any, flow: { flow: string; flow
//check cancellation_terms
// revisit & handle external_ref check
try {
if (!on_init?.cancellation_terms)
errorObj.cancellation_terms = `cancellation_terms missing in /${constants.ON_INIT}`
else {
logger.info(`Checking cancellation terms in /${constants.ON_INIT}`)

const cancellationErrors = validateCancellationTerms(on_init?.cancellation_terms, constants.ON_INIT)
if (!isNil(cancellationErrors)) Object.assign(errorObj, cancellationErrors)
if (String(flow?.flow)?.toUpperCase() === 'METRO') {
if (!on_init?.cancellation_terms)
errorObj.cancellation_terms = `cancellation_terms missing in /${constants.ON_INIT}`
else {
logger.info(`Checking cancellation terms in /${constants.ON_INIT}`)

const cancellationErrors = validateCancellationTerms(on_init?.cancellation_terms, constants.ON_INIT)
if (!isNil(cancellationErrors)) Object.assign(errorObj, cancellationErrors)
}
}
} catch (error: any) {
logger.error(`!!Error while checking cancellation_terms in /${constants.ON_INIT}, ${error.stack}`)
Expand Down
37 changes: 30 additions & 7 deletions utils/metro/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,14 @@ export const search = (data: any, msgIdSet: any, secondSearch: boolean, flow: {
}

const schemaValidation = validateSchema('TRV', constants.SEARCH, data)
const contextRes: any = validateContext(context, msgIdSet, constants.ON_SEARCH, constants.SEARCH, false)
const contextRes: any = validateContext(
context,
msgIdSet,
constants.ON_SEARCH,
constants.SEARCH,
false,
secondSearch,
)
setValue(`${metroSequence.SEARCH1}_message`, message)
msgIdSet.add(data.context.message_id)

Expand Down Expand Up @@ -97,13 +104,29 @@ export const search = (data: any, msgIdSet: any, secondSearch: boolean, flow: {
try {
logger.info(`Validating payments object for /${constants.SEARCH}`)
const payment = data?.message?.intent?.payment
if (!payment?.collected_by)
errorObj['collected_by'] =
`payment.collected_by must be present in ${secondSearch ? metroSequence?.SEARCH2 : metroSequence.SEARCH1}`

const tagsValidation = validatePaymentTags(payment?.tags, secondSearch ? 'search2' : constants.SEARCH)
if (!tagsValidation?.isValid) {
Object.assign(errorObj, { tags: tagsValidation?.errors })
if (!payment) {
errorObj['payment'] = 'payment object is missing.'
} else {
// Validate `collected_by`
if (!payment.collected_by) {
errorObj['collected_by'] = `payment.collected_by must be present in ${
secondSearch ? metroSequence?.SEARCH2 : metroSequence.SEARCH1
}`
}

// Validate `tags`
if (!payment.tags) {
errorObj['payment.tags'] = `payment.tags is missing in ${
secondSearch ? metroSequence?.SEARCH2 : metroSequence.SEARCH1
}`
} else {
// Validate tags using external function
const tagsValidation = validatePaymentTags(payment.tags, secondSearch ? 'search2' : constants.SEARCH)
if (!tagsValidation?.isValid) {
errorObj.tags = tagsValidation.errors
}
}
}
} catch (error: any) {
logger.error(`!!Error occcurred while validating payments in /${constants.SEARCH}, ${error.message}`)
Expand Down
4 changes: 2 additions & 2 deletions utils/metro/tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ export const validatePaymentTags = (tags: Tag[], action: string): ValidationResu
break
}

tag.list.forEach((item: any, itemIndex) => {
tag?.list?.forEach((item: any, itemIndex) => {
switch (item.descriptor.code) {
case 'SETTLEMENT_WINDOW':
if (!/^(P(\d+D)?(T(\d+H)?(\d+M)?(\d+S)?)?)$/.test(item.value)) {
Expand Down Expand Up @@ -221,7 +221,7 @@ export const validatePaymentTags = (tags: Tag[], action: string): ValidationResu
setValue(`DELAY_INTEREST`, item.value)
} else {
const delayInterest = getValue('DELAY_INTEREST')
if (delayInterest !== item?.value)
if (delayInterest && delayInterest !== item?.value)
errors.push(
`SETTLEMENT_TERMS_[${index}], DELAY_INTEREST must be similar to /search value ${delayInterest} instead of ${item?.value} at item[${itemIndex}] in ${action}`,
)
Expand Down
Loading

0 comments on commit 31fcd83

Please sign in to comment.