Untitled
unknown
plain_text
2 years ago
9.1 kB
10
Indexable
import { APIGatewayEvent } from "aws-lambda";
import * as B from "fp-ts/boolean";
import * as C from "fp-ts/Console";
import { pipe } from "fp-ts/function";
import * as TE from "fp-ts/TaskEither";
import { readUrl } from "@lambdas/shared/configuration";
import { catchAndLogTE } from "@lambdas/shared/errors/CatchAndLog";
import * as Json from "@lambdas/shared/json";
import {
LAMBDA_FUNCTION_TIMEOUT_DURATION,
calculateSentryTimeoutWarningLimit,
} from "@lambdas/shared/monitoring/lambda";
import { decryptDbsNotificationMessage } from "@lambdas/shared/pgp";
import { EDDAMandateRepository } from "@lambdas/shared/repositories/EDDAMandateRepository";
import {
getBankDetailsRepository,
getEddaCollectFundsRequestRepo,
getEddaMandateRepo,
} from "@lambdas/shared/repositoryFactory";
import { sendEddaAccountLinkFailEvent } from "@lambdas/shared/services/blueshift/sendEddaAccountLinkFailEvent";
import {
initializeSentry,
sentryWrapHandler,
} from "@lambdas/shared/services/sentry";
import { genericApiHandler } from "@lambdas/shared/sharedApiHandler";
import { sendMessagesToQueue } from "@lambdas/shared/sqs/sendMessagesToQueue";
import { HandlerContext, noPayload } from "@lambdas/shared/types";
import * as creationCallbackPayloadParser from "./creationCallbackParser";
import { getRequestIdFromEvent } from "./getRequestIdFromEvent";
import { encodeError, encodeSuccess } from "./httpResponseEncoder";
import {
isLinkedAccountExistError,
linkedAccountExistError,
} from "./linkedAccountExistError";
import { logError, logSuccess } from "./logger";
import { EDDAMandateWithBank } from "@lambdas/shared/models/EDDAMandate";
import { EDDACollectFundsRequest } from "@lambdas/shared/models/EDDACollectFundsRequest";
import { sendEgiroLinkAbortedDuplicateAccountPendingCollection } from "@lambdas/shared/services/blueshift/sendEgiroLinkAbortedDuplicateAccountPendingCollection";
initializeSentry();
export const handler = sentryWrapHandler(
(event: APIGatewayEvent, context: HandlerContext) =>
genericApiHandler(
{
event,
name: "dbs-egiro-creation-callback",
context,
isEventBodyRequired: true,
},
(event: APIGatewayEvent) =>
pipe(
TE.Do,
TE.bindW("requestId", () =>
TE.fromEither(getRequestIdFromEvent(event))
),
TE.bindW("payload", ({ requestId }) =>
getRequestPayload(event, requestId)
),
TE.bindW("eddaMandateRepo", getEddaMandateRepo),
TE.bindW("eddaMandate", ({ eddaMandateRepo, payload }) =>
eddaMandateRepo.findByTransactionIdWithBankAndUser(
payload.boTransactionRefNo
)
),
TE.bindW("validBankAccount", ({ eddaMandate, payload }) =>
validateBankAccount(
eddaMandate.userId,
payload.applicantBankCode!,
payload.applicantBankAccNo!
)
),
TE.chainFirstW(({ eddaMandateRepo, payload, validBankAccount }) =>
completeTokenReceipt(validBankAccount, eddaMandateRepo, payload)
),
TE.chainFirstW(({ payload }) =>
!!payload.errorMessage
? catchAndLogTE(C)(
"Send edda linking fail event error with reason"
)(publishRejectEventToBlueshift(payload.boTransactionRefNo))
: handleSendMessageToQueue(payload)
),
TE.orElseFirstIOK(logError),
TE.chainFirstIOK(logSuccess),
TE.match(encodeError, ({ requestId }) => encodeSuccess(requestId))
)()
),
{
timeoutWarningLimit: calculateSentryTimeoutWarningLimit(
LAMBDA_FUNCTION_TIMEOUT_DURATION.dbsEgiroCreationToken
),
}
);
const getRequestPayload = (event: APIGatewayEvent, requestId: string) =>
pipe(
event.body,
TE.fromNullable(noPayload()),
TE.chainW(decryptDbsNotificationMessage),
TE.chainEitherKW(Json.decode),
TE.chainEitherKW((payload) =>
creationCallbackPayloadParser.parse(payload, requestId)
)
);
const composeMessage = (
payload: creationCallbackPayloadParser.CreationCallbackPayload
) => ({
Id: payload.boTransactionRefNo,
MessageGroupId: payload.boTransactionRefNo,
MessageBody: JSON.stringify({
applicantBankAccNo: payload.applicantBankAccNo,
applicantBankCode: payload.applicantBankCode,
boDDARefNo: payload.boDDARefNo,
boTransactionRefNo: payload.boTransactionRefNo,
bankToken: payload.bankToken,
maxAmount: payload.maxAmount,
fromDate: payload.fromDate?.toFormat("dd-MM-yyyy"),
toDate: payload.toDate?.toFormat("dd-MM-yyyy"),
}),
});
const handleSendMessageToQueue = (
payload: creationCallbackPayloadParser.CreationCallbackPayload
) =>
pipe(
readUrl("QUEUE_URL"),
TE.fromEither,
TE.chainW((queueUrl) =>
sendMessagesToQueue(queueUrl, [composeMessage(payload)])
),
TE.map(() => undefined)
);
const publishRejectEventToBlueshift = (transactionId: string) =>
pipe(
getEddaMandateRepo(),
TE.chainW((repo) => repo.findByTransactionIdWithBankAndUser(transactionId)),
TE.chainW(sendEddaAccountLinkFailEvent)
);
const validateBankAccount = (
userId: string,
bic: string,
accountNumber: string
) =>
pipe(
getBankDetailsRepository(),
TE.chainW((repo) => repo.findByBicAndAccountNumber(bic, accountNumber)),
TE.chainW(
TE.fromPredicate(
(bankDetail) => !bankDetail || bankDetail.userId === userId,
linkedAccountExistError
)
),
TE.chainW(() => TE.of(true)),
TE.orElseW((error) => {
if (isLinkedAccountExistError(error)) {
console.error("The requested bank account was already registered");
return TE.right(false);
}
return TE.left(error);
})
);
const completeTokenReceipt = (
validBankAccount: boolean,
eddaMandateRepo: EDDAMandateRepository,
payload: creationCallbackPayloadParser.CreationCallbackPayload
) =>
pipe(
validBankAccount,
B.foldW(
() =>
eddaMandateRepo.completeTokenReceipt(
payload.boTransactionRefNo,
payload.boDDARefNo,
false,
undefined,
`Complete token receipt: The requested bank account was already registered`
),
() =>
eddaMandateRepo.completeTokenReceipt(
payload.boTransactionRefNo,
payload.boDDARefNo,
!payload.errorMessage,
payload.applicantBankAccNo,
payload.errorMessage &&
`Complete token receipt: ${payload.errorMessage}`,
payload.toDate
)
)
);
const validateDuplidateEddaMandate = (
eddaMandateRepo: EDDAMandateRepository,
payload: creationCallbackPayloadParser.CreationCallbackPayload
) =>
pipe(
// !payload.errorMessage &&,
// B.foldW(
// () =>
// ,
// () =>
// eddaMandateRepo.completeTokenReceipt(
// payload.boTransactionRefNo,
// payload.boDDARefNo,
// !payload.errorMessage,
// payload.applicantBankAccNo,
// payload.errorMessage &&
// `Complete token receipt: ${payload.errorMessage}`,
// payload.toDate
// )
// )
// getEddaCollectFundsRequestRepo(),
// TE.chainW(
// TE.fromPredicate(
// (eddaMandate) => eddaMandate === null,
// () => pipe(
// getEddaCollectFundsRequestRepo(),
// TE.chainW((repo) => repo.findPendingRequestsByMandateTransactionId(payload.boTransactionRefNo)),
// )
// )
// ),
eddaMandateRepo.findActiveAccountsByAndBicAndBankAccountNumber(payload.applicantBankCode!, payload.applicantBankAccNo!),
TE.bindTo("eddaMandate"),
TE.bindW('collectFundsRequestRepo', getEddaCollectFundsRequestRepo),
TE.bindW('pendingRequest', ({ collectFundsRequestRepo }) => collectFundsRequestRepo.findPendingRequestsByMandateTransactionId(payload.boTransactionRefNo)),
TE.chainW(
TE.fromPredicate(
({ eddaMandate }) => eddaMandate === null,
({ eddaMandate, pendingRequest }) => removeOldMandate(eddaMandate!, pendingRequest, eddaMandateRepo)
)
)
// TE.chainW(({ eddaMandate, pendingRequest }) => pipe(
// eddaMandate === null || pendingRequest.length === 0,
// B.foldW(
// () => ,
// () =>
// eddaMandateRepo.completeTokenReceipt(
// payload.boTransactionRefNo,
// payload.boDDARefNo,
// !payload.errorMessage,
// payload.applicantBankAccNo,
// payload.errorMessage &&
// `Complete token receipt: ${payload.errorMessage}`,
// payload.toDate
// )
// )
// ))
);
const removeOldMandate = (
eddaMandate: EDDAMandateWithBank,
pendingRequest: EDDACollectFundsRequest[],
eddaMandateRepo: EDDAMandateRepository,
) =>
pipe(
pendingRequest.length > 0,
B.foldW(
() => eddaMandateRepo.deleteByTransactionId(eddaMandate.transactionId),
() => sendEgiroLinkAbortedDuplicateAccountPendingCollection(eddaMandate.userId)
)
)Editor is loading...
Leave a Comment