Skip to content

Commit

Permalink
Merge pull request #1717 from ministryofjustice/MLPAB-2726-do-not-reg…
Browse files Browse the repository at this point in the history
…ister-banner

MLPAB-2726 Show banner when do-not-register
  • Loading branch information
hawx authored Jan 14, 2025
2 parents 41bb95e + 9a736e6 commit 2590228
Show file tree
Hide file tree
Showing 10 changed files with 274 additions and 7 deletions.
30 changes: 30 additions & 0 deletions cmd/event-received/lpastore_event_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ func (h *lpastoreEventHandler) Handle(ctx context.Context, factory factory, clou
case "CANNOT_REGISTER":
return handleCannotRegister(ctx, factory.ScheduledStore(), v)

case "OPG_STATUS_CHANGE":
lpaStoreClient, err := factory.LpaStoreClient()
if err != nil {
return fmt.Errorf("could not create LpaStoreClient: %w", err)
}

return handleOpgStatusChange(ctx, factory.DynamoClient(), lpaStoreClient, factory.Now(), v)

default:
return nil
}
Expand Down Expand Up @@ -212,3 +220,25 @@ func handleStatutoryWaitingPeriod(ctx context.Context, client dynamodbClient, no
func handleCannotRegister(ctx context.Context, store ScheduledStore, event lpaUpdatedEvent) error {
return store.DeleteAllByUID(ctx, event.UID)
}

func handleOpgStatusChange(ctx context.Context, client dynamodbClient, lpaStoreClient LpaStoreClient, now func() time.Time, v lpaUpdatedEvent) error {
donor, err := getDonorByLpaUID(ctx, client, v.UID)
if err != nil {
return err
}

lpa, err := lpaStoreClient.Lpa(ctx, v.UID)
if err != nil {
return fmt.Errorf("error getting lpa: %w", err)
}

if lpa.Status.IsDoNotRegister() {
donor.DoNotRegisterAt = now()

if err := putDonor(ctx, donor, now, client); err != nil {
return fmt.Errorf("failed to update donor details: %w", err)
}
}

return nil
}
180 changes: 180 additions & 0 deletions cmd/event-received/lpastore_event_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -954,3 +954,183 @@ func TestHandleCannotRegisterWhenStoreErrors(t *testing.T) {
err := handleCannotRegister(ctx, scheduledStore, event)
assert.ErrorIs(t, err, expectedError)
}

func TestLpaStoreEventHandlerHandleLpaUpdatedOpgStatusChange(t *testing.T) {
event := &events.CloudWatchEvent{
DetailType: "lpa-updated",
Detail: json.RawMessage(`{"uid":"M-1111-2222-3333","changeType":"OPG_STATUS_CHANGE"}`),
}

updated := &donordata.Provided{
PK: dynamo.LpaKey("123"),
SK: dynamo.LpaOwnerKey(dynamo.DonorKey("456")),
DoNotRegisterAt: testNow,
UpdatedAt: testNow,
}
updated.UpdateHash()

client := newMockDynamodbClient(t)
client.EXPECT().
OneByUID(ctx, "M-1111-2222-3333", mock.Anything).
Return(nil).
SetData(dynamo.Keys{PK: dynamo.LpaKey("123"), SK: dynamo.DonorKey("456")})
client.EXPECT().
One(ctx, dynamo.LpaKey("123"), dynamo.DonorKey("456"), mock.Anything).
Return(nil).
SetData(donordata.Provided{PK: dynamo.LpaKey("123"), SK: dynamo.LpaOwnerKey(dynamo.DonorKey("456"))})
client.EXPECT().
Put(ctx, updated).
Return(nil)

lpaStoreClient := newMockLpaStoreClient(t)
lpaStoreClient.EXPECT().
Lpa(ctx, "M-1111-2222-3333").
Return(&lpadata.Lpa{Status: lpadata.StatusDoNotRegister}, nil)

factory := newMockFactory(t)
factory.EXPECT().DynamoClient().Return(client)
factory.EXPECT().LpaStoreClient().Return(lpaStoreClient, nil)
factory.EXPECT().Now().Return(testNowFn)

handler := &lpastoreEventHandler{}

err := handler.Handle(ctx, factory, event)
assert.Nil(t, err)
}

func TestLpaStoreEventHandlerHandleLpaUpdatedOpgStatusChangeWhenFactoryErrors(t *testing.T) {
event := &events.CloudWatchEvent{
DetailType: "lpa-updated",
Detail: json.RawMessage(`{"uid":"M-1111-2222-3333","changeType":"OPG_STATUS_CHANGE"}`),
}

factory := newMockFactory(t)
factory.EXPECT().LpaStoreClient().Return(nil, expectedError)

handler := &lpastoreEventHandler{}

err := handler.Handle(ctx, factory, event)
assert.ErrorIs(t, err, expectedError)
}

func TestOpgStatusChangeWhenNotDoNotRegister(t *testing.T) {
dynamodbClient := newMockDynamodbClient(t)
dynamodbClient.EXPECT().
OneByUID(mock.Anything, mock.Anything, mock.Anything).
Return(nil).
SetData(dynamo.Keys{PK: dynamo.LpaKey("pk"), SK: dynamo.DonorKey("sk")})
dynamodbClient.EXPECT().
One(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
Return(nil)

lpaStoreClient := newMockLpaStoreClient(t)
lpaStoreClient.EXPECT().
Lpa(mock.Anything, mock.Anything).
Return(&lpadata.Lpa{}, nil)

event := lpaUpdatedEvent{
UID: "M-1111-2222-3333",
ChangeType: "OPG_STATUS_CHANGE",
}

err := handleOpgStatusChange(ctx, dynamodbClient, lpaStoreClient, testNowFn, event)
assert.Nil(t, err)
}

func TestOpgStatusChangeWhenErrors(t *testing.T) {
testcases := map[string]struct {
dynamoClient func(*testing.T) *mockDynamodbClient
lpaStoreClient func(*testing.T) *mockLpaStoreClient
expectedError error
}{
"OneByUID": {
dynamoClient: func(t *testing.T) *mockDynamodbClient {
client := newMockDynamodbClient(t)
client.EXPECT().
OneByUID(ctx, mock.Anything, mock.Anything).
Return(expectedError)

return client
},
lpaStoreClient: func(*testing.T) *mockLpaStoreClient { return nil },
expectedError: fmt.Errorf("failed to resolve uid: %w", expectedError),
},
"One": {
dynamoClient: func(t *testing.T) *mockDynamodbClient {
client := newMockDynamodbClient(t)
client.EXPECT().
OneByUID(mock.Anything, mock.Anything, mock.Anything).
Return(nil).
SetData(dynamo.Keys{PK: dynamo.LpaKey("pk"), SK: dynamo.DonorKey("sk")})
client.EXPECT().
One(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
Return(expectedError)

return client
},
lpaStoreClient: func(*testing.T) *mockLpaStoreClient { return nil },
expectedError: fmt.Errorf("failed to get LPA: %w", expectedError),
},
"LpaStore": {
dynamoClient: func(t *testing.T) *mockDynamodbClient {
client := newMockDynamodbClient(t)
client.EXPECT().
OneByUID(mock.Anything, mock.Anything, mock.Anything).
Return(nil).
SetData(dynamo.Keys{PK: dynamo.LpaKey("pk"), SK: dynamo.DonorKey("sk")})
client.EXPECT().
One(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
Return(nil)

return client
},
lpaStoreClient: func(*testing.T) *mockLpaStoreClient {
client := newMockLpaStoreClient(t)
client.EXPECT().
Lpa(mock.Anything, mock.Anything).
Return(nil, expectedError)

return client
},
expectedError: fmt.Errorf("error getting lpa: %w", expectedError),
},
"Put": {
dynamoClient: func(t *testing.T) *mockDynamodbClient {
client := newMockDynamodbClient(t)
client.EXPECT().
OneByUID(mock.Anything, mock.Anything, mock.Anything).
Return(nil).
SetData(dynamo.Keys{PK: dynamo.LpaKey("pk"), SK: dynamo.DonorKey("sk")})
client.EXPECT().
One(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
Return(nil)
client.EXPECT().
Put(mock.Anything, mock.Anything).
Return(expectedError)

return client
},
lpaStoreClient: func(*testing.T) *mockLpaStoreClient {
client := newMockLpaStoreClient(t)
client.EXPECT().
Lpa(mock.Anything, mock.Anything).
Return(&lpadata.Lpa{Status: lpadata.StatusDoNotRegister}, nil)

return client
},
expectedError: fmt.Errorf("failed to update donor details: %w", expectedError),
},
}

for testName, tc := range testcases {
t.Run(testName, func(t *testing.T) {
event := lpaUpdatedEvent{
UID: "M-1111-2222-3333",
ChangeType: "OPG_STATUS_CHANGE",
}

err := handleOpgStatusChange(ctx, tc.dynamoClient(t), tc.lpaStoreClient(t), testNowFn, event)
assert.ErrorIs(t, err, expectedError)
})
}
}
11 changes: 10 additions & 1 deletion cypress/e2e/donor/progress.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,5 +126,14 @@ describe('Progress', () => {
cy.contains('Simone Sutherland has been unable to confirm your identity');
cy.contains('We contacted you on 2 April 2023 with guidance about what to do next.');
});
})

it('when status is do not register', () => {
cy.visit('/fixtures?redirect=/progress&progress=doNotRegister');
cy.checkA11yApp();
cy.contains('Important:');
cy.contains('1 notification from OPG');

cy.contains('There is a problem with your LPA');
});
});
});
7 changes: 5 additions & 2 deletions internal/donor/donordata/provided.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,12 @@ type Provided struct {
SignedAt time.Time `checkhash:"-"`
// WithdrawnAt is when the Lpa was withdrawn by the donor
WithdrawnAt time.Time `checkhash:"-"`
// StatutoryWaitingPeriodAt is when the Lpa transitioned to the STATUTORY_WAITING_PERIOD
// status in the lpa-store
// StatutoryWaitingPeriodAt is when the Lpa transitioned to the
// statutory-waiting-period status in the lpa-store
StatutoryWaitingPeriodAt time.Time `checkhash:"-"`
// DoNotRegisterAt is when the Lpa transitioned to do-not-register status in
// the lpa-store
DoNotRegisterAt time.Time `checkhash:"-"`
// RegisteringWithCourtOfProtection is set when the donor wishes to take the
// Lpa to the Court of Protection for registration.
RegisteringWithCourtOfProtection bool `checkhash:"-"`
Expand Down
4 changes: 2 additions & 2 deletions internal/donor/donordata/provided_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,14 @@ func TestGenerateHash(t *testing.T) {
}

// DO change this value to match the updates
const modified uint64 = 0x7840b403479b6b58
const modified uint64 = 0x1124ca5d68ecf931

// DO NOT change these initial hash values. If a field has been added/removed
// you will need to handle the version gracefully by modifying
// (*Provided).HashInclude and adding another testcase for the new
// version.
testcases := map[uint8]uint64{
0: 0x50ff9ab239bc1918,
0: 0x9b0861af4f047273,
}

for version, initial := range testcases {
Expand Down
10 changes: 10 additions & 0 deletions internal/donor/donorpage/progress.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,16 @@ func Progress(tmpl template.Template, lpaStoreResolvingService LpaStoreResolving
})
}

if lpa.Status.IsDoNotRegister() && !donor.DoNotRegisterAt.IsZero() {
data.InfoNotifications = append(data.InfoNotifications, progressNotification{
Heading: appData.Localizer.T("thereIsAProblemWithYourLpa"),
Body: appData.Localizer.Format(
"weContactedYouOnWithGuidanceAboutWhatToDoNext",
map[string]any{"ContactedDate": appData.Localizer.FormatDate(donor.DoNotRegisterAt)},
),
})
}

return tmpl(w, data)
}
}
32 changes: 32 additions & 0 deletions internal/donor/donorpage/progress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,38 @@ func TestGetProgress(t *testing.T) {
return l
},
},
"do not register": {
donor: &donordata.Provided{
LpaUID: "lpa-uid",
DoNotRegisterAt: testNow,
},
lpa: &lpadata.Lpa{
LpaUID: "lpa-uid",
Status: lpadata.StatusDoNotRegister,
},
infoNotifications: []progressNotification{
{
Heading: "translated heading",
Body: "translated body",
},
},
setupLocalizer: func() *mockLocalizer {
l := newMockLocalizer(t)
l.EXPECT().
T("thereIsAProblemWithYourLpa").
Return("translated heading")
l.EXPECT().
Format(
"weContactedYouOnWithGuidanceAboutWhatToDoNext",
map[string]any{"ContactedDate": "translated date"},
).
Return("translated body")
l.EXPECT().
FormatDate(testNow).
Return("translated date")
return l
},
},
}

for name, tc := range testCases {
Expand Down
1 change: 1 addition & 0 deletions internal/page/fixtures/donor.go
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,7 @@ func updateLPAProgress(
fns = append(fns, func(ctx context.Context, client *lpastore.Client, _ *lpadata.Lpa) error {
return client.SendChangeStatus(ctx, donorDetails.LpaUID, lpadata.StatusStatutoryWaitingPeriod, lpadata.StatusDoNotRegister)
})
donorDetails.DoNotRegisterAt = time.Now()
}

return donorDetails, fns, nil
Expand Down
3 changes: 2 additions & 1 deletion lang/cy.json
Original file line number Diff line number Diff line change
Expand Up @@ -1513,5 +1513,6 @@
"youDoNotNeedToTakeAnyAction": "Welsh",
"youMustPayForYourLPA": "Welsh",
"returnToTaskListToPayForLPAWeWillThenContactVoucher": "Welsh {{.VoucherFullName}} Welsh",
"voucherHasBeenUnableToConfirmYourIdentity": "{{.VoucherFullName}} Welsh"
"voucherHasBeenUnableToConfirmYourIdentity": "{{.VoucherFullName}} Welsh",
"thereIsAProblemWithYourLpa": "Welsh"
}
3 changes: 2 additions & 1 deletion lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1409,5 +1409,6 @@
"youDoNotNeedToTakeAnyAction": "You do not need to take any action.",
"youMustPayForYourLPA": "You must pay for your LPA",
"returnToTaskListToPayForLPAWeWillThenContactVoucher": "Return to your task list to pay for your LPA. We will then be able to contact {{.VoucherFullName}} to ask them to confirm your identity.",
"voucherHasBeenUnableToConfirmYourIdentity": "{{.VoucherFullName}} has been unable to confirm your identity"
"voucherHasBeenUnableToConfirmYourIdentity": "{{.VoucherFullName}} has been unable to confirm your identity",
"thereIsAProblemWithYourLpa": "There is a problem with your LPA"
}

0 comments on commit 2590228

Please sign in to comment.