From 9f515b32d5a9bf33acad9a32524c8e6d5fcdccfa Mon Sep 17 00:00:00 2001 From: Joshua Hawxwell Date: Tue, 29 Oct 2024 11:11:34 +0000 Subject: [PATCH 1/3] Allow changing voucher when they haven't started --- cmd/event-received/mock_Handler_test.go | 12 +- cypress/e2e/donor/what-you-can-do-now.cy.js | 81 ++++++++++ .../donor/donordata/enum_novoucherdecision.go | 18 +-- .../donor/donordata/no_voucher_decision.go | 2 +- ...are_you_sure_you_no_longer_need_voucher.go | 52 +++++++ ...ou_sure_you_no_longer_need_voucher_test.go | 141 ++++++++++++++++++ .../donor/donorpage/mock_DonorStore_test.go | 47 ++++++ internal/donor/donorpage/register.go | 5 + .../donor/donorpage/what_you_can_do_now.go | 67 +++++---- .../donorpage/what_you_can_do_now_expired.go | 4 +- .../what_you_can_do_now_expired_test.go | 46 +++--- .../donorpage/what_you_can_do_now_test.go | 91 ++++++++--- internal/donor/path.go | 8 +- internal/donor/store.go | 20 +++ internal/donor/store_test.go | 53 +++++++ internal/dynamo/keys.go | 17 ++- internal/dynamo/keys_test.go | 13 +- internal/page/fixtures/fixtures.go | 1 + internal/sharecode/store.go | 6 +- internal/sharecode/store_test.go | 9 +- lang/cy.json | 22 ++- lang/en.json | 22 ++- ...you_sure_you_no_longer_need_voucher.gohtml | 18 +++ .../donor/we_have_contacted_voucher.gohtml | 51 +++++-- ...e_informed_voucher_no_longer_needed.gohtml | 17 +++ web/template/donor/what_you_can_do_now.gohtml | 8 +- .../donor/what_you_can_do_now_expired.gohtml | 4 +- web/template/layout/buttons.gohtml | 4 +- 28 files changed, 720 insertions(+), 119 deletions(-) create mode 100644 internal/donor/donorpage/are_you_sure_you_no_longer_need_voucher.go create mode 100644 internal/donor/donorpage/are_you_sure_you_no_longer_need_voucher_test.go create mode 100644 web/template/donor/are_you_sure_you_no_longer_need_voucher.gohtml create mode 100644 web/template/donor/we_have_informed_voucher_no_longer_needed.gohtml diff --git a/cmd/event-received/mock_Handler_test.go b/cmd/event-received/mock_Handler_test.go index 8497c5a5c2..56925d46b0 100644 --- a/cmd/event-received/mock_Handler_test.go +++ b/cmd/event-received/mock_Handler_test.go @@ -23,7 +23,7 @@ func (_m *mockHandler) EXPECT() *mockHandler_Expecter { } // Handle provides a mock function with given fields: _a0, _a1, _a2 -func (_m *mockHandler) Handle(_a0 context.Context, _a1 factory, _a2 events.CloudWatchEvent) error { +func (_m *mockHandler) Handle(_a0 context.Context, _a1 factory, _a2 *events.CloudWatchEvent) error { ret := _m.Called(_a0, _a1, _a2) if len(ret) == 0 { @@ -31,7 +31,7 @@ func (_m *mockHandler) Handle(_a0 context.Context, _a1 factory, _a2 events.Cloud } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, factory, events.CloudWatchEvent) error); ok { + if rf, ok := ret.Get(0).(func(context.Context, factory, *events.CloudWatchEvent) error); ok { r0 = rf(_a0, _a1, _a2) } else { r0 = ret.Error(0) @@ -48,14 +48,14 @@ type mockHandler_Handle_Call struct { // Handle is a helper method to define mock.On call // - _a0 context.Context // - _a1 factory -// - _a2 events.CloudWatchEvent +// - _a2 *events.CloudWatchEvent func (_e *mockHandler_Expecter) Handle(_a0 interface{}, _a1 interface{}, _a2 interface{}) *mockHandler_Handle_Call { return &mockHandler_Handle_Call{Call: _e.mock.On("Handle", _a0, _a1, _a2)} } -func (_c *mockHandler_Handle_Call) Run(run func(_a0 context.Context, _a1 factory, _a2 events.CloudWatchEvent)) *mockHandler_Handle_Call { +func (_c *mockHandler_Handle_Call) Run(run func(_a0 context.Context, _a1 factory, _a2 *events.CloudWatchEvent)) *mockHandler_Handle_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(factory), args[2].(events.CloudWatchEvent)) + run(args[0].(context.Context), args[1].(factory), args[2].(*events.CloudWatchEvent)) }) return _c } @@ -65,7 +65,7 @@ func (_c *mockHandler_Handle_Call) Return(_a0 error) *mockHandler_Handle_Call { return _c } -func (_c *mockHandler_Handle_Call) RunAndReturn(run func(context.Context, factory, events.CloudWatchEvent) error) *mockHandler_Handle_Call { +func (_c *mockHandler_Handle_Call) RunAndReturn(run func(context.Context, factory, *events.CloudWatchEvent) error) *mockHandler_Handle_Call { _c.Call.Return(run) return _c } diff --git a/cypress/e2e/donor/what-you-can-do-now.cy.js b/cypress/e2e/donor/what-you-can-do-now.cy.js index aeb5c43ad0..6c7ce0e6cf 100644 --- a/cypress/e2e/donor/what-you-can-do-now.cy.js +++ b/cypress/e2e/donor/what-you-can-do-now.cy.js @@ -144,4 +144,85 @@ describe('what you can do now', () => { cy.url().should('contain', '/what-happens-next-registering-with-court-of-protection') }) }) + + context('want a different voucher', () => { + beforeEach(() => { + cy.visit('/fixtures?redirect=/what-is-vouching&progress=payForTheLpa'); + cy.get('input[name="yes-no"]').check('yes', { force: true }); + cy.contains('button', 'Save and continue').click(); + cy.get('#f-first-names').type('Shopping'); + cy.get('#f-last-name').type('Voucher'); + cy.get('#f-email').type('voucher@example.com'); + cy.contains('button', 'Save and continue').click(); + cy.contains('button', 'Continue').click(); + cy.contains('a', 'Confirm my identity another way').click(); + }) + + it('keeps the voucher until choice is made', () => { + cy.visitLpa('/enter-voucher'); + cy.get('#f-first-names').should('have.value', 'Shopping'); + cy.get('#f-last-name').should('have.value', 'Voucher'); + cy.get('#f-email').should('have.value', 'voucher@example.com'); + }); + + it('can choose to get ID documents', () => { + cy.contains('label', 'I will get or find ID documents and confirm my own identity').click(); + cy.contains('button', 'Continue').click(); + + cy.url().should('contain', '/are-you-sure-you-no-longer-need-voucher'); + cy.checkA11yApp(); + + cy.contains('button', 'Shopping Voucher no longer needed').click(); + + cy.contains('You have chosen to find, replace or get new ID'); + cy.contains('a', 'Continue').click(); + + cy.url().should('contain', '/task-list') + }); + + it('can choose to add a voucher', () => { + cy.contains('label', 'I have someone else who can vouch for me').click(); + cy.contains('button', 'Continue').click(); + + cy.url().should('contain', '/are-you-sure-you-no-longer-need-voucher'); + cy.checkA11yApp(); + + cy.contains('button', 'Shopping Voucher no longer needed').click(); + + cy.contains('You have chosen to ask someone else'); + cy.contains('a', 'Continue').click(); + + cy.url().should('contain', '/enter-voucher') + }) + + it('can choose to withdraw LPA', () => { + cy.contains('label', 'I no longer want to make this LPA').click(); + cy.contains('button', 'Continue').click(); + + cy.url().should('contain', '/are-you-sure-you-no-longer-need-voucher'); + cy.checkA11yApp(); + + cy.contains('button', 'Shopping Voucher no longer needed').click(); + + cy.contains('You have told us you no longer want to make this LPA'); + cy.contains('a', 'Continue').click(); + + cy.url().should('contain', '/withdraw-this-lpa') + }) + + it('can choose to apply to court of protection', () => { + cy.contains('label', 'I will apply to the Court of Protection to register this LPA').click(); + cy.contains('button', 'Continue').click(); + + cy.url().should('contain', '/are-you-sure-you-no-longer-need-voucher'); + cy.checkA11yApp(); + + cy.contains('button', 'Shopping Voucher no longer needed').click(); + + cy.contains('You have chosen to have your LPA reviewed by the Court of Protection'); + cy.contains('a', 'Continue').click(); + + cy.url().should('contain', '/what-happens-next-registering-with-court-of-protection') + }); + }); }) diff --git a/internal/donor/donordata/enum_novoucherdecision.go b/internal/donor/donordata/enum_novoucherdecision.go index 18d1e3dcdc..194c187db3 100644 --- a/internal/donor/donordata/enum_novoucherdecision.go +++ b/internal/donor/donordata/enum_novoucherdecision.go @@ -11,15 +11,15 @@ func _() { // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. var x [1]struct{} - _ = x[ProveOwnID-1] + _ = x[ProveOwnIdentity-1] _ = x[SelectNewVoucher-2] _ = x[WithdrawLPA-3] _ = x[ApplyToCOP-4] } -const _NoVoucherDecision_name = "prove-own-idselect-new-voucherwithdraw-lpaapply-to-cop" +const _NoVoucherDecision_name = "prove-own-identityselect-new-voucherwithdraw-lpaapply-to-cop" -var _NoVoucherDecision_index = [...]uint8{0, 12, 30, 42, 54} +var _NoVoucherDecision_index = [...]uint8{0, 18, 36, 48, 60} func (i NoVoucherDecision) String() string { if i == 0 { @@ -46,8 +46,8 @@ func (i *NoVoucherDecision) UnmarshalText(text []byte) error { return nil } -func (i NoVoucherDecision) IsProveOwnID() bool { - return i == ProveOwnID +func (i NoVoucherDecision) IsProveOwnIdentity() bool { + return i == ProveOwnIdentity } func (i NoVoucherDecision) IsSelectNewVoucher() bool { @@ -66,8 +66,8 @@ func ParseNoVoucherDecision(s string) (NoVoucherDecision, error) { switch s { case "": return NoVoucherDecision(0), nil - case "prove-own-id": - return ProveOwnID, nil + case "prove-own-identity": + return ProveOwnIdentity, nil case "select-new-voucher": return SelectNewVoucher, nil case "withdraw-lpa": @@ -80,14 +80,14 @@ func ParseNoVoucherDecision(s string) (NoVoucherDecision, error) { } type NoVoucherDecisionOptions struct { - ProveOwnID NoVoucherDecision + ProveOwnIdentity NoVoucherDecision SelectNewVoucher NoVoucherDecision WithdrawLPA NoVoucherDecision ApplyToCOP NoVoucherDecision } var NoVoucherDecisionValues = NoVoucherDecisionOptions{ - ProveOwnID: ProveOwnID, + ProveOwnIdentity: ProveOwnIdentity, SelectNewVoucher: SelectNewVoucher, WithdrawLPA: WithdrawLPA, ApplyToCOP: ApplyToCOP, diff --git a/internal/donor/donordata/no_voucher_decision.go b/internal/donor/donordata/no_voucher_decision.go index fbf9668b64..03582aca7d 100644 --- a/internal/donor/donordata/no_voucher_decision.go +++ b/internal/donor/donordata/no_voucher_decision.go @@ -4,7 +4,7 @@ package donordata type NoVoucherDecision uint8 const ( - ProveOwnID NoVoucherDecision = iota + 1 // prove-own-id + ProveOwnIdentity NoVoucherDecision = iota + 1 // prove-own-identity SelectNewVoucher // select-new-voucher WithdrawLPA // withdraw-lpa ApplyToCOP // apply-to-cop diff --git a/internal/donor/donorpage/are_you_sure_you_no_longer_need_voucher.go b/internal/donor/donorpage/are_you_sure_you_no_longer_need_voucher.go new file mode 100644 index 0000000000..919654c22c --- /dev/null +++ b/internal/donor/donorpage/are_you_sure_you_no_longer_need_voucher.go @@ -0,0 +1,52 @@ +package donorpage + +import ( + "net/http" + "net/url" + + "github.com/ministryofjustice/opg-go-common/template" + "github.com/ministryofjustice/opg-modernising-lpa/internal/appcontext" + "github.com/ministryofjustice/opg-modernising-lpa/internal/donor" + "github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata" + "github.com/ministryofjustice/opg-modernising-lpa/internal/form" + "github.com/ministryofjustice/opg-modernising-lpa/internal/validation" +) + +type areYouSureYouNoLongerNeedVoucherData struct { + App appcontext.Data + Errors validation.List + Donor *donordata.Provided +} + +func AreYouSureYouNoLongerNeedVoucher(tmpl template.Template, donorStore DonorStore) Handler { + return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, provided *donordata.Provided) error { + data := &areYouSureYouNoLongerNeedVoucherData{ + App: appData, + Donor: provided, + } + + if r.Method == http.MethodPost { + voucherFullName := provided.Voucher.FullName() + + doNext, err := donordata.ParseNoVoucherDecision(r.FormValue("choice")) + if err != nil { + return err + } + + provided.WantVoucher = form.YesNoUnknown + nextPage := handleDoNext(doNext, provided).Format(provided.LpaID) + + if err := donorStore.DeleteVoucher(r.Context(), provided); err != nil { + return err + } + + return donor.PathWeHaveInformedVoucherNoLongerNeeded.RedirectQuery(w, r, appData, provided, url.Values{ + "choice": {r.FormValue("choice")}, + "next": {nextPage}, + "voucherFullName": {voucherFullName}, + }) + } + + return tmpl(w, data) + } +} diff --git a/internal/donor/donorpage/are_you_sure_you_no_longer_need_voucher_test.go b/internal/donor/donorpage/are_you_sure_you_no_longer_need_voucher_test.go new file mode 100644 index 0000000000..211555538d --- /dev/null +++ b/internal/donor/donorpage/are_you_sure_you_no_longer_need_voucher_test.go @@ -0,0 +1,141 @@ +package donorpage + +import ( + "net/http" + "net/http/httptest" + "net/url" + "testing" + + "github.com/ministryofjustice/opg-modernising-lpa/internal/donor" + "github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata" + "github.com/ministryofjustice/opg-modernising-lpa/internal/form" + "github.com/ministryofjustice/opg-modernising-lpa/internal/identity" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func TestGetAreYouSureYouNoLongerNeedVoucher(t *testing.T) { + w := httptest.NewRecorder() + r, _ := http.NewRequest(http.MethodGet, "/", nil) + + template := newMockTemplate(t) + template.EXPECT(). + Execute(w, &areYouSureYouNoLongerNeedVoucherData{ + App: testAppData, + Donor: &donordata.Provided{}, + }). + Return(nil) + + err := AreYouSureYouNoLongerNeedVoucher(template.Execute, nil)(testAppData, w, r, &donordata.Provided{}) + resp := w.Result() + + assert.Nil(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) +} + +func TestGetAreYouSureYouNoLongerNeedVoucherWhenTemplateErrors(t *testing.T) { + w := httptest.NewRecorder() + r, _ := http.NewRequest(http.MethodGet, "/", nil) + + template := newMockTemplate(t) + template.EXPECT(). + Execute(w, mock.Anything). + Return(expectedError) + + err := AreYouSureYouNoLongerNeedVoucher(template.Execute, nil)(testAppData, w, r, &donordata.Provided{}) + resp := w.Result() + + assert.Equal(t, expectedError, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) +} + +func TestPostAreYouSureYouNoLongerNeedVoucher(t *testing.T) { + testcases := map[donordata.NoVoucherDecision]struct { + redirect donor.Path + provided *donordata.Provided + }{ + donordata.ProveOwnIdentity: { + redirect: donor.PathTaskList, + provided: &donordata.Provided{ + LpaID: "lpa-id", + Voucher: donordata.Voucher{FirstNames: "a", LastName: "b"}, + }, + }, + donordata.SelectNewVoucher: { + redirect: donor.PathEnterVoucher, + provided: &donordata.Provided{ + LpaID: "lpa-id", + WantVoucher: form.Yes, + Voucher: donordata.Voucher{FirstNames: "a", LastName: "b"}, + IdentityUserData: identity.UserData{Status: identity.StatusConfirmed}, + }, + }, + donordata.WithdrawLPA: { + redirect: donor.PathWithdrawThisLpa, + provided: &donordata.Provided{ + LpaID: "lpa-id", + Voucher: donordata.Voucher{FirstNames: "a", LastName: "b"}, + IdentityUserData: identity.UserData{Status: identity.StatusConfirmed}, + }, + }, + donordata.ApplyToCOP: { + redirect: donor.PathWhatHappensNextRegisteringWithCourtOfProtection, + provided: &donordata.Provided{ + LpaID: "lpa-id", + Voucher: donordata.Voucher{FirstNames: "a", LastName: "b"}, + IdentityUserData: identity.UserData{Status: identity.StatusConfirmed}, + RegisteringWithCourtOfProtection: true, + }, + }, + } + + for choice, tc := range testcases { + t.Run(choice.String(), func(t *testing.T) { + w := httptest.NewRecorder() + r, _ := http.NewRequest(http.MethodPost, "/?choice="+choice.String(), nil) + + donorStore := newMockDonorStore(t) + donorStore.EXPECT(). + DeleteVoucher(r.Context(), tc.provided). + Return(nil) + + err := AreYouSureYouNoLongerNeedVoucher(nil, donorStore)(testAppData, w, r, &donordata.Provided{ + LpaID: "lpa-id", + WantVoucher: form.Yes, + Voucher: donordata.Voucher{FirstNames: "a", LastName: "b"}, + IdentityUserData: identity.UserData{Status: identity.StatusConfirmed}, + }) + resp := w.Result() + + assert.Nil(t, err) + assert.Equal(t, http.StatusFound, resp.StatusCode) + assert.Equal(t, donor.PathWeHaveInformedVoucherNoLongerNeeded.FormatQuery("lpa-id", url.Values{ + "choice": {choice.String()}, + "voucherFullName": {"a b"}, + "next": {tc.redirect.Format("lpa-id")}, + }), resp.Header.Get("Location")) + }) + } +} + +func TestPostAreYouSureYouNoLongerNeedVoucherWhenStoreErrors(t *testing.T) { + w := httptest.NewRecorder() + r, _ := http.NewRequest(http.MethodPost, "/?choice="+donordata.ProveOwnIdentity.String(), nil) + + donorStore := newMockDonorStore(t) + donorStore.EXPECT(). + DeleteVoucher(r.Context(), mock.Anything). + Return(expectedError) + + err := AreYouSureYouNoLongerNeedVoucher(nil, donorStore)(testAppData, w, r, &donordata.Provided{}) + + assert.Equal(t, expectedError, err) +} + +func TestPostAreYouSureYouNoLongerNeedVoucherWhenInvalidChoice(t *testing.T) { + w := httptest.NewRecorder() + r, _ := http.NewRequest(http.MethodPost, "/?choice=what", nil) + + err := AreYouSureYouNoLongerNeedVoucher(nil, nil)(testAppData, w, r, &donordata.Provided{}) + assert.Error(t, err) +} diff --git a/internal/donor/donorpage/mock_DonorStore_test.go b/internal/donor/donorpage/mock_DonorStore_test.go index b92f64538c..c2f65acb71 100644 --- a/internal/donor/donorpage/mock_DonorStore_test.go +++ b/internal/donor/donorpage/mock_DonorStore_test.go @@ -70,6 +70,53 @@ func (_c *mockDonorStore_Delete_Call) RunAndReturn(run func(context.Context) err return _c } +// DeleteVoucher provides a mock function with given fields: ctx, provided +func (_m *mockDonorStore) DeleteVoucher(ctx context.Context, provided *donordata.Provided) error { + ret := _m.Called(ctx, provided) + + if len(ret) == 0 { + panic("no return value specified for DeleteVoucher") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *donordata.Provided) error); ok { + r0 = rf(ctx, provided) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockDonorStore_DeleteVoucher_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteVoucher' +type mockDonorStore_DeleteVoucher_Call struct { + *mock.Call +} + +// DeleteVoucher is a helper method to define mock.On call +// - ctx context.Context +// - provided *donordata.Provided +func (_e *mockDonorStore_Expecter) DeleteVoucher(ctx interface{}, provided interface{}) *mockDonorStore_DeleteVoucher_Call { + return &mockDonorStore_DeleteVoucher_Call{Call: _e.mock.On("DeleteVoucher", ctx, provided)} +} + +func (_c *mockDonorStore_DeleteVoucher_Call) Run(run func(ctx context.Context, provided *donordata.Provided)) *mockDonorStore_DeleteVoucher_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*donordata.Provided)) + }) + return _c +} + +func (_c *mockDonorStore_DeleteVoucher_Call) Return(_a0 error) *mockDonorStore_DeleteVoucher_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockDonorStore_DeleteVoucher_Call) RunAndReturn(run func(context.Context, *donordata.Provided) error) *mockDonorStore_DeleteVoucher_Call { + _c.Call.Return(run) + return _c +} + // Get provides a mock function with given fields: ctx func (_m *mockDonorStore) Get(ctx context.Context) (*donordata.Provided, error) { ret := _m.Called(ctx) diff --git a/internal/donor/donorpage/register.go b/internal/donor/donorpage/register.go index ab3fc9c837..780077b9aa 100644 --- a/internal/donor/donorpage/register.go +++ b/internal/donor/donorpage/register.go @@ -54,6 +54,7 @@ type DonorStore interface { Put(ctx context.Context, donor *donordata.Provided) error Delete(ctx context.Context) error Link(ctx context.Context, data sharecodedata.Link, donorEmail string) error + DeleteVoucher(ctx context.Context, provided *donordata.Provided) error } type GetDonorStore interface { @@ -419,6 +420,10 @@ func Register( WhatYouCanDoNowExpired(tmpls.Get("what_you_can_do_now_expired.gohtml"), donorStore)) handleWithDonor(donor.PathWhatHappensNextRegisteringWithCourtOfProtection, page.None, Guidance(tmpls.Get("what_happens_next_registering_with_court_of_protection.gohtml"))) + handleWithDonor(donor.PathAreYouSureYouNoLongerNeedVoucher, page.CanGoBack, + AreYouSureYouNoLongerNeedVoucher(tmpls.Get("are_you_sure_you_no_longer_need_voucher.gohtml"), donorStore)) + handleWithDonor(donor.PathWeHaveInformedVoucherNoLongerNeeded, page.None, + Guidance(tmpls.Get("we_have_informed_voucher_no_longer_needed.gohtml"))) handleWithDonor(donor.PathHowToSignYourLpa, page.None, Guidance(tmpls.Get("how_to_sign_your_lpa.gohtml"))) diff --git a/internal/donor/donorpage/what_you_can_do_now.go b/internal/donor/donorpage/what_you_can_do_now.go index ed893206ae..eae515ab61 100644 --- a/internal/donor/donorpage/what_you_can_do_now.go +++ b/internal/donor/donorpage/what_you_can_do_now.go @@ -2,6 +2,7 @@ package donorpage import ( "net/http" + "net/url" "github.com/ministryofjustice/opg-go-common/template" "github.com/ministryofjustice/opg-modernising-lpa/internal/appcontext" @@ -14,13 +15,13 @@ import ( ) type whatYouCanDoNowData struct { - App appcontext.Data - Errors validation.List - Form *whatYouCanDoNowForm - ProveOwnIDLabel string - NewVoucherLabel string - BannerContent string - FailedVouchAttempts int + App appcontext.Data + Errors validation.List + Form *whatYouCanDoNowForm + ProveOwnIdentityLabel string + NewVoucherLabel string + BannerContent string + FailedVouchAttempts int } func WhatYouCanDoNow(tmpl template.Template, donorStore DonorStore) Handler { @@ -39,50 +40,62 @@ func WhatYouCanDoNow(tmpl template.Template, donorStore DonorStore) Handler { data.Errors = data.Form.Validate() if data.Errors.None() { - nextPage := handleDoNext(data.Form.DoNext, provided) + var nextPage string + if provided.Voucher.Allowed { + nextPage = donor.PathAreYouSureYouNoLongerNeedVoucher.FormatQuery(provided.LpaID, url.Values{ + "choice": {data.Form.DoNext.String()}, + }) + } else { + nextPage = handleDoNext(data.Form.DoNext, provided).Format(provided.LpaID) + } if err := donorStore.Put(r.Context(), provided); err != nil { return err } - return nextPage.Redirect(w, r, appData, provided) + return appData.Redirect(w, r, nextPage) } } - switch provided.FailedVouchAttempts { - case 0: - data.BannerContent = "youHaveNotChosenAnyoneToVouchForYou" - data.NewVoucherLabel = "iHaveSomeoneWhoCanVouch" - data.ProveOwnIDLabel = "iWillReturnToOneLogin" - case 1: - data.BannerContent = "thePersonYouAskedToVouchHasBeenUnableToContinue" + if !provided.Voucher.Allowed { + switch provided.FailedVouchAttempts { + case 0: + data.BannerContent = "youHaveNotChosenAnyoneToVouchForYou" + data.NewVoucherLabel = "iHaveSomeoneWhoCanVouch" + data.ProveOwnIdentityLabel = "iWillReturnToOneLogin" + case 1: + data.BannerContent = "thePersonYouAskedToVouchHasBeenUnableToContinue" + data.NewVoucherLabel = "iHaveSomeoneElseWhoCanVouch" + data.ProveOwnIdentityLabel = "iWillGetOrFindID" + default: + data.BannerContent = "thePersonYouAskedToVouchHasBeenUnableToContinueSecondAttempt" + data.ProveOwnIdentityLabel = "iWillGetOrFindID" + } + } else { data.NewVoucherLabel = "iHaveSomeoneElseWhoCanVouch" - data.ProveOwnIDLabel = "iWillGetOrFindID" - default: - data.BannerContent = "thePersonYouAskedToVouchHasBeenUnableToContinueSecondAttempt" - data.ProveOwnIDLabel = "iWillGetOrFindID" + data.ProveOwnIdentityLabel = "iWillGetOrFindID" } return tmpl(w, data) } } -func handleDoNext(doNext donordata.NoVoucherDecision, provided *donordata.Provided) (nextPage donor.Path) { +func handleDoNext(doNext donordata.NoVoucherDecision, provided *donordata.Provided) donor.Path { switch doNext { - case donordata.ProveOwnID: + case donordata.ProveOwnIdentity: provided.IdentityUserData = identity.UserData{} - nextPage = donor.PathTaskList + return donor.PathTaskList case donordata.SelectNewVoucher: provided.WantVoucher = form.Yes - nextPage = donor.PathEnterVoucher + return donor.PathEnterVoucher case donordata.WithdrawLPA: - nextPage = donor.PathWithdrawThisLpa + return donor.PathWithdrawThisLpa case donordata.ApplyToCOP: provided.RegisteringWithCourtOfProtection = true - nextPage = donor.PathWhatHappensNextRegisteringWithCourtOfProtection + return donor.PathWhatHappensNextRegisteringWithCourtOfProtection } - return nextPage + panic("doNext invalid") } type whatYouCanDoNowForm struct { diff --git a/internal/donor/donorpage/what_you_can_do_now_expired.go b/internal/donor/donorpage/what_you_can_do_now_expired.go index b50e316291..bfc88fddd3 100644 --- a/internal/donor/donorpage/what_you_can_do_now_expired.go +++ b/internal/donor/donorpage/what_you_can_do_now_expired.go @@ -36,10 +36,10 @@ func WhatYouCanDoNowExpired(tmpl template.Template, donorStore DonorStore) Handl data.BannerContent = "yourConfirmedIdentityHasExpired" data.NewVoucherLabel = "iHaveSomeoneWhoCanVouch" - data.ProveOwnIDLabel = "iWillReturnToOneLogin" + data.ProveOwnIdentityLabel = "iWillReturnToOneLogin" if provided.IdentityUserData.VouchedFor { - data.ProveOwnIDLabel = "iWillGetOrFindID" + data.ProveOwnIdentityLabel = "iWillGetOrFindID" switch provided.FailedVouchAttempts { case 1: diff --git a/internal/donor/donorpage/what_you_can_do_now_expired_test.go b/internal/donor/donorpage/what_you_can_do_now_expired_test.go index 9a1033e3d8..6bbfecfe7e 100644 --- a/internal/donor/donorpage/what_you_can_do_now_expired_test.go +++ b/internal/donor/donorpage/what_you_can_do_now_expired_test.go @@ -20,30 +20,30 @@ import ( func TestGetWhatYouCanDoNowExpired(t *testing.T) { testcases := map[int]struct { - BannerContent string - NewVoucherLabel string - ProveOwnIDLabel string - CanHaveVoucher bool - VouchedForIdentity bool + BannerContent string + NewVoucherLabel string + ProveOwnIdentityLabel string + CanHaveVoucher bool + VouchedForIdentity bool }{ 0: { - BannerContent: "yourConfirmedIdentityHasExpired", - NewVoucherLabel: "iHaveSomeoneWhoCanVouch", - ProveOwnIDLabel: "iWillReturnToOneLogin", - CanHaveVoucher: true, + BannerContent: "yourConfirmedIdentityHasExpired", + NewVoucherLabel: "iHaveSomeoneWhoCanVouch", + ProveOwnIdentityLabel: "iWillReturnToOneLogin", + CanHaveVoucher: true, }, 1: { - BannerContent: "yourVouchedForIdentityHasExpired", - NewVoucherLabel: "iHaveSomeoneWhoCanVouch", - ProveOwnIDLabel: "iWillGetOrFindID", - CanHaveVoucher: true, - VouchedForIdentity: true, + BannerContent: "yourVouchedForIdentityHasExpired", + NewVoucherLabel: "iHaveSomeoneWhoCanVouch", + ProveOwnIdentityLabel: "iWillGetOrFindID", + CanHaveVoucher: true, + VouchedForIdentity: true, }, 2: { - BannerContent: "yourVouchedForIdentityHasExpiredSecondAttempt", - NewVoucherLabel: "iHaveSomeoneWhoCanVouch", - ProveOwnIDLabel: "iWillGetOrFindID", - VouchedForIdentity: true, + BannerContent: "yourVouchedForIdentityHasExpiredSecondAttempt", + NewVoucherLabel: "iHaveSomeoneWhoCanVouch", + ProveOwnIdentityLabel: "iWillGetOrFindID", + VouchedForIdentity: true, }, } @@ -60,10 +60,10 @@ func TestGetWhatYouCanDoNowExpired(t *testing.T) { Options: donordata.NoVoucherDecisionValues, CanHaveVoucher: tc.CanHaveVoucher, }, - FailedVouchAttempts: failedVouchAttempts, - BannerContent: tc.BannerContent, - NewVoucherLabel: tc.NewVoucherLabel, - ProveOwnIDLabel: tc.ProveOwnIDLabel, + FailedVouchAttempts: failedVouchAttempts, + BannerContent: tc.BannerContent, + NewVoucherLabel: tc.NewVoucherLabel, + ProveOwnIdentityLabel: tc.ProveOwnIdentityLabel, }). Return(nil) @@ -97,7 +97,7 @@ func TestPostWhatYouCanDoNowExpired(t *testing.T) { expectedPath string expectedDonor *donordata.Provided }{ - donordata.ProveOwnID: { + donordata.ProveOwnIdentity: { expectedPath: donor.PathTaskList.Format("lpa-id"), expectedDonor: &donordata.Provided{ LpaID: "lpa-id", diff --git a/internal/donor/donorpage/what_you_can_do_now_test.go b/internal/donor/donorpage/what_you_can_do_now_test.go index ece1a82059..1b258f458f 100644 --- a/internal/donor/donorpage/what_you_can_do_now_test.go +++ b/internal/donor/donorpage/what_you_can_do_now_test.go @@ -20,26 +20,26 @@ import ( func TestGetWhatYouCanDoNow(t *testing.T) { testcases := map[int]struct { - BannerContent string - NewVoucherLabel string - ProveOwnIDLabel string - CanHaveVoucher bool + BannerContent string + NewVoucherLabel string + ProveOwnIdentityLabel string + CanHaveVoucher bool }{ 0: { - BannerContent: "youHaveNotChosenAnyoneToVouchForYou", - NewVoucherLabel: "iHaveSomeoneWhoCanVouch", - ProveOwnIDLabel: "iWillReturnToOneLogin", - CanHaveVoucher: true, + BannerContent: "youHaveNotChosenAnyoneToVouchForYou", + NewVoucherLabel: "iHaveSomeoneWhoCanVouch", + ProveOwnIdentityLabel: "iWillReturnToOneLogin", + CanHaveVoucher: true, }, 1: { - BannerContent: "thePersonYouAskedToVouchHasBeenUnableToContinue", - NewVoucherLabel: "iHaveSomeoneElseWhoCanVouch", - ProveOwnIDLabel: "iWillGetOrFindID", - CanHaveVoucher: true, + BannerContent: "thePersonYouAskedToVouchHasBeenUnableToContinue", + NewVoucherLabel: "iHaveSomeoneElseWhoCanVouch", + ProveOwnIdentityLabel: "iWillGetOrFindID", + CanHaveVoucher: true, }, 2: { - BannerContent: "thePersonYouAskedToVouchHasBeenUnableToContinueSecondAttempt", - ProveOwnIDLabel: "iWillGetOrFindID", + BannerContent: "thePersonYouAskedToVouchHasBeenUnableToContinueSecondAttempt", + ProveOwnIdentityLabel: "iWillGetOrFindID", }, } @@ -56,10 +56,10 @@ func TestGetWhatYouCanDoNow(t *testing.T) { Options: donordata.NoVoucherDecisionValues, CanHaveVoucher: tc.CanHaveVoucher, }, - FailedVouchAttempts: failedVouchAttempts, - BannerContent: tc.BannerContent, - NewVoucherLabel: tc.NewVoucherLabel, - ProveOwnIDLabel: tc.ProveOwnIDLabel, + FailedVouchAttempts: failedVouchAttempts, + BannerContent: tc.BannerContent, + NewVoucherLabel: tc.NewVoucherLabel, + ProveOwnIdentityLabel: tc.ProveOwnIdentityLabel, }). Return(nil) @@ -68,7 +68,28 @@ func TestGetWhatYouCanDoNow(t *testing.T) { assert.Nil(t, err) }) } +} + +func TestGetWhatYouCanDoNowWhenChangingVoucher(t *testing.T) { + w := httptest.NewRecorder() + r := httptest.NewRequest(http.MethodGet, "/", nil) + + template := newMockTemplate(t) + template.EXPECT(). + Execute(w, &whatYouCanDoNowData{ + App: testAppData, + Form: &whatYouCanDoNowForm{ + Options: donordata.NoVoucherDecisionValues, + CanHaveVoucher: true, + }, + NewVoucherLabel: "iHaveSomeoneElseWhoCanVouch", + ProveOwnIdentityLabel: "iWillGetOrFindID", + }). + Return(nil) + err := WhatYouCanDoNow(template.Execute, nil)(testAppData, w, r, &donordata.Provided{Voucher: donordata.Voucher{Allowed: true}}) + + assert.Nil(t, err) } func TestGetWhatYouCanDoNowWhenTemplateError(t *testing.T) { @@ -90,7 +111,7 @@ func TestPostWhatYouCanDoNow(t *testing.T) { expectedPath string expectedDonor *donordata.Provided }{ - donordata.ProveOwnID: { + donordata.ProveOwnIdentity: { expectedPath: donor.PathTaskList.Format("lpa-id"), expectedDonor: &donordata.Provided{ LpaID: "lpa-id", @@ -147,6 +168,38 @@ func TestPostWhatYouCanDoNow(t *testing.T) { } } +func TestPostWhatYouCanDoNowWhenChangingVoucher(t *testing.T) { + f := url.Values{ + "do-next": {donordata.ApplyToCOP.String()}, + } + + w := httptest.NewRecorder() + r := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(f.Encode())) + r.Header.Add("Content-Type", page.FormUrlEncoded) + + donorStore := newMockDonorStore(t) + donorStore.EXPECT(). + Put(r.Context(), &donordata.Provided{ + LpaID: "lpa-id", + IdentityUserData: identity.UserData{Status: identity.StatusInsufficientEvidence}, + Voucher: donordata.Voucher{Allowed: true}, + }). + Return(nil) + + err := WhatYouCanDoNow(nil, donorStore)(testAppData, w, r, &donordata.Provided{ + LpaID: "lpa-id", + IdentityUserData: identity.UserData{Status: identity.StatusInsufficientEvidence}, + Voucher: donordata.Voucher{Allowed: true}, + }) + resp := w.Result() + + assert.Nil(t, err) + assert.Equal(t, http.StatusFound, resp.StatusCode) + assert.Equal(t, donor.PathAreYouSureYouNoLongerNeedVoucher.FormatQuery("lpa-id", url.Values{ + "choice": {donordata.ApplyToCOP.String()}, + }), resp.Header.Get("Location")) +} + func TestPostWhatYouCanDoNowWhenDonorStoreError(t *testing.T) { f := url.Values{ "do-next": {donordata.ApplyToCOP.String()}, diff --git a/internal/donor/path.go b/internal/donor/path.go index 0ade1bcdc4..b44eb596fc 100644 --- a/internal/donor/path.go +++ b/internal/donor/path.go @@ -13,6 +13,7 @@ const ( PathAboutPayment = Path("/about-payment") PathAddCorrespondent = Path("/add-correspondent") PathAreYouApplyingForFeeDiscountOrExemption = Path("/are-you-applying-for-fee-discount-or-exemption") + PathAreYouSureYouNoLongerNeedVoucher = Path("/are-you-sure-you-no-longer-need-voucher") PathBecauseYouHaveChosenJointly = Path("/because-you-have-chosen-jointly") PathBecauseYouHaveChosenJointlyForSomeSeverallyForOthers = Path("/because-you-have-chosen-jointly-for-some-severally-for-others") PathCanYouSignYourLpa = Path("/can-you-sign-your-lpa") @@ -98,6 +99,7 @@ const ( PathUseExistingAddress = Path("/use-existing-address") PathViewLPA = Path("/view-lpa") PathWeHaveContactedVoucher = Path("/we-have-contacted-voucher") + PathWeHaveInformedVoucherNoLongerNeeded = Path("/we-have-informed-voucher-no-longer-needed") PathWeHaveReceivedVoucherDetails = Path("/we-have-received-voucher-details") PathWeHaveUpdatedYourDetails = Path("/we-have-updated-your-details") PathWhatACertificateProviderDoes = Path("/what-a-certificate-provider-does") @@ -139,6 +141,10 @@ func (p Path) Format(id string) string { return "/lpa/" + id + string(p) } +func (p Path) FormatQuery(id string, query url.Values) string { + return p.Format(id) + "?" + query.Encode() +} + func (p Path) Redirect(w http.ResponseWriter, r *http.Request, appData appcontext.Data, donor *donordata.Provided) error { rurl := p.Format(donor.LpaID) if fromURL := r.FormValue("from"); fromURL != "" { @@ -150,7 +156,7 @@ func (p Path) Redirect(w http.ResponseWriter, r *http.Request, appData appcontex } func (p Path) RedirectQuery(w http.ResponseWriter, r *http.Request, appData appcontext.Data, donor *donordata.Provided, query url.Values) error { - rurl := p.Format(donor.LpaID) + "?" + query.Encode() + rurl := p.FormatQuery(donor.LpaID, query) if fromURL := r.FormValue("from"); fromURL != "" { rurl = fromURL } diff --git a/internal/donor/store.go b/internal/donor/store.go index 7b3b9f28b1..df38136074 100644 --- a/internal/donor/store.go +++ b/internal/donor/store.go @@ -458,3 +458,23 @@ func (s *Store) DeleteDonorAccess(ctx context.Context, shareCodeData sharecodeda return s.dynamoClient.WriteTransaction(ctx, transaction) } + +func (s *Store) DeleteVoucher(ctx context.Context, provided *donordata.Provided) error { + sessionData, err := appcontext.SessionFromContext(ctx) + if err != nil { + return err + } + + var link sharecodedata.Link + if err := s.dynamoClient.OneBySK(ctx, dynamo.VoucherShareSortKey(dynamo.LpaKey(sessionData.LpaID)), &link); err != nil { + return err + } + + provided.Voucher = donordata.Voucher{} + + transaction := dynamo.NewTransaction(). + Delete(dynamo.Keys{PK: link.PK, SK: link.SK}). + Put(provided) + + return s.dynamoClient.WriteTransaction(ctx, transaction) +} diff --git a/internal/donor/store_test.go b/internal/donor/store_test.go index f29dc4959e..6b73543b35 100644 --- a/internal/donor/store_test.go +++ b/internal/donor/store_test.go @@ -1029,3 +1029,56 @@ func TestDonorStoreDeleteDonorAccessWhenWriteTransactionError(t *testing.T) { err := donorStore.DeleteDonorAccess(ctx, sharecodedata.Link{LpaOwnerKey: dynamo.LpaOwnerKey(dynamo.OrganisationKey("org-id")), LpaKey: dynamo.LpaKey("lpa-id")}) assert.Error(t, err) } + +func TestDonorStoreDeleteVoucher(t *testing.T) { + ctx := appcontext.ContextWithSession(context.Background(), &appcontext.Session{SessionID: "an-id", LpaID: "lpa-id"}) + + dynamoClient := newMockDynamoClient(t) + dynamoClient. + ExpectOneBySK(ctx, dynamo.VoucherShareSortKey(dynamo.LpaKey("lpa-id")), + sharecodedata.Link{ + PK: dynamo.ShareKey(dynamo.VoucherShareKey("hey")), + SK: dynamo.ShareSortKey(dynamo.VoucherShareSortKey(dynamo.LpaKey("lpa-id"))), + }, nil) + dynamoClient.EXPECT(). + WriteTransaction(ctx, &dynamo.Transaction{ + Deletes: []dynamo.Keys{{ + PK: dynamo.ShareKey(dynamo.VoucherShareKey("hey")), + SK: dynamo.ShareSortKey(dynamo.VoucherShareSortKey(dynamo.LpaKey("lpa-id"))), + }}, + Puts: []any{ + &donordata.Provided{}, + }, + }). + Return(expectedError) + + donorStore := &Store{dynamoClient: dynamoClient} + + err := donorStore.DeleteVoucher(ctx, &donordata.Provided{ + Voucher: donordata.Voucher{FirstNames: "a"}, + }) + assert.Equal(t, expectedError, err) +} + +func TestDonorStoreDeleteVoucherWhenSessionMissing(t *testing.T) { + donorStore := &Store{} + + err := donorStore.DeleteVoucher(context.Background(), &donordata.Provided{}) + assert.Equal(t, appcontext.SessionMissingError{}, err) +} + +func TestDonorStoreDeleteVoucherWhenOneBySKErrors(t *testing.T) { + ctx := appcontext.ContextWithSession(context.Background(), &appcontext.Session{SessionID: "an-id", LpaID: "lpa-id"}) + + dynamoClient := newMockDynamoClient(t) + dynamoClient. + ExpectOneBySK(ctx, dynamo.VoucherShareSortKey(dynamo.LpaKey("lpa-id")), + sharecodedata.Link{}, expectedError) + + donorStore := &Store{dynamoClient: dynamoClient} + + err := donorStore.DeleteVoucher(ctx, &donordata.Provided{ + Voucher: donordata.Voucher{FirstNames: "a"}, + }) + assert.Equal(t, expectedError, err) +} diff --git a/internal/dynamo/keys.go b/internal/dynamo/keys.go index 538206ab0e..f3811368e2 100644 --- a/internal/dynamo/keys.go +++ b/internal/dynamo/keys.go @@ -23,6 +23,7 @@ const ( memberIDPrefix = "MEMBERID" voucherPrefix = "VOUCHER" metadataPrefix = "METADATA" + voucherShareSortPrefix = "VOUCHERSHARESORT" donorSharePrefix = "DONORSHARE" donorInvitePrefix = "DONORINVITE" certificateProviderSharePrefix = "CERTIFICATEPROVIDERSHARE" @@ -71,6 +72,8 @@ func readKey(s string) (any, error) { return MemberIDKeyType(s), nil case metadataPrefix: return MetadataKeyType(s), nil + case voucherShareSortPrefix: + return VoucherShareSortKeyType(s), nil case donorInvitePrefix: return DonorInviteKeyType(s), nil case voucherPrefix: @@ -220,11 +223,23 @@ type MetadataKeyType string func (t MetadataKeyType) SK() string { return string(t) } func (t MetadataKeyType) shareSort() {} // mark as usable with ShareSortKey -// MetadataKey is used as the SK when the value of the SK is not used for any purpose. +// Metadata is used as the SK when the value of the SK is not used for any +// purpose. func MetadataKey(s string) MetadataKeyType { return MetadataKeyType(metadataPrefix + "#" + s) } +type VoucherShareSortKeyType string + +func (t VoucherShareSortKeyType) SK() string { return string(t) } +func (t VoucherShareSortKeyType) shareSort() {} // mark as usable with ShareSortKey + +// VoucherShareSortKey is used as the SK (with ShareKey as PK) for sharing an Lpa +// with an actor. +func VoucherShareSortKey(lpa LpaKeyType) VoucherShareSortKeyType { + return VoucherShareSortKeyType(voucherShareSortPrefix + "#" + lpa.ID()) +} + type DonorShareKeyType string func (t DonorShareKeyType) PK() string { return string(t) } diff --git a/internal/dynamo/keys_test.go b/internal/dynamo/keys_test.go index 73bd013a6b..1a423a5b20 100644 --- a/internal/dynamo/keys_test.go +++ b/internal/dynamo/keys_test.go @@ -80,6 +80,7 @@ func TestSK(t *testing.T) { "MemberIDKey": {MemberIDKey("S"), "MEMBERID#S"}, "OrganisationKey": {OrganisationKey("S"), "ORGANISATION#S"}, "MetadataKey": {MetadataKey("S"), "METADATA#S"}, + "VoucherShareSortKey": {VoucherShareSortKey(LpaKey("S")), "VOUCHERSHARESORT#S"}, "DonorInviteKey": {DonorInviteKey(OrganisationKey("org-id"), LpaKey("lpa-id")), "DONORINVITE#org-id#lpa-id"}, "VoucherKey": {VoucherKey("S"), "VOUCHER#S"}, "ScheduledKey": {ScheduledKey(time.Date(2024, time.January, 2, 12, 13, 14, 15, time.UTC), 99), "SCHEDULED#2024-01-02T12:13:14Z#99"}, @@ -117,13 +118,21 @@ func TestLpaOwnerKeyTypes(t *testing.T) { } func TestShareKeyTypes(t *testing.T) { - for _, key := range []interface{ share() }{DonorShareKey("hey"), CertificateProviderShareKey("what"), AttorneyShareKey("hello")} { + for _, key := range []interface{ share() }{ + DonorShareKey("hey"), + CertificateProviderShareKey("what"), + AttorneyShareKey("hello"), + } { key.share() } } func TestShareSortKeyTypes(t *testing.T) { - for _, key := range []interface{ shareSort() }{MetadataKey("hey"), DonorInviteKey(OrganisationKey("what"), LpaKey("hello"))} { + for _, key := range []interface{ shareSort() }{ + MetadataKey("hey"), + DonorInviteKey(OrganisationKey("what"), LpaKey("hello")), + VoucherShareSortKey(LpaKey("hi")), + } { key.shareSort() } } diff --git a/internal/page/fixtures/fixtures.go b/internal/page/fixtures/fixtures.go index 46c1adfa42..dcd47d36d4 100644 --- a/internal/page/fixtures/fixtures.go +++ b/internal/page/fixtures/fixtures.go @@ -278,6 +278,7 @@ func createVoucher(ctx context.Context, shareCodeStore ShareCodeStore, voucherSt SK: dynamo.ShareSortKey(dynamo.MetadataKey(shareCode)), ActorUID: donor.Voucher.UID, LpaOwnerKey: donor.SK, + LpaKey: donor.PK, } err := shareCodeStore.Put(ctx, actor.TypeVoucher, shareCode, shareCodeData) diff --git a/internal/sharecode/store.go b/internal/sharecode/store.go index a0aee2d767..5d98bd0e0a 100644 --- a/internal/sharecode/store.go +++ b/internal/sharecode/store.go @@ -55,7 +55,11 @@ func (s *Store) Put(ctx context.Context, actorType actor.Type, shareCode string, } data.PK = pk - data.SK = dynamo.ShareSortKey(dynamo.MetadataKey(shareCode)) + if actorType.IsVoucher() { + data.SK = dynamo.ShareSortKey(dynamo.VoucherShareSortKey(data.LpaKey)) + } else { + data.SK = dynamo.ShareSortKey(dynamo.MetadataKey(shareCode)) + } return s.dynamoClient.Put(ctx, data) } diff --git a/internal/sharecode/store_test.go b/internal/sharecode/store_test.go index d75f1b5662..34845149cb 100644 --- a/internal/sharecode/store_test.go +++ b/internal/sharecode/store_test.go @@ -10,7 +10,7 @@ import ( "github.com/ministryofjustice/opg-modernising-lpa/internal/actor" "github.com/ministryofjustice/opg-modernising-lpa/internal/appcontext" "github.com/ministryofjustice/opg-modernising-lpa/internal/dynamo" - sharecodedata "github.com/ministryofjustice/opg-modernising-lpa/internal/sharecode/sharecodedata" + "github.com/ministryofjustice/opg-modernising-lpa/internal/sharecode/sharecodedata" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) @@ -126,29 +126,34 @@ func TestShareCodeStorePut(t *testing.T) { testcases := map[string]struct { actor actor.Type pk dynamo.ShareKeyType + sk dynamo.ShareSortKeyType }{ "attorney": { actor: actor.TypeAttorney, pk: dynamo.ShareKey(dynamo.AttorneyShareKey("123")), + sk: dynamo.ShareSortKey(dynamo.MetadataKey("123")), }, "replacement attorney": { actor: actor.TypeReplacementAttorney, pk: dynamo.ShareKey(dynamo.AttorneyShareKey("123")), + sk: dynamo.ShareSortKey(dynamo.MetadataKey("123")), }, "certificate provider": { actor: actor.TypeCertificateProvider, pk: dynamo.ShareKey(dynamo.CertificateProviderShareKey("123")), + sk: dynamo.ShareSortKey(dynamo.MetadataKey("123")), }, "voucher": { actor: actor.TypeVoucher, pk: dynamo.ShareKey(dynamo.VoucherShareKey("123")), + sk: dynamo.ShareSortKey(dynamo.VoucherShareSortKey("lpa-id")), }, } for name, tc := range testcases { t.Run(name, func(t *testing.T) { ctx := context.Background() - data := sharecodedata.Link{PK: tc.pk, SK: dynamo.ShareSortKey(dynamo.MetadataKey("123")), LpaKey: "lpa-id"} + data := sharecodedata.Link{PK: tc.pk, SK: tc.sk, LpaKey: "lpa-id"} dynamoClient := newMockDynamoClient(t) dynamoClient.EXPECT(). diff --git a/lang/cy.json b/lang/cy.json index c1c4d928c8..a0ee0cc47a 100644 --- a/lang/cy.json +++ b/lang/cy.json @@ -1261,8 +1261,10 @@ "yesIKnowSomeone": "Oes, rydw i’n adnabod rhywun ac maen nhw wedi cytuno i dystio drosof i", "noIDoNotKnowSomeone": "Nac oes, dydw i ddim yn adnabod neb arall all dystio drostaf", "yesIfHaveSomeoneCanVouchForYou": "oes, os ydych chi’n adnabod rhywun a’u bod wedi cytuno i dystio drosoch chi", - "weHaveContactedVoucher": "Rydym wedi cysylltu â’r unigolyn yr hoffech iddynt dystio drosoch chi.", + "weHaveContactedVoucherTitle": "Welsh", + "weHaveContactedVoucher": "Welsh {{.VoucherFullName}}", "weHaveContactedVoucherContent": "", + "voucherWhatHappensNextBullets": "
  • Welsh {{.VoucherFullName}} {{.VoucherFullName}}
  • ", "registerYourLpaThroughCOPContent": "

    Welsh

    ", "registerYourLpaThroughCOPWarning": "Mae’n costio £371 i gofrestru eich LPA drwy’r Llys Gwarchod a bydd yn cymryd sawl mis.", "whatWouldYouLikeToDo": "Beth fyddech chi’n hoffi ei wneud?", @@ -1447,5 +1449,21 @@ "youCanTrackTheProgressAnyTime": "Welsh", "wellThenContactYouAboutGettingReviewed": "Welsh", "howToSignYourLpa": "Welsh", - "howToSignYourLpaIntro": "Welsh {{.CertificateProviderFullName}}." + "howToSignYourLpaIntro": "Welsh {{.CertificateProviderFullName}}.", + "weAreProcessingFeeWhenResolvedWillContactVoucher": "Welsh {{.VoucherFullName}}.", + "confirmYourIdentityAnotherWay": "Welsh", + "confirmYourIdentityAnotherWayContent": "

    Welsh {{.VoucherFullName}} {{.VoucherFullName}}

    ", + "weWillContactVoucher": "Welsh {{.VoucherFullName}}", + "theirName": "Welsh", + "theirEmailAddress": "Welsh", + "confirmMyIdentityAnotherWay": "Welsh", + "areYouSureYouNoLongerNeedVoucherTitle": "Welsh", + "areYouSureYouNoLongerNeedVoucher": "Welsh {{.VoucherFullName}}", + "weWillInformVoucherTheyNoLongerNeedTo": "Welsh {{.VoucherFullName}}", + "voucherNoLongerNeeded": "Welsh {{.VoucherFullName}}", + "weHaveInformedVoucherTheyNoLongerNeedTo": "Welsh {{.VoucherFullName}}", + "youHaveChosen:prove-own-identity": "Welsh", + "youHaveChosen:select-new-voucher": "Welsh", + "youHaveChosen:withdraw-lpa": "Welsh", + "youHaveChosen:apply-to-cop": "Welsh" } diff --git a/lang/en.json b/lang/en.json index 64552552da..0e55051ee7 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1181,8 +1181,10 @@ "yesIKnowSomeone": "Yes, I know someone and they have agreed to vouch for me", "noIDoNotKnowSomeone": "No, I do not know someone who can vouch for me", "yesIfHaveSomeoneCanVouchForYou": "yes if you know someone and they have agreed to vouch for you", - "weHaveContactedVoucher": "We have contacted the person you would like to vouch for you.", + "weHaveContactedVoucherTitle": "We have contacted the person you want to vouch for your identity", + "weHaveContactedVoucher": "We have contacted {{.VoucherFullName}} to confirm your identity", "weHaveContactedVoucherContent": "", + "voucherWhatHappensNextBullets": "
  • We’ll send you a code you’ll need to give {{.VoucherFullName}}.
  • {{.VoucherFullName}} can use the code to log into the vouching service and confirm your identity.
  • In the meantime, you can return to your task list to sign your LPA.
  • ", "registerYourLpaThroughCOPContent": "

    The Office of the Public Guardian (OPG) will not be able to register this LPA because you have been unable to confirm your identity.

    You can now either:

    Register your LPA through the Court of Protection

    You can apply to the Court of Protection to register your LPA without completing an ID check.

    ", "registerYourLpaThroughCOPWarning": "It costs £371 to register your LPA through the Court of Protection and will take several months.", "whatWouldYouLikeToDo": "What would you like to do?", @@ -1364,5 +1366,21 @@ "youCanTrackTheProgressAnyTime": "You can track the progress of your LPA at any time.", "wellThenContactYouAboutGettingReviewed": "We’ll then contact you with guidance about getting your LPA reviewed by the Court of Protection.", "howToSignYourLpa": "How to sign your LPA", - "howToSignYourLpaIntro": "There are 2 parts to signing your LPA. These must be completed in a single sitting, in the presence of {{.CertificateProviderFullName}}." + "howToSignYourLpaIntro": "There are 2 parts to signing your LPA. These must be completed in a single sitting, in the presence of {{.CertificateProviderFullName}}.", + "weAreProcessingFeeWhenResolvedWillContactVoucher": "We are processing your LPA fee request – when this is resolved, we’ll contact {{.VoucherFullName}}.", + "confirmYourIdentityAnotherWay": "Confirm your identity another way", + "confirmYourIdentityAnotherWayContent": "

    If you have changed your mind about asking {{.VoucherFullName}} to confirm your identity, you can:

    We will inform {{.VoucherFullName}} they no longer need to confirm your identity. The one-time code allowing them to log into the vouching service will be cancelled.

    ", + "weWillContactVoucher": "We will contact {{.VoucherFullName}} to confirm your identity", + "theirName": "Their name", + "theirEmailAddress": "Their email address", + "confirmMyIdentityAnotherWay": "Confirm my identity another way", + "areYouSureYouNoLongerNeedVoucherTitle": "Are you sure you no longer need someone to confirm your identity", + "areYouSureYouNoLongerNeedVoucher": "Are you sure you no longer need {{.VoucherFullName}} to confirm your identity?", + "weWillInformVoucherTheyNoLongerNeedTo": "We will inform {{.VoucherFullName}} they no longer need to confirm your identity. The one-time code allowing them to log into the vouching service will be cancelled.", + "voucherNoLongerNeeded": "{{.VoucherFullName}} no longer needed", + "weHaveInformedVoucherTheyNoLongerNeedTo": "We have informed {{.VoucherFullName}} they no longer need to confirm your identity.", + "youHaveChosen:prove-own-identity": "You have chosen to find, replace or get new ID documents and confirm your identity using GOV.UK One Login.", + "youHaveChosen:select-new-voucher": "You have chosen to ask someone else to confirm your identity by vouching for you.", + "youHaveChosen:withdraw-lpa": "You have told us you no longer want to make this LPA.", + "youHaveChosen:apply-to-cop": "You have chosen to have your LPA reviewed by the Court of Protection." } diff --git a/web/template/donor/are_you_sure_you_no_longer_need_voucher.gohtml b/web/template/donor/are_you_sure_you_no_longer_need_voucher.gohtml new file mode 100644 index 0000000000..ec7437d1f4 --- /dev/null +++ b/web/template/donor/are_you_sure_you_no_longer_need_voucher.gohtml @@ -0,0 +1,18 @@ +{{ template "page" . }} + +{{ define "pageTitle" }}{{ tr .App "areYouSureYouNoLongerNeedVoucherTitle" }}{{ end }} + +{{ define "main" }} +
    +
    +

    {{ trFormat .App "areYouSureYouNoLongerNeedVoucher" "VoucherFullName" .Donor.Voucher.FullName }}

    + +

    {{ trFormat .App "weWillInformVoucherTheyNoLongerNeedTo" "VoucherFullName" .Donor.Voucher.FullName }}

    + +
    + {{ template "buttons" (button .App (trFormat .App "voucherNoLongerNeeded" "VoucherFullName" .Donor.Voucher.FullName) "warning" true) }} + {{ template "csrf-field" . }} +
    +
    +
    +{{ end }} diff --git a/web/template/donor/we_have_contacted_voucher.gohtml b/web/template/donor/we_have_contacted_voucher.gohtml index 9a1bb2bf11..4accc9f2c4 100644 --- a/web/template/donor/we_have_contacted_voucher.gohtml +++ b/web/template/donor/we_have_contacted_voucher.gohtml @@ -1,24 +1,47 @@ {{ template "page" . }} -{{ define "pageTitle" }}{{ tr .App "whatHappensNext" }}{{ end }} +{{ define "pageTitle" }}{{ tr .App "weHaveContactedVoucherTitle" }}{{ end }} {{ define "main" }} -
    -
    - {{ template "notification-banner" (notificationBanner .App "success" (trHtml .App "weHaveContactedVoucher") "success" "heading") }} +
    +
    +

    + {{ if .Donor.Tasks.PayForLpa.IsPending }} + {{ trFormat .App "weWillContactVoucher" "VoucherFullName" .Donor.Voucher.FullName }} + {{ else }} + {{ trFormat .App "weHaveContactedVoucher" "VoucherFullName" .Donor.Voucher.FullName }} + {{ end }} +

    -

    {{ tr .App "whatHappensNext" }}

    +
    +
    +
    +
    {{ tr .App "theirName" }}
    +
    {{ tr .App .Donor.Voucher.FullName }}
    +
    +
    +
    {{ tr .App "theirEmailAddress" }}
    +
    {{ tr .App .Donor.Voucher.Email }}
    +
    +
    +
    - {{ $contactType := "anEmail" }} - {{ if .Donor.Donor.Mobile }} - {{ $contactType = "aTextMessage" }} - {{ end }} +

    {{ tr .App "whatHappensNext" }}

    - {{ trFormatHtml .App "weHaveContactedVoucherContent" "ContactType" ( tr .App $contactType ) }} +
      + {{ if .Donor.Tasks.PayForLpa.IsPending }} +
    1. {{ tr .App "weAreProcessingFeeWhenResolvedWillContactVoucher" }}
    2. + {{ end }} + + {{ trFormatHtml .App "voucherWhatHappensNextBullets" "VoucherFullName" .Donor.Voucher.FullName }} +
    - + {{ template "details" (details . "confirmYourIdentityAnotherWay" (trFormat .App "confirmYourIdentityAnotherWayContent" "VoucherFullName" .Donor.Voucher.FullName) false) }} + + +
    -
    {{ end }} diff --git a/web/template/donor/we_have_informed_voucher_no_longer_needed.gohtml b/web/template/donor/we_have_informed_voucher_no_longer_needed.gohtml new file mode 100644 index 0000000000..2c1b8a5540 --- /dev/null +++ b/web/template/donor/we_have_informed_voucher_no_longer_needed.gohtml @@ -0,0 +1,17 @@ +{{ template "page" . }} + +{{ define "pageTitle" }}{{ tr .App "weHaveInformedThePersonYouWantedToVouchForYouTheyAreNoLongerNeeded" }}{{ end }} + +{{ define "main" }} +
    +
    + {{ template "notification-banner" (notificationBanner .App "success" (trFormatHtml .App "weHaveInformedVoucherTheyNoLongerNeedTo" "VoucherFullName" (.App.Query.Get "voucherFullName")) "success" "heading") }} + +

    {{ tr .App "whatHappensNext" }}

    + +

    {{ trFormat .App (printf "youHaveChosen:%s" (.App.Query.Get "choice")) }}

    + + {{ template "buttons" (button .App "continue" "link" (.App.Query.Get "next")) }} +
    +
    +{{ end }} diff --git a/web/template/donor/what_you_can_do_now.gohtml b/web/template/donor/what_you_can_do_now.gohtml index d787a8d8f5..7e25e141ab 100644 --- a/web/template/donor/what_you_can_do_now.gohtml +++ b/web/template/donor/what_you_can_do_now.gohtml @@ -5,7 +5,9 @@ {{ define "main" }}
    - {{ template "notification-banner" ( notificationBanner .App "important" (trHtml .App .BannerContent) "contents" "1" ) }} + {{ if .BannerContent }} + {{ template "notification-banner" ( notificationBanner .App "important" (trHtml .App .BannerContent) "contents" "1" ) }} + {{ end }}

    {{ tr .App "whatYouCanDoNow" }}

    @@ -25,14 +27,14 @@ {{ if .Form.CanHaveVoucher }} {{ template "radios" (items . "do-next" "" - (item .Form.Options.ProveOwnID.String .ProveOwnIDLabel) + (item .Form.Options.ProveOwnIdentity.String .ProveOwnIdentityLabel) (item .Form.Options.SelectNewVoucher.String .NewVoucherLabel) (item .Form.Options.WithdrawLPA.String "iNoLongerWantToMakeThisLPA" "hint" "iUnderstandIWillNotGetRefundHint" "orDivider" "1") (item .Form.Options.ApplyToCOP.String "iWillApplyToCOPToRegister" "hint" "iUnderstandICannotChangeMyMind") ) }} {{ else }} {{ template "radios" (items . "do-next" "" - (item .Form.Options.ProveOwnID.String .ProveOwnIDLabel) + (item .Form.Options.ProveOwnIdentity.String .ProveOwnIdentityLabel) (item .Form.Options.WithdrawLPA.String "iNoLongerWantToMakeThisLPA" "hint" "iUnderstandIWillNotGetRefundHint" "orDivider" "1") (item .Form.Options.ApplyToCOP.String "iWillApplyToCOPToRegister" "hint" "iUnderstandICannotChangeMyMind") ) }} diff --git a/web/template/donor/what_you_can_do_now_expired.gohtml b/web/template/donor/what_you_can_do_now_expired.gohtml index 8b393015d9..9bcfe2b9fe 100644 --- a/web/template/donor/what_you_can_do_now_expired.gohtml +++ b/web/template/donor/what_you_can_do_now_expired.gohtml @@ -31,14 +31,14 @@ {{ if .Form.CanHaveVoucher }} {{ template "radios" (items . "do-next" "" - (item .Form.Options.ProveOwnID.String .ProveOwnIDLabel) + (item .Form.Options.ProveOwnIdentity.String .ProveOwnIdentityLabel) (item .Form.Options.SelectNewVoucher.String .NewVoucherLabel) (item .Form.Options.WithdrawLPA.String "iNoLongerWantToMakeThisLPA" "hint" "iUnderstandIWillNotGetRefundHint" "orDivider" "1") (item .Form.Options.ApplyToCOP.String "iWillApplyToCOPToRegister" "hint" "iUnderstandICannotChangeMyMind") ) }} {{ else }} {{ template "radios" (items . "do-next" "" - (item .Form.Options.ProveOwnID.String .ProveOwnIDLabel) + (item .Form.Options.ProveOwnIdentity.String .ProveOwnIdentityLabel) (item .Form.Options.WithdrawLPA.String "iNoLongerWantToMakeThisLPA" "hint" "iUnderstandIWillNotGetRefundHint" "orDivider" "1") (item .Form.Options.ApplyToCOP.String "iWillApplyToCOPToRegister" "hint" "iUnderstandICannotChangeMyMind") ) }} diff --git a/web/template/layout/buttons.gohtml b/web/template/layout/buttons.gohtml index 502851ed20..0ffdd86399 100644 --- a/web/template/layout/buttons.gohtml +++ b/web/template/layout/buttons.gohtml @@ -15,9 +15,9 @@
    {{ if .link }} - {{ tr .app .label }} + {{ tr .app .label }} {{ else }} - + {{ end }} {{ tr .app "returnToTaskList" }}
    From 071e95d6ae512695cbb9a58072edcd634d1f7f41 Mon Sep 17 00:00:00 2001 From: Joshua Hawxwell Date: Wed, 30 Oct 2024 10:45:48 +0000 Subject: [PATCH 2/3] Remove unused translation key (again) --- lang/cy.json | 1 - lang/en.json | 1 - 2 files changed, 2 deletions(-) diff --git a/lang/cy.json b/lang/cy.json index a0ee0cc47a..1ebb44b598 100644 --- a/lang/cy.json +++ b/lang/cy.json @@ -1381,7 +1381,6 @@ "youHaveToldUsDetailsDoNotMatchIdentity": "Welsh {{.DonorFullName}}", "youHaveToldUsDetailsDoNotMatchIdentityContent": "

    Rydym wedi cysylltu â {{.DonorFirstNames}} i roi gwybod iddynt. Does dim angen i chi wneud unrhyw beth arall.

    Gallwch gau’r ffenestr bori hon nawr.

    ", "voucherConfirmYourIdentityIntro": "Welsh {{.DonorFullName}}", - "voucherConfirmYourIdentityContent": "

    Welsh {{.DonorFullName}}

    ", "voucherUnableToConfirmIdentityContent": "

    Mae hyn yn golygu nad ydych chi’n gallu tystio dros {{.DonorFullName}}. Rydyn ni wedi cysylltu â {{.DonorFirstNames}} i roi gwybod iddyn nhw.

    Nid oes angen i chi wneud unrhyw beth arall.

    Gallwch gau’r ffenestr bori hon nawr.

    ", "yourDeclaration": "Eich datganiad", "yourDeclarationContent": "

    Welsh {{.DonorFullName}} {{.DonorFirstNames}} {{.DonorFirstNames}} {{.DonorFirstNames}}

    ", diff --git a/lang/en.json b/lang/en.json index 0e55051ee7..9b53bff022 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1298,7 +1298,6 @@ "youHaveToldUsDetailsDoNotMatchIdentity": "You have told us that the details do not match {{possessive .DonorFullName}} identity.", "youHaveToldUsDetailsDoNotMatchIdentityContent": "

    We have contacted {{.DonorFirstNames}} to let them know. You do not need to do anything else.

    You can now close this browsing window.

    ", "voucherConfirmYourIdentityIntro": "Before you can confirm {{possessive .DonorFullName}} identity, you must confirm your own identity.", - "voucherConfirmYourIdentityContent": "

    English {{.DonorFullName}}

    ", "voucherUnableToConfirmIdentityContent": "

    This means you cannot vouch for {{.DonorFullName}}. We have contacted {{.DonorFirstNames}} to let them know.

    You do not need to do anything else.

    You can now close this browsing window.

    ", "yourDeclaration": "Your declaration", "yourDeclarationContent": "

    Sign your declaration to vouch for {{possessive .DonorFullName}} identity.

    By signing this declaration, I confirm all of the following:

    • I am over 18
    • I am allowed to vouch for {{.DonorFirstNames}}
    • I am not a person named on {{possessive .DonorFirstNames}} LPA
    • I am not in a relationship with, related to or living with {{.DonorFirstNames}}
    • the identity details match my understanding of the person who asked me to vouch for them
    ", From 2199b1f6d84934367af63bdcd5864f64bc9cdce5 Mon Sep 17 00:00:00 2001 From: Joshua Hawxwell Date: Thu, 31 Oct 2024 08:23:19 +0000 Subject: [PATCH 3/3] Use the correct page when fee hasn't been paid --- cypress/e2e/donor/check-your-details.cy.js | 4 +-- .../donor/donorpage/check_your_details.go | 10 +++---- .../donorpage/check_your_details_test.go | 2 +- internal/donor/donorpage/register.go | 2 -- internal/donor/path.go | 1 - internal/templatefn/paths.go | 2 -- lang/cy.json | 2 -- lang/en.json | 2 -- .../donor/we_have_contacted_voucher.gohtml | 10 +++---- .../we_have_received_voucher_details.gohtml | 28 ------------------- 10 files changed, 12 insertions(+), 51 deletions(-) delete mode 100644 web/template/donor/we_have_received_voucher_details.gohtml diff --git a/cypress/e2e/donor/check-your-details.cy.js b/cypress/e2e/donor/check-your-details.cy.js index a301b1db41..f4b9a632b3 100644 --- a/cypress/e2e/donor/check-your-details.cy.js +++ b/cypress/e2e/donor/check-your-details.cy.js @@ -21,8 +21,8 @@ describe('Check your details', () => { cy.visit('/fixtures?redirect=/check-your-details&progress=payForTheLpa&feeType=NoFee&paymentTaskProgress=Pending'); cy.contains('button', 'Continue').click(); - cy.url().should('contain', '/we-have-received-voucher-details'); + cy.url().should('contain', '/we-have-contacted-voucher'); cy.checkA11yApp(); - cy.contains('no fee (exemption)'); + cy.contains('We are processing your LPA fee request'); }); }); diff --git a/internal/donor/donorpage/check_your_details.go b/internal/donor/donorpage/check_your_details.go index 2c58bf2740..c0aa09df6b 100644 --- a/internal/donor/donorpage/check_your_details.go +++ b/internal/donor/donorpage/check_your_details.go @@ -19,12 +19,10 @@ type checkYourDetailsData struct { func CheckYourDetails(tmpl template.Template, shareCodeSender ShareCodeSender) Handler { return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, provided *donordata.Provided) error { if r.Method == http.MethodPost { - if !provided.Tasks.PayForLpa.IsCompleted() { - return donor.PathWeHaveReceivedVoucherDetails.Redirect(w, r, appData, provided) - } - - if err := shareCodeSender.SendVoucherAccessCode(r.Context(), provided, appData); err != nil { - return err + if provided.Tasks.PayForLpa.IsCompleted() { + if err := shareCodeSender.SendVoucherAccessCode(r.Context(), provided, appData); err != nil { + return err + } } return donor.PathWeHaveContactedVoucher.Redirect(w, r, appData, provided) diff --git a/internal/donor/donorpage/check_your_details_test.go b/internal/donor/donorpage/check_your_details_test.go index bcdfcebc70..7d227bf2ac 100644 --- a/internal/donor/donorpage/check_your_details_test.go +++ b/internal/donor/donorpage/check_your_details_test.go @@ -76,7 +76,7 @@ func TestPostCheckYourDetailsWhenUnpaid(t *testing.T) { assert.Nil(t, err) assert.Equal(t, http.StatusFound, resp.StatusCode) - assert.Equal(t, donor.PathWeHaveReceivedVoucherDetails.Format("lpa-id"), resp.Header.Get("Location")) + assert.Equal(t, donor.PathWeHaveContactedVoucher.Format("lpa-id"), resp.Header.Get("Location")) } func TestPostCheckYourDetailsWhenShareCodeStoreError(t *testing.T) { diff --git a/internal/donor/donorpage/register.go b/internal/donor/donorpage/register.go index 780077b9aa..cdef95579a 100644 --- a/internal/donor/donorpage/register.go +++ b/internal/donor/donorpage/register.go @@ -410,8 +410,6 @@ func Register( ConfirmPersonAllowedToVouch(tmpls.Get("confirm_person_allowed_to_vouch.gohtml"), donorStore)) handleWithDonor(donor.PathCheckYourDetails, page.CanGoBack, CheckYourDetails(tmpls.Get("check_your_details.gohtml"), shareCodeSender)) - handleWithDonor(donor.PathWeHaveReceivedVoucherDetails, page.None, - Guidance(tmpls.Get("we_have_received_voucher_details.gohtml"))) handleWithDonor(donor.PathWeHaveContactedVoucher, page.None, Guidance(tmpls.Get("we_have_contacted_voucher.gohtml"))) handleWithDonor(donor.PathWhatYouCanDoNow, page.CanGoBack, diff --git a/internal/donor/path.go b/internal/donor/path.go index b44eb596fc..155f262a87 100644 --- a/internal/donor/path.go +++ b/internal/donor/path.go @@ -100,7 +100,6 @@ const ( PathViewLPA = Path("/view-lpa") PathWeHaveContactedVoucher = Path("/we-have-contacted-voucher") PathWeHaveInformedVoucherNoLongerNeeded = Path("/we-have-informed-voucher-no-longer-needed") - PathWeHaveReceivedVoucherDetails = Path("/we-have-received-voucher-details") PathWeHaveUpdatedYourDetails = Path("/we-have-updated-your-details") PathWhatACertificateProviderDoes = Path("/what-a-certificate-provider-does") PathWhatHappensNextPostEvidence = Path("/what-happens-next-post-evidence") diff --git a/internal/templatefn/paths.go b/internal/templatefn/paths.go index 9d5a4261c6..8b8a292779 100644 --- a/internal/templatefn/paths.go +++ b/internal/templatefn/paths.go @@ -215,7 +215,6 @@ type appPaths struct { UseExistingAddress donor.Path ViewLPA donor.Path WeHaveContactedVoucher donor.Path - WeHaveReceivedVoucherDetails donor.Path WeHaveUpdatedYourDetails donor.Path WhatACertificateProviderDoes donor.Path WhatHappensNextPostEvidence donor.Path @@ -444,7 +443,6 @@ var paths = appPaths{ UseExistingAddress: donor.PathUseExistingAddress, ViewLPA: donor.PathViewLPA, WeHaveContactedVoucher: donor.PathWeHaveContactedVoucher, - WeHaveReceivedVoucherDetails: donor.PathWeHaveReceivedVoucherDetails, WeHaveUpdatedYourDetails: donor.PathWeHaveUpdatedYourDetails, WhatACertificateProviderDoes: donor.PathWhatACertificateProviderDoes, WhatHappensNextPostEvidence: donor.PathWhatHappensNextPostEvidence, diff --git a/lang/cy.json b/lang/cy.json index 1ebb44b598..873a1874cc 100644 --- a/lang/cy.json +++ b/lang/cy.json @@ -1249,8 +1249,6 @@ "checkYourDetailsAreCorrectBeforeYouContinue": "Cadarnhewch fod eich manylion yn gywir cyn parhau.", "youHaveBeenUnableToConfirmYourIdentity": "Dydych chi ddim wedi gallu cadarnhau pwy ydych chi drwy ddefnyddio GOV.UK One Login.", "vouchingLandingPageContent": "

    Mae angen i chi gadarnhau pwy ydych chi cyn y gall Swyddfa’r Gwarcheidwad Cyhoeddus gofrestru eich atwrneiaeth arhosol.

    Gallwch naill ai:

    • mynd yn ôl i GOV.UK One Login a cheisio cadarnhau pwy ydych chi eto
    • gofyn i rywun rydych chi’n ei adnabod gadarnhau pwy ydych chi drwy dystio drosoch chi

    Bwrw ymlaen i gael gwybodaeth am dystio dros rywun a phwy sy’n cael cadarnhau pwy ydych chi.

    ", - "weHaveReceivedDetailsOfVoucher": "Rydym wedi derbyn manylion yr unigolyn yr hoffech iddynt dystio drosoch chi.", - "weHaveReceivedDetailsOfVoucherContent": "
    • Byddwn yn cysylltu â’r unigolyn sy’n tystio drosoch chi ar ôl i’ch cais am {{.FeeType}} gael ei ddatrys
    • Pan fyddwn yn cysylltu â’r unigolyn sy’n tystio drosoch chi, byddwn yn anfon cod atoch chi drwy neges testun/e-bost
    • Rhaid i chi roi’r cod hwn i’r unigolyn sy’n tystio drosoch chi, er mwyn iddyn nhw allu cwblhau eu tasgau
    • Gallwch fwrw ymlaen i lofnodi eich LPA
    ", "payingNoFee": "talu dim ffi (esemptiad)", "payingHalfFee": "talu hanner ffi (gostyngiad)", "aRepeatApplicationDiscount": "disgownt am ail gais", diff --git a/lang/en.json b/lang/en.json index 9b53bff022..fab65305c0 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1169,8 +1169,6 @@ "checkYourDetailsAreCorrectBeforeYouContinue": "Check your details are correct before you continue.", "youHaveBeenUnableToConfirmYourIdentity": "You were not able to confirm your identity using GOV.UK One Login.", "vouchingLandingPageContent": "

    You can confirm your identity by asking someone you know well to vouch for you. The person you ask must be able to confirm their own identity using GOV.UK One Login.

    The Office of the Public Guardian (OPG) will not be able to register your LPA until you have confirmed your identity.

    ", - "weHaveReceivedDetailsOfVoucher": "We have received the details of the person you would like to vouch for you.", - "weHaveReceivedDetailsOfVoucherContent": "
    • We will contact the person vouching for you once your request for {{.FeeType}} is resolved
    • When we contact the person vouching for you, we will send you a code by text/email
    • You must give this code to the person vouching for you, so that they can complete their tasks
    • You can continue to sign your LPA
    ", "payingNoFee": "paying no fee (exemption)", "payingHalfFee": "paying a half fee (remission)", "aRepeatApplicationDiscount": "a repeat application discount", diff --git a/web/template/donor/we_have_contacted_voucher.gohtml b/web/template/donor/we_have_contacted_voucher.gohtml index 4accc9f2c4..db62fd9207 100644 --- a/web/template/donor/we_have_contacted_voucher.gohtml +++ b/web/template/donor/we_have_contacted_voucher.gohtml @@ -6,10 +6,10 @@

    - {{ if .Donor.Tasks.PayForLpa.IsPending }} - {{ trFormat .App "weWillContactVoucher" "VoucherFullName" .Donor.Voucher.FullName }} - {{ else }} + {{ if .Donor.Tasks.PayForLpa.IsCompleted }} {{ trFormat .App "weHaveContactedVoucher" "VoucherFullName" .Donor.Voucher.FullName }} + {{ else }} + {{ trFormat .App "weWillContactVoucher" "VoucherFullName" .Donor.Voucher.FullName }} {{ end }}

    @@ -29,8 +29,8 @@

    {{ tr .App "whatHappensNext" }}

      - {{ if .Donor.Tasks.PayForLpa.IsPending }} -
    1. {{ tr .App "weAreProcessingFeeWhenResolvedWillContactVoucher" }}
    2. + {{ if not .Donor.Tasks.PayForLpa.IsCompleted }} +
    3. {{ trFormat .App "weAreProcessingFeeWhenResolvedWillContactVoucher" "VoucherFullName" .Donor.Voucher.FullName }}
    4. {{ end }} {{ trFormatHtml .App "voucherWhatHappensNextBullets" "VoucherFullName" .Donor.Voucher.FullName }} diff --git a/web/template/donor/we_have_received_voucher_details.gohtml b/web/template/donor/we_have_received_voucher_details.gohtml deleted file mode 100644 index 7e2ad43f8d..0000000000 --- a/web/template/donor/we_have_received_voucher_details.gohtml +++ /dev/null @@ -1,28 +0,0 @@ -{{ template "page" . }} - -{{ define "pageTitle" }}{{ tr .App "whatHappensNext" }}{{ end }} - -{{ define "main" }} -
      -
      - {{ template "notification-banner" (notificationBanner .App "success" (trHtml .App "weHaveReceivedDetailsOfVoucher") "success" "heading") }} - -

      {{ tr .App "whatHappensNext" }}

      - - {{ $feeTypeKey := "" }} - {{ if .Donor.FeeType.IsNoFee }} - {{ $feeTypeKey = "payingNoFee" }} - {{ else if .Donor.FeeType.IsHalfFee }} - {{ $feeTypeKey = "payingHalfFee" }} - {{ else if .Donor.FeeType.IsRepeatApplicationFee }} - {{ $feeTypeKey = "aRepeatApplicationDiscount" }} - {{ else if .Donor.FeeType.IsHardshipFee }} - {{ $feeTypeKey = "aHardshipApplication" }} - {{ end }} - - {{ trFormatHtml .App "weHaveReceivedDetailsOfVoucherContent" "FeeType" (tr .App $feeTypeKey) }} - - {{ tr .App "returnToTaskList" }} -
      -
      -{{ end }}