diff --git a/cypress/e2e/donor/application-reason.cy.js b/cypress/e2e/donor/application-reason.cy.js deleted file mode 100644 index 88f8bd5e99..0000000000 --- a/cypress/e2e/donor/application-reason.cy.js +++ /dev/null @@ -1,23 +0,0 @@ -describe('Application reason', () => { - it('can be submitted', () => { - cy.visit('/fixtures?redirect=/application-reason&progress=provideYourDetails'); - cy.checkA11yApp(); - - cy.contains('label', 'noneOfTheAbove').click(); - - cy.contains('button', 'Continue').click(); - cy.url().should('contain', '/task-list'); - }); - - it('errors when unselected', () => { - cy.visit('/fixtures?redirect=/application-reason&progress=provideYourDetails'); - - cy.contains('button', 'Continue').click(); - - cy.get('.govuk-error-summary').within(() => { - cy.contains('Select theReasonForMakingTheApplication'); - }); - - cy.contains('.govuk-fieldset .govuk-error-message', 'Select theReasonForMakingTheApplication'); - }); -}); diff --git a/cypress/e2e/donor/lpa-type.cy.js b/cypress/e2e/donor/lpa-type.cy.js index 77e3c1adec..c81c261a2b 100644 --- a/cypress/e2e/donor/lpa-type.cy.js +++ b/cypress/e2e/donor/lpa-type.cy.js @@ -7,7 +7,7 @@ describe('LPA type', () => { cy.checkA11yApp(); cy.contains('button', 'Continue').click(); - cy.url().should('contain', '/application-reason'); + cy.url().should('contain', '/task-list'); }); it('errors when unselected', () => { diff --git a/cypress/e2e/donor/previous-application-number.cy.js b/cypress/e2e/donor/previous-application-number.cy.js index c9d15df24b..34177b924e 100644 --- a/cypress/e2e/donor/previous-application-number.cy.js +++ b/cypress/e2e/donor/previous-application-number.cy.js @@ -1,23 +1,35 @@ describe('Previous application number', () => { - it('can be submitted', () => { + beforeEach(() => { cy.visit('/fixtures?redirect=/previous-application-number'); + }); + + it('can be submitted', () => { cy.checkA11yApp(); - cy.get('#f-previous-application-number').type('ABC'); + cy.get('#f-previous-application-number').type('MABC'); + cy.contains('button', 'Save and continue').click(); - cy.contains('button', 'Continue').click(); - cy.url().should('contain', '/task-list'); + cy.url().should('contain', '/what-happens-after-no-fee'); }); it('errors when unselected', () => { - cy.visit('/fixtures?redirect=/previous-application-number'); + cy.contains('button', 'Save and continue').click(); - cy.contains('button', 'Continue').click(); + cy.get('.govuk-error-summary').within(() => { + cy.contains('Enter previous reference number'); + }); + + cy.contains('.govuk-error-message', 'Enter previous reference number'); + }); + + it('errors when not correct format', () => { + cy.get('#f-previous-application-number').type('ABC'); + cy.contains('button', 'Save and continue').click(); cy.get('.govuk-error-summary').within(() => { - cy.contains('Enter previousApplicationNumber'); + cy.contains('Previous reference number must begin with 7 or M'); }); - cy.contains('.govuk-fieldset .govuk-error-message', 'Enter previousApplicationNumber'); + cy.contains('.govuk-error-message', 'Previous reference number must begin with 7 or M'); }); }); diff --git a/internal/app/donor_store.go b/internal/app/donor_store.go index ca4120c133..8768a100e5 100644 --- a/internal/app/donor_store.go +++ b/internal/app/donor_store.go @@ -162,7 +162,6 @@ func (s *donorStore) Put(ctx context.Context, lpa *page.Lpa) error { if lpa.UID != "" && lpa.PreviousApplicationNumber != "" && !lpa.HasSentPreviousApplicationLinkedEvent { if err := s.eventClient.Send(ctx, "previous-application-linked", previousApplicationLinkedEvent{ UID: lpa.UID, - ApplicationReason: lpa.ApplicationReason.String(), PreviousApplicationNumber: lpa.PreviousApplicationNumber, }); err != nil { s.logger.Print(err) @@ -256,7 +255,6 @@ type applicationUpdatedEventDonor struct { type previousApplicationLinkedEvent struct { UID string `json:"uid"` - ApplicationReason string `json:"applicationReason"` PreviousApplicationNumber string `json:"previousApplicationNumber"` } diff --git a/internal/app/donor_store_test.go b/internal/app/donor_store_test.go index 1177cfa2bd..acb81acd1b 100644 --- a/internal/app/donor_store_test.go +++ b/internal/app/donor_store_test.go @@ -373,7 +373,6 @@ func TestDonorStorePutWhenPreviousApplicationLinked(t *testing.T) { eventClient. On("Send", ctx, "previous-application-linked", previousApplicationLinkedEvent{ UID: "M-1111", - ApplicationReason: "remake", PreviousApplicationNumber: "5555", }). Return(nil) @@ -386,7 +385,6 @@ func TestDonorStorePutWhenPreviousApplicationLinked(t *testing.T) { ID: "5", UID: "M-1111", UpdatedAt: now, - ApplicationReason: page.RemakeOfInvalidApplication, PreviousApplicationNumber: "5555", HasSentApplicationUpdatedEvent: true, HasSentPreviousApplicationLinkedEvent: true, @@ -400,7 +398,6 @@ func TestDonorStorePutWhenPreviousApplicationLinked(t *testing.T) { SK: "#DONOR#an-id", ID: "5", UID: "M-1111", - ApplicationReason: page.RemakeOfInvalidApplication, PreviousApplicationNumber: "5555", HasSentApplicationUpdatedEvent: true, }) @@ -423,7 +420,6 @@ func TestDonorStorePutWhenPreviousApplicationLinkedWontResend(t *testing.T) { SK: "#DONOR#an-id", ID: "5", UID: "M-1111", - ApplicationReason: page.RemakeOfInvalidApplication, PreviousApplicationNumber: "5555", HasSentApplicationUpdatedEvent: true, HasSentPreviousApplicationLinkedEvent: true, @@ -456,7 +452,6 @@ func TestDonorStorePutWhenPreviousApplicationLinkedWhenError(t *testing.T) { SK: "#DONOR#an-id", ID: "5", UID: "M-1111", - ApplicationReason: page.RemakeOfInvalidApplication, PreviousApplicationNumber: "5555", HasSentApplicationUpdatedEvent: true, }) diff --git a/internal/page/data.go b/internal/page/data.go index 0649cdb993..9c52acdccc 100644 --- a/internal/page/data.go +++ b/internal/page/data.go @@ -66,15 +66,6 @@ const ( ReplacementAttorneysStepInAnotherWay // other ) -//go:generate enumerator -type ApplicationReason -linecomment -empty -type ApplicationReason uint8 - -const ( - NewApplication ApplicationReason = iota + 1 // new-application - RemakeOfInvalidApplication // remake - AdditionalApplication // additional-application -) - //go:generate enumerator -type FeeType type FeeType uint8 @@ -119,8 +110,6 @@ type Lpa struct { CertificateProvider actor.CertificateProvider // Type of LPA being drafted Type LpaType - // ApplicationReason is why the application is being made - ApplicationReason ApplicationReason // PreviousApplicationNumber if the application is related to an existing application PreviousApplicationNumber string // Whether the applicant wants to add replacement attorneys diff --git a/internal/page/donor/application_reason.go b/internal/page/donor/application_reason.go deleted file mode 100644 index d897d68deb..0000000000 --- a/internal/page/donor/application_reason.go +++ /dev/null @@ -1,75 +0,0 @@ -package donor - -import ( - "net/http" - - "github.com/ministryofjustice/opg-go-common/template" - "github.com/ministryofjustice/opg-modernising-lpa/internal/actor" - "github.com/ministryofjustice/opg-modernising-lpa/internal/page" - "github.com/ministryofjustice/opg-modernising-lpa/internal/validation" -) - -type applicationReasonData struct { - App page.AppData - Errors validation.List - Form *applicationReasonForm - Options page.ApplicationReasonOptions -} - -func ApplicationReason(tmpl template.Template, donorStore DonorStore) Handler { - return func(appData page.AppData, w http.ResponseWriter, r *http.Request, lpa *page.Lpa) error { - data := &applicationReasonData{ - App: appData, - Form: &applicationReasonForm{ - ApplicationReason: lpa.ApplicationReason, - }, - Options: page.ApplicationReasonValues, - } - - if r.Method == http.MethodPost { - data.Form = readApplicationReasonForm(r) - data.Errors = data.Form.Validate() - - if data.Errors.None() { - redirect := page.Paths.PreviousApplicationNumber - lpa.ApplicationReason = data.Form.ApplicationReason - - if lpa.ApplicationReason.IsNewApplication() { - redirect = page.Paths.TaskList - lpa.Tasks.YourDetails = actor.TaskCompleted - } - - if err := donorStore.Put(r.Context(), lpa); err != nil { - return err - } - - return appData.Redirect(w, r, lpa, redirect.Format(lpa.ID)) - } - } - - return tmpl(w, data) - } -} - -type applicationReasonForm struct { - ApplicationReason page.ApplicationReason - Error error -} - -func readApplicationReasonForm(r *http.Request) *applicationReasonForm { - applicationReason, err := page.ParseApplicationReason(page.PostFormString(r, "application-reason")) - - return &applicationReasonForm{ - ApplicationReason: applicationReason, - Error: err, - } -} - -func (f *applicationReasonForm) Validate() validation.List { - var errors validation.List - - errors.Error("application-reason", "theReasonForMakingTheApplication", f.Error, - validation.Selected()) - - return errors -} diff --git a/internal/page/donor/application_reason_test.go b/internal/page/donor/application_reason_test.go deleted file mode 100644 index ff86a28862..0000000000 --- a/internal/page/donor/application_reason_test.go +++ /dev/null @@ -1,206 +0,0 @@ -package donor - -import ( - "net/http" - "net/http/httptest" - "net/url" - "strings" - "testing" - - "github.com/ministryofjustice/opg-modernising-lpa/internal/actor" - "github.com/ministryofjustice/opg-modernising-lpa/internal/date" - "github.com/ministryofjustice/opg-modernising-lpa/internal/page" - "github.com/ministryofjustice/opg-modernising-lpa/internal/place" - "github.com/ministryofjustice/opg-modernising-lpa/internal/validation" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" -) - -func TestGetApplicationReason(t *testing.T) { - w := httptest.NewRecorder() - r, _ := http.NewRequest(http.MethodGet, "/", nil) - - template := newMockTemplate(t) - template. - On("Execute", w, &applicationReasonData{ - App: testAppData, - Form: &applicationReasonForm{}, - Options: page.ApplicationReasonValues, - }). - Return(nil) - - err := ApplicationReason(template.Execute, nil)(testAppData, w, r, &page.Lpa{}) - resp := w.Result() - - assert.Nil(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) -} - -func TestGetApplicationReasonFromStore(t *testing.T) { - w := httptest.NewRecorder() - r, _ := http.NewRequest(http.MethodGet, "/", nil) - - template := newMockTemplate(t) - template. - On("Execute", w, &applicationReasonData{ - App: testAppData, - Form: &applicationReasonForm{ - ApplicationReason: page.RemakeOfInvalidApplication, - }, - Options: page.ApplicationReasonValues, - }). - Return(nil) - - err := ApplicationReason(template.Execute, nil)(testAppData, w, r, &page.Lpa{ApplicationReason: page.RemakeOfInvalidApplication}) - resp := w.Result() - - assert.Nil(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) -} - -func TestGetApplicationReasonWhenTemplateErrors(t *testing.T) { - w := httptest.NewRecorder() - r, _ := http.NewRequest(http.MethodGet, "/", nil) - - template := newMockTemplate(t) - template. - On("Execute", w, mock.Anything). - Return(expectedError) - - err := ApplicationReason(template.Execute, nil)(testAppData, w, r, &page.Lpa{}) - resp := w.Result() - - assert.Equal(t, expectedError, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) -} - -func TestPostApplicationReason(t *testing.T) { - testcases := map[page.ApplicationReason]struct { - redirect string - tasks page.Tasks - }{ - page.NewApplication: { - redirect: page.Paths.TaskList.Format("lpa-id"), - tasks: page.Tasks{YourDetails: actor.TaskCompleted}, - }, - page.RemakeOfInvalidApplication: { - redirect: page.Paths.PreviousApplicationNumber.Format("lpa-id"), - }, - } - - for reason, tc := range testcases { - t.Run(reason.String(), func(t *testing.T) { - form := url.Values{ - "application-reason": {reason.String()}, - } - - w := httptest.NewRecorder() - r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(form.Encode())) - r.Header.Add("Content-Type", page.FormUrlEncoded) - - donorStore := newMockDonorStore(t) - donorStore. - On("Put", r.Context(), &page.Lpa{ - ID: "lpa-id", - Donor: actor.Donor{ - FirstNames: "Jane", - LastName: "Smith", - DateOfBirth: date.New("2000", "1", "2"), - Address: place.Address{Postcode: "ABC123"}, - }, - ApplicationReason: reason, - Tasks: tc.tasks, - }). - Return(nil) - - err := ApplicationReason(nil, donorStore)(testAppData, w, r, &page.Lpa{ - ID: "lpa-id", - Donor: actor.Donor{ - FirstNames: "Jane", - LastName: "Smith", - DateOfBirth: date.New("2000", "1", "2"), - Address: place.Address{Postcode: "ABC123"}, - }, - }) - resp := w.Result() - - assert.Nil(t, err) - assert.Equal(t, http.StatusFound, resp.StatusCode) - assert.Equal(t, tc.redirect, resp.Header.Get("Location")) - }) - } -} - -func TestPostApplicationReasonWhenStoreErrors(t *testing.T) { - form := url.Values{ - "application-reason": {page.NewApplication.String()}, - } - - w := httptest.NewRecorder() - r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(form.Encode())) - r.Header.Add("Content-Type", page.FormUrlEncoded) - - donorStore := newMockDonorStore(t) - donorStore. - On("Put", r.Context(), mock.Anything). - Return(expectedError) - - err := ApplicationReason(nil, donorStore)(testAppData, w, r, &page.Lpa{}) - - assert.Equal(t, expectedError, err) -} - -func TestPostApplicationReasonWhenValidationErrors(t *testing.T) { - w := httptest.NewRecorder() - r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader("")) - r.Header.Add("Content-Type", page.FormUrlEncoded) - - template := newMockTemplate(t) - template. - On("Execute", w, mock.MatchedBy(func(data *applicationReasonData) bool { - return assert.Equal(t, validation.With("application-reason", validation.SelectError{Label: "theReasonForMakingTheApplication"}), data.Errors) - })). - Return(nil) - - err := ApplicationReason(template.Execute, nil)(testAppData, w, r, &page.Lpa{}) - resp := w.Result() - - assert.Nil(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) -} - -func TestReadApplicationReasonForm(t *testing.T) { - form := url.Values{ - "application-reason": {page.NewApplication.String()}, - } - - r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(form.Encode())) - r.Header.Add("Content-Type", page.FormUrlEncoded) - - result := readApplicationReasonForm(r) - - assert.Equal(t, page.NewApplication, result.ApplicationReason) -} - -func TestApplicationReasonFormValidate(t *testing.T) { - testCases := map[string]struct { - form *applicationReasonForm - errors validation.List - }{ - "valid": { - form: &applicationReasonForm{}, - }, - "invalid": { - form: &applicationReasonForm{ - Error: expectedError, - }, - errors: validation.With("application-reason", validation.SelectError{Label: "theReasonForMakingTheApplication"}), - }, - } - - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - assert.Equal(t, tc.errors, tc.form.Validate()) - }) - } -} diff --git a/internal/page/donor/lpa_type.go b/internal/page/donor/lpa_type.go index 1d74236a14..c4fd4330e2 100644 --- a/internal/page/donor/lpa_type.go +++ b/internal/page/donor/lpa_type.go @@ -4,6 +4,7 @@ import ( "net/http" "github.com/ministryofjustice/opg-go-common/template" + "github.com/ministryofjustice/opg-modernising-lpa/internal/actor" "github.com/ministryofjustice/opg-modernising-lpa/internal/page" "github.com/ministryofjustice/opg-modernising-lpa/internal/validation" ) @@ -40,6 +41,7 @@ func LpaType(tmpl template.Template, donorStore DonorStore) Handler { if data.Errors.None() { if lpa.Type != data.Form.LpaType { lpa.Type = data.Form.LpaType + lpa.Tasks.YourDetails = actor.TaskCompleted lpa.HasSentApplicationUpdatedEvent = false if err := donorStore.Put(r.Context(), lpa); err != nil { @@ -47,7 +49,7 @@ func LpaType(tmpl template.Template, donorStore DonorStore) Handler { } } - return appData.Redirect(w, r, lpa, page.Paths.ApplicationReason.Format(lpa.ID)) + return appData.Redirect(w, r, lpa, page.Paths.TaskList.Format(lpa.ID)) } } diff --git a/internal/page/donor/lpa_type_test.go b/internal/page/donor/lpa_type_test.go index 052e527dd9..cb39069129 100644 --- a/internal/page/donor/lpa_type_test.go +++ b/internal/page/donor/lpa_type_test.go @@ -7,6 +7,7 @@ import ( "strings" "testing" + "github.com/ministryofjustice/opg-modernising-lpa/internal/actor" "github.com/ministryofjustice/opg-modernising-lpa/internal/page" "github.com/ministryofjustice/opg-modernising-lpa/internal/validation" "github.com/stretchr/testify/assert" @@ -89,8 +90,9 @@ func TestPostLpaType(t *testing.T) { donorStore := newMockDonorStore(t) donorStore. On("Put", r.Context(), &page.Lpa{ - ID: "lpa-id", - Type: page.LpaTypePropertyFinance, + ID: "lpa-id", + Type: page.LpaTypePropertyFinance, + Tasks: page.Tasks{YourDetails: actor.TaskCompleted}, }). Return(nil) @@ -102,7 +104,7 @@ func TestPostLpaType(t *testing.T) { assert.Nil(t, err) assert.Equal(t, http.StatusFound, resp.StatusCode) - assert.Equal(t, page.Paths.ApplicationReason.Format("lpa-id"), resp.Header.Get("Location")) + assert.Equal(t, page.Paths.TaskList.Format("lpa-id"), resp.Header.Get("Location")) } func TestPostLpaTypeWhenNotChanged(t *testing.T) { @@ -122,7 +124,7 @@ func TestPostLpaTypeWhenNotChanged(t *testing.T) { assert.Nil(t, err) assert.Equal(t, http.StatusFound, resp.StatusCode) - assert.Equal(t, page.Paths.ApplicationReason.Format("lpa-id"), resp.Header.Get("Location")) + assert.Equal(t, page.Paths.TaskList.Format("lpa-id"), resp.Header.Get("Location")) } func TestPostLpaTypeWhenStoreErrors(t *testing.T) { diff --git a/internal/page/donor/previous_application_number.go b/internal/page/donor/previous_application_number.go index 191bb543bc..52a48bbe3e 100644 --- a/internal/page/donor/previous_application_number.go +++ b/internal/page/donor/previous_application_number.go @@ -4,7 +4,6 @@ import ( "net/http" "github.com/ministryofjustice/opg-go-common/template" - "github.com/ministryofjustice/opg-modernising-lpa/internal/actor" "github.com/ministryofjustice/opg-modernising-lpa/internal/page" "github.com/ministryofjustice/opg-modernising-lpa/internal/validation" ) @@ -30,16 +29,18 @@ func PreviousApplicationNumber(tmpl template.Template, donorStore DonorStore) Ha if data.Errors.None() { if lpa.PreviousApplicationNumber != data.Form.PreviousApplicationNumber { - lpa.HasSentApplicationUpdatedEvent = false lpa.PreviousApplicationNumber = data.Form.PreviousApplicationNumber - lpa.Tasks.YourDetails = actor.TaskCompleted if err := donorStore.Put(r.Context(), lpa); err != nil { return err } } - return appData.Redirect(w, r, lpa, page.Paths.TaskList.Format(lpa.ID)) + if lpa.PreviousApplicationNumber[0] == '7' { + return appData.Redirect(w, r, lpa, page.Paths.WhatWasYourOriginalFee.Format(lpa.ID)) + } else { + return appData.Redirect(w, r, lpa, page.Paths.WhatHappensAfterNoFee.Format(lpa.ID)) + } } } @@ -61,7 +62,8 @@ func (f *previousApplicationNumberForm) Validate() validation.List { var errors validation.List errors.String("previous-application-number", "previousApplicationNumber", f.PreviousApplicationNumber, - validation.Empty()) + validation.Empty(), + validation.ReferenceNumber()) return errors } diff --git a/internal/page/donor/previous_application_number_test.go b/internal/page/donor/previous_application_number_test.go index 62b9d4da67..d65368a234 100644 --- a/internal/page/donor/previous_application_number_test.go +++ b/internal/page/donor/previous_application_number_test.go @@ -7,7 +7,6 @@ import ( "strings" "testing" - "github.com/ministryofjustice/opg-modernising-lpa/internal/actor" "github.com/ministryofjustice/opg-modernising-lpa/internal/page" "github.com/ministryofjustice/opg-modernising-lpa/internal/validation" "github.com/stretchr/testify/assert" @@ -71,41 +70,46 @@ func TestGetPreviousApplicationNumberWhenTemplateErrors(t *testing.T) { } func TestPostPreviousApplicationNumber(t *testing.T) { - form := url.Values{ - "previous-application-number": {"ABC"}, + testcases := map[string]page.LpaPath{ + "7": page.Paths.WhatWasYourOriginalFee, + "M": page.Paths.WhatHappensAfterNoFee, } - w := httptest.NewRecorder() - r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(form.Encode())) - r.Header.Add("Content-Type", page.FormUrlEncoded) - - donorStore := newMockDonorStore(t) - donorStore. - On("Put", r.Context(), &page.Lpa{ - ID: "lpa-id", - UID: "lpa-uid", - ApplicationReason: page.AdditionalApplication, - PreviousApplicationNumber: "ABC", - Tasks: page.Tasks{YourDetails: actor.TaskCompleted}, - }). - Return(nil) - - err := PreviousApplicationNumber(nil, donorStore)(testAppData, w, r, &page.Lpa{ - ID: "lpa-id", - UID: "lpa-uid", - ApplicationReason: page.AdditionalApplication, - HasSentApplicationUpdatedEvent: true, - }) - resp := w.Result() - - assert.Nil(t, err) - assert.Equal(t, http.StatusFound, resp.StatusCode) - assert.Equal(t, page.Paths.TaskList.Format("lpa-id"), resp.Header.Get("Location")) + for start, redirect := range testcases { + t.Run(start, func(t *testing.T) { + form := url.Values{ + "previous-application-number": {start}, + } + + w := httptest.NewRecorder() + r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(form.Encode())) + r.Header.Add("Content-Type", page.FormUrlEncoded) + + donorStore := newMockDonorStore(t) + donorStore. + On("Put", r.Context(), &page.Lpa{ + ID: "lpa-id", + UID: "lpa-uid", + PreviousApplicationNumber: start, + }). + Return(nil) + + err := PreviousApplicationNumber(nil, donorStore)(testAppData, w, r, &page.Lpa{ + ID: "lpa-id", + UID: "lpa-uid", + }) + resp := w.Result() + + assert.Nil(t, err) + assert.Equal(t, http.StatusFound, resp.StatusCode) + assert.Equal(t, redirect.Format("lpa-id"), resp.Header.Get("Location")) + }) + } } func TestPostPreviousApplicationNumberWhenNotChanged(t *testing.T) { form := url.Values{ - "previous-application-number": {"ABC"}, + "previous-application-number": {"M-0000"}, } w := httptest.NewRecorder() @@ -115,19 +119,18 @@ func TestPostPreviousApplicationNumberWhenNotChanged(t *testing.T) { err := PreviousApplicationNumber(nil, nil)(testAppData, w, r, &page.Lpa{ ID: "lpa-id", UID: "lpa-uid", - ApplicationReason: page.AdditionalApplication, - PreviousApplicationNumber: "ABC", + PreviousApplicationNumber: "M-0000", }) resp := w.Result() assert.Nil(t, err) assert.Equal(t, http.StatusFound, resp.StatusCode) - assert.Equal(t, page.Paths.TaskList.Format("lpa-id"), resp.Header.Get("Location")) + assert.Equal(t, page.Paths.WhatHappensAfterNoFee.Format("lpa-id"), resp.Header.Get("Location")) } func TestPostPreviousApplicationNumberWhenStoreErrors(t *testing.T) { form := url.Values{ - "previous-application-number": {"ABC"}, + "previous-application-number": {"MABC"}, } w := httptest.NewRecorder() @@ -180,10 +183,21 @@ func TestPreviousApplicationNumberFormValidate(t *testing.T) { form *previousApplicationNumberForm errors validation.List }{ - "valid": { + "valid modernised": { + form: &previousApplicationNumberForm{ + PreviousApplicationNumber: "M", + }, + }, + "valid old": { + form: &previousApplicationNumberForm{ + PreviousApplicationNumber: "7", + }, + }, + "invalid": { form: &previousApplicationNumberForm{ - PreviousApplicationNumber: "A", + PreviousApplicationNumber: "x", }, + errors: validation.With("previous-application-number", validation.ReferenceNumberError{Label: "previousApplicationNumber"}), }, "empty": { form: &previousApplicationNumberForm{}, diff --git a/internal/page/donor/register.go b/internal/page/donor/register.go index 4994c30f79..b7eee091c1 100644 --- a/internal/page/donor/register.go +++ b/internal/page/donor/register.go @@ -198,8 +198,6 @@ func Register( YourAddress(logger, tmpls.Get("your_address.gohtml"), addressClient, donorStore)) handleWithLpa(page.Paths.LpaType, None, LpaType(tmpls.Get("lpa_type.gohtml"), donorStore)) - handleWithLpa(page.Paths.ApplicationReason, None, - ApplicationReason(tmpls.Get("application_reason.gohtml"), donorStore)) handleWithLpa(page.Paths.PreviousApplicationNumber, None, PreviousApplicationNumber(tmpls.Get("previous_application_number.gohtml"), donorStore)) handleWithLpa(page.Paths.CheckYouCanSign, None, diff --git a/internal/page/donor/which_fee_type_are_you_applying_for.go b/internal/page/donor/which_fee_type_are_you_applying_for.go index 284a1cd285..addc0ed7b5 100644 --- a/internal/page/donor/which_fee_type_are_you_applying_for.go +++ b/internal/page/donor/which_fee_type_are_you_applying_for.go @@ -35,7 +35,11 @@ func WhichFeeTypeAreYouApplyingFor(tmpl template.Template, donorStore DonorStore return err } - return appData.Redirect(w, r, lpa, page.Paths.EvidenceRequired.Format(lpa.ID)) + if lpa.FeeType.IsRepeatApplicationFee() { + return appData.Redirect(w, r, lpa, page.Paths.PreviousApplicationNumber.Format(lpa.ID)) + } else { + return appData.Redirect(w, r, lpa, page.Paths.EvidenceRequired.Format(lpa.ID)) + } } } diff --git a/internal/page/donor/which_fee_type_are_you_applying_for_test.go b/internal/page/donor/which_fee_type_are_you_applying_for_test.go index e2c9823943..12d8250949 100644 --- a/internal/page/donor/which_fee_type_are_you_applying_for_test.go +++ b/internal/page/donor/which_fee_type_are_you_applying_for_test.go @@ -74,25 +74,36 @@ func TestGetWhichFeeTypeAreYouApplyingForOnTemplateError(t *testing.T) { } func TestPostWhichFeeTypeAreYouApplyingFor(t *testing.T) { - form := url.Values{ - "fee-type": {page.HalfFee.String()}, + testcases := map[page.FeeType]page.LpaPath{ + page.HalfFee: page.Paths.EvidenceRequired, + page.NoFee: page.Paths.EvidenceRequired, + page.HardshipFee: page.Paths.EvidenceRequired, + page.RepeatApplicationFee: page.Paths.PreviousApplicationNumber, } - w := httptest.NewRecorder() - r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(form.Encode())) - r.Header.Add("Content-Type", page.FormUrlEncoded) + for feeType, redirect := range testcases { + t.Run(feeType.String(), func(t *testing.T) { + form := url.Values{ + "fee-type": {feeType.String()}, + } - donorStore := newMockDonorStore(t) - donorStore. - On("Put", r.Context(), &page.Lpa{ID: "lpa-id", FeeType: page.HalfFee}). - Return(nil) + w := httptest.NewRecorder() + r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(form.Encode())) + r.Header.Add("Content-Type", page.FormUrlEncoded) - err := WhichFeeTypeAreYouApplyingFor(nil, donorStore)(testAppData, w, r, &page.Lpa{ID: "lpa-id"}) - resp := w.Result() + donorStore := newMockDonorStore(t) + donorStore. + On("Put", r.Context(), &page.Lpa{ID: "lpa-id", FeeType: feeType}). + Return(nil) - assert.Nil(t, err) - assert.Equal(t, page.Paths.EvidenceRequired.Format("lpa-id"), resp.Header.Get("Location")) - assert.Equal(t, http.StatusFound, resp.StatusCode) + err := WhichFeeTypeAreYouApplyingFor(nil, donorStore)(testAppData, w, r, &page.Lpa{ID: "lpa-id"}) + resp := w.Result() + + assert.Nil(t, err) + assert.Equal(t, redirect.Format("lpa-id"), resp.Header.Get("Location")) + assert.Equal(t, http.StatusFound, resp.StatusCode) + }) + } } func TestPostWhichFeeTypeAreYouApplyingForOnStoreError(t *testing.T) { diff --git a/internal/page/enum_applicationreason.go b/internal/page/enum_applicationreason.go deleted file mode 100644 index 5b97cbe5e4..0000000000 --- a/internal/page/enum_applicationreason.go +++ /dev/null @@ -1,69 +0,0 @@ -// Code generated by "enumerator -type ApplicationReason -linecomment -empty"; DO NOT EDIT. -package page - -import ( - "fmt" - "strconv" -) - -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[NewApplication-1] - _ = x[RemakeOfInvalidApplication-2] - _ = x[AdditionalApplication-3] -} - -const _ApplicationReason_name = "new-applicationremakeadditional-application" - -var _ApplicationReason_index = [...]uint8{0, 15, 21, 43} - -func (i ApplicationReason) String() string { - i -= 1 - if i >= ApplicationReason(len(_ApplicationReason_index)-1) { - return "ApplicationReason(" + strconv.FormatInt(int64(i+1), 10) + ")" - } - return _ApplicationReason_name[_ApplicationReason_index[i]:_ApplicationReason_index[i+1]] -} - -func (i ApplicationReason) IsNewApplication() bool { - return i == NewApplication -} - -func (i ApplicationReason) IsRemakeOfInvalidApplication() bool { - return i == RemakeOfInvalidApplication -} - -func (i ApplicationReason) IsAdditionalApplication() bool { - return i == AdditionalApplication -} - -func ParseApplicationReason(s string) (ApplicationReason, error) { - switch s { - case "new-application": - return NewApplication, nil - case "remake": - return RemakeOfInvalidApplication, nil - case "additional-application": - return AdditionalApplication, nil - default: - return ApplicationReason(0), fmt.Errorf("invalid ApplicationReason '%s'", s) - } -} - -type ApplicationReasonOptions struct { - NewApplication ApplicationReason - RemakeOfInvalidApplication ApplicationReason - AdditionalApplication ApplicationReason -} - -var ApplicationReasonValues = ApplicationReasonOptions{ - NewApplication: NewApplication, - RemakeOfInvalidApplication: RemakeOfInvalidApplication, - AdditionalApplication: AdditionalApplication, -} - -func (i ApplicationReason) Empty() bool { - return i == ApplicationReason(0) -} diff --git a/internal/page/paths.go b/internal/page/paths.go index dfe1655d22..aaa0ab0f7b 100644 --- a/internal/page/paths.go +++ b/internal/page/paths.go @@ -106,7 +106,6 @@ type AppPaths struct { YourLegalRightsAndResponsibilities Path AboutPayment LpaPath - ApplicationReason LpaPath AreYouApplyingForFeeDiscountOrExemption LpaPath CertificateProviderAddress LpaPath CertificateProviderDetails LpaPath @@ -174,6 +173,7 @@ type AppPaths struct { UseExistingAddress LpaPath WhatACertificateProviderDoes LpaPath WhatHappensAfterNoFee LpaPath + WhatWasYourOriginalFee LpaPath WhenCanTheLpaBeUsed LpaPath WhichFeeTypeAreYouApplyingFor LpaPath WithdrawThisLpa LpaPath @@ -232,7 +232,6 @@ var Paths = AppPaths{ }, AboutPayment: "/about-payment", - ApplicationReason: "/application-reason", AreYouApplyingForFeeDiscountOrExemption: "/are-you-applying-for-fee-discount-or-exemption", AttorneyFixtures: "/fixtures/attorney", AuthRedirect: "/auth/redirect", @@ -315,6 +314,7 @@ var Paths = AppPaths{ UseExistingAddress: "/use-existing-address", WhatACertificateProviderDoes: "/what-a-certificate-provider-does", WhatHappensAfterNoFee: "/what-happens-after-no-fee", + WhatWasYourOriginalFee: "/what-was-your-original-fee", WhenCanTheLpaBeUsed: "/when-can-the-lpa-be-used", WhichFeeTypeAreYouApplyingFor: "/which-fee-type-are-you-applying-for", WithdrawThisLpa: "/withdraw-this-lpa", diff --git a/internal/validation/check.go b/internal/validation/check.go index edbcc13260..47ecc7d24c 100644 --- a/internal/validation/check.go +++ b/internal/validation/check.go @@ -360,3 +360,17 @@ func (c DateMustBePastCheck) CheckDate(label string, value date.Date) Formattabl func DateMustBePast() DateMustBePastCheck { return DateMustBePastCheck{} } + +type ReferenceNumberCheck struct{} + +func (c ReferenceNumberCheck) CheckString(label, value string) FormattableError { + if value[0] != 'M' && value[0] != '7' { + return ReferenceNumberError{Label: label} + } + + return nil +} + +func ReferenceNumber() ReferenceNumberCheck { + return ReferenceNumberCheck{} +} diff --git a/internal/validation/check_test.go b/internal/validation/check_test.go index 2edc7e95c0..11b5e611e4 100644 --- a/internal/validation/check_test.go +++ b/internal/validation/check_test.go @@ -195,6 +195,19 @@ func TestCheckString(t *testing.T) { checks: []StringChecker{Email()}, expected: With(name, EmailError{Label: label}), }, + "reference number modernised": { + input: "M", + checks: []StringChecker{ReferenceNumber()}, + }, + "reference number old": { + input: "7", + checks: []StringChecker{ReferenceNumber()}, + }, + "reference number invalid": { + input: "a", + checks: []StringChecker{ReferenceNumber()}, + expected: With(name, ReferenceNumberError{Label: label}), + }, } for scenario, tc := range testcases { diff --git a/internal/validation/error.go b/internal/validation/error.go index 9d39bd6203..5b585697d1 100644 --- a/internal/validation/error.go +++ b/internal/validation/error.go @@ -149,6 +149,16 @@ func (e DateMustBePastError) Format(l Localizer) string { }) } +type ReferenceNumberError struct { + Label string +} + +func (e ReferenceNumberError) Format(l Localizer) string { + return l.Format("errorReferenceNumber", map[string]any{ + "Label": l.T(e.Label), + }) +} + func lowerFirst(s string) string { r, n := utf8.DecodeRuneInString(s) return string(unicode.ToLower(r)) + s[n:] diff --git a/lang/cy.json b/lang/cy.json index 3a4e64b2c7..3a138278af 100644 --- a/lang/cy.json +++ b/lang/cy.json @@ -49,6 +49,7 @@ "errorSelect": "Dewiswch {{.Label}}", "errorEmail": "{{.Label}} Welsh", "errorPostcode": "{{.Label}} Welsh", + "errorReferenceNumber": "{{.Label}} Welsh", "donorMatchesActorWarning": "Welsh {{.FirstNames}} {{.LastName}} {{.Type}}", "attorneyMatchesActorWarning": "Welsh {{.FirstNames}} {{.LastName}} {{.Type}}", "attorneyMatchesAttorneyWarning": "Welsh {{.FirstNames}} {{.LastName}}", @@ -897,5 +898,10 @@ "youHaveWithdrawnLpaNumber": "Welsh {{.UID}}", "opgWillNowContactAnyoneWhoHasAlreadyBeenContacted": "Welsh", "withdrawn": "Welsh", - "dateLpaSigned": "Welsh" + "dateLpaSigned": "Welsh", + "whatIsYourPreviousReferenceNumber": "Welsh", + "whatIsYourPreviousReferenceNumberContent": "
Welsh
", + "whereCanFindReferenceNumber": "Welsh", + "whereCanFindReferenceNumberDetails": "Welsh
", + "previousApplicationNumber": "Welsh" } diff --git a/lang/en.json b/lang/en.json index 3af9cf8257..f71d1fc267 100644 --- a/lang/en.json +++ b/lang/en.json @@ -50,6 +50,7 @@ "errorSelect": "Select {{.Label}}", "errorEmail": "{{.Label}} must be in the correct format, like name@example.com", "errorPostcode": "{{.Label}} must be a UK postcode", + "errorReferenceNumber": "{{.Label}} must begin with 7 or M", "donorMatchesActorWarning": "The donor’s name is also {{.FirstNames}} {{.LastName}}. The donor cannot be {{.Type}}.", "attorneyMatchesActorWarning": "There is also an attorney called {{.FirstNames}} {{.LastName}}. An attorney cannot be {{.Type}}.", "attorneyMatchesAttorneyWarning": "There is already an attorney called {{.FirstNames}} {{.LastName}}.", @@ -841,5 +842,10 @@ "youHaveWithdrawnLpaNumber": "You have withdrawn LPA number {{.UID}}.", "opgWillNowContactAnyoneWhoHasAlreadyBeenContacted": "OPG will now contact anyone who has already been contacted in relation to your LPA and notify them of your decision to withdraw.", "withdrawn": "Withdrawn", - "dateLpaSigned": "Date LPA signed" + "dateLpaSigned": "Date LPA signed", + "whatIsYourPreviousReferenceNumber": "What is your previous reference number?", + "whatIsYourPreviousReferenceNumberContent": "You’ve told us that you recently made an LPA application.
We need your previous reference number so that we can match your old application to your new one.
", + "whereCanFindReferenceNumber": "Where can I find my reference number?", + "whereCanFindReferenceNumberDetails": "Your reference number (also called ‘OPG reference number’ or ‘Our ref’) is on any letter you have from the Office of the Public Guardian.
It should also be on the cover letter we sent you when we sent your original application back to you.
", + "previousApplicationNumber": "Previous reference number" } diff --git a/web/template/application_reason.gohtml b/web/template/application_reason.gohtml deleted file mode 100644 index 008ed6d0ab..0000000000 --- a/web/template/application_reason.gohtml +++ /dev/null @@ -1,29 +0,0 @@ -{{ template "page" . }} - -{{ define "pageTitle" }}{{ tr .App "remakeOrMove" }}{{ end }} - -{{ define "main" }} -