-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DRAFT]PP-13333 parity checker checks exemption data matches #5669
base: master
Are you sure you want to change the base?
Conversation
f1b61f9
to
06efe47
Compare
06efe47
to
8bd30c9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Mostly stylistic changes requested. A couple of small logic changes and some more tests also.
var chargeEvent = chargeEventEntities | ||
.stream() | ||
.filter(event -> event.getStatus() == AUTHORISATION_SUCCESS || event.getStatus() == AUTHORISATION_REJECTED) | ||
.findFirst(); | ||
|
||
chargeEvent.ifPresent(event -> { | ||
var threeDsInfoEvent = Gateway3dsExemptionResultObtained.from(charge, event.getUpdated().toInstant()); | ||
boolean hasBeenEmittedBefore = emittedEventDao.hasBeenEmittedBefore(threeDsInfoEvent); | ||
if (forceEmission || !hasBeenEmittedBefore) { | ||
eventService.emitAndRecordEvent(threeDsInfoEvent, getDoNotRetryEmitUntilDate()); | ||
} | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can all be done as one:
chargeEventEntities
.stream()
.filter(event -> event.getStatus() == AUTHORISATION_SUCCESS || event.getStatus() == AUTHORISATION_REJECTED)
.findFirst()
.map(event -> Gateway3dsExemptionResultObtained.from(charge, event.getUpdated().toInstant()))
.filter(threeDsInfoEvent -> forceEmission || !emittedEventDao.hasBeenEmittedBefore(threeDsInfoEvent))
.ifPresent(threeDsInfoEvent -> eventService.emitAndRecordEvent(threeDsInfoEvent, getDoNotRetryEmitUntilDate()));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think threeDsInfoEvent
has been copied and pasted from elsewhere. gateway3dsExemptionResultObtainedEvent
would be better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add some logging (inside the ifPresent(…)
to say we’re outputting the event (we have similar for other events)?
var chargeEvent = chargeEventEntities | ||
.stream() | ||
.filter(event -> TERMINAL_AUTHENTICATION_STATES.contains(event.getStatus())) | ||
.findFirst(); | ||
|
||
chargeEvent.ifPresent(event -> { | ||
var requested3dsExemptionEvent = Requested3dsExemption.from(charge, event.getUpdated().toInstant()); | ||
boolean hasBeenEmittedBefore = emittedEventDao.hasBeenEmittedBefore(requested3dsExemptionEvent); | ||
if (forceEmission || !hasBeenEmittedBefore) { | ||
eventService.emitAndRecordEvent(requested3dsExemptionEvent, getDoNotRetryEmitUntilDate()); | ||
} | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly:
chargeEventEntities
.stream()
.filter(event -> TERMINAL_AUTHENTICATION_STATES.contains(event.getStatus()))
.findFirst()
.map(event -> Requested3dsExemption.from(charge, event.getUpdated().toInstant()))
.filter(requested3dsExemptionEvent -> forceEmission || !emittedEventDao.hasBeenEmittedBefore(requested3dsExemptionEvent))
.ifPresent(requested3dsExemptionEvent -> eventService.emitAndRecordEvent(requested3dsExemptionEvent, getDoNotRetryEmitUntilDate()));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also add some logging here too.
if (chargeEntity.getExemption3dsRequested() == null) { | ||
return CONNECTOR_HAS_EXEMPTION_3DS_REQUESTED_NULL; | ||
} else { | ||
if (chargeEntity.getExemption3dsRequested() == Exemption3dsType.OPTIMISED) { | ||
return CONNECTOR_HAS_EXEMPTION_3DS_REQUESTED_OPTIMISED; | ||
} else { | ||
return CONNECTOR_HAS_EXEMPTION_3DS_REQUESTED_CORPORATE; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can all be done in a single elegant switch expression that explicitly enumerates all possible values:
return switch (chargeEntity.getExemption3dsRequested()) {
case null -> CONNECTOR_HAS_EXEMPTION_3DS_REQUESTED_NULL;
case OPTIMISED -> CONNECTOR_HAS_EXEMPTION_3DS_REQUESTED_OPTIMISED;
case CORPORATE -> CONNECTOR_HAS_EXEMPTION_3DS_REQUESTED_CORPORATE;
};
if (chargeEntity.getExemption3ds() == null) { | ||
return CONNECTOR_HAS_EXEMPTION_NULL; | ||
} else { | ||
return switch (chargeEntity.getExemption3ds()) { | ||
case EXEMPTION_HONOURED -> CONNECTOR_HAS_EXEMPTION_HONOURED; | ||
case EXEMPTION_REJECTED -> CONNECTOR_HAS_EXEMPTION_REJECTED; | ||
case EXEMPTION_NOT_REQUESTED -> CONNECTOR_HAS_EXEMPTION_NOT_REQUESTED; | ||
case EXEMPTION_OUT_OF_SCOPE -> CONNECTOR_HAS_EXEMPTION_OUT_OF_SCOPE; | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because we’re living in the future, switch expressions can handle null now:
return switch (chargeEntity.getExemption3ds()) {
case null -> CONNECTOR_HAS_EXEMPTION_NULL;
case EXEMPTION_HONOURED -> CONNECTOR_HAS_EXEMPTION_HONOURED;
case EXEMPTION_REJECTED -> CONNECTOR_HAS_EXEMPTION_REJECTED;
case EXEMPTION_NOT_REQUESTED -> CONNECTOR_HAS_EXEMPTION_NOT_REQUESTED;
case EXEMPTION_OUT_OF_SCOPE -> CONNECTOR_HAS_EXEMPTION_OUT_OF_SCOPE;
};
import static uk.gov.pay.connector.tasks.service.LedgerAuthorisationSummaryState.LEDGER_HAS_NO_AUTHORISATION_SUMMARY; | ||
import static uk.gov.pay.connector.tasks.service.LedgerAuthorisationSummaryState.LEDGER_HAS_AUTHORISATION_SUMMARY_WITH_THREE_D_S_REQUIRED_FALSE; | ||
import static uk.gov.pay.connector.tasks.service.LedgerAuthorisationSummaryState.LEDGER_HAS_AUTHORISATION_SUMMARY_WITH_THREE_D_S_REQUIRED_TRUE; | ||
import static uk.gov.pay.connector.tasks.service.LedgerAuthorisationSummaryState.LEDGER_HAS_SOMETHING_COMPLETELY_DIFFERENT; | ||
import static uk.gov.pay.connector.tasks.service.LedgerExemptionState.*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don’t like wildcard import statements
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Woops!
historicalEventEmitterService.emitHistoricEventsById(1L, OptionalLong.empty(), 1L); | ||
|
||
ArgumentCaptor<Gateway3dsExemptionResultObtained> argument = ArgumentCaptor.forClass(Gateway3dsExemptionResultObtained.class); | ||
verify(eventService, times(1)).emitAndRecordEvent(argument.capture(), isNotNull()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for times(1)
: it’s the default
Arguments.of(EXEMPTION_NOT_REQUESTED, AUTHORISATION_SUCCESS), | ||
Arguments.of(EXEMPTION_HONOURED, AUTHORISATION_SUCCESS), | ||
Arguments.of(EXEMPTION_REJECTED, AUTHORISATION_SUCCESS), | ||
Arguments.of(EXEMPTION_OUT_OF_SCOPE, AUTHORISATION_SUCCESS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presumably we want AUTHORISATION_REJECTED
too?
} | ||
|
||
@Test | ||
void shouldCheckEventTypeIsNot3dsWhen3dsDetailsSetToNull(){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what this is supposed to be testing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarified with clearer name.
Arguments.of(CORPORATE, "CORPORATE", EXEMPTION_HONOURED, AUTHORISATION_REJECTED), | ||
Arguments.of(CORPORATE, "CORPORATE", EXEMPTION_REJECTED, AUTHORISATION_REJECTED), | ||
Arguments.of(CORPORATE, "CORPORATE", EXEMPTION_OUT_OF_SCOPE, AUTHORISATION_REJECTED) | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are other terminal authorisation states as well but it would be silly to test them all
Arguments.of(OPTIMISED, EXEMPTION_HONOURED, "honoured", true), | ||
Arguments.of(OPTIMISED, EXEMPTION_REJECTED, "rejected", true), | ||
Arguments.of(OPTIMISED, EXEMPTION_OUT_OF_SCOPE, "out of scope", true) | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we want (possibly as part of another test) ones with corporate exemptions too.
And probably at least some where it doesn’t match (focus on the most likely ones, like connector having an exemption result but ledger not).
WHAT YOU DID
When the historical events emitter is emitting events for a change in connector, if the charge has an
exemption_3ds_requested
orexemption_3ds
value then when the historical events emitter emits the events for the charge it should include aGATEWAY_3DS_EXEMPTION_RESULT_OBTAINED
with specific event details dependant upon the combination of exemption 3ds data as per below.exemption3dsRequested
exemption3ds
exemption
"exemption": {"requested": true,"outcome": {"result": "honoured"}}
"exemption": {"requested": true,"outcome": {"result": "rejected"}}
"exemption": {"requested": true,"outcome": {"result": "out of scope"}}
"exemption": {"requested": true,"type": "corporate","outcome": {"result": "honoured"}}
"exemption": {"requested": true,"type": "corporate","outcome": {"result": "rejected"}}
"exemption": {"requested": true,"type": "corporate","outcome": {"result": "out of scope"}}
"exemption": {"requested": true,"outcome": {"result": "honoured"}}
"exemption": {"requested": true,"outcome": {"result": "rejected"}}
"exemption": {"requested": false}
"exemption": {"requested": true,"outcome": {"result": "out of scope"}}
exemption
objectHow to test
TBC
Code review checklist
TBD
Logging
TBC