diff --git a/cmd/event-received/factory.go b/cmd/event-received/factory.go index 61a4ef6bf8..407ccf2073 100644 --- a/cmd/event-received/factory.go +++ b/cmd/event-received/factory.go @@ -32,7 +32,7 @@ type LambdaClient interface { } type LpaStoreClient interface { - SendLpa(ctx context.Context, donor *donordata.Provided) error + SendLpa(ctx context.Context, uid string, body lpastore.CreateLpa) error Lpa(ctx context.Context, uid string) (*lpadata.Lpa, error) } diff --git a/cmd/event-received/mock_LpaStoreClient_test.go b/cmd/event-received/mock_LpaStoreClient_test.go index 0db8c5b5e1..3dd0b2a5ba 100644 --- a/cmd/event-received/mock_LpaStoreClient_test.go +++ b/cmd/event-received/mock_LpaStoreClient_test.go @@ -5,7 +5,7 @@ package main import ( context "context" - donordata "github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata" + lpastore "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore" lpadata "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore/lpadata" mock "github.com/stretchr/testify/mock" @@ -83,17 +83,17 @@ func (_c *mockLpaStoreClient_Lpa_Call) RunAndReturn(run func(context.Context, st return _c } -// SendLpa provides a mock function with given fields: ctx, donor -func (_m *mockLpaStoreClient) SendLpa(ctx context.Context, donor *donordata.Provided) error { - ret := _m.Called(ctx, donor) +// SendLpa provides a mock function with given fields: ctx, uid, body +func (_m *mockLpaStoreClient) SendLpa(ctx context.Context, uid string, body lpastore.CreateLpa) error { + ret := _m.Called(ctx, uid, body) if len(ret) == 0 { panic("no return value specified for SendLpa") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *donordata.Provided) error); ok { - r0 = rf(ctx, donor) + if rf, ok := ret.Get(0).(func(context.Context, string, lpastore.CreateLpa) error); ok { + r0 = rf(ctx, uid, body) } else { r0 = ret.Error(0) } @@ -108,14 +108,15 @@ type mockLpaStoreClient_SendLpa_Call struct { // SendLpa is a helper method to define mock.On call // - ctx context.Context -// - donor *donordata.Provided -func (_e *mockLpaStoreClient_Expecter) SendLpa(ctx interface{}, donor interface{}) *mockLpaStoreClient_SendLpa_Call { - return &mockLpaStoreClient_SendLpa_Call{Call: _e.mock.On("SendLpa", ctx, donor)} +// - uid string +// - body lpastore.CreateLpa +func (_e *mockLpaStoreClient_Expecter) SendLpa(ctx interface{}, uid interface{}, body interface{}) *mockLpaStoreClient_SendLpa_Call { + return &mockLpaStoreClient_SendLpa_Call{Call: _e.mock.On("SendLpa", ctx, uid, body)} } -func (_c *mockLpaStoreClient_SendLpa_Call) Run(run func(ctx context.Context, donor *donordata.Provided)) *mockLpaStoreClient_SendLpa_Call { +func (_c *mockLpaStoreClient_SendLpa_Call) Run(run func(ctx context.Context, uid string, body lpastore.CreateLpa)) *mockLpaStoreClient_SendLpa_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*donordata.Provided)) + run(args[0].(context.Context), args[1].(string), args[2].(lpastore.CreateLpa)) }) return _c } @@ -125,7 +126,7 @@ func (_c *mockLpaStoreClient_SendLpa_Call) Return(_a0 error) *mockLpaStoreClient return _c } -func (_c *mockLpaStoreClient_SendLpa_Call) RunAndReturn(run func(context.Context, *donordata.Provided) error) *mockLpaStoreClient_SendLpa_Call { +func (_c *mockLpaStoreClient_SendLpa_Call) RunAndReturn(run func(context.Context, string, lpastore.CreateLpa) error) *mockLpaStoreClient_SendLpa_Call { _c.Call.Return(run) return _c } diff --git a/cmd/event-received/sirius_event_handler.go b/cmd/event-received/sirius_event_handler.go index 10b4963ba5..7a66799c49 100644 --- a/cmd/event-received/sirius_event_handler.go +++ b/cmd/event-received/sirius_event_handler.go @@ -13,6 +13,7 @@ import ( "github.com/ministryofjustice/opg-modernising-lpa/internal/dynamo" "github.com/ministryofjustice/opg-modernising-lpa/internal/event" "github.com/ministryofjustice/opg-modernising-lpa/internal/localize" + "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore" "github.com/ministryofjustice/opg-modernising-lpa/internal/notify" "github.com/ministryofjustice/opg-modernising-lpa/internal/pay" "github.com/ministryofjustice/opg-modernising-lpa/internal/sharecode" @@ -126,7 +127,7 @@ func handleFeeApproved( donor.Tasks.PayForLpa = task.PaymentStateCompleted if donor.Tasks.SignTheLpa.IsCompleted() { - if err := lpaStoreClient.SendLpa(ctx, donor); err != nil { + if err := lpaStoreClient.SendLpa(ctx, donor.LpaUID, lpastore.CreateLpaFromDonorProvided(donor)); err != nil { return fmt.Errorf("failed to send to lpastore: %w", err) } @@ -229,16 +230,19 @@ func handleDonorSubmissionCompleted(ctx context.Context, client dynamodbClient, lpaID := uuidString() + donor := &donordata.Provided{ + PK: dynamo.LpaKey(lpaID), + SK: dynamo.LpaOwnerKey(dynamo.DonorKey("PAPER")), + LpaID: lpaID, + LpaUID: v.UID, + CreatedAt: now(), + Version: 1, + } + transaction := dynamo.NewTransaction(). - Create(&donordata.Provided{ - PK: dynamo.LpaKey(lpaID), - SK: dynamo.LpaOwnerKey(dynamo.DonorKey("PAPER")), - LpaID: lpaID, - LpaUID: v.UID, - CreatedAt: now(), - Version: 1, - }). - Create(dynamo.Keys{PK: dynamo.UIDKey(v.UID), SK: dynamo.MetadataKey("")}) + Create(donor). + Create(dynamo.Keys{PK: dynamo.UIDKey(v.UID), SK: dynamo.MetadataKey("")}). + Create(dynamo.Keys{PK: donor.PK, SK: dynamo.ReservedKey(dynamo.DonorKey)}) if err := client.WriteTransaction(ctx, transaction); err != nil { return err diff --git a/cmd/event-received/sirius_event_handler_test.go b/cmd/event-received/sirius_event_handler_test.go index c4c49407d4..916808ee0e 100644 --- a/cmd/event-received/sirius_event_handler_test.go +++ b/cmd/event-received/sirius_event_handler_test.go @@ -16,6 +16,7 @@ import ( "github.com/ministryofjustice/opg-modernising-lpa/internal/dynamo" "github.com/ministryofjustice/opg-modernising-lpa/internal/event" "github.com/ministryofjustice/opg-modernising-lpa/internal/localize" + "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore" "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore/lpadata" "github.com/ministryofjustice/opg-modernising-lpa/internal/notify" "github.com/ministryofjustice/opg-modernising-lpa/internal/pay" @@ -141,7 +142,7 @@ func TestHandleFeeApproved(t *testing.T) { lpaStoreClient := newMockLpaStoreClient(t) lpaStoreClient.EXPECT(). - SendLpa(ctx, &completedDonorProvided). + SendLpa(ctx, completedDonorProvided.LpaUID, lpastore.CreateLpaFromDonorProvided(&completedDonorProvided)). Return(nil) eventClient := newMockEventClient(t) @@ -418,7 +419,7 @@ func TestHandleFeeApprovedWhenShareCodeSenderError(t *testing.T) { lpaStoreClient := newMockLpaStoreClient(t) lpaStoreClient.EXPECT(). - SendLpa(mock.Anything, mock.Anything). + SendLpa(mock.Anything, mock.Anything, mock.Anything). Return(nil) eventClient := newMockEventClient(t) @@ -464,7 +465,7 @@ func TestHandleFeeApprovedWhenEventClientError(t *testing.T) { lpaStoreClient := newMockLpaStoreClient(t) lpaStoreClient.EXPECT(). - SendLpa(mock.Anything, mock.Anything). + SendLpa(mock.Anything, mock.Anything, mock.Anything). Return(nil) eventClient := newMockEventClient(t) @@ -505,7 +506,7 @@ func TestHandleFeeApprovedWhenLpaStoreError(t *testing.T) { lpaStoreClient := newMockLpaStoreClient(t) lpaStoreClient.EXPECT(). - SendLpa(ctx, mock.Anything). + SendLpa(ctx, mock.Anything, mock.Anything). Return(expectedError) err := handleFeeApproved(ctx, client, event, nil, lpaStoreClient, nil, appcontext.Data{}, testNowFn) @@ -763,6 +764,7 @@ func TestHandleDonorSubmissionCompleted(t *testing.T) { Version: 1, }, dynamo.Keys{PK: dynamo.UIDKey("M-1111-2222-3333"), SK: dynamo.MetadataKey("")}, + dynamo.Keys{PK: dynamo.LpaKey(testUuidString), SK: dynamo.ReservedKey(dynamo.DonorKey)}, }, }). Return(nil) diff --git a/cypress/e2e/attorney/confirm-your-details.cy.js b/cypress/e2e/attorney/confirm-your-details.cy.js index a28a6ac9b1..fe7124c878 100644 --- a/cypress/e2e/attorney/confirm-your-details.cy.js +++ b/cypress/e2e/attorney/confirm-your-details.cy.js @@ -1,27 +1,126 @@ -import { TestMobile } from '../../support/e2e'; +import { TestMobile, TestMobile2 } from '../../support/e2e'; describe('Confirm your details', () => { - beforeEach(() => { - cy.visit('/fixtures/attorney?redirect=/phone-number'); + describe('online donor', () => { + beforeEach(() => { + cy.visit('/fixtures/attorney?redirect=/task-list'); - cy.get('#f-phone').type(TestMobile); - cy.contains('button', 'Save and continue').click(); + cy.contains('li', 'Confirm your details').should('contain', 'Not started').click(); - cy.get('[name="language-preference"]').check('cy', { force: true }) - cy.contains('button', 'Save and continue').click() - }); + cy.get('#f-phone').type(TestMobile); + cy.contains('button', 'Save and continue').click(); - it('shows details', () => { - cy.url().should('contain', '/confirm-your-details'); - cy.checkA11yApp(); + cy.get('[name="language-preference"]').check('cy', { force: true }) + cy.contains('button', 'Save and continue').click() + }); - cy.contains('2 January 2000'); - cy.contains('Jessie Jones'); - cy.contains('2 RICHMOND PLACE'); - cy.contains('07700 900 000'); - cy.contains('Welsh'); + it('shows details', () => { + cy.url().should('contain', '/confirm-your-details'); + cy.checkA11yApp(); - cy.contains('button', 'Continue').click(); - cy.url().should('contain', '/task-list'); - }); + cy.contains('2 January 2000'); + cy.contains('Jessie Jones'); + cy.contains('2 RICHMOND PLACE'); + cy.contains('07700 900 000'); + cy.contains('Welsh'); + + cy.contains('button', 'Continue').click(); + cy.url().should('contain', '/task-list'); + }); + }); + + describe('paper donor', () => { + beforeEach(() => { + cy.visit('/fixtures/attorney?is-paper-donor=1&redirect=/task-list'); + + cy.contains('li', 'Confirm your details').should('contain', 'Not started').click(); + + cy.get('#f-phone').type(TestMobile); + cy.contains('button', 'Save and continue').click(); + + cy.get('[name="language-preference"]').check('cy', { force: true }) + cy.contains('button', 'Save and continue').click() + }); + + it('shows details', () => { + cy.url().should('contain', '/confirm-your-details'); + cy.checkA11yApp(); + + cy.contains('2 January 2000'); + cy.contains('Jessie Jones'); + cy.contains('2 RICHMOND PLACE'); + cy.contains('07700 900 000'); + cy.contains('Welsh'); + + cy.contains('button', 'Continue').click(); + cy.url().should('contain', '/task-list'); + }); + }); + + describe('paper donor gave phone number', () => { + beforeEach(() => { + cy.visit('/fixtures/attorney?is-paper-donor=1&has-phone-number=1&redirect=/task-list'); + + cy.contains('li', 'Confirm your details').should('contain', 'Not started').click(); + + cy.get('[name="language-preference"]').check('cy', { force: true }) + cy.contains('button', 'Save and continue').click() + }); + + it('shows details', () => { + cy.url().should('contain', '/confirm-your-details'); + cy.checkA11yApp(); + + cy.contains('h2', 'Details you have given us').next().within(() => { + cy.contains('Welsh'); + cy.contains('Phone number').should('not.exist'); + }); + + cy.contains('h2', 'Details the donor has given about you').next().within(() => { + cy.contains('2 January 2000'); + cy.contains('Jessie Jones'); + cy.contains('2 RICHMOND PLACE'); + cy.contains('07700 900 000'); + }); + + cy.contains('button', 'Continue').click(); + cy.url().should('contain', '/task-list'); + }); + + it('can change the phone number', () => { + cy.contains('.govuk-summary-list__row', 'Phone number').contains('a', 'Change').click(); + cy.get('#f-phone').clear().type(TestMobile2); + cy.contains('button', 'Save and continue').click() + + cy.contains('h2', 'Details you have given us').next().within(() => { + cy.contains('07700 900 111'); + cy.contains('Welsh'); + }); + + cy.contains('h2', 'Details the donor has given about you').next().within(() => { + cy.contains('2 January 2000'); + cy.contains('Jessie Jones'); + cy.contains('2 RICHMOND PLACE'); + cy.contains('Phone number').should('not.exist'); + }); + }); + + it('can remove the phone number', () => { + cy.contains('.govuk-summary-list__row', 'Phone number').contains('a', 'Change').click(); + cy.get('#f-phone').clear(); + cy.contains('button', 'Save and continue').click() + + cy.contains('h2', 'Details you have given us').next().within(() => { + cy.contains('Enter phone number'); + cy.contains('Welsh'); + }); + + cy.contains('h2', 'Details the donor has given about you').next().within(() => { + cy.contains('2 January 2000'); + cy.contains('Jessie Jones'); + cy.contains('2 RICHMOND PLACE'); + cy.contains('Phone number').should('not.exist'); + }); + }); + }); }); diff --git a/cypress/support/e2e.js b/cypress/support/e2e.js index b4ad04f8c9..f8a8dd510a 100644 --- a/cypress/support/e2e.js +++ b/cypress/support/e2e.js @@ -5,7 +5,8 @@ import "cypress-real-events" export const TestEmail = 'simulate-delivered@notifications.service.gov.uk', TestEmail2 = 'simulate-delivered-2@notifications.service.gov.uk', - TestMobile = '07700900000' + TestMobile = '07700900000', + TestMobile2 = '07700900111'; export function randomShareCode() { const characters = 'abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789' diff --git a/internal/app/app.go b/internal/app/app.go index 47e39bdb45..cd7372ea01 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -133,7 +133,7 @@ func App( handleRoot(page.PathCertificateProviderFixtures, None, fixtures.CertificateProvider(tmpls.Get("certificate_provider_fixtures.gohtml"), sessionStore, shareCodeSender, donorStore, certificateProviderStore, eventClient, lpaStoreClient, lpaDynamoClient, organisationStore, memberStore, shareCodeStore)) handleRoot(page.PathAttorneyFixtures, None, - fixtures.Attorney(tmpls.Get("attorney_fixtures.gohtml"), sessionStore, shareCodeSender, donorStore, certificateProviderStore, attorneyStore, eventClient, lpaStoreClient, organisationStore, memberStore, shareCodeStore)) + fixtures.Attorney(tmpls.Get("attorney_fixtures.gohtml"), sessionStore, shareCodeSender, donorStore, certificateProviderStore, attorneyStore, eventClient, lpaStoreClient, organisationStore, memberStore, shareCodeStore, lpaDynamoClient)) handleRoot(page.PathSupporterFixtures, None, fixtures.Supporter(tmpls.Get("supporter_fixtures.gohtml"), sessionStore, organisationStore, donorStore, memberStore, lpaDynamoClient, searchClient, shareCodeStore, certificateProviderStore, attorneyStore, documentStore, eventClient, lpaStoreClient)) handleRoot(page.PathVoucherFixtures, None, diff --git a/internal/attorney/attorneydata/provided.go b/internal/attorney/attorneydata/provided.go index b3c4d988c1..9fe2060ec4 100644 --- a/internal/attorney/attorneydata/provided.go +++ b/internal/attorney/attorneydata/provided.go @@ -30,6 +30,9 @@ type Provided struct { IsTrustCorporation bool // Phone number of the attorney or replacement attorney (mobile or landline) Phone string + // PhoneSet is set to true when Phone is first set, then we can determine if + // the attorney has chosen to remove the number a paper donor provided. + PhoneSet bool // SignedAt is when the attorney or replacement attorney submitted their // signature SignedAt time.Time diff --git a/internal/attorney/attorneypage/confirm_dont_want_to_be_attorney.go b/internal/attorney/attorneypage/confirm_dont_want_to_be_attorney.go index dba961df38..4379f9bd53 100644 --- a/internal/attorney/attorneypage/confirm_dont_want_to_be_attorney.go +++ b/internal/attorney/attorneypage/confirm_dont_want_to_be_attorney.go @@ -20,20 +20,15 @@ type confirmDontWantToBeAttorneyData struct { Lpa *lpadata.Lpa } -func ConfirmDontWantToBeAttorney(tmpl template.Template, lpaStoreResolvingService LpaStoreResolvingService, attorneyStore AttorneyStore, notifyClient NotifyClient, appPublicURL string, lpaStoreClient LpaStoreClient) Handler { - return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, attorneyProvidedDetails *attorneydata.Provided) error { - lpa, err := lpaStoreResolvingService.Get(r.Context()) - if err != nil { - return err - } - +func ConfirmDontWantToBeAttorney(tmpl template.Template, attorneyStore AttorneyStore, notifyClient NotifyClient, appPublicURL string, lpaStoreClient LpaStoreClient) Handler { + return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, attorneyProvidedDetails *attorneydata.Provided, lpa *lpadata.Lpa) error { data := &confirmDontWantToBeAttorneyData{ App: appData, Lpa: lpa, } if r.Method == http.MethodPost { - fullName, actorType := lpa.Attorney(attorneyProvidedDetails.UID) + fullName, _, actorType := lpa.Attorney(attorneyProvidedDetails.UID) if actorType.IsNone() { return errors.New("attorney not found") } diff --git a/internal/attorney/attorneypage/confirm_dont_want_to_be_attorney_logged_out.go b/internal/attorney/attorneypage/confirm_dont_want_to_be_attorney_logged_out.go index 8496a258d5..096c7653d1 100644 --- a/internal/attorney/attorneypage/confirm_dont_want_to_be_attorney_logged_out.go +++ b/internal/attorney/attorneypage/confirm_dont_want_to_be_attorney_logged_out.go @@ -45,7 +45,7 @@ func ConfirmDontWantToBeAttorneyLoggedOut(tmpl template.Template, shareCodeStore return err } - fullName, actorType := lpa.Attorney(shareCode.ActorUID) + fullName, _, actorType := lpa.Attorney(shareCode.ActorUID) if actorType.IsNone() { return errors.New("attorney not found") } diff --git a/internal/attorney/attorneypage/confirm_dont_want_to_be_attorney_test.go b/internal/attorney/attorneypage/confirm_dont_want_to_be_attorney_test.go index e34db95ffe..a075dfc628 100644 --- a/internal/attorney/attorneypage/confirm_dont_want_to_be_attorney_test.go +++ b/internal/attorney/attorneypage/confirm_dont_want_to_be_attorney_test.go @@ -23,59 +23,33 @@ func TestGetConfirmDontWantToBeAttorney(t *testing.T) { w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodGet, "/", nil) - lpa := lpadata.Lpa{LpaUID: "lpa-uid"} - - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpa, nil) + lpa := &lpadata.Lpa{LpaUID: "lpa-uid"} template := newMockTemplate(t) template.EXPECT(). Execute(w, &confirmDontWantToBeAttorneyData{ App: testAppData, - Lpa: &lpa, + Lpa: lpa, }). Return(nil) - err := ConfirmDontWantToBeAttorney(template.Execute, lpaStoreResolvingService, nil, nil, "example.com", nil)(testAppData, w, r, &attorneydata.Provided{}) + err := ConfirmDontWantToBeAttorney(template.Execute, nil, nil, "example.com", nil)(testAppData, w, r, &attorneydata.Provided{}, lpa) resp := w.Result() assert.Nil(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode) } -func TestGetConfirmDontWantToBeAttorneyWhenLpaStoreResolvingServiceErrors(t *testing.T) { - w := httptest.NewRecorder() - r, _ := http.NewRequest(http.MethodGet, "/", nil) - - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(mock.Anything). - Return(&lpadata.Lpa{}, expectedError) - - err := ConfirmDontWantToBeAttorney(nil, lpaStoreResolvingService, nil, nil, "example.com", nil)(testAppData, w, r, &attorneydata.Provided{}) - resp := w.Result() - - assert.Equal(t, expectedError, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) -} - func TestGetConfirmDontWantToBeAttorneyWhenTemplateErrors(t *testing.T) { w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodGet, "/", nil) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(mock.Anything). - Return(&lpadata.Lpa{}, nil) - template := newMockTemplate(t) template.EXPECT(). Execute(mock.Anything, mock.Anything). Return(expectedError) - err := ConfirmDontWantToBeAttorney(template.Execute, lpaStoreResolvingService, nil, nil, "example.com", nil)(testAppData, w, r, &attorneydata.Provided{}) + err := ConfirmDontWantToBeAttorney(template.Execute, nil, nil, "example.com", nil)(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{}) resp := w.Result() assert.Equal(t, expectedError, err) @@ -102,11 +76,6 @@ func TestPostConfirmDontWantToBeAttorney(t *testing.T) { Type: lpadata.LpaTypePersonalWelfare, } - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(lpa, nil) - certificateProviderStore := newMockAttorneyStore(t) certificateProviderStore.EXPECT(). Delete(r.Context()). @@ -139,9 +108,9 @@ func TestPostConfirmDontWantToBeAttorney(t *testing.T) { SendAttorneyOptOut(r.Context(), "lpa-uid", uid, actor.TypeAttorney). Return(nil) - err := ConfirmDontWantToBeAttorney(nil, lpaStoreResolvingService, certificateProviderStore, notifyClient, "example.com", lpaStoreClient)(testAppData, w, r, &attorneydata.Provided{ + err := ConfirmDontWantToBeAttorney(nil, certificateProviderStore, notifyClient, "example.com", lpaStoreClient)(testAppData, w, r, &attorneydata.Provided{ UID: uid, - }) + }, lpa) resp := w.Result() @@ -155,20 +124,15 @@ func TestPostConfirmDontWantToBeAttorneyWhenAttorneyNotFound(t *testing.T) { w := httptest.NewRecorder() uid := actoruid.New() - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{ - LpaUID: "lpa-uid", - SignedAt: time.Now(), - Donor: lpadata.Donor{ - FirstNames: "a b", LastName: "c", Email: "a@example.com", - }, - Type: lpadata.LpaTypePersonalWelfare, - }, nil) - - err := ConfirmDontWantToBeAttorney(nil, lpaStoreResolvingService, nil, nil, "example.com", nil)(testAppData, w, r, &attorneydata.Provided{ + err := ConfirmDontWantToBeAttorney(nil, nil, nil, "example.com", nil)(testAppData, w, r, &attorneydata.Provided{ UID: uid, + }, &lpadata.Lpa{ + LpaUID: "lpa-uid", + SignedAt: time.Now(), + Donor: lpadata.Donor{ + FirstNames: "a b", LastName: "c", Email: "a@example.com", + }, + Type: lpadata.LpaTypePersonalWelfare, }) assert.EqualError(t, err, "attorney not found") } @@ -248,11 +212,6 @@ func TestPostConfirmDontWantToBeAttorneyErrors(t *testing.T) { t.Run(name, func(t *testing.T) { w := httptest.NewRecorder() - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{LpaUID: "lpa-uid", SignedAt: time.Now()}, nil) - localizer := newMockLocalizer(t) localizer.EXPECT(). T(mock.Anything). @@ -260,7 +219,7 @@ func TestPostConfirmDontWantToBeAttorneyErrors(t *testing.T) { testAppData.Localizer = localizer - err := ConfirmDontWantToBeAttorney(nil, lpaStoreResolvingService, evalT(tc.attorneyStore, t), evalT(tc.notifyClient, t), "example.com", evalT(tc.lpaStoreClient, t))(testAppData, w, r, &attorneydata.Provided{}) + err := ConfirmDontWantToBeAttorney(nil, evalT(tc.attorneyStore, t), evalT(tc.notifyClient, t), "example.com", evalT(tc.lpaStoreClient, t))(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{LpaUID: "lpa-uid", SignedAt: time.Now()}) resp := w.Result() diff --git a/internal/attorney/attorneypage/confirm_your_details.go b/internal/attorney/attorneypage/confirm_your_details.go index a20f45ffc1..1f8f874cec 100644 --- a/internal/attorney/attorneypage/confirm_your_details.go +++ b/internal/attorney/attorneypage/confirm_your_details.go @@ -19,29 +19,28 @@ type confirmYourDetailsData struct { Attorney lpadata.Attorney TrustCorporation lpadata.TrustCorporation AttorneyProvidedDetails *attorneydata.Provided + DonorProvidedMobile string } -func ConfirmYourDetails(tmpl template.Template, attorneyStore AttorneyStore, lpaStoreResolvingService LpaStoreResolvingService) Handler { - return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, attorneyProvidedDetails *attorneydata.Provided) error { +func ConfirmYourDetails(tmpl template.Template, attorneyStore AttorneyStore) Handler { + return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, provided *attorneydata.Provided, lpa *lpadata.Lpa) error { if r.Method == http.MethodPost { - attorneyProvidedDetails.Tasks.ConfirmYourDetails = task.StateCompleted + provided.Tasks.ConfirmYourDetails = task.StateCompleted - if err := attorneyStore.Put(r.Context(), attorneyProvidedDetails); err != nil { + if err := attorneyStore.Put(r.Context(), provided); err != nil { return err } - return attorney.PathTaskList.Redirect(w, r, appData, attorneyProvidedDetails.LpaID) + return attorney.PathTaskList.Redirect(w, r, appData, provided.LpaID) } - lpa, err := lpaStoreResolvingService.Get(r.Context()) - if err != nil { - return err - } + _, mobile, _ := lpa.Attorney(provided.UID) data := &confirmYourDetailsData{ App: appData, Lpa: lpa, - AttorneyProvidedDetails: attorneyProvidedDetails, + AttorneyProvidedDetails: provided, + DonorProvidedMobile: mobile, } attorneys := lpa.Attorneys @@ -52,7 +51,7 @@ func ConfirmYourDetails(tmpl template.Template, attorneyStore AttorneyStore, lpa if appData.IsTrustCorporation() { data.TrustCorporation = attorneys.TrustCorporation } else { - data.Attorney, _ = attorneys.Get(attorneyProvidedDetails.UID) + data.Attorney, _ = attorneys.Get(provided.UID) } return tmpl(w, data) diff --git a/internal/attorney/attorneypage/confirm_your_details_test.go b/internal/attorney/attorneypage/confirm_your_details_test.go index 72c522633a..248d29eb10 100644 --- a/internal/attorney/attorneypage/confirm_your_details_test.go +++ b/internal/attorney/attorneypage/confirm_your_details_test.go @@ -17,16 +17,16 @@ import ( func TestGetConfirmYourDetails(t *testing.T) { uid := actoruid.New() - attorneyProvidedDetails := &attorneydata.Provided{UID: uid} + provided := &attorneydata.Provided{UID: uid} testcases := map[string]struct { appData appcontext.Data - donor *lpadata.Lpa + lpa *lpadata.Lpa data *confirmYourDetailsData }{ "attorney": { appData: testAppData, - donor: &lpadata.Lpa{ + lpa: &lpadata.Lpa{ Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid, FirstNames: "John"}}}, }, data: &confirmYourDetailsData{ @@ -35,12 +35,12 @@ func TestGetConfirmYourDetails(t *testing.T) { Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid, FirstNames: "John"}}}, }, Attorney: lpadata.Attorney{UID: uid, FirstNames: "John"}, - AttorneyProvidedDetails: attorneyProvidedDetails, + AttorneyProvidedDetails: provided, }, }, "trust corporation": { appData: testTrustCorporationAppData, - donor: &lpadata.Lpa{ + lpa: &lpadata.Lpa{ Attorneys: lpadata.Attorneys{TrustCorporation: lpadata.TrustCorporation{Name: "company"}}, }, data: &confirmYourDetailsData{ @@ -49,7 +49,7 @@ func TestGetConfirmYourDetails(t *testing.T) { Attorneys: lpadata.Attorneys{TrustCorporation: lpadata.TrustCorporation{Name: "company"}}, }, TrustCorporation: lpadata.TrustCorporation{Name: "company"}, - AttorneyProvidedDetails: attorneyProvidedDetails, + AttorneyProvidedDetails: provided, }, }, } @@ -59,17 +59,12 @@ func TestGetConfirmYourDetails(t *testing.T) { w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodGet, "/", nil) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(tc.donor, nil) - template := newMockTemplate(t) template.EXPECT(). Execute(w, tc.data). Return(nil) - err := ConfirmYourDetails(template.Execute, nil, lpaStoreResolvingService)(tc.appData, w, r, attorneyProvidedDetails) + err := ConfirmYourDetails(template.Execute, nil)(tc.appData, w, r, provided, tc.lpa) resp := w.Result() assert.Nil(t, err) @@ -78,37 +73,16 @@ func TestGetConfirmYourDetails(t *testing.T) { } } -func TestGetConfirmYourDetailsWhenLpaStoreResolvingServiceErrors(t *testing.T) { - w := httptest.NewRecorder() - r, _ := http.NewRequest(http.MethodGet, "/", nil) - - donor := &lpadata.Lpa{} - - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(donor, expectedError) - - err := ConfirmYourDetails(nil, nil, lpaStoreResolvingService)(testAppData, w, r, nil) - - assert.Equal(t, expectedError, err) -} - func TestGetConfirmYourDetailsWhenTemplateErrors(t *testing.T) { w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodGet, "/", nil) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{}, nil) - template := newMockTemplate(t) template.EXPECT(). Execute(w, mock.Anything). Return(expectedError) - err := ConfirmYourDetails(template.Execute, nil, lpaStoreResolvingService)(testAppData, w, r, &attorneydata.Provided{}) + err := ConfirmYourDetails(template.Execute, nil)(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{}) assert.Equal(t, expectedError, err) } @@ -127,7 +101,7 @@ func TestPostConfirmYourDetails(t *testing.T) { }). Return(nil) - err := ConfirmYourDetails(nil, attorneyStore, nil)(testAppData, w, r, &attorneydata.Provided{UID: uid, LpaID: "lpa-id"}) + err := ConfirmYourDetails(nil, attorneyStore)(testAppData, w, r, &attorneydata.Provided{UID: uid, LpaID: "lpa-id"}, &lpadata.Lpa{}) resp := w.Result() assert.Nil(t, err) @@ -144,6 +118,6 @@ func TestPostConfirmYourDetailsWhenStoreErrors(t *testing.T) { Put(r.Context(), mock.Anything). Return(expectedError) - err := ConfirmYourDetails(nil, attorneyStore, nil)(testAppData, w, r, &attorneydata.Provided{UID: actoruid.New(), LpaID: "lpa-id"}) + err := ConfirmYourDetails(nil, attorneyStore)(testAppData, w, r, &attorneydata.Provided{UID: actoruid.New(), LpaID: "lpa-id"}, &lpadata.Lpa{}) assert.Equal(t, expectedError, err) } diff --git a/internal/attorney/attorneypage/guidance.go b/internal/attorney/attorneypage/guidance.go index 5228a1b08b..c0717a7216 100644 --- a/internal/attorney/attorneypage/guidance.go +++ b/internal/attorney/attorneypage/guidance.go @@ -16,18 +16,11 @@ type guidanceData struct { Lpa *lpadata.Lpa } -func Guidance(tmpl template.Template, lpaStoreResolvingService LpaStoreResolvingService) Handler { - return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, _ *attorneydata.Provided) error { +func Guidance(tmpl template.Template) Handler { + return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, _ *attorneydata.Provided, lpa *lpadata.Lpa) error { data := &guidanceData{ App: appData, - } - - if lpaStoreResolvingService != nil { - lpa, err := lpaStoreResolvingService.Get(r.Context()) - if err != nil { - return err - } - data.Lpa = lpa + Lpa: lpa, } return tmpl(w, data) diff --git a/internal/attorney/attorneypage/guidance_test.go b/internal/attorney/attorneypage/guidance_test.go index b138da0bcf..9f5cd7f4f5 100644 --- a/internal/attorney/attorneypage/guidance_test.go +++ b/internal/attorney/attorneypage/guidance_test.go @@ -13,73 +13,29 @@ func TestGuidance(t *testing.T) { w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodGet, "/", nil) - donor := &lpadata.Lpa{} - - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(donor, nil) - - template := newMockTemplate(t) - template.EXPECT(). - Execute(w, &guidanceData{App: testAppData, Lpa: donor}). - Return(nil) - - err := Guidance(template.Execute, lpaStoreResolvingService)(testAppData, w, r, nil) - resp := w.Result() - - assert.Nil(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) -} - -func TestGuidanceWhenNilDataStores(t *testing.T) { - w := httptest.NewRecorder() + lpa := &lpadata.Lpa{} template := newMockTemplate(t) template.EXPECT(). - Execute(w, &guidanceData{App: testAppData}). + Execute(w, &guidanceData{App: testAppData, Lpa: lpa}). Return(nil) - r, _ := http.NewRequest(http.MethodGet, "/", nil) - - err := Guidance(template.Execute, nil)(testAppData, w, r, nil) + err := Guidance(template.Execute)(testAppData, w, r, nil, lpa) resp := w.Result() assert.Nil(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode) } -func TestGuidanceWhenLpaStoreResolvingServiceErrors(t *testing.T) { - w := httptest.NewRecorder() - r, _ := http.NewRequest(http.MethodGet, "/", nil) - - donor := &lpadata.Lpa{} - - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(donor, expectedError) - - err := Guidance(nil, lpaStoreResolvingService)(testAppData, w, r, nil) - - assert.Equal(t, expectedError, err) -} - func TestGuidanceWhenTemplateErrors(t *testing.T) { w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodGet, "/", nil) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{}, nil) - template := newMockTemplate(t) template.EXPECT(). Execute(w, &guidanceData{App: testAppData, Lpa: &lpadata.Lpa{}}). Return(expectedError) - err := Guidance(template.Execute, lpaStoreResolvingService)(testAppData, w, r, nil) - + err := Guidance(template.Execute)(testAppData, w, r, nil, &lpadata.Lpa{}) assert.Equal(t, expectedError, err) } diff --git a/internal/attorney/attorneypage/phone_number.go b/internal/attorney/attorneypage/phone_number.go index 084dc16c47..4a4bffdc54 100644 --- a/internal/attorney/attorneypage/phone_number.go +++ b/internal/attorney/attorneypage/phone_number.go @@ -25,11 +25,16 @@ type phoneNumberForm struct { } func PhoneNumber(tmpl template.Template, attorneyStore AttorneyStore) Handler { - return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, attorneyProvidedDetails *attorneydata.Provided) error { + return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, provided *attorneydata.Provided, lpa *lpadata.Lpa) error { + _, mobile, _ := lpa.Attorney(provided.UID) + if provided.PhoneSet { + mobile = provided.Phone + } + data := &phoneNumberData{ App: appData, Form: &phoneNumberForm{ - Phone: attorneyProvidedDetails.Phone, + Phone: mobile, }, } @@ -38,16 +43,17 @@ func PhoneNumber(tmpl template.Template, attorneyStore AttorneyStore) Handler { data.Errors = data.Form.Validate() if data.Errors.None() { - attorneyProvidedDetails.Phone = data.Form.Phone - if attorneyProvidedDetails.Tasks.ConfirmYourDetails == task.StateNotStarted { - attorneyProvidedDetails.Tasks.ConfirmYourDetails = task.StateInProgress + provided.Phone = data.Form.Phone + provided.PhoneSet = true + if provided.Tasks.ConfirmYourDetails == task.StateNotStarted { + provided.Tasks.ConfirmYourDetails = task.StateInProgress } - if err := attorneyStore.Put(r.Context(), attorneyProvidedDetails); err != nil { + if err := attorneyStore.Put(r.Context(), provided); err != nil { return err } - return attorney.PathYourPreferredLanguage.Redirect(w, r, appData, attorneyProvidedDetails.LpaID) + return attorney.PathYourPreferredLanguage.Redirect(w, r, appData, provided.LpaID) } } diff --git a/internal/attorney/attorneypage/phone_number_test.go b/internal/attorney/attorneypage/phone_number_test.go index b65ea341b4..0aeb8ee1f7 100644 --- a/internal/attorney/attorneypage/phone_number_test.go +++ b/internal/attorney/attorneypage/phone_number_test.go @@ -10,6 +10,7 @@ import ( "github.com/ministryofjustice/opg-modernising-lpa/internal/appcontext" "github.com/ministryofjustice/opg-modernising-lpa/internal/attorney" "github.com/ministryofjustice/opg-modernising-lpa/internal/attorney/attorneydata" + "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore/lpadata" "github.com/ministryofjustice/opg-modernising-lpa/internal/page" "github.com/ministryofjustice/opg-modernising-lpa/internal/task" "github.com/ministryofjustice/opg-modernising-lpa/internal/validation" @@ -42,7 +43,7 @@ func TestGetPhoneNumber(t *testing.T) { }). Return(nil) - err := PhoneNumber(template.Execute, nil)(tc.appData, w, r, &attorneydata.Provided{}) + err := PhoneNumber(template.Execute, nil)(tc.appData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{}) resp := w.Result() assert.Nil(t, err) @@ -79,7 +80,10 @@ func TestGetPhoneNumberFromStore(t *testing.T) { }). Return(nil) - err := PhoneNumber(template.Execute, nil)(tc.appData, w, r, &attorneydata.Provided{Phone: "07535111222"}) + err := PhoneNumber(template.Execute, nil)(tc.appData, w, r, &attorneydata.Provided{ + Phone: "07535111222", + PhoneSet: true, + }, &lpadata.Lpa{}) resp := w.Result() assert.Nil(t, err) @@ -97,7 +101,7 @@ func TestGetPhoneNumberWhenTemplateErrors(t *testing.T) { Execute(w, mock.Anything). Return(expectedError) - err := PhoneNumber(template.Execute, nil)(testAppData, w, r, &attorneydata.Provided{}) + err := PhoneNumber(template.Execute, nil)(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{}) resp := w.Result() assert.Equal(t, expectedError, err) @@ -117,8 +121,9 @@ func TestPostPhoneNumber(t *testing.T) { }, attorney: &attorneydata.Provided{LpaID: "lpa-id"}, updatedAttorney: &attorneydata.Provided{ - LpaID: "lpa-id", - Phone: "07535111222", + LpaID: "lpa-id", + Phone: "07535111222", + PhoneSet: true, Tasks: attorneydata.Tasks{ ConfirmYourDetails: task.StateInProgress, }, @@ -134,7 +139,8 @@ func TestPostPhoneNumber(t *testing.T) { }, }, updatedAttorney: &attorneydata.Provided{ - LpaID: "lpa-id", + LpaID: "lpa-id", + PhoneSet: true, Tasks: attorneydata.Tasks{ ConfirmYourDetails: task.StateCompleted, }, @@ -146,8 +152,9 @@ func TestPostPhoneNumber(t *testing.T) { }, attorney: &attorneydata.Provided{LpaID: "lpa-id"}, updatedAttorney: &attorneydata.Provided{ - LpaID: "lpa-id", - Phone: "07535111222", + LpaID: "lpa-id", + Phone: "07535111222", + PhoneSet: true, Tasks: attorneydata.Tasks{ ConfirmYourDetails: task.StateInProgress, }, @@ -158,7 +165,8 @@ func TestPostPhoneNumber(t *testing.T) { appData: testReplacementAppData, attorney: &attorneydata.Provided{LpaID: "lpa-id"}, updatedAttorney: &attorneydata.Provided{ - LpaID: "lpa-id", + LpaID: "lpa-id", + PhoneSet: true, Tasks: attorneydata.Tasks{ ConfirmYourDetails: task.StateInProgress, }, @@ -177,7 +185,7 @@ func TestPostPhoneNumber(t *testing.T) { Put(r.Context(), tc.updatedAttorney). Return(nil) - err := PhoneNumber(nil, attorneyStore)(tc.appData, w, r, tc.attorney) + err := PhoneNumber(nil, attorneyStore)(tc.appData, w, r, tc.attorney, &lpadata.Lpa{}) resp := w.Result() assert.Nil(t, err) @@ -207,7 +215,7 @@ func TestPostPhoneNumberWhenValidationError(t *testing.T) { })). Return(nil) - err := PhoneNumber(template.Execute, nil)(testAppData, w, r, &attorneydata.Provided{}) + err := PhoneNumber(template.Execute, nil)(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{}) resp := w.Result() assert.Nil(t, err) @@ -229,7 +237,7 @@ func TestPostPhoneNumberWhenAttorneyStoreErrors(t *testing.T) { Put(r.Context(), mock.Anything). Return(expectedError) - err := PhoneNumber(nil, attorneyStore)(testAppData, w, r, &attorneydata.Provided{}) + err := PhoneNumber(nil, attorneyStore)(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{}) resp := w.Result() assert.Equal(t, expectedError, err) diff --git a/internal/attorney/attorneypage/progress.go b/internal/attorney/attorneypage/progress.go index 8d8d4fd4fc..c23fb62120 100644 --- a/internal/attorney/attorneypage/progress.go +++ b/internal/attorney/attorneypage/progress.go @@ -18,13 +18,8 @@ type progressData struct { AttorneysSigned bool } -func Progress(tmpl template.Template, lpaStoreResolvingService LpaStoreResolvingService) Handler { - return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, attorneyProvidedDetails *attorneydata.Provided) error { - lpa, err := lpaStoreResolvingService.Get(r.Context()) - if err != nil { - return err - } - +func Progress(tmpl template.Template) Handler { + return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, attorneyProvidedDetails *attorneydata.Provided, lpa *lpadata.Lpa) error { data := &progressData{ App: appData, Lpa: lpa, diff --git a/internal/attorney/attorneypage/progress_test.go b/internal/attorney/attorneypage/progress_test.go index 1752d2745a..6815aeef26 100644 --- a/internal/attorney/attorneypage/progress_test.go +++ b/internal/attorney/attorneypage/progress_test.go @@ -16,25 +16,25 @@ func TestProgress(t *testing.T) { attorneySignedAt := lpaSignedAt.Add(time.Second) testcases := map[string]struct { - attorney *attorneydata.Provided + provided *attorneydata.Provided attorneys []lpadata.Attorney signed bool attorneysSigned bool }{ "unsigned": { - attorney: &attorneydata.Provided{}, + provided: &attorneydata.Provided{}, }, "attorney signed": { - attorney: &attorneydata.Provided{ + provided: &attorneydata.Provided{ SignedAt: attorneySignedAt, }, attorneys: []lpadata.Attorney{{}}, signed: true, }, "all signed": { - attorney: &attorneydata.Provided{}, + provided: &attorneydata.Provided{}, attorneys: []lpadata.Attorney{{ - SignedAt: attorneySignedAt, + SignedAt: &attorneySignedAt, }}, attorneysSigned: true, }, @@ -45,22 +45,17 @@ func TestProgress(t *testing.T) { w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodGet, "/", nil) - donor := &lpadata.Lpa{ + lpa := &lpadata.Lpa{ SignedAt: lpaSignedAt, Attorneys: lpadata.Attorneys{Attorneys: tc.attorneys}, } - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(donor, nil) - template := newMockTemplate(t) template.EXPECT(). - Execute(w, &progressData{App: testAppData, Lpa: donor, Signed: tc.signed, AttorneysSigned: tc.attorneysSigned}). + Execute(w, &progressData{App: testAppData, Lpa: lpa, Signed: tc.signed, AttorneysSigned: tc.attorneysSigned}). Return(nil) - err := Progress(template.Execute, lpaStoreResolvingService)(testAppData, w, r, tc.attorney) + err := Progress(template.Execute)(testAppData, w, r, tc.provided, lpa) resp := w.Result() assert.Nil(t, err) @@ -69,35 +64,15 @@ func TestProgress(t *testing.T) { } } -func TestProgressWhenLpaStoreResolvingServiceErrors(t *testing.T) { - w := httptest.NewRecorder() - r, _ := http.NewRequest(http.MethodGet, "/", nil) - - donor := &lpadata.Lpa{} - - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(donor, expectedError) - - err := Progress(nil, lpaStoreResolvingService)(testAppData, w, r, &attorneydata.Provided{}) - assert.Equal(t, expectedError, err) -} - func TestProgressWhenTemplateErrors(t *testing.T) { w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodGet, "/", nil) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{}, nil) - template := newMockTemplate(t) template.EXPECT(). Execute(w, &progressData{App: testAppData, Lpa: &lpadata.Lpa{}}). Return(expectedError) - err := Progress(template.Execute, lpaStoreResolvingService)(testAppData, w, r, &attorneydata.Provided{}) + err := Progress(template.Execute)(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{}) assert.Equal(t, expectedError, err) } diff --git a/internal/attorney/attorneypage/read_the_lpa.go b/internal/attorney/attorneypage/read_the_lpa.go index 880c94ee59..39905f39d9 100644 --- a/internal/attorney/attorneypage/read_the_lpa.go +++ b/internal/attorney/attorneypage/read_the_lpa.go @@ -18,8 +18,8 @@ type readTheLpaData struct { Lpa *lpadata.Lpa } -func ReadTheLpa(tmpl template.Template, lpaStoreResolvingService LpaStoreResolvingService, attorneyStore AttorneyStore) Handler { - return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, attorneyProvidedDetails *attorneydata.Provided) error { +func ReadTheLpa(tmpl template.Template, attorneyStore AttorneyStore) Handler { + return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, attorneyProvidedDetails *attorneydata.Provided, lpa *lpadata.Lpa) error { if r.Method == http.MethodPost { attorneyProvidedDetails.Tasks.ReadTheLpa = task.StateCompleted @@ -30,11 +30,6 @@ func ReadTheLpa(tmpl template.Template, lpaStoreResolvingService LpaStoreResolvi return attorney.PathTaskList.Redirect(w, r, appData, attorneyProvidedDetails.LpaID) } - lpa, err := lpaStoreResolvingService.Get(r.Context()) - if err != nil { - return err - } - data := &readTheLpaData{ App: appData, Lpa: lpa, diff --git a/internal/attorney/attorneypage/read_the_lpa_test.go b/internal/attorney/attorneypage/read_the_lpa_test.go index 2843f251b9..cd0e1d09b9 100644 --- a/internal/attorney/attorneypage/read_the_lpa_test.go +++ b/internal/attorney/attorneypage/read_the_lpa_test.go @@ -7,7 +7,7 @@ import ( "github.com/ministryofjustice/opg-modernising-lpa/internal/actor/actoruid" "github.com/ministryofjustice/opg-modernising-lpa/internal/attorney" - attorneydata "github.com/ministryofjustice/opg-modernising-lpa/internal/attorney/attorneydata" + "github.com/ministryofjustice/opg-modernising-lpa/internal/attorney/attorneydata" "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore/lpadata" "github.com/ministryofjustice/opg-modernising-lpa/internal/task" "github.com/stretchr/testify/assert" @@ -18,11 +18,6 @@ func TestGetReadTheLpaWithAttorney(t *testing.T) { w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodGet, "/", nil) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid}}}}, nil) - template := newMockTemplate(t) template.EXPECT(). Execute(w, &readTheLpaData{ @@ -31,7 +26,7 @@ func TestGetReadTheLpaWithAttorney(t *testing.T) { }). Return(nil) - err := ReadTheLpa(template.Execute, lpaStoreResolvingService, nil)(testAppData, w, r, &attorneydata.Provided{}) + err := ReadTheLpa(template.Execute, nil)(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid}}}}) resp := w.Result() assert.Nil(t, err) @@ -43,11 +38,6 @@ func TestGetReadTheLpaWithReplacementAttorney(t *testing.T) { w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodGet, "/", nil) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{ReplacementAttorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid}}}}, nil) - template := newMockTemplate(t) template.EXPECT(). Execute(w, &readTheLpaData{ @@ -56,40 +46,18 @@ func TestGetReadTheLpaWithReplacementAttorney(t *testing.T) { }). Return(nil) - err := ReadTheLpa(template.Execute, lpaStoreResolvingService, nil)(testReplacementAppData, w, r, &attorneydata.Provided{}) + err := ReadTheLpa(template.Execute, nil)(testReplacementAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{ReplacementAttorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid}}}}) resp := w.Result() assert.Nil(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode) } -func TestGetReadTheLpaWithAttorneyWhenLpaStoreResolvingServiceErrors(t *testing.T) { - uid := actoruid.New() - w := httptest.NewRecorder() - r, _ := http.NewRequest(http.MethodGet, "/", nil) - - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid}}}}, expectedError) - - err := ReadTheLpa(nil, lpaStoreResolvingService, nil)(testAppData, w, r, nil) - resp := w.Result() - - assert.Equal(t, expectedError, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) -} - func TestGetReadTheLpaWhenTemplateError(t *testing.T) { uid := actoruid.New() w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodGet, "/", nil) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid}}}}, nil) - template := newMockTemplate(t) template.EXPECT(). Execute(w, &readTheLpaData{ @@ -98,7 +66,7 @@ func TestGetReadTheLpaWhenTemplateError(t *testing.T) { }). Return(expectedError) - err := ReadTheLpa(template.Execute, lpaStoreResolvingService, nil)(testAppData, w, r, &attorneydata.Provided{}) + err := ReadTheLpa(template.Execute, nil)(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid}}}}) resp := w.Result() assert.Equal(t, expectedError, err) @@ -119,7 +87,7 @@ func TestPostReadTheLpa(t *testing.T) { }). Return(nil) - err := ReadTheLpa(nil, nil, attorneyStore)(testAppData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}) + err := ReadTheLpa(nil, attorneyStore)(testAppData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}, &lpadata.Lpa{}) resp := w.Result() assert.Nil(t, err) diff --git a/internal/attorney/attorneypage/register.go b/internal/attorney/attorneypage/register.go index d71377b72a..1802dd6c37 100644 --- a/internal/attorney/attorneypage/register.go +++ b/internal/attorney/attorneypage/register.go @@ -33,7 +33,7 @@ type LpaStoreResolvingService interface { Get(ctx context.Context) (*lpadata.Lpa, error) } -type Handler func(data appcontext.Data, w http.ResponseWriter, r *http.Request, details *attorneydata.Provided) error +type Handler func(data appcontext.Data, w http.ResponseWriter, r *http.Request, details *attorneydata.Provided, lpa *lpadata.Lpa) error type Template func(io.Writer, interface{}) error @@ -122,35 +122,35 @@ func Register( handleRoot(page.PathAttorneyYouHaveDecidedNotToBeAttorney, None, page.Guidance(tmpls.Get("you_have_decided_not_to_be_attorney.gohtml"))) - handleAttorney := makeAttorneyHandle(rootMux, sessionStore, errorHandler, attorneyStore) + handleAttorney := makeAttorneyHandle(rootMux, sessionStore, errorHandler, attorneyStore, lpaStoreResolvingService) handleAttorney(attorney.PathCodeOfConduct, None, - Guidance(tmpls.Get("code_of_conduct.gohtml"), lpaStoreResolvingService)) + Guidance(tmpls.Get("code_of_conduct.gohtml"))) handleAttorney(attorney.PathTaskList, None, - TaskList(tmpls.Get("task_list.gohtml"), lpaStoreResolvingService)) + TaskList(tmpls.Get("task_list.gohtml"))) handleAttorney(attorney.PathPhoneNumber, None, PhoneNumber(tmpls.Get("phone_number.gohtml"), attorneyStore)) handleAttorney(attorney.PathYourPreferredLanguage, CanGoBack, - YourPreferredLanguage(commonTmpls.Get("your_preferred_language.gohtml"), attorneyStore, lpaStoreResolvingService)) + YourPreferredLanguage(commonTmpls.Get("your_preferred_language.gohtml"), attorneyStore)) handleAttorney(attorney.PathConfirmYourDetails, None, - ConfirmYourDetails(tmpls.Get("confirm_your_details.gohtml"), attorneyStore, lpaStoreResolvingService)) + ConfirmYourDetails(tmpls.Get("confirm_your_details.gohtml"), attorneyStore)) handleAttorney(attorney.PathReadTheLpa, None, - ReadTheLpa(tmpls.Get("read_the_lpa.gohtml"), lpaStoreResolvingService, attorneyStore)) + ReadTheLpa(tmpls.Get("read_the_lpa.gohtml"), attorneyStore)) handleAttorney(attorney.PathRightsAndResponsibilities, None, - Guidance(tmpls.Get("legal_rights_and_responsibilities.gohtml"), nil)) + Guidance(tmpls.Get("legal_rights_and_responsibilities.gohtml"))) handleAttorney(attorney.PathWhatHappensWhenYouSign, CanGoBack, - Guidance(tmpls.Get("what_happens_when_you_sign.gohtml"), lpaStoreResolvingService)) + Guidance(tmpls.Get("what_happens_when_you_sign.gohtml"))) handleAttorney(attorney.PathSign, CanGoBack, - Sign(tmpls.Get("sign.gohtml"), lpaStoreResolvingService, attorneyStore, lpaStoreClient, time.Now)) + Sign(tmpls.Get("sign.gohtml"), attorneyStore, lpaStoreClient, time.Now)) handleAttorney(attorney.PathWouldLikeSecondSignatory, None, - WouldLikeSecondSignatory(tmpls.Get("would_like_second_signatory.gohtml"), attorneyStore, lpaStoreResolvingService, lpaStoreClient)) + WouldLikeSecondSignatory(tmpls.Get("would_like_second_signatory.gohtml"), attorneyStore, lpaStoreClient)) handleAttorney(attorney.PathWhatHappensNext, None, - Guidance(tmpls.Get("what_happens_next.gohtml"), lpaStoreResolvingService)) + Guidance(tmpls.Get("what_happens_next.gohtml"))) handleAttorney(attorney.PathProgress, None, - Progress(tmpls.Get("progress.gohtml"), lpaStoreResolvingService)) + Progress(tmpls.Get("progress.gohtml"))) handleAttorney(attorney.PathConfirmDontWantToBeAttorney, CanGoBack, - ConfirmDontWantToBeAttorney(tmpls.Get("confirm_dont_want_to_be_attorney.gohtml"), lpaStoreResolvingService, attorneyStore, notifyClient, appPublicURL, lpaStoreClient)) + ConfirmDontWantToBeAttorney(tmpls.Get("confirm_dont_want_to_be_attorney.gohtml"), attorneyStore, notifyClient, appPublicURL, lpaStoreClient)) } type handleOpt byte @@ -188,7 +188,7 @@ func makeHandle(mux *http.ServeMux, store SessionStore, errorHandler page.ErrorH } } -func makeAttorneyHandle(mux *http.ServeMux, store SessionStore, errorHandler page.ErrorHandler, attorneyStore AttorneyStore) func(attorney.Path, handleOpt, Handler) { +func makeAttorneyHandle(mux *http.ServeMux, store SessionStore, errorHandler page.ErrorHandler, attorneyStore AttorneyStore, lpaStoreResolvingService LpaStoreResolvingService) func(attorney.Path, handleOpt, Handler) { return func(path attorney.Path, opt handleOpt, h Handler) { mux.HandleFunc(path.String(), func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() @@ -220,7 +220,13 @@ func makeAttorneyHandle(mux *http.ServeMux, store SessionStore, errorHandler pag return } - if !attorney.CanGoTo(provided, r.URL.String()) { + lpa, err := lpaStoreResolvingService.Get(ctx) + if err != nil { + errorHandler(w, r, err) + return + } + + if !path.CanGoTo(provided, lpa) { attorney.PathTaskList.Redirect(w, r, appData, provided.LpaID) return } @@ -237,7 +243,7 @@ func makeAttorneyHandle(mux *http.ServeMux, store SessionStore, errorHandler pag appData.ActorType = actor.TypeAttorney } - if err := h(appData, w, r.WithContext(appcontext.ContextWithData(ctx, appData)), provided); err != nil { + if err := h(appData, w, r.WithContext(appcontext.ContextWithData(ctx, appData)), provided, lpa); err != nil { errorHandler(w, r, err) } }) diff --git a/internal/attorney/attorneypage/register_test.go b/internal/attorney/attorneypage/register_test.go index cb0164d095..0d6ef57fdc 100644 --- a/internal/attorney/attorneypage/register_test.go +++ b/internal/attorney/attorneypage/register_test.go @@ -13,6 +13,7 @@ import ( "github.com/ministryofjustice/opg-modernising-lpa/internal/attorney" "github.com/ministryofjustice/opg-modernising-lpa/internal/attorney/attorneydata" "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore" + "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore/lpadata" "github.com/ministryofjustice/opg-modernising-lpa/internal/page" "github.com/ministryofjustice/opg-modernising-lpa/internal/sesh" "github.com/stretchr/testify/assert" @@ -152,7 +153,9 @@ func TestMakeAttorneyHandleExistingSession(t *testing.T) { uid := actoruid.New() w := httptest.NewRecorder() r, _ := http.NewRequestWithContext(ctx, http.MethodGet, "/attorney/lpa-id/path?a=b", nil) + expectedDetails := &attorneydata.Provided{UID: uid} + expectedLpa := &lpadata.Lpa{LpaID: "lpa-id"} sessionStore := newMockSessionStore(t) sessionStore.EXPECT(). @@ -164,10 +167,16 @@ func TestMakeAttorneyHandleExistingSession(t *testing.T) { Get(mock.Anything). Return(expectedDetails, nil) + lpaStoreResolvingService := newMockLpaStoreResolvingService(t) + lpaStoreResolvingService.EXPECT(). + Get(mock.Anything). + Return(expectedLpa, nil) + mux := http.NewServeMux() - handle := makeAttorneyHandle(mux, sessionStore, nil, attorneyStore) - handle("/path", CanGoBack, func(appData appcontext.Data, hw http.ResponseWriter, hr *http.Request, details *attorneydata.Provided) error { + handle := makeAttorneyHandle(mux, sessionStore, nil, attorneyStore, lpaStoreResolvingService) + handle("/path", CanGoBack, func(appData appcontext.Data, hw http.ResponseWriter, hr *http.Request, details *attorneydata.Provided, lpa *lpadata.Lpa) error { assert.Equal(t, expectedDetails, details) + assert.Equal(t, expectedLpa, lpa) assert.Equal(t, appcontext.Data{ Page: "/attorney/lpa-id/path", @@ -232,9 +241,14 @@ func TestMakeAttorneyHandleExistingLpaData(t *testing.T) { Get(mock.Anything). Return(tc.details, nil) + lpaStoreResolvingService := newMockLpaStoreResolvingService(t) + lpaStoreResolvingService.EXPECT(). + Get(mock.Anything). + Return(&lpadata.Lpa{}, nil) + mux := http.NewServeMux() - handle := makeAttorneyHandle(mux, sessionStore, nil, attorneyStore) - handle("/path", CanGoBack, func(appData appcontext.Data, hw http.ResponseWriter, hr *http.Request, details *attorneydata.Provided) error { + handle := makeAttorneyHandle(mux, sessionStore, nil, attorneyStore, lpaStoreResolvingService) + handle("/path", CanGoBack, func(appData appcontext.Data, hw http.ResponseWriter, hr *http.Request, details *attorneydata.Provided, lpa *lpadata.Lpa) error { assert.Equal(t, tc.details, details) assert.Equal(t, appcontext.Data{ Page: "/attorney/lpa-id/path", @@ -280,11 +294,14 @@ func TestMakeAttorneyHandleExistingSessionWhenCannotGoToURL(t *testing.T) { Get(mock.Anything). Return(expectedDetails, nil) + lpaStoreResolvingService := newMockLpaStoreResolvingService(t) + lpaStoreResolvingService.EXPECT(). + Get(mock.Anything). + Return(&lpadata.Lpa{}, nil) + mux := http.NewServeMux() - handle := makeAttorneyHandle(mux, sessionStore, nil, attorneyStore) - handle(path, CanGoBack, func(appData appcontext.Data, hw http.ResponseWriter, hr *http.Request, details *attorneydata.Provided) error { - return nil - }) + handle := makeAttorneyHandle(mux, sessionStore, nil, attorneyStore, lpaStoreResolvingService) + handle(path, CanGoBack, nil) mux.ServeHTTP(w, r) resp := w.Result() @@ -311,9 +328,14 @@ func TestMakeAttorneyHandleErrors(t *testing.T) { errorHandler.EXPECT(). Execute(w, r, expectedError) + lpaStoreResolvingService := newMockLpaStoreResolvingService(t) + lpaStoreResolvingService.EXPECT(). + Get(mock.Anything). + Return(&lpadata.Lpa{}, nil) + mux := http.NewServeMux() - handle := makeAttorneyHandle(mux, sessionStore, errorHandler.Execute, attorneyStore) - handle("/path", None, func(_ appcontext.Data, _ http.ResponseWriter, _ *http.Request, _ *attorneydata.Provided) error { + handle := makeAttorneyHandle(mux, sessionStore, errorHandler.Execute, attorneyStore, lpaStoreResolvingService) + handle("/path", None, func(_ appcontext.Data, _ http.ResponseWriter, _ *http.Request, _ *attorneydata.Provided, _ *lpadata.Lpa) error { return expectedError }) @@ -339,10 +361,38 @@ func TestMakeAttorneyHandleAttorneyStoreErrors(t *testing.T) { Execute(w, r, expectedError) mux := http.NewServeMux() - handle := makeAttorneyHandle(mux, sessionStore, errorHandler.Execute, attorneyStore) - handle("/path", None, func(_ appcontext.Data, _ http.ResponseWriter, _ *http.Request, _ *attorneydata.Provided) error { - return nil - }) + handle := makeAttorneyHandle(mux, sessionStore, errorHandler.Execute, attorneyStore, nil) + handle("/path", None, nil) + + mux.ServeHTTP(w, r) +} + +func TestMakeAttorneyHandleLpaStoreErrors(t *testing.T) { + w := httptest.NewRecorder() + r, _ := http.NewRequest(http.MethodGet, "/attorney/id/path", nil) + + attorneyStore := newMockAttorneyStore(t) + attorneyStore.EXPECT(). + Get(mock.Anything). + Return(&attorneydata.Provided{}, nil) + + sessionStore := newMockSessionStore(t) + sessionStore.EXPECT(). + Login(r). + Return(&sesh.LoginSession{Sub: "random"}, nil) + + lpaStoreResolvingService := newMockLpaStoreResolvingService(t) + lpaStoreResolvingService.EXPECT(). + Get(mock.Anything). + Return(nil, expectedError) + + errorHandler := newMockErrorHandler(t) + errorHandler.EXPECT(). + Execute(w, r, expectedError) + + mux := http.NewServeMux() + handle := makeAttorneyHandle(mux, sessionStore, errorHandler.Execute, attorneyStore, lpaStoreResolvingService) + handle("/path", None, nil) mux.ServeHTTP(w, r) } @@ -357,10 +407,8 @@ func TestMakeAttorneyHandleSessionError(t *testing.T) { Return(nil, expectedError) mux := http.NewServeMux() - handle := makeAttorneyHandle(mux, sessionStore, nil, nil) - handle("/path", RequireSession, func(_ appcontext.Data, _ http.ResponseWriter, _ *http.Request, _ *attorneydata.Provided) error { - return nil - }) + handle := makeAttorneyHandle(mux, sessionStore, nil, nil, nil) + handle("/path", RequireSession, nil) mux.ServeHTTP(w, r) resp := w.Result() diff --git a/internal/attorney/attorneypage/sign.go b/internal/attorney/attorneypage/sign.go index 250f7c5435..2c4e07d8d3 100644 --- a/internal/attorney/attorneypage/sign.go +++ b/internal/attorney/attorneypage/sign.go @@ -26,14 +26,8 @@ type signData struct { Form *signForm } -func Sign( - tmpl template.Template, - lpaStoreResolvingService LpaStoreResolvingService, - attorneyStore AttorneyStore, - lpaStoreClient LpaStoreClient, - now func() time.Time, -) Handler { - signAttorney := func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, attorneyProvidedDetails *attorneydata.Provided, lpa *lpadata.Lpa) error { +func Sign(tmpl template.Template, attorneyStore AttorneyStore, lpaStoreClient LpaStoreClient, now func() time.Time) Handler { + signAttorney := func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, provided *attorneydata.Provided, lpa *lpadata.Lpa) error { data := &signData{ App: appData, LpaID: lpa.LpaID, @@ -61,22 +55,28 @@ func Sign( data.Errors = data.Form.Validate(appData.IsTrustCorporation(), appData.IsReplacementAttorney()) if data.Errors.None() { - attorneyProvidedDetails.Tasks.SignTheLpa = task.StateCompleted - attorneyProvidedDetails.SignedAt = now() + provided.Tasks.SignTheLpa = task.StateCompleted + provided.SignedAt = now() - if data.Attorney.SignedAt.IsZero() { - if err := lpaStoreClient.SendAttorney(r.Context(), lpa, attorneyProvidedDetails); err != nil { + if !provided.PhoneSet { + if _, mobile, _ := lpa.Attorney(provided.UID); mobile != "" { + provided.Phone = mobile + } + } + + if data.Attorney.SignedAt == nil || data.Attorney.SignedAt.IsZero() { + if err := lpaStoreClient.SendAttorney(r.Context(), lpa, provided); err != nil { return err } } else { - attorneyProvidedDetails.SignedAt = data.Attorney.SignedAt + provided.SignedAt = *data.Attorney.SignedAt } - if err := attorneyStore.Put(r.Context(), attorneyProvidedDetails); err != nil { + if err := attorneyStore.Put(r.Context(), provided); err != nil { return err } - return attorney.PathWhatHappensNext.Redirect(w, r, appData, attorneyProvidedDetails.LpaID) + return attorney.PathWhatHappensNext.Redirect(w, r, appData, provided.LpaID) } } @@ -153,16 +153,11 @@ func Sign( return tmpl(w, data) } - return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, attorneyProvidedDetails *attorneydata.Provided) error { + return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, attorneyProvidedDetails *attorneydata.Provided, lpa *lpadata.Lpa) error { if attorneyProvidedDetails.Signed() { return attorney.PathWhatHappensNext.Redirect(w, r, appData, attorneyProvidedDetails.LpaID) } - lpa, err := lpaStoreResolvingService.Get(r.Context()) - if err != nil { - return err - } - if !lpa.SignedForDonor() || lpa.CertificateProvider.SignedAt.IsZero() { return attorney.PathTaskList.Redirect(w, r, appData, attorneyProvidedDetails.LpaID) } diff --git a/internal/attorney/attorneypage/sign_test.go b/internal/attorney/attorneypage/sign_test.go index db24132f23..ecde0a7b92 100644 --- a/internal/attorney/attorneypage/sign_test.go +++ b/internal/attorney/attorneypage/sign_test.go @@ -22,6 +22,8 @@ import ( ) func TestGetSign(t *testing.T) { + signedAt := time.Now() + testcases := map[string]struct { appData appcontext.Data lpa *lpadata.Lpa @@ -38,7 +40,7 @@ func TestGetSign(t *testing.T) { {UID: actoruid.New(), FirstNames: "Dave", LastName: "Smith"}, }}, CertificateProvider: lpadata.CertificateProvider{ - SignedAt: time.Now(), + SignedAt: &signedAt, }, }, data: &signData{ @@ -59,7 +61,7 @@ func TestGetSign(t *testing.T) { {UID: actoruid.New(), FirstNames: "Dave", LastName: "Smith"}, }}, CertificateProvider: lpadata.CertificateProvider{ - SignedAt: time.Now(), + SignedAt: &signedAt, }, }, data: &signData{ @@ -79,7 +81,7 @@ func TestGetSign(t *testing.T) { {UID: actoruid.New(), FirstNames: "Dave", LastName: "Smith"}, }}, CertificateProvider: lpadata.CertificateProvider{ - SignedAt: time.Now(), + SignedAt: &signedAt, }, }, data: &signData{ @@ -101,7 +103,7 @@ func TestGetSign(t *testing.T) { {UID: actoruid.New(), FirstNames: "Dave", LastName: "Smith"}, }}, CertificateProvider: lpadata.CertificateProvider{ - SignedAt: time.Now(), + SignedAt: &signedAt, }, }, data: &signData{ @@ -121,7 +123,7 @@ func TestGetSign(t *testing.T) { Name: "Corp", }}, CertificateProvider: lpadata.CertificateProvider{ - SignedAt: time.Now(), + SignedAt: &signedAt, }, }, data: &signData{ @@ -143,12 +145,7 @@ func TestGetSign(t *testing.T) { Execute(w, tc.data). Return(nil) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(tc.lpa, nil) - - err := Sign(template.Execute, lpaStoreResolvingService, nil, nil, nil)(tc.appData, w, r, &attorneydata.Provided{}) + err := Sign(template.Execute, nil, nil, nil)(tc.appData, w, r, &attorneydata.Provided{}, tc.lpa) resp := w.Result() assert.Nil(t, err) @@ -178,7 +175,7 @@ func TestGetSignWhenSigned(t *testing.T) { r, _ := http.NewRequest(http.MethodGet, "/", nil) w := httptest.NewRecorder() - err := Sign(nil, nil, nil, nil, nil)(testAppData, w, r, attorneyProvidedDetails) + err := Sign(nil, nil, nil, nil)(testAppData, w, r, attorneyProvidedDetails, &lpadata.Lpa{}) resp := w.Result() assert.Nil(t, err) @@ -190,6 +187,7 @@ func TestGetSignWhenSigned(t *testing.T) { func TestGetSignCantSignYet(t *testing.T) { uid := actoruid.New() + signedAt := time.Now() testcases := map[string]struct { appData appcontext.Data @@ -214,7 +212,7 @@ func TestGetSignCantSignYet(t *testing.T) { {UID: actoruid.New(), FirstNames: "Dave", LastName: "Smith"}, }}, CertificateProvider: lpadata.CertificateProvider{ - SignedAt: time.Now(), + SignedAt: &signedAt, }, }, }, @@ -225,12 +223,7 @@ func TestGetSignCantSignYet(t *testing.T) { r, _ := http.NewRequest(http.MethodGet, "/", nil) w := httptest.NewRecorder() - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(tc.lpa, nil) - - err := Sign(nil, lpaStoreResolvingService, nil, nil, nil)(tc.appData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}) + err := Sign(nil, nil, nil, nil)(tc.appData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}, tc.lpa) resp := w.Result() assert.Nil(t, err) @@ -242,6 +235,7 @@ func TestGetSignCantSignYet(t *testing.T) { func TestGetSignWhenAttorneyDoesNotExist(t *testing.T) { uid := actoruid.New() + signedAt := time.Now() testcases := map[string]struct { appData appcontext.Data @@ -256,7 +250,7 @@ func TestGetSignWhenAttorneyDoesNotExist(t *testing.T) { {UID: uid, FirstNames: "Bob", LastName: "Smith"}, }}, CertificateProvider: lpadata.CertificateProvider{ - SignedAt: time.Now(), + SignedAt: &signedAt, }, }, }, @@ -269,7 +263,7 @@ func TestGetSignWhenAttorneyDoesNotExist(t *testing.T) { {UID: uid, FirstNames: "Bob", LastName: "Smith"}, }}, CertificateProvider: lpadata.CertificateProvider{ - SignedAt: time.Now(), + SignedAt: &signedAt, }, }, }, @@ -280,12 +274,7 @@ func TestGetSignWhenAttorneyDoesNotExist(t *testing.T) { r, _ := http.NewRequest(http.MethodGet, "/", nil) w := httptest.NewRecorder() - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(tc.lpa, nil) - - err := Sign(nil, lpaStoreResolvingService, nil, nil, nil)(tc.appData, w, r, &attorneydata.Provided{}) + err := Sign(nil, nil, nil, nil)(tc.appData, w, r, &attorneydata.Provided{}, tc.lpa) resp := w.Result() assert.Nil(t, err) @@ -295,44 +284,22 @@ func TestGetSignWhenAttorneyDoesNotExist(t *testing.T) { } } -func TestGetSignOnLpaStoreResolvingServiceError(t *testing.T) { - r, _ := http.NewRequest(http.MethodGet, "/", nil) - w := httptest.NewRecorder() - - template := newMockTemplate(t) - - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{}, expectedError) - - err := Sign(template.Execute, lpaStoreResolvingService, nil, nil, nil)(testAppData, w, r, &attorneydata.Provided{}) - resp := w.Result() - - assert.Equal(t, expectedError, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) -} - func TestGetSignOnTemplateError(t *testing.T) { r, _ := http.NewRequest(http.MethodGet, "/", nil) w := httptest.NewRecorder() + signedAt := time.Now() template := newMockTemplate(t) template.EXPECT(). Execute(w, mock.Anything). Return(expectedError) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{ - SignedAt: time.Now(), - WitnessedByCertificateProviderAt: time.Now(), - Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID}}}, - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, - }, nil) - - err := Sign(template.Execute, lpaStoreResolvingService, nil, nil, nil)(testAppData, w, r, &attorneydata.Provided{}) + err := Sign(template.Execute, nil, nil, nil)(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{ + SignedAt: time.Now(), + WitnessedByCertificateProviderAt: time.Now(), + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID}}}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &signedAt}, + }) resp := w.Result() assert.Equal(t, expectedError, err) @@ -347,34 +314,106 @@ func TestPostSign(t *testing.T) { url string appData appcontext.Data form url.Values + provided *attorneydata.Provided lpa *lpadata.Lpa updatedAttorney *attorneydata.Provided }{ "attorney": { + appData: testAppData, + form: url.Values{"confirm": {"1"}}, + provided: &attorneydata.Provided{UID: testUID, LpaID: "lpa-id"}, + lpa: &lpadata.Lpa{ + SignedAt: lpaSignedAt, + WitnessedByCertificateProviderAt: lpaSignedAt, + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID, FirstNames: "Bob", LastName: "Smith"}}}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &lpaSignedAt}, + }, + updatedAttorney: &attorneydata.Provided{ + UID: testUID, + LpaID: "lpa-id", + SignedAt: now, + Tasks: attorneydata.Tasks{SignTheLpa: task.StateCompleted}, + }, + }, + "attorney with set mobile": { appData: testAppData, form: url.Values{"confirm": {"1"}}, + provided: &attorneydata.Provided{ + UID: testUID, + LpaID: "lpa-id", + Phone: "0777", + PhoneSet: true, + }, lpa: &lpadata.Lpa{ SignedAt: lpaSignedAt, WitnessedByCertificateProviderAt: lpaSignedAt, - Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID, FirstNames: "Bob", LastName: "Smith"}}}, - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID, FirstNames: "Bob", LastName: "Smith", Mobile: "0888"}}}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &lpaSignedAt}, }, updatedAttorney: &attorneydata.Provided{ + UID: testUID, LpaID: "lpa-id", SignedAt: now, + Phone: "0777", + PhoneSet: true, Tasks: attorneydata.Tasks{SignTheLpa: task.StateCompleted}, }, }, - "replacement attorney": { - appData: testReplacementAppData, + "attorney with removed mobile": { + appData: testAppData, + form: url.Values{"confirm": {"1"}}, + provided: &attorneydata.Provided{ + UID: testUID, + LpaID: "lpa-id", + PhoneSet: true, + }, + lpa: &lpadata.Lpa{ + SignedAt: lpaSignedAt, + WitnessedByCertificateProviderAt: lpaSignedAt, + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID, FirstNames: "Bob", LastName: "Smith", Mobile: "0888"}}}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &lpaSignedAt}, + }, + updatedAttorney: &attorneydata.Provided{ + UID: testUID, + LpaID: "lpa-id", + SignedAt: now, + PhoneSet: true, + Tasks: attorneydata.Tasks{SignTheLpa: task.StateCompleted}, + }, + }, + "attorney with donor provided mobile": { + appData: testAppData, form: url.Values{"confirm": {"1"}}, + provided: &attorneydata.Provided{ + UID: testUID, + LpaID: "lpa-id", + }, + lpa: &lpadata.Lpa{ + SignedAt: lpaSignedAt, + WitnessedByCertificateProviderAt: lpaSignedAt, + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID, FirstNames: "Bob", LastName: "Smith", Mobile: "0888"}}}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &lpaSignedAt}, + }, + updatedAttorney: &attorneydata.Provided{ + UID: testUID, + LpaID: "lpa-id", + SignedAt: now, + Phone: "0888", + Tasks: attorneydata.Tasks{SignTheLpa: task.StateCompleted}, + }, + }, + "replacement attorney": { + appData: testReplacementAppData, + form: url.Values{"confirm": {"1"}}, + provided: &attorneydata.Provided{UID: testUID, LpaID: "lpa-id"}, lpa: &lpadata.Lpa{ SignedAt: lpaSignedAt, WitnessedByCertificateProviderAt: lpaSignedAt, ReplacementAttorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID, FirstNames: "Bob", LastName: "Smith"}}}, - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &lpaSignedAt}, }, updatedAttorney: &attorneydata.Provided{ + UID: testUID, LpaID: "lpa-id", SignedAt: now, Tasks: attorneydata.Tasks{SignTheLpa: task.StateCompleted}, @@ -389,13 +428,15 @@ func TestPostSign(t *testing.T) { "professional-title": {"c"}, "confirm": {"1"}, }, + provided: &attorneydata.Provided{UID: testUID, LpaID: "lpa-id"}, lpa: &lpadata.Lpa{ SignedAt: lpaSignedAt, WitnessedByCertificateProviderAt: lpaSignedAt, - Attorneys: lpadata.Attorneys{TrustCorporation: lpadata.TrustCorporation{Name: "Corp"}}, - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, + Attorneys: lpadata.Attorneys{TrustCorporation: lpadata.TrustCorporation{UID: testUID, Name: "Corp"}}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &lpaSignedAt}, }, updatedAttorney: &attorneydata.Provided{ + UID: testUID, LpaID: "lpa-id", AuthorisedSignatories: [2]attorneydata.TrustCorporationSignatory{{}, { FirstNames: "a", @@ -415,13 +456,15 @@ func TestPostSign(t *testing.T) { "professional-title": {"c"}, "confirm": {"1"}, }, + provided: &attorneydata.Provided{UID: testUID, LpaID: "lpa-id"}, lpa: &lpadata.Lpa{ SignedAt: lpaSignedAt, WitnessedByCertificateProviderAt: lpaSignedAt, - ReplacementAttorneys: lpadata.Attorneys{TrustCorporation: lpadata.TrustCorporation{Name: "Corp"}}, - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, + ReplacementAttorneys: lpadata.Attorneys{TrustCorporation: lpadata.TrustCorporation{UID: testUID, Name: "Corp"}}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &lpaSignedAt}, }, updatedAttorney: &attorneydata.Provided{ + UID: testUID, LpaID: "lpa-id", AuthorisedSignatories: [2]attorneydata.TrustCorporationSignatory{{}, { FirstNames: "a", @@ -441,11 +484,6 @@ func TestPostSign(t *testing.T) { w := httptest.NewRecorder() - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(tc.lpa, nil) - attorneyStore := newMockAttorneyStore(t) attorneyStore.EXPECT(). Put(r.Context(), tc.updatedAttorney). @@ -456,7 +494,7 @@ func TestPostSign(t *testing.T) { SendAttorney(r.Context(), tc.lpa, tc.updatedAttorney). Return(nil) - err := Sign(nil, lpaStoreResolvingService, attorneyStore, lpaStoreClient, func() time.Time { return now })(tc.appData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}) + err := Sign(nil, attorneyStore, lpaStoreClient, func() time.Time { return now })(tc.appData, w, r, tc.provided, tc.lpa) resp := w.Result() assert.Nil(t, err) @@ -484,8 +522,8 @@ func TestPostSignWhenSignedInLpaStore(t *testing.T) { lpa: &lpadata.Lpa{ SignedAt: lpaSignedAt, WitnessedByCertificateProviderAt: lpaSignedAt, - Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID, FirstNames: "Bob", LastName: "Smith", SignedAt: attorneySignedAt}}}, - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID, FirstNames: "Bob", LastName: "Smith", SignedAt: &attorneySignedAt}}}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &lpaSignedAt}, }, updatedAttorney: &attorneydata.Provided{ LpaID: "lpa-id", @@ -499,8 +537,8 @@ func TestPostSignWhenSignedInLpaStore(t *testing.T) { lpa: &lpadata.Lpa{ SignedAt: lpaSignedAt, WitnessedByCertificateProviderAt: lpaSignedAt, - ReplacementAttorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID, FirstNames: "Bob", LastName: "Smith", SignedAt: attorneySignedAt}}}, - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, + ReplacementAttorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID, FirstNames: "Bob", LastName: "Smith", SignedAt: &attorneySignedAt}}}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &lpaSignedAt}, }, updatedAttorney: &attorneydata.Provided{ LpaID: "lpa-id", @@ -521,7 +559,7 @@ func TestPostSignWhenSignedInLpaStore(t *testing.T) { SignedAt: lpaSignedAt, WitnessedByCertificateProviderAt: lpaSignedAt, Attorneys: lpadata.Attorneys{TrustCorporation: lpadata.TrustCorporation{Name: "Corp", Signatories: []lpadata.TrustCorporationSignatory{{}, {SignedAt: attorneySignedAt}}}}, - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &lpaSignedAt}, }, updatedAttorney: &attorneydata.Provided{ LpaID: "lpa-id", @@ -547,7 +585,7 @@ func TestPostSignWhenSignedInLpaStore(t *testing.T) { SignedAt: lpaSignedAt, WitnessedByCertificateProviderAt: lpaSignedAt, ReplacementAttorneys: lpadata.Attorneys{TrustCorporation: lpadata.TrustCorporation{Name: "Corp", Signatories: []lpadata.TrustCorporationSignatory{{}, {SignedAt: attorneySignedAt}}}}, - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &lpaSignedAt}, }, updatedAttorney: &attorneydata.Provided{ LpaID: "lpa-id", @@ -569,17 +607,12 @@ func TestPostSignWhenSignedInLpaStore(t *testing.T) { w := httptest.NewRecorder() - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(tc.lpa, nil) - attorneyStore := newMockAttorneyStore(t) attorneyStore.EXPECT(). Put(r.Context(), tc.updatedAttorney). Return(nil) - err := Sign(nil, lpaStoreResolvingService, attorneyStore, nil, func() time.Time { return now })(tc.appData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}) + err := Sign(nil, attorneyStore, nil, func() time.Time { return now })(tc.appData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}, tc.lpa) resp := w.Result() assert.Nil(t, err) @@ -612,7 +645,7 @@ func TestPostSignWhenWantSecondSignatory(t *testing.T) { SignedAt: lpaSignedAt, WitnessedByCertificateProviderAt: lpaSignedAt, Attorneys: lpadata.Attorneys{TrustCorporation: lpadata.TrustCorporation{Name: "Corp"}}, - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &lpaSignedAt}, }, updatedAttorney: &attorneydata.Provided{ LpaID: "lpa-id", @@ -637,7 +670,7 @@ func TestPostSignWhenWantSecondSignatory(t *testing.T) { SignedAt: lpaSignedAt, WitnessedByCertificateProviderAt: lpaSignedAt, ReplacementAttorneys: lpadata.Attorneys{TrustCorporation: lpadata.TrustCorporation{Name: "Corp"}}, - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &lpaSignedAt}, }, updatedAttorney: &attorneydata.Provided{ LpaID: "lpa-id", @@ -659,17 +692,12 @@ func TestPostSignWhenWantSecondSignatory(t *testing.T) { w := httptest.NewRecorder() - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(tc.lpa, nil) - attorneyStore := newMockAttorneyStore(t) attorneyStore.EXPECT(). Put(r.Context(), tc.updatedAttorney). Return(nil) - err := Sign(nil, lpaStoreResolvingService, attorneyStore, nil, func() time.Time { return now })(tc.appData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}) + err := Sign(nil, attorneyStore, nil, func() time.Time { return now })(tc.appData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}, tc.lpa) resp := w.Result() assert.Nil(t, err) @@ -681,27 +709,23 @@ func TestPostSignWhenWantSecondSignatory(t *testing.T) { func TestPostSignWhenLpaStoreClientErrors(t *testing.T) { form := url.Values{"confirm": {"1"}} + signedAt := time.Now() w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodPost, "", strings.NewReader(form.Encode())) r.Header.Add("Content-Type", page.FormUrlEncoded) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{ - SignedAt: time.Now(), - WitnessedByCertificateProviderAt: time.Now(), - Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID, FirstNames: "Bob", LastName: "Smith"}}}, - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, - }, nil) - lpaStoreClient := newMockLpaStoreClient(t) lpaStoreClient.EXPECT(). SendAttorney(r.Context(), mock.Anything, mock.Anything). Return(expectedError) - err := Sign(nil, lpaStoreResolvingService, nil, lpaStoreClient, time.Now)(testAppData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}) + err := Sign(nil, nil, lpaStoreClient, time.Now)(testAppData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}, &lpadata.Lpa{ + SignedAt: time.Now(), + WitnessedByCertificateProviderAt: time.Now(), + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID, FirstNames: "Bob", LastName: "Smith"}}}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &signedAt}, + }) assert.Equal(t, expectedError, err) } @@ -709,21 +733,12 @@ func TestPostSignWhenStoreError(t *testing.T) { form := url.Values{ "confirm": {"1"}, } + signedAt := time.Now() w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(form.Encode())) r.Header.Add("Content-Type", page.FormUrlEncoded) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{ - SignedAt: time.Now(), - WitnessedByCertificateProviderAt: time.Now(), - Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID, FirstNames: "Bob", LastName: "Smith"}}}, - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, - }, nil) - lpaStoreClient := newMockLpaStoreClient(t) lpaStoreClient.EXPECT(). SendAttorney(r.Context(), mock.Anything, mock.Anything). @@ -734,7 +749,12 @@ func TestPostSignWhenStoreError(t *testing.T) { Put(r.Context(), mock.Anything). Return(expectedError) - err := Sign(nil, lpaStoreResolvingService, attorneyStore, lpaStoreClient, time.Now)(testAppData, w, r, &attorneydata.Provided{}) + err := Sign(nil, attorneyStore, lpaStoreClient, time.Now)(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{ + SignedAt: time.Now(), + WitnessedByCertificateProviderAt: time.Now(), + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID, FirstNames: "Bob", LastName: "Smith"}}}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &signedAt}, + }) resp := w.Result() assert.Equal(t, expectedError, err) @@ -743,21 +763,12 @@ func TestPostSignWhenStoreError(t *testing.T) { func TestPostSignOnValidationError(t *testing.T) { form := url.Values{} + signedAt := time.Now() w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(form.Encode())) r.Header.Add("Content-Type", page.FormUrlEncoded) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{ - SignedAt: time.Now(), - WitnessedByCertificateProviderAt: time.Now(), - Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID, FirstNames: "Bob", LastName: "Smith"}}}, - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, - }, nil) - template := newMockTemplate(t) template.EXPECT(). Execute(w, &signData{ @@ -768,7 +779,12 @@ func TestPostSignOnValidationError(t *testing.T) { }). Return(nil) - err := Sign(template.Execute, lpaStoreResolvingService, nil, nil, time.Now)(testAppData, w, r, &attorneydata.Provided{}) + err := Sign(template.Execute, nil, nil, time.Now)(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{ + SignedAt: time.Now(), + WitnessedByCertificateProviderAt: time.Now(), + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: testUID, FirstNames: "Bob", LastName: "Smith"}}}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &signedAt}, + }) resp := w.Result() assert.Nil(t, err) diff --git a/internal/attorney/attorneypage/task_list.go b/internal/attorney/attorneypage/task_list.go index c2d36c4e11..cd02edbe3a 100644 --- a/internal/attorney/attorneypage/task_list.go +++ b/internal/attorney/attorneypage/task_list.go @@ -13,64 +13,65 @@ import ( ) type taskListData struct { - App appcontext.Data - Errors validation.List - Lpa *lpadata.Lpa - Items []taskListItem + App appcontext.Data + Errors validation.List + Provided *attorneydata.Provided + Lpa *lpadata.Lpa + Items []taskListItem } type taskListItem struct { Name string - Path string + Path attorney.Path + Query string State task.State Count int } -func TaskList(tmpl template.Template, lpaStoreResolvingService LpaStoreResolvingService) Handler { - return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, provided *attorneydata.Provided) error { - lpa, err := lpaStoreResolvingService.Get(r.Context()) - if err != nil { - return err - } - +func TaskList(tmpl template.Template) Handler { + return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, provided *attorneydata.Provided, lpa *lpadata.Lpa) error { tasks := provided.Tasks - var signPath string - if tasks.ConfirmYourDetails.IsCompleted() && tasks.ReadTheLpa.IsCompleted() && - lpa.SignedForDonor() && !lpa.CertificateProvider.SignedAt.IsZero() { - signPath = attorney.PathRightsAndResponsibilities.Format(lpa.LpaID) - } - signItems := []taskListItem{{ Name: "signTheLpa", - Path: signPath, + Path: attorney.PathRightsAndResponsibilities, State: tasks.SignTheLpa, }} - if provided.WouldLikeSecondSignatory.IsYes() && signPath != "" { + if provided.WouldLikeSecondSignatory.IsYes() { signItems = []taskListItem{{ Name: "signTheLpaSignatory1", - Path: signPath, + Path: attorney.PathRightsAndResponsibilities, State: tasks.SignTheLpa, }, { Name: "signTheLpaSignatory2", - Path: attorney.PathSign.Format(lpa.LpaID) + "?second", + Path: attorney.PathSign, + Query: "?second", State: tasks.SignTheLpaSecond, }} } + confirmYourDetailsPath := attorney.PathPhoneNumber + if _, mobile, _ := lpa.Attorney(provided.UID); mobile != "" { + confirmYourDetailsPath = attorney.PathYourPreferredLanguage + } + if tasks.ConfirmYourDetails.IsCompleted() { + confirmYourDetailsPath = attorney.PathConfirmYourDetails + } + data := &taskListData{ - App: appData, - Lpa: lpa, + App: appData, + Provided: provided, + Lpa: lpa, Items: append([]taskListItem{ { Name: "confirmYourDetails", - Path: attorney.PathPhoneNumber.Format(lpa.LpaID), + Path: confirmYourDetailsPath, State: tasks.ConfirmYourDetails, }, { Name: "readTheLpa", - Path: attorney.PathReadTheLpa.Format(lpa.LpaID), + Path: attorney.PathReadTheLpa, State: tasks.ReadTheLpa, }, }, signItems...), diff --git a/internal/attorney/attorneypage/task_list_test.go b/internal/attorney/attorneypage/task_list_test.go index b190b0f286..f3029edafb 100644 --- a/internal/attorney/attorneypage/task_list_test.go +++ b/internal/attorney/attorneypage/task_list_test.go @@ -6,6 +6,7 @@ import ( "testing" "time" + "github.com/ministryofjustice/opg-modernising-lpa/internal/actor/actoruid" "github.com/ministryofjustice/opg-modernising-lpa/internal/appcontext" "github.com/ministryofjustice/opg-modernising-lpa/internal/attorney" "github.com/ministryofjustice/opg-modernising-lpa/internal/attorney/attorneydata" @@ -17,26 +18,56 @@ import ( ) func TestGetTaskList(t *testing.T) { + signedAt := time.Now() + attorneyUID := actoruid.New() + testCases := map[string]struct { lpa *lpadata.Lpa - attorney *attorneydata.Provided + provided *attorneydata.Provided appData appcontext.Data expected func([]taskListItem) []taskListItem }{ "empty": { - lpa: &lpadata.Lpa{LpaID: "lpa-id"}, - attorney: &attorneydata.Provided{}, + lpa: &lpadata.Lpa{ + LpaID: "lpa-id", + Attorneys: lpadata.Attorneys{ + Attorneys: []lpadata.Attorney{{ + UID: attorneyUID, + }}, + }, + }, + provided: &attorneydata.Provided{UID: attorneyUID}, appData: testAppData, expected: func(items []taskListItem) []taskListItem { return items }, }, + "donor gave phone number": { + lpa: &lpadata.Lpa{ + LpaID: "lpa-id", + SignedAt: time.Now(), + WitnessedByCertificateProviderAt: time.Now(), + Attorneys: lpadata.Attorneys{ + Attorneys: []lpadata.Attorney{{ + UID: attorneyUID, + Mobile: "07777", + }}, + }, + }, + provided: &attorneydata.Provided{UID: attorneyUID}, + appData: testAppData, + expected: func(items []taskListItem) []taskListItem { + items[0].Path = attorney.PathYourPreferredLanguage + + return items + }, + }, "trust corporation": { lpa: &lpadata.Lpa{LpaID: "lpa-id"}, - attorney: &attorneydata.Provided{}, + provided: &attorneydata.Provided{}, appData: testTrustCorporationAppData, expected: func(items []taskListItem) []taskListItem { - items[0].Path = attorney.PathPhoneNumber.Format("lpa-id") + items[0].Path = attorney.PathPhoneNumber return items }, @@ -46,9 +77,9 @@ func TestGetTaskList(t *testing.T) { LpaID: "lpa-id", SignedAt: time.Now(), WitnessedByCertificateProviderAt: time.Now(), - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &signedAt}, }, - attorney: &attorneydata.Provided{ + provided: &attorneydata.Provided{ WouldLikeSecondSignatory: form.Yes, Tasks: attorneydata.Tasks{ ConfirmYourDetails: task.StateCompleted, @@ -58,14 +89,15 @@ func TestGetTaskList(t *testing.T) { appData: testTrustCorporationAppData, expected: func(items []taskListItem) []taskListItem { items[0].State = task.StateCompleted - items[0].Path = attorney.PathPhoneNumber.Format("lpa-id") + items[0].Path = attorney.PathConfirmYourDetails items[1].State = task.StateCompleted items[2].Name = "signTheLpaSignatory1" - items[2].Path = attorney.PathRightsAndResponsibilities.Format("lpa-id") + items[2].Path = attorney.PathRightsAndResponsibilities return append(items, taskListItem{ - Name: "signTheLpaSignatory2", - Path: attorney.PathSign.Format("lpa-id") + "?second", + Name: "signTheLpaSignatory2", + Path: attorney.PathSign, + Query: "?second", }) }, }, @@ -75,7 +107,7 @@ func TestGetTaskList(t *testing.T) { SignedAt: time.Now(), WitnessedByCertificateProviderAt: time.Now(), }, - attorney: &attorneydata.Provided{ + provided: &attorneydata.Provided{ Tasks: attorneydata.Tasks{ ConfirmYourDetails: task.StateCompleted, ReadTheLpa: task.StateCompleted, @@ -84,6 +116,7 @@ func TestGetTaskList(t *testing.T) { appData: testAppData, expected: func(items []taskListItem) []taskListItem { items[0].State = task.StateCompleted + items[0].Path = attorney.PathConfirmYourDetails items[1].State = task.StateCompleted return items @@ -94,9 +127,9 @@ func TestGetTaskList(t *testing.T) { LpaID: "lpa-id", SignedAt: time.Now(), WitnessedByCertificateProviderAt: time.Now(), - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &signedAt}, }, - attorney: &attorneydata.Provided{ + provided: &attorneydata.Provided{ Tasks: attorneydata.Tasks{ ConfirmYourDetails: task.StateCompleted, ReadTheLpa: task.StateCompleted, @@ -105,8 +138,9 @@ func TestGetTaskList(t *testing.T) { appData: testAppData, expected: func(items []taskListItem) []taskListItem { items[0].State = task.StateCompleted + items[0].Path = attorney.PathConfirmYourDetails items[1].State = task.StateCompleted - items[2].Path = attorney.PathRightsAndResponsibilities.Format("lpa-id") + items[2].Path = attorney.PathRightsAndResponsibilities return items }, @@ -116,9 +150,9 @@ func TestGetTaskList(t *testing.T) { LpaID: "lpa-id", SignedAt: time.Now(), WitnessedByCertificateProviderAt: time.Now(), - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &signedAt}, }, - attorney: &attorneydata.Provided{ + provided: &attorneydata.Provided{ Tasks: attorneydata.Tasks{ ConfirmYourDetails: task.StateCompleted, ReadTheLpa: task.StateCompleted, @@ -128,9 +162,10 @@ func TestGetTaskList(t *testing.T) { appData: testAppData, expected: func(items []taskListItem) []taskListItem { items[0].State = task.StateCompleted + items[0].Path = attorney.PathConfirmYourDetails items[1].State = task.StateCompleted items[2].State = task.StateCompleted - items[2].Path = attorney.PathRightsAndResponsibilities.Format("lpa-id") + items[2].Path = attorney.PathRightsAndResponsibilities return items }, @@ -140,9 +175,9 @@ func TestGetTaskList(t *testing.T) { LpaID: "lpa-id", SignedAt: time.Now(), WitnessedByCertificateProviderAt: time.Now(), - CertificateProvider: lpadata.CertificateProvider{SignedAt: time.Now()}, + CertificateProvider: lpadata.CertificateProvider{SignedAt: &signedAt}, }, - attorney: &attorneydata.Provided{ + provided: &attorneydata.Provided{ Tasks: attorneydata.Tasks{ ConfirmYourDetails: task.StateCompleted, ReadTheLpa: task.StateCompleted, @@ -152,9 +187,10 @@ func TestGetTaskList(t *testing.T) { appData: testReplacementAppData, expected: func(items []taskListItem) []taskListItem { items[0].State = task.StateCompleted + items[0].Path = attorney.PathConfirmYourDetails items[1].State = task.StateCompleted items[2].State = task.StateCompleted - items[2].Path = attorney.PathRightsAndResponsibilities.Format("lpa-id") + items[2].Path = attorney.PathRightsAndResponsibilities return items }, @@ -166,25 +202,21 @@ func TestGetTaskList(t *testing.T) { w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodGet, "/", nil) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(tc.lpa, nil) - template := newMockTemplate(t) template.EXPECT(). Execute(w, &taskListData{ - App: tc.appData, - Lpa: tc.lpa, + App: tc.appData, + Lpa: tc.lpa, + Provided: tc.provided, Items: tc.expected([]taskListItem{ - {Name: "confirmYourDetails", Path: attorney.PathPhoneNumber.Format("lpa-id")}, - {Name: "readTheLpa", Path: attorney.PathReadTheLpa.Format("lpa-id")}, - {Name: "signTheLpa"}, + {Name: "confirmYourDetails", Path: attorney.PathPhoneNumber}, + {Name: "readTheLpa", Path: attorney.PathReadTheLpa}, + {Name: "signTheLpa", Path: attorney.PathRightsAndResponsibilities}, }), }). Return(nil) - err := TaskList(template.Execute, lpaStoreResolvingService)(tc.appData, w, r, tc.attorney) + err := TaskList(template.Execute)(tc.appData, w, r, tc.provided, tc.lpa) resp := w.Result() assert.Nil(t, err) @@ -193,35 +225,16 @@ func TestGetTaskList(t *testing.T) { } } -func TestGetTaskListWhenLpaStoreResolvingServiceErrors(t *testing.T) { - w := httptest.NewRecorder() - r, _ := http.NewRequest(http.MethodGet, "/", nil) - - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{}, expectedError) - - err := TaskList(nil, lpaStoreResolvingService)(testAppData, w, r, nil) - - assert.Equal(t, expectedError, err) -} - func TestGetTaskListWhenTemplateErrors(t *testing.T) { w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodGet, "/", nil) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{LpaID: "lpa-id"}, nil) - template := newMockTemplate(t) template.EXPECT(). Execute(w, mock.Anything). Return(expectedError) - err := TaskList(template.Execute, lpaStoreResolvingService)(testAppData, w, r, &attorneydata.Provided{}) + err := TaskList(template.Execute)(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{LpaID: "lpa-id"}) resp := w.Result() assert.Equal(t, expectedError, err) diff --git a/internal/attorney/attorneypage/would_like_second_signatory.go b/internal/attorney/attorneypage/would_like_second_signatory.go index b978965720..0f1584df6a 100644 --- a/internal/attorney/attorneypage/would_like_second_signatory.go +++ b/internal/attorney/attorneypage/would_like_second_signatory.go @@ -9,6 +9,7 @@ import ( "github.com/ministryofjustice/opg-modernising-lpa/internal/attorney" "github.com/ministryofjustice/opg-modernising-lpa/internal/attorney/attorneydata" "github.com/ministryofjustice/opg-modernising-lpa/internal/form" + "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore/lpadata" "github.com/ministryofjustice/opg-modernising-lpa/internal/validation" ) @@ -18,8 +19,8 @@ type wouldLikeSecondSignatoryData struct { Form *form.YesNoForm } -func WouldLikeSecondSignatory(tmpl template.Template, attorneyStore AttorneyStore, lpaStoreResolvingService LpaStoreResolvingService, lpaStoreClient LpaStoreClient) Handler { - return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, attorneyProvidedDetails *attorneydata.Provided) error { +func WouldLikeSecondSignatory(tmpl template.Template, attorneyStore AttorneyStore, lpaStoreClient LpaStoreClient) Handler { + return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, attorneyProvidedDetails *attorneydata.Provided, lpa *lpadata.Lpa) error { if attorneyProvidedDetails.Signed() { return attorney.PathWhatHappensNext.Redirect(w, r, appData, attorneyProvidedDetails.LpaID) } @@ -44,11 +45,6 @@ func WouldLikeSecondSignatory(tmpl template.Template, attorneyStore AttorneyStor return attorney.PathSign.RedirectQuery(w, r, appData, attorneyProvidedDetails.LpaID, url.Values{"second": {""}}) } - lpa, err := lpaStoreResolvingService.Get(r.Context()) - if err != nil { - return err - } - hasSigned := (appData.IsReplacementAttorney() && len(lpa.ReplacementAttorneys.TrustCorporation.Signatories) > 0) || (!appData.IsReplacementAttorney() && diff --git a/internal/attorney/attorneypage/would_like_second_signatory_test.go b/internal/attorney/attorneypage/would_like_second_signatory_test.go index 38a8a3d231..96b7d2808a 100644 --- a/internal/attorney/attorneypage/would_like_second_signatory_test.go +++ b/internal/attorney/attorneypage/would_like_second_signatory_test.go @@ -31,7 +31,7 @@ func TestGetWouldLikeSecondSignatory(t *testing.T) { }). Return(nil) - err := WouldLikeSecondSignatory(template.Execute, nil, nil, nil)(testAppData, w, r, &attorneydata.Provided{}) + err := WouldLikeSecondSignatory(template.Execute, nil, nil)(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{}) resp := w.Result() assert.Nil(t, err) @@ -42,10 +42,10 @@ func TestGetWouldLikeSecondSignatoryWhenAlreadySigned(t *testing.T) { w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodGet, "/", nil) - err := WouldLikeSecondSignatory(nil, nil, nil, nil)(testAppData, w, r, &attorneydata.Provided{ + err := WouldLikeSecondSignatory(nil, nil, nil)(testAppData, w, r, &attorneydata.Provided{ LpaID: "lpa-id", SignedAt: time.Now(), - }) + }, &lpadata.Lpa{}) resp := w.Result() assert.Nil(t, err) @@ -65,7 +65,7 @@ func TestGetWouldLikeSecondSignatoryWhenTemplateErrors(t *testing.T) { }). Return(expectedError) - err := WouldLikeSecondSignatory(template.Execute, nil, nil, nil)(testAppData, w, r, &attorneydata.Provided{}) + err := WouldLikeSecondSignatory(template.Execute, nil, nil)(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{}) resp := w.Result() assert.Equal(t, expectedError, err) @@ -89,9 +89,9 @@ func TestPostWouldLikeSecondSignatoryWhenYes(t *testing.T) { }). Return(nil) - err := WouldLikeSecondSignatory(nil, attorneyStore, nil, nil)(testAppData, w, r, &attorneydata.Provided{ + err := WouldLikeSecondSignatory(nil, attorneyStore, nil)(testAppData, w, r, &attorneydata.Provided{ LpaID: "lpa-id", - }) + }, &lpadata.Lpa{}) resp := w.Result() assert.Nil(t, err) @@ -100,7 +100,7 @@ func TestPostWouldLikeSecondSignatoryWhenYes(t *testing.T) { } func TestPostWouldLikeSecondSignatoryWhenNo(t *testing.T) { - donor := &lpadata.Lpa{SignedAt: time.Now()} + lpa := &lpadata.Lpa{SignedAt: time.Now()} updatedAttorney := &attorneydata.Provided{ LpaID: "lpa-id", WouldLikeSecondSignatory: form.No, @@ -119,19 +119,14 @@ func TestPostWouldLikeSecondSignatoryWhenNo(t *testing.T) { Put(r.Context(), updatedAttorney). Return(nil) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(donor, nil) - lpaStoreClient := newMockLpaStoreClient(t) lpaStoreClient.EXPECT(). - SendAttorney(r.Context(), donor, updatedAttorney). + SendAttorney(r.Context(), lpa, updatedAttorney). Return(nil) - err := WouldLikeSecondSignatory(nil, attorneyStore, lpaStoreResolvingService, lpaStoreClient)(testAppData, w, r, &attorneydata.Provided{ + err := WouldLikeSecondSignatory(nil, attorneyStore, lpaStoreClient)(testAppData, w, r, &attorneydata.Provided{ LpaID: "lpa-id", - }) + }, lpa) resp := w.Result() assert.Nil(t, err) @@ -182,14 +177,9 @@ func TestPostWouldLikeSecondSignatoryWhenNoAndSignedInLpaStore(t *testing.T) { Put(r.Context(), updatedAttorney). Return(nil) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(tc.lpa, nil) - - err := WouldLikeSecondSignatory(nil, attorneyStore, lpaStoreResolvingService, nil)(tc.appData, w, r, &attorneydata.Provided{ + err := WouldLikeSecondSignatory(nil, attorneyStore, nil)(tc.appData, w, r, &attorneydata.Provided{ LpaID: "lpa-id", - }) + }, tc.lpa) resp := w.Result() assert.Nil(t, err) @@ -200,7 +190,7 @@ func TestPostWouldLikeSecondSignatoryWhenNoAndSignedInLpaStore(t *testing.T) { } func TestPostWouldLikeSecondSignatoryWhenLpaStoreClientErrors(t *testing.T) { - donor := &lpadata.Lpa{SignedAt: time.Now()} + lpa := &lpadata.Lpa{SignedAt: time.Now()} f := url.Values{ form.FieldNames.YesNo: {form.No.String()}, @@ -210,35 +200,12 @@ func TestPostWouldLikeSecondSignatoryWhenLpaStoreClientErrors(t *testing.T) { r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(f.Encode())) r.Header.Add("Content-Type", page.FormUrlEncoded) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(donor, nil) - lpaStoreClient := newMockLpaStoreClient(t) lpaStoreClient.EXPECT(). SendAttorney(r.Context(), mock.Anything, mock.Anything). Return(expectedError) - err := WouldLikeSecondSignatory(nil, nil, lpaStoreResolvingService, lpaStoreClient)(testAppData, w, r, &attorneydata.Provided{}) - assert.Equal(t, expectedError, err) -} - -func TestPostWouldLikeSecondSignatoryWhenLpaStoreResolvingServiceErrors(t *testing.T) { - f := url.Values{ - form.FieldNames.YesNo: {form.No.String()}, - } - - w := httptest.NewRecorder() - r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(f.Encode())) - r.Header.Add("Content-Type", page.FormUrlEncoded) - - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(nil, expectedError) - - err := WouldLikeSecondSignatory(nil, nil, lpaStoreResolvingService, nil)(testAppData, w, r, &attorneydata.Provided{}) + err := WouldLikeSecondSignatory(nil, nil, lpaStoreClient)(testAppData, w, r, &attorneydata.Provided{}, lpa) assert.Equal(t, expectedError, err) } @@ -251,11 +218,6 @@ func TestPostWouldLikeSecondSignatoryWhenAttorneyStoreErrors(t *testing.T) { r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(form.Encode())) r.Header.Add("Content-Type", page.FormUrlEncoded) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{}, nil) - lpaStoreClient := newMockLpaStoreClient(t) lpaStoreClient.EXPECT(). SendAttorney(r.Context(), mock.Anything, mock.Anything). @@ -266,7 +228,7 @@ func TestPostWouldLikeSecondSignatoryWhenAttorneyStoreErrors(t *testing.T) { Put(r.Context(), mock.Anything). Return(expectedError) - err := WouldLikeSecondSignatory(nil, attorneyStore, lpaStoreResolvingService, lpaStoreClient)(testAppData, w, r, &attorneydata.Provided{}) + err := WouldLikeSecondSignatory(nil, attorneyStore, lpaStoreClient)(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{}) assert.Equal(t, expectedError, err) } @@ -288,7 +250,7 @@ func TestPostWouldLikeSecondSignatoryWhenValidationError(t *testing.T) { })). Return(nil) - err := WouldLikeSecondSignatory(template.Execute, nil, nil, nil)(testAppData, w, r, &attorneydata.Provided{}) + err := WouldLikeSecondSignatory(template.Execute, nil, nil)(testAppData, w, r, &attorneydata.Provided{}, &lpadata.Lpa{}) resp := w.Result() assert.Nil(t, err) diff --git a/internal/attorney/attorneypage/your_preferred_language.go b/internal/attorney/attorneypage/your_preferred_language.go index 2f56ec4186..747c4a096e 100644 --- a/internal/attorney/attorneypage/your_preferred_language.go +++ b/internal/attorney/attorneypage/your_preferred_language.go @@ -22,13 +22,8 @@ type yourPreferredLanguageData struct { Lpa *lpadata.Lpa } -func YourPreferredLanguage(tmpl template.Template, attorneyStore AttorneyStore, lpaStoreResolvingService LpaStoreResolvingService) Handler { - return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, attorneyProvidedDetails *attorneydata.Provided) error { - lpa, err := lpaStoreResolvingService.Get(r.Context()) - if err != nil { - return err - } - +func YourPreferredLanguage(tmpl template.Template, attorneyStore AttorneyStore) Handler { + return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, attorneyProvidedDetails *attorneydata.Provided, lpa *lpadata.Lpa) error { data := &yourPreferredLanguageData{ App: appData, Form: &form.LanguagePreferenceForm{ diff --git a/internal/attorney/attorneypage/your_preferred_language_test.go b/internal/attorney/attorneypage/your_preferred_language_test.go index d67f3ec516..17c686a6ab 100644 --- a/internal/attorney/attorneypage/your_preferred_language_test.go +++ b/internal/attorney/attorneypage/your_preferred_language_test.go @@ -22,11 +22,6 @@ func TestGetYourPreferredLanguage(t *testing.T) { w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodGet, "/", nil) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{}, nil) - template := newMockTemplate(t) template.EXPECT(). Execute(w, &yourPreferredLanguageData{ @@ -40,7 +35,7 @@ func TestGetYourPreferredLanguage(t *testing.T) { }). Return(nil) - err := YourPreferredLanguage(template.Execute, nil, lpaStoreResolvingService)(testAppData, w, r, &attorneydata.Provided{LpaID: "lpa-id", ContactLanguagePreference: localize.Cy}) + err := YourPreferredLanguage(template.Execute, nil)(testAppData, w, r, &attorneydata.Provided{LpaID: "lpa-id", ContactLanguagePreference: localize.Cy}, &lpadata.Lpa{}) resp := w.Result() @@ -48,38 +43,16 @@ func TestGetYourPreferredLanguage(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) } -func TestGetYourPreferredLanguageWhenLpaStoreResolvingServiceError(t *testing.T) { - w := httptest.NewRecorder() - r, _ := http.NewRequest(http.MethodGet, "/", nil) - - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{}, expectedError) - - err := YourPreferredLanguage(nil, nil, lpaStoreResolvingService)(testAppData, w, r, &attorneydata.Provided{LpaID: "lpa-id", ContactLanguagePreference: localize.Cy}) - - resp := w.Result() - - assert.Equal(t, expectedError, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) -} - func TestGetYourPreferredLanguageWhenTemplateError(t *testing.T) { w := httptest.NewRecorder() r, _ := http.NewRequest(http.MethodGet, "/", nil) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{}, nil) - template := newMockTemplate(t) template.EXPECT(). Execute(w, mock.Anything). Return(expectedError) - err := YourPreferredLanguage(template.Execute, nil, lpaStoreResolvingService)(testAppData, w, r, &attorneydata.Provided{LpaID: "lpa-id", ContactLanguagePreference: localize.Cy}) + err := YourPreferredLanguage(template.Execute, nil)(testAppData, w, r, &attorneydata.Provided{LpaID: "lpa-id", ContactLanguagePreference: localize.Cy}, &lpadata.Lpa{}) resp := w.Result() @@ -98,17 +71,12 @@ func TestPostYourPreferredLanguage(t *testing.T) { r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(formValues.Encode())) r.Header.Add("Content-Type", page.FormUrlEncoded) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{}, nil) - attorneyStore := newMockAttorneyStore(t) attorneyStore.EXPECT(). Put(r.Context(), &attorneydata.Provided{LpaID: "lpa-id", ContactLanguagePreference: lang}). Return(nil) - err := YourPreferredLanguage(nil, attorneyStore, lpaStoreResolvingService)(testAppData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}) + err := YourPreferredLanguage(nil, attorneyStore)(testAppData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}, &lpadata.Lpa{}) resp := w.Result() @@ -126,17 +94,12 @@ func TestPostYourPreferredLanguageWhenAttorneyStoreError(t *testing.T) { r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(formValues.Encode())) r.Header.Add("Content-Type", page.FormUrlEncoded) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{}, nil) - attorneyStore := newMockAttorneyStore(t) attorneyStore.EXPECT(). Put(r.Context(), mock.Anything). Return(expectedError) - err := YourPreferredLanguage(nil, attorneyStore, lpaStoreResolvingService)(testAppData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}) + err := YourPreferredLanguage(nil, attorneyStore)(testAppData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}, &lpadata.Lpa{}) resp := w.Result() @@ -151,11 +114,6 @@ func TestPostYourPreferredLanguageWhenInvalidData(t *testing.T) { r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(formValues.Encode())) r.Header.Add("Content-Type", page.FormUrlEncoded) - lpaStoreResolvingService := newMockLpaStoreResolvingService(t) - lpaStoreResolvingService.EXPECT(). - Get(r.Context()). - Return(&lpadata.Lpa{}, nil) - template := newMockTemplate(t) template.EXPECT(). Execute(w, &yourPreferredLanguageData{ @@ -170,7 +128,7 @@ func TestPostYourPreferredLanguageWhenInvalidData(t *testing.T) { }). Return(nil) - err := YourPreferredLanguage(template.Execute, nil, lpaStoreResolvingService)(testAppData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}) + err := YourPreferredLanguage(template.Execute, nil)(testAppData, w, r, &attorneydata.Provided{LpaID: "lpa-id"}, &lpadata.Lpa{}) resp := w.Result() diff --git a/internal/attorney/path.go b/internal/attorney/path.go index f6c0ac3aaf..5cf7efbb80 100644 --- a/internal/attorney/path.go +++ b/internal/attorney/path.go @@ -7,6 +7,7 @@ import ( "github.com/ministryofjustice/opg-modernising-lpa/internal/appcontext" "github.com/ministryofjustice/opg-modernising-lpa/internal/attorney/attorneydata" + "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore/lpadata" ) const ( @@ -55,36 +56,27 @@ func (p Path) RedirectQuery(w http.ResponseWriter, r *http.Request, appData appc return nil } -func (p Path) canVisit(attorney *attorneydata.Provided) bool { +func (p Path) CanGoTo(attorney *attorneydata.Provided, lpa *lpadata.Lpa) bool { switch p { case PathRightsAndResponsibilities, PathWhatHappensWhenYouSign, PathSign, PathWhatHappensNext: - return attorney.Tasks.ConfirmYourDetails.IsCompleted() && attorney.Tasks.ReadTheLpa.IsCompleted() + return lpa.Paid && lpa.SignedForDonor() && + lpa.CertificateProvider.SignedAt != nil && !lpa.CertificateProvider.SignedAt.IsZero() && + attorney.Tasks.ConfirmYourDetails.IsCompleted() && attorney.Tasks.ReadTheLpa.IsCompleted() case PathWouldLikeSecondSignatory: - return attorney.Tasks.ConfirmYourDetails.IsCompleted() && attorney.Tasks.ReadTheLpa.IsCompleted() && attorney.IsTrustCorporation + return lpa.Paid && lpa.SignedForDonor() && + lpa.CertificateProvider.SignedAt != nil && !lpa.CertificateProvider.SignedAt.IsZero() && + attorney.Tasks.ConfirmYourDetails.IsCompleted() && attorney.Tasks.ReadTheLpa.IsCompleted() && + attorney.IsTrustCorporation default: return true } } -func CanGoTo(attorney *attorneydata.Provided, url string) bool { - path, _, _ := strings.Cut(url, "?") - if path == "" { - return false - } - - if strings.HasPrefix(path, "/attorney/") { - _, attorneyPath, _ := strings.Cut(strings.TrimPrefix(path, "/attorney/"), "/") - return Path("/" + attorneyPath).canVisit(attorney) - } - - return true -} - func canFrom(fromURL string, lpaID string) bool { return strings.HasPrefix(fromURL, Path("").Format(lpaID)) } diff --git a/internal/attorney/path_test.go b/internal/attorney/path_test.go index 48254ea377..a6c7afae28 100644 --- a/internal/attorney/path_test.go +++ b/internal/attorney/path_test.go @@ -5,10 +5,12 @@ import ( "net/http/httptest" "net/url" "testing" + "time" "github.com/ministryofjustice/opg-modernising-lpa/internal/appcontext" "github.com/ministryofjustice/opg-modernising-lpa/internal/attorney/attorneydata" "github.com/ministryofjustice/opg-modernising-lpa/internal/localize" + "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore/lpadata" "github.com/ministryofjustice/opg-modernising-lpa/internal/task" "github.com/stretchr/testify/assert" ) @@ -66,22 +68,17 @@ func TestAttorneyPathRedirectQuery(t *testing.T) { func TestAttorneyCanGoTo(t *testing.T) { testCases := map[string]struct { attorney *attorneydata.Provided - url string + path Path expected bool }{ "empty path": { attorney: &attorneydata.Provided{}, - url: "", - expected: false, - }, - "unexpected path": { - attorney: &attorneydata.Provided{}, - url: "/whatever", + path: Path(""), expected: true, }, "unrestricted path": { attorney: &attorneydata.Provided{}, - url: PathConfirmYourDetails.Format("123"), + path: PathConfirmYourDetails, expected: true, }, "sign without task": { @@ -90,7 +87,7 @@ func TestAttorneyCanGoTo(t *testing.T) { ConfirmYourDetails: task.StateCompleted, }, }, - url: PathSign.Format("123"), + path: PathSign, expected: false, }, "sign with task": { @@ -100,7 +97,7 @@ func TestAttorneyCanGoTo(t *testing.T) { ReadTheLpa: task.StateCompleted, }, }, - url: PathSign.Format("123"), + path: PathSign, expected: true, }, "would like second signatory not trust corp": { @@ -110,7 +107,7 @@ func TestAttorneyCanGoTo(t *testing.T) { ReadTheLpa: task.StateCompleted, }, }, - url: PathWouldLikeSecondSignatory.Format("123"), + path: PathWouldLikeSecondSignatory, expected: false, }, "would like second signatory as trust corp": { @@ -121,14 +118,23 @@ func TestAttorneyCanGoTo(t *testing.T) { }, IsTrustCorporation: true, }, - url: PathWouldLikeSecondSignatory.Format("123"), + path: PathWouldLikeSecondSignatory, expected: true, }, } for name, tc := range testCases { t.Run(name, func(t *testing.T) { - assert.Equal(t, tc.expected, CanGoTo(tc.attorney, tc.url)) + signedAt := time.Now() + + assert.Equal(t, tc.expected, tc.path.CanGoTo(tc.attorney, &lpadata.Lpa{ + Paid: true, + SignedAt: time.Now(), + WitnessedByCertificateProviderAt: time.Now(), + CertificateProvider: lpadata.CertificateProvider{ + SignedAt: &signedAt, + }, + })) }) } } diff --git a/internal/certificateprovider/certificateproviderpage/provide_certificate.go b/internal/certificateprovider/certificateproviderpage/provide_certificate.go index aa429cd0b6..8616212d09 100644 --- a/internal/certificateprovider/certificateproviderpage/provide_certificate.go +++ b/internal/certificateprovider/certificateproviderpage/provide_certificate.go @@ -63,12 +63,12 @@ func ProvideCertificate( certificateProvider.SignedAt = now() certificateProvider.Tasks.ProvideTheCertificate = task.StateCompleted - if lpa.CertificateProvider.SignedAt.IsZero() { + if lpa.CertificateProvider.SignedAt == nil || lpa.CertificateProvider.SignedAt.IsZero() { if err := lpaStoreClient.SendCertificateProvider(r.Context(), certificateProvider, lpa); err != nil { return err } } else { - certificateProvider.SignedAt = lpa.CertificateProvider.SignedAt + certificateProvider.SignedAt = *lpa.CertificateProvider.SignedAt } if err := notifyClient.SendActorEmail(r.Context(), notify.ToLpaCertificateProvider(certificateProvider, lpa), lpa.LpaUID, notify.CertificateProviderCertificateProvidedEmail{ diff --git a/internal/certificateprovider/certificateproviderpage/provide_certificate_test.go b/internal/certificateprovider/certificateproviderpage/provide_certificate_test.go index 4abd09cce2..41011530ab 100644 --- a/internal/certificateprovider/certificateproviderpage/provide_certificate_test.go +++ b/internal/certificateprovider/certificateproviderpage/provide_certificate_test.go @@ -178,7 +178,7 @@ func TestPostProvideCertificateWhenSignedInLpaStore(t *testing.T) { Email: "cp@example.org", FirstNames: "a", LastName: "b", - SignedAt: signedAt, + SignedAt: &signedAt, }, Donor: lpadata.Donor{FirstNames: "c", LastName: "d"}, Type: lpadata.LpaTypePropertyAndAffairs, diff --git a/internal/donor/donorpage/mock_LpaStoreClient_test.go b/internal/donor/donorpage/mock_LpaStoreClient_test.go index 39ea433fc4..e5de6a418e 100644 --- a/internal/donor/donorpage/mock_LpaStoreClient_test.go +++ b/internal/donor/donorpage/mock_LpaStoreClient_test.go @@ -8,6 +8,8 @@ import ( donordata "github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata" lpadata "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore/lpadata" + lpastore "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore" + mock "github.com/stretchr/testify/mock" ) @@ -177,17 +179,17 @@ func (_c *mockLpaStoreClient_SendDonorWithdrawLPA_Call) RunAndReturn(run func(co return _c } -// SendLpa provides a mock function with given fields: ctx, details -func (_m *mockLpaStoreClient) SendLpa(ctx context.Context, details *donordata.Provided) error { - ret := _m.Called(ctx, details) +// SendLpa provides a mock function with given fields: ctx, uid, body +func (_m *mockLpaStoreClient) SendLpa(ctx context.Context, uid string, body lpastore.CreateLpa) error { + ret := _m.Called(ctx, uid, body) if len(ret) == 0 { panic("no return value specified for SendLpa") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *donordata.Provided) error); ok { - r0 = rf(ctx, details) + if rf, ok := ret.Get(0).(func(context.Context, string, lpastore.CreateLpa) error); ok { + r0 = rf(ctx, uid, body) } else { r0 = ret.Error(0) } @@ -202,14 +204,15 @@ type mockLpaStoreClient_SendLpa_Call struct { // SendLpa is a helper method to define mock.On call // - ctx context.Context -// - details *donordata.Provided -func (_e *mockLpaStoreClient_Expecter) SendLpa(ctx interface{}, details interface{}) *mockLpaStoreClient_SendLpa_Call { - return &mockLpaStoreClient_SendLpa_Call{Call: _e.mock.On("SendLpa", ctx, details)} +// - uid string +// - body lpastore.CreateLpa +func (_e *mockLpaStoreClient_Expecter) SendLpa(ctx interface{}, uid interface{}, body interface{}) *mockLpaStoreClient_SendLpa_Call { + return &mockLpaStoreClient_SendLpa_Call{Call: _e.mock.On("SendLpa", ctx, uid, body)} } -func (_c *mockLpaStoreClient_SendLpa_Call) Run(run func(ctx context.Context, details *donordata.Provided)) *mockLpaStoreClient_SendLpa_Call { +func (_c *mockLpaStoreClient_SendLpa_Call) Run(run func(ctx context.Context, uid string, body lpastore.CreateLpa)) *mockLpaStoreClient_SendLpa_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*donordata.Provided)) + run(args[0].(context.Context), args[1].(string), args[2].(lpastore.CreateLpa)) }) return _c } @@ -219,7 +222,7 @@ func (_c *mockLpaStoreClient_SendLpa_Call) Return(_a0 error) *mockLpaStoreClient return _c } -func (_c *mockLpaStoreClient_SendLpa_Call) RunAndReturn(run func(context.Context, *donordata.Provided) error) *mockLpaStoreClient_SendLpa_Call { +func (_c *mockLpaStoreClient_SendLpa_Call) RunAndReturn(run func(context.Context, string, lpastore.CreateLpa) error) *mockLpaStoreClient_SendLpa_Call { _c.Call.Return(run) return _c } diff --git a/internal/donor/donorpage/payment_confirmation.go b/internal/donor/donorpage/payment_confirmation.go index 8922f3dfc3..56a0ef8afa 100644 --- a/internal/donor/donorpage/payment_confirmation.go +++ b/internal/donor/donorpage/payment_confirmation.go @@ -12,6 +12,7 @@ import ( "github.com/ministryofjustice/opg-modernising-lpa/internal/donor" "github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata" "github.com/ministryofjustice/opg-modernising-lpa/internal/event" + "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore" "github.com/ministryofjustice/opg-modernising-lpa/internal/notify" "github.com/ministryofjustice/opg-modernising-lpa/internal/task" ) @@ -101,7 +102,7 @@ func PaymentConfirmation(logger Logger, payClient PayClient, donorStore DonorSto return fmt.Errorf("failed to send certificate-provider-started event: %w", err) } - if err := lpaStoreClient.SendLpa(r.Context(), provided); err != nil { + if err := lpaStoreClient.SendLpa(r.Context(), provided.LpaUID, lpastore.CreateLpaFromDonorProvided(provided)); err != nil { return fmt.Errorf("failed to send to lpastore: %w", err) } } diff --git a/internal/donor/donorpage/payment_confirmation_test.go b/internal/donor/donorpage/payment_confirmation_test.go index 1a2e461b64..8c5f1a4f93 100644 --- a/internal/donor/donorpage/payment_confirmation_test.go +++ b/internal/donor/donorpage/payment_confirmation_test.go @@ -14,6 +14,7 @@ import ( "github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata" "github.com/ministryofjustice/opg-modernising-lpa/internal/event" "github.com/ministryofjustice/opg-modernising-lpa/internal/localize" + lpastore "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore" "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore/lpadata" "github.com/ministryofjustice/opg-modernising-lpa/internal/notify" "github.com/ministryofjustice/opg-modernising-lpa/internal/pay" @@ -414,7 +415,7 @@ func TestGetPaymentConfirmationApprovedOrDeniedWhenSigned(t *testing.T) { lpaStoreClient := newMockLpaStoreClient(t) lpaStoreClient.EXPECT(). - SendLpa(r.Context(), updatedDonor). + SendLpa(r.Context(), updatedDonor.LpaUID, lpastore.CreateLpaFromDonorProvided(updatedDonor)). Return(nil) eventClient := newMockEventClient(t) @@ -816,7 +817,7 @@ func TestGetPaymentConfirmationWhenLpaStoreClientErrors(t *testing.T) { lpaStoreClient := newMockLpaStoreClient(t) lpaStoreClient.EXPECT(). - SendLpa(r.Context(), mock.Anything). + SendLpa(r.Context(), mock.Anything, mock.Anything). Return(expectedError) eventClient := newMockEventClient(t) diff --git a/internal/donor/donorpage/progress.go b/internal/donor/donorpage/progress.go index 0e779c4d47..c041e2a850 100644 --- a/internal/donor/donorpage/progress.go +++ b/internal/donor/donorpage/progress.go @@ -45,7 +45,7 @@ func Progress(tmpl template.Template, lpaStoreResolvingService LpaStoreResolving }) } - if lpa.Submitted && lpa.CertificateProvider.SignedAt.IsZero() { + if lpa.Submitted && (lpa.CertificateProvider.SignedAt == nil || lpa.CertificateProvider.SignedAt.IsZero()) { _, err := certificateProviderStore.GetAny(r.Context()) if errors.Is(err, dynamo.NotFoundError{}) { data.InfoNotifications = append(data.InfoNotifications, progressNotification{ diff --git a/internal/donor/donorpage/progress_test.go b/internal/donor/donorpage/progress_test.go index 94c286d706..9f66d8f5e3 100644 --- a/internal/donor/donorpage/progress_test.go +++ b/internal/donor/donorpage/progress_test.go @@ -16,6 +16,8 @@ import ( ) func TestGetProgress(t *testing.T) { + signedAt := time.Now() + testCases := map[string]struct { donor *donordata.Provided setupCertificateProviderStore func(*mockCertificateProviderStore_GetAny_Call) @@ -95,7 +97,7 @@ func TestGetProgress(t *testing.T) { LpaUID: "lpa-uid", Submitted: true, CertificateProvider: lpadata.CertificateProvider{ - SignedAt: time.Now(), + SignedAt: &signedAt, }, }, }, diff --git a/internal/donor/donorpage/register.go b/internal/donor/donorpage/register.go index b778650bf5..03f1b0a92e 100644 --- a/internal/donor/donorpage/register.go +++ b/internal/donor/donorpage/register.go @@ -18,6 +18,7 @@ import ( "github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata" "github.com/ministryofjustice/opg-modernising-lpa/internal/event" "github.com/ministryofjustice/opg-modernising-lpa/internal/identity" + "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore" "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore/lpadata" "github.com/ministryofjustice/opg-modernising-lpa/internal/notify" "github.com/ministryofjustice/opg-modernising-lpa/internal/onelogin" @@ -155,7 +156,7 @@ type DashboardStore interface { type LpaStoreClient interface { Lpa(ctx context.Context, lpaUID string) (*lpadata.Lpa, error) SendDonorConfirmIdentity(ctx context.Context, donor *donordata.Provided) error - SendLpa(ctx context.Context, details *donordata.Provided) error + SendLpa(ctx context.Context, uid string, body lpastore.CreateLpa) error SendDonorWithdrawLPA(ctx context.Context, lpaUID string) error } diff --git a/internal/donor/donorpage/view_lpa.go b/internal/donor/donorpage/view_lpa.go index 3cec653470..613abec00d 100644 --- a/internal/donor/donorpage/view_lpa.go +++ b/internal/donor/donorpage/view_lpa.go @@ -26,7 +26,7 @@ func ViewLpa(tmpl template.Template, lpaStoreClient LpaStoreClient) Handler { return err } - lpa = lpastore.FromDonorProvidedDetails(donor) + lpa = lpastore.LpaFromDonorProvided(donor) } return tmpl(w, &viewLpaData{ diff --git a/internal/donor/donorpage/view_lpa_test.go b/internal/donor/donorpage/view_lpa_test.go index 00e3a3b74f..1b19e2119d 100644 --- a/internal/donor/donorpage/view_lpa_test.go +++ b/internal/donor/donorpage/view_lpa_test.go @@ -49,7 +49,7 @@ func TestViewLpaWhenNotFound(t *testing.T) { template := newMockTemplate(t) template.EXPECT(). - Execute(w, &viewLpaData{App: testAppData, Lpa: lpastore.FromDonorProvidedDetails(donor)}). + Execute(w, &viewLpaData{App: testAppData, Lpa: lpastore.LpaFromDonorProvided(donor)}). Return(nil) err := ViewLpa(template.Execute, lpaStoreClient)(testAppData, w, r, donor) diff --git a/internal/donor/donorpage/witnessing_as_certificate_provider.go b/internal/donor/donorpage/witnessing_as_certificate_provider.go index 98476c15f5..fd3c4f2cfb 100644 --- a/internal/donor/donorpage/witnessing_as_certificate_provider.go +++ b/internal/donor/donorpage/witnessing_as_certificate_provider.go @@ -9,6 +9,7 @@ import ( "github.com/ministryofjustice/opg-modernising-lpa/internal/donor" "github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata" "github.com/ministryofjustice/opg-modernising-lpa/internal/event" + "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore" "github.com/ministryofjustice/opg-modernising-lpa/internal/page" "github.com/ministryofjustice/opg-modernising-lpa/internal/task" "github.com/ministryofjustice/opg-modernising-lpa/internal/validation" @@ -81,7 +82,7 @@ func WitnessingAsCertificateProvider( return err } - if err := lpaStoreClient.SendLpa(r.Context(), provided); err != nil { + if err := lpaStoreClient.SendLpa(r.Context(), provided.LpaUID, lpastore.CreateLpaFromDonorProvided(provided)); err != nil { return err } } diff --git a/internal/donor/donorpage/witnessing_as_certificate_provider_test.go b/internal/donor/donorpage/witnessing_as_certificate_provider_test.go index 706a3408e1..5b3a142d23 100644 --- a/internal/donor/donorpage/witnessing_as_certificate_provider_test.go +++ b/internal/donor/donorpage/witnessing_as_certificate_provider_test.go @@ -12,6 +12,7 @@ import ( "github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata" "github.com/ministryofjustice/opg-modernising-lpa/internal/event" "github.com/ministryofjustice/opg-modernising-lpa/internal/identity" + lpastore "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore" "github.com/ministryofjustice/opg-modernising-lpa/internal/page" "github.com/ministryofjustice/opg-modernising-lpa/internal/task" "github.com/ministryofjustice/opg-modernising-lpa/internal/validation" @@ -125,7 +126,7 @@ func TestPostWitnessingAsCertificateProvider(t *testing.T) { lpaStoreClient := newMockLpaStoreClient(t) lpaStoreClient.EXPECT(). - SendLpa(r.Context(), provided). + SendLpa(r.Context(), provided.LpaUID, lpastore.CreateLpaFromDonorProvided(provided)). Return(nil) err := WitnessingAsCertificateProvider(nil, donorStore, shareCodeSender, lpaStoreClient, eventClient, testNowFn)(testAppData, w, r, &donordata.Provided{ @@ -211,7 +212,7 @@ func TestPostWitnessingAsCertificateProviderWhenSendLpaErrors(t *testing.T) { lpaStoreClient := newMockLpaStoreClient(t) lpaStoreClient.EXPECT(). - SendLpa(r.Context(), mock.Anything). + SendLpa(r.Context(), mock.Anything, mock.Anything). Return(expectedError) err := WitnessingAsCertificateProvider(nil, donorStore, shareCodeSender, lpaStoreClient, eventClient, testNowFn)(testAppData, w, r, &donordata.Provided{ diff --git a/internal/lpastore/client_test.go b/internal/lpastore/client_test.go index 2ff34278e1..c42804d136 100644 --- a/internal/lpastore/client_test.go +++ b/internal/lpastore/client_test.go @@ -183,7 +183,7 @@ func TestClientServiceContract(t *testing.T) { now: now, } - err := client.SendLpa(context.Background(), &donordata.Provided{ + err := client.SendLpa(context.Background(), "M-0000-1111-2222", CreateLpaFromDonorProvided(&donordata.Provided{ LpaUID: "M-0000-1111-2222", Type: lpadata.LpaTypePersonalWelfare, LifeSustainingTreatmentOption: lpadata.LifeSustainingTreatmentOptionA, @@ -235,7 +235,7 @@ func TestClientServiceContract(t *testing.T) { Restrictions: "hmm", SignedAt: time.Date(2000, time.January, 2, 12, 13, 14, 0, time.UTC), WitnessedByCertificateProviderAt: time.Date(2000, time.January, 2, 13, 14, 15, 0, time.UTC), - }) + })) assert.Nil(t, err) return nil @@ -348,7 +348,7 @@ func TestClientServiceContract(t *testing.T) { now: now, } - err := client.SendLpa(context.Background(), &donordata.Provided{ + err := client.SendLpa(context.Background(), "M-0000-1111-2222", CreateLpaFromDonorProvided(&donordata.Provided{ LpaUID: "M-0000-1111-2222", Type: lpadata.LpaTypePersonalWelfare, Donor: donordata.Donor{ @@ -399,7 +399,7 @@ func TestClientServiceContract(t *testing.T) { Restrictions: "hmm", SignedAt: time.Date(2000, time.January, 2, 12, 13, 14, 0, time.UTC), WitnessedByCertificateProviderAt: time.Date(2000, time.January, 2, 13, 14, 15, 0, time.UTC), - }) + })) assert.Nil(t, err) return nil @@ -427,7 +427,7 @@ func TestClientServiceContract(t *testing.T) { "new": matchers.Like("07777777"), }, { "key": matchers.Like("/attorneys/0/contactLanguagePreference"), - "old": matchers.Like(nil), + "old": matchers.Like(""), "new": matchers.Like("cy"), }, { "key": matchers.Like("/attorneys/0/signedAt"), @@ -503,7 +503,7 @@ func TestClientServiceContract(t *testing.T) { "new": matchers.Like("07777777"), }, { "key": matchers.Like("/trustCorporations/0/contactLanguagePreference"), - "old": matchers.Like(nil), + "old": matchers.Like(""), "new": matchers.Like("cy"), }, { "key": matchers.Like("/trustCorporations/0/email"), diff --git a/internal/lpastore/lpa.go b/internal/lpastore/lpa.go index 00a8a59d8b..e446a80de4 100644 --- a/internal/lpastore/lpa.go +++ b/internal/lpastore/lpa.go @@ -10,27 +10,24 @@ import ( "time" "github.com/ministryofjustice/opg-modernising-lpa/internal/actor/actoruid" - "github.com/ministryofjustice/opg-modernising-lpa/internal/date" "github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata" - "github.com/ministryofjustice/opg-modernising-lpa/internal/localize" "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore/lpadata" - "github.com/ministryofjustice/opg-modernising-lpa/internal/place" ) type abstractError struct { Detail string `json:"detail"` } -type lpaRequest struct { +type CreateLpa struct { LpaType lpadata.LpaType `json:"lpaType"` Channel lpadata.Channel `json:"channel"` - Donor lpaRequestDonor `json:"donor"` - Attorneys []lpaRequestAttorney `json:"attorneys"` - TrustCorporations []lpaRequestTrustCorporation `json:"trustCorporations,omitempty"` - CertificateProvider lpaRequestCertificateProvider `json:"certificateProvider"` - PeopleToNotify []lpaRequestPersonToNotify `json:"peopleToNotify,omitempty"` - IndependentWitness *lpaRequestIndependentWitness `json:"independentWitness,omitempty"` - AuthorisedSignatory *lpaRequestAuthorisedSignatory `json:"authorisedSignatory,omitempty"` + Donor lpadata.Donor `json:"donor"` + Attorneys []lpadata.Attorney `json:"attorneys"` + TrustCorporations []lpadata.TrustCorporation `json:"trustCorporations,omitempty"` + CertificateProvider lpadata.CertificateProvider `json:"certificateProvider"` + PeopleToNotify []lpadata.PersonToNotify `json:"peopleToNotify,omitempty"` + IndependentWitness *lpadata.IndependentWitness `json:"independentWitness,omitempty"` + AuthorisedSignatory *lpadata.AuthorisedSignatory `json:"authorisedSignatory,omitempty"` HowAttorneysMakeDecisions lpadata.AttorneysAct `json:"howAttorneysMakeDecisions,omitempty"` HowAttorneysMakeDecisionsDetails string `json:"howAttorneysMakeDecisionsDetails,omitempty"` HowReplacementAttorneysMakeDecisions lpadata.AttorneysAct `json:"howReplacementAttorneysMakeDecisions,omitempty"` @@ -46,92 +43,22 @@ type lpaRequest struct { CertificateProviderNotRelatedConfirmedAt *time.Time `json:"certificateProviderNotRelatedConfirmedAt,omitempty"` } -type lpaRequestIdentityCheck struct { - CheckedAt time.Time `json:"checkedAt"` - Type string `json:"type"` -} - -type lpaRequestDonor struct { - UID actoruid.UID `json:"uid"` - FirstNames string `json:"firstNames"` - LastName string `json:"lastName"` - DateOfBirth date.Date `json:"dateOfBirth"` - Email string `json:"email"` - Address place.Address `json:"address"` - OtherNamesKnownBy string `json:"otherNamesKnownBy,omitempty"` - ContactLanguagePreference localize.Lang `json:"contactLanguagePreference"` - IdentityCheck *lpaRequestIdentityCheck `json:"identityCheck,omitempty"` -} - -type lpaRequestAttorney struct { - UID actoruid.UID `json:"uid"` - FirstNames string `json:"firstNames"` - LastName string `json:"lastName"` - DateOfBirth date.Date `json:"dateOfBirth"` - Email string `json:"email,omitempty"` - Address place.Address `json:"address"` - Status string `json:"status"` - AppointmentType string `json:"appointmentType"` - Channel lpadata.Channel `json:"channel"` -} - -type lpaRequestTrustCorporation struct { - UID actoruid.UID `json:"uid"` - Name string `json:"name"` - CompanyNumber string `json:"companyNumber"` - Email string `json:"email,omitempty"` - Address place.Address `json:"address"` - Status string `json:"status"` - AppointmentType string `json:"appointmentType"` - Channel lpadata.Channel `json:"channel"` -} - -type lpaRequestCertificateProvider struct { - UID actoruid.UID `json:"uid"` - FirstNames string `json:"firstNames"` - LastName string `json:"lastName"` - Email string `json:"email,omitempty"` - Phone string `json:"phone,omitempty"` - Address place.Address `json:"address"` - Channel lpadata.Channel `json:"channel"` -} - -type lpaRequestPersonToNotify struct { - UID actoruid.UID `json:"uid"` - FirstNames string `json:"firstNames"` - LastName string `json:"lastName"` - Address place.Address `json:"address"` -} - -type lpaRequestIndependentWitness struct { - UID actoruid.UID `json:"uid"` - FirstNames string `json:"firstNames"` - LastName string `json:"lastName"` - Phone string `json:"phone"` - Address place.Address `json:"address"` -} - -type lpaRequestAuthorisedSignatory struct { - UID actoruid.UID `json:"uid"` - FirstNames string `json:"firstNames"` - LastName string `json:"lastName"` -} - -func (c *Client) SendLpa(ctx context.Context, donor *donordata.Provided) error { - body := lpaRequest{ +func CreateLpaFromDonorProvided(donor *donordata.Provided) CreateLpa { + body := CreateLpa{ LpaType: donor.Type, Channel: lpadata.ChannelOnline, - Donor: lpaRequestDonor{ + Donor: lpadata.Donor{ UID: donor.Donor.UID, FirstNames: donor.Donor.FirstNames, LastName: donor.Donor.LastName, DateOfBirth: donor.Donor.DateOfBirth, Email: donor.Donor.Email, + Mobile: donor.Donor.Mobile, Address: donor.Donor.Address, OtherNamesKnownBy: donor.Donor.OtherNames, ContactLanguagePreference: donor.Donor.ContactLanguagePreference, }, - CertificateProvider: lpaRequestCertificateProvider{ + CertificateProvider: lpadata.CertificateProvider{ UID: donor.CertificateProvider.UID, FirstNames: donor.CertificateProvider.FirstNames, LastName: donor.CertificateProvider.LastName, @@ -146,7 +73,7 @@ func (c *Client) SendLpa(ctx context.Context, donor *donordata.Provided) error { } if donor.DonorIdentityConfirmed() { - body.Donor.IdentityCheck = &lpaRequestIdentityCheck{ + body.Donor.IdentityCheck = &lpadata.IdentityCheck{ CheckedAt: donor.IdentityUserData.CheckedAt, Type: "one-login", } @@ -183,61 +110,61 @@ func (c *Client) SendLpa(ctx context.Context, donor *donordata.Provided) error { } for _, attorney := range donor.Attorneys.Attorneys { - body.Attorneys = append(body.Attorneys, lpaRequestAttorney{ + body.Attorneys = append(body.Attorneys, lpadata.Attorney{ UID: attorney.UID, FirstNames: attorney.FirstNames, LastName: attorney.LastName, DateOfBirth: attorney.DateOfBirth, Email: attorney.Email, Address: attorney.Address, - Status: statusActive, - AppointmentType: appointmentTypeOriginal, + Status: lpadata.AttorneyStatusActive, + AppointmentType: lpadata.AppointmentTypeOriginal, Channel: attorney.Channel(), }) } if trustCorporation := donor.Attorneys.TrustCorporation; trustCorporation.Name != "" { - body.TrustCorporations = append(body.TrustCorporations, lpaRequestTrustCorporation{ + body.TrustCorporations = append(body.TrustCorporations, lpadata.TrustCorporation{ UID: trustCorporation.UID, Name: trustCorporation.Name, CompanyNumber: trustCorporation.CompanyNumber, Email: trustCorporation.Email, Address: trustCorporation.Address, - Status: statusActive, - AppointmentType: appointmentTypeOriginal, + Status: lpadata.AttorneyStatusActive, + AppointmentType: lpadata.AppointmentTypeOriginal, Channel: trustCorporation.Channel(), }) } for _, attorney := range donor.ReplacementAttorneys.Attorneys { - body.Attorneys = append(body.Attorneys, lpaRequestAttorney{ + body.Attorneys = append(body.Attorneys, lpadata.Attorney{ UID: attorney.UID, FirstNames: attorney.FirstNames, LastName: attorney.LastName, DateOfBirth: attorney.DateOfBirth, Email: attorney.Email, Address: attorney.Address, - Status: statusInactive, - AppointmentType: appointmentTypeReplacement, + Status: lpadata.AttorneyStatusInactive, + AppointmentType: lpadata.AppointmentTypeReplacement, Channel: attorney.Channel(), }) } if trustCorporation := donor.ReplacementAttorneys.TrustCorporation; trustCorporation.Name != "" { - body.TrustCorporations = append(body.TrustCorporations, lpaRequestTrustCorporation{ + body.TrustCorporations = append(body.TrustCorporations, lpadata.TrustCorporation{ UID: trustCorporation.UID, Name: trustCorporation.Name, CompanyNumber: trustCorporation.CompanyNumber, Email: trustCorporation.Email, Address: trustCorporation.Address, - Status: statusInactive, - AppointmentType: appointmentTypeReplacement, + Status: lpadata.AttorneyStatusInactive, + AppointmentType: lpadata.AppointmentTypeReplacement, Channel: trustCorporation.Channel(), }) } for _, person := range donor.PeopleToNotify { - body.PeopleToNotify = append(body.PeopleToNotify, lpaRequestPersonToNotify{ + body.PeopleToNotify = append(body.PeopleToNotify, lpadata.PersonToNotify{ UID: person.UID, FirstNames: person.FirstNames, LastName: person.LastName, @@ -246,7 +173,7 @@ func (c *Client) SendLpa(ctx context.Context, donor *donordata.Provided) error { } if !donor.IndependentWitness.UID.IsZero() { - body.IndependentWitness = &lpaRequestIndependentWitness{ + body.IndependentWitness = &lpadata.IndependentWitness{ UID: donor.IndependentWitness.UID, FirstNames: donor.IndependentWitness.FirstNames, LastName: donor.IndependentWitness.LastName, @@ -256,24 +183,28 @@ func (c *Client) SendLpa(ctx context.Context, donor *donordata.Provided) error { } if !donor.AuthorisedSignatory.UID.IsZero() { - body.AuthorisedSignatory = &lpaRequestAuthorisedSignatory{ + body.AuthorisedSignatory = &lpadata.AuthorisedSignatory{ UID: donor.AuthorisedSignatory.UID, FirstNames: donor.AuthorisedSignatory.FirstNames, LastName: donor.AuthorisedSignatory.LastName, } } + return body +} + +func (c *Client) SendLpa(ctx context.Context, uid string, body CreateLpa) error { var buf bytes.Buffer if err := json.NewEncoder(&buf).Encode(body); err != nil { return err } - req, err := http.NewRequestWithContext(ctx, http.MethodPut, c.baseURL+"/lpas/"+donor.LpaUID, &buf) + req, err := http.NewRequestWithContext(ctx, http.MethodPut, c.baseURL+"/lpas/"+uid, &buf) if err != nil { return err } - resp, err := c.do(ctx, donor.Donor.UID, req) + resp, err := c.do(ctx, body.Donor.UID, req) if err != nil { return err } @@ -309,30 +240,16 @@ func (c *Client) SendLpa(ctx context.Context, donor *donordata.Provided) error { } } -type lpaResponseAttorney struct { - lpaRequestAttorney - Mobile string `json:"mobile"` - SignedAt time.Time `json:"signedAt"` - ContactLanguagePreference localize.Lang `json:"contactLanguagePreference"` -} - -type lpaResponseTrustCorporation struct { - lpaRequestTrustCorporation - Mobile string `json:"mobile"` - Signatories []lpadata.TrustCorporationSignatory `json:"signatories"` - ContactLanguagePreference localize.Lang `json:"contactLanguagePreference"` -} - type lpaResponse struct { LpaType lpadata.LpaType `json:"lpaType"` - Donor lpaRequestDonor `json:"donor"` + Donor lpadata.Donor `json:"donor"` Channel lpadata.Channel `json:"channel"` - Attorneys []lpaResponseAttorney `json:"attorneys"` - TrustCorporations []lpaResponseTrustCorporation `json:"trustCorporations"` + Attorneys []lpadata.Attorney `json:"attorneys"` + TrustCorporations []lpadata.TrustCorporation `json:"trustCorporations"` CertificateProvider lpadata.CertificateProvider `json:"certificateProvider"` - PeopleToNotify []lpaRequestPersonToNotify `json:"peopleToNotify"` - IndependentWitness *lpaRequestIndependentWitness `json:"independentWitness"` - AuthorisedSignatory *lpaRequestAuthorisedSignatory `json:"authorisedSignatory"` + PeopleToNotify []lpadata.PersonToNotify `json:"peopleToNotify"` + IndependentWitness *lpadata.IndependentWitness `json:"independentWitness"` + AuthorisedSignatory *lpadata.AuthorisedSignatory `json:"authorisedSignatory"` HowAttorneysMakeDecisions lpadata.AttorneysAct `json:"howAttorneysMakeDecisions"` HowAttorneysMakeDecisionsDetails string `json:"howAttorneysMakeDecisionsDetails"` HowReplacementAttorneysMakeDecisions lpadata.AttorneysAct `json:"howReplacementAttorneysMakeDecisions"` @@ -366,7 +283,7 @@ func lpaResponseToLpa(l lpaResponse) *lpadata.Lpa { DateOfBirth: l.Donor.DateOfBirth, Email: l.Donor.Email, Address: l.Donor.Address, - OtherNames: l.Donor.OtherNamesKnownBy, + OtherNamesKnownBy: l.Donor.OtherNamesKnownBy, Channel: l.Channel, ContactLanguagePreference: l.Donor.ContactLanguagePreference, }, @@ -404,10 +321,10 @@ func lpaResponseToLpa(l lpaResponse) *lpadata.Lpa { SignedAt: a.SignedAt, ContactLanguagePreference: a.ContactLanguagePreference, Channel: a.Channel, - Removed: a.Status == statusRemoved, + Removed: a.Status.IsRemoved(), } - if a.AppointmentType == appointmentTypeReplacement { + if a.AppointmentType.IsReplacement() { data.ReplacementAttorneys.Attorneys = append(data.ReplacementAttorneys.Attorneys, at) } else { data.Attorneys.Attorneys = append(data.Attorneys.Attorneys, at) @@ -425,10 +342,10 @@ func lpaResponseToLpa(l lpaResponse) *lpadata.Lpa { Signatories: t.Signatories, ContactLanguagePreference: t.ContactLanguagePreference, Channel: t.Channel, - Removed: t.Status == statusRemoved, + Removed: t.Status.IsRemoved(), } - if t.AppointmentType == appointmentTypeReplacement { + if t.AppointmentType.IsReplacement() { data.ReplacementAttorneys.TrustCorporation = tc } else { data.Attorneys.TrustCorporation = tc @@ -457,7 +374,7 @@ func lpaResponseToLpa(l lpaResponse) *lpadata.Lpa { UID: l.IndependentWitness.UID, FirstNames: l.IndependentWitness.FirstNames, LastName: l.IndependentWitness.LastName, - Mobile: l.IndependentWitness.Phone, + Phone: l.IndependentWitness.Phone, Address: l.IndependentWitness.Address, } } @@ -471,14 +388,16 @@ func lpaResponseToLpa(l lpaResponse) *lpadata.Lpa { } if l.Donor.IdentityCheck != nil { - data.Donor.IdentityCheck.CheckedAt = l.Donor.IdentityCheck.CheckedAt - data.Donor.IdentityCheck.Type = l.Donor.IdentityCheck.Type + data.Donor.IdentityCheck = &lpadata.IdentityCheck{ + CheckedAt: l.Donor.IdentityCheck.CheckedAt, + Type: l.Donor.IdentityCheck.Type, + } } return data } -func FromDonorProvidedDetails(l *donordata.Provided) *lpadata.Lpa { +func LpaFromDonorProvided(l *donordata.Provided) *lpadata.Lpa { data := &lpadata.Lpa{ LpaID: l.LpaID, LpaUID: l.LpaUID, @@ -489,7 +408,7 @@ func FromDonorProvidedDetails(l *donordata.Provided) *lpadata.Lpa { FirstNames: l.Donor.FirstNames, LastName: l.Donor.LastName, Email: l.Donor.Email, - OtherNames: l.Donor.OtherNames, + OtherNamesKnownBy: l.Donor.OtherNames, DateOfBirth: l.Donor.DateOfBirth, Address: l.Donor.Address, Channel: l.Donor.Channel, @@ -571,8 +490,10 @@ func FromDonorProvidedDetails(l *donordata.Provided) *lpadata.Lpa { } if l.DonorIdentityConfirmed() { - data.Donor.IdentityCheck.CheckedAt = l.IdentityUserData.CheckedAt - data.Donor.IdentityCheck.Type = "one-login" + data.Donor.IdentityCheck = &lpadata.IdentityCheck{ + CheckedAt: l.IdentityUserData.CheckedAt, + Type: "one-login", + } } var peopleToNotify []lpadata.PersonToNotify @@ -607,7 +528,7 @@ func FromDonorProvidedDetails(l *donordata.Provided) *lpadata.Lpa { UID: v.UID, FirstNames: v.FirstNames, LastName: v.LastName, - Mobile: v.Mobile, + Phone: v.Mobile, Address: v.Address, } } diff --git a/internal/lpastore/lpa_test.go b/internal/lpastore/lpa_test.go index ebbd8c14ed..cd8e7725a4 100644 --- a/internal/lpastore/lpa_test.go +++ b/internal/lpastore/lpa_test.go @@ -336,7 +336,7 @@ func TestClientSendLpa(t *testing.T) { client := New("http://base", secretsClient, "secret", doer) client.now = func() time.Time { return time.Date(2000, time.January, 2, 3, 4, 5, 6, time.UTC) } - err := client.SendLpa(ctx, tc.donor) + err := client.SendLpa(ctx, tc.donor.LpaUID, CreateLpaFromDonorProvided(tc.donor)) assert.Nil(t, err) }) @@ -345,7 +345,7 @@ func TestClientSendLpa(t *testing.T) { func TestClientSendLpaWhenNewRequestError(t *testing.T) { client := New("http://base", nil, "secret", nil) - err := client.SendLpa(nil, &donordata.Provided{}) + err := client.SendLpa(nil, "", CreateLpa{}) assert.NotNil(t, err) } @@ -359,7 +359,7 @@ func TestClientSendLpaWhenSecretsClientError(t *testing.T) { Return("", expectedError) client := New("http://base", secretsClient, "secret", nil) - err := client.SendLpa(ctx, &donordata.Provided{}) + err := client.SendLpa(ctx, "", CreateLpa{}) assert.Equal(t, expectedError, err) } @@ -378,7 +378,7 @@ func TestClientSendLpaWhenDoerError(t *testing.T) { Return(nil, expectedError) client := New("http://base", secretsClient, "secret", doer) - err := client.SendLpa(ctx, &donordata.Provided{}) + err := client.SendLpa(ctx, "", CreateLpa{}) assert.Equal(t, expectedError, err) } @@ -404,7 +404,7 @@ func TestClientSendLpaWhenStatusCodeIsNotOK(t *testing.T) { Return(&http.Response{StatusCode: code, Body: io.NopCloser(strings.NewReader("hey"))}, nil) client := New("http://base", secretsClient, "secret", doer) - err := client.SendLpa(ctx, &donordata.Provided{}) + err := client.SendLpa(ctx, "", CreateLpa{}) assert.Equal(t, responseError{name: errorName, body: "hey"}, err) }) @@ -444,8 +444,8 @@ func TestClientLpa(t *testing.T) { TownOrCity: "town", Country: "GB", }, - OtherNames: "JJ", - Channel: lpadata.ChannelOnline, + OtherNamesKnownBy: "JJ", + Channel: lpadata.ChannelOnline, }, Attorneys: lpadata.Attorneys{ Attorneys: []lpadata.Attorney{{ @@ -503,8 +503,8 @@ func TestClientLpa(t *testing.T) { TownOrCity: "town", Country: "GB", }, - OtherNames: "JJ", - Channel: lpadata.ChannelOnline, + OtherNamesKnownBy: "JJ", + Channel: lpadata.ChannelOnline, }, Attorneys: lpadata.Attorneys{ Attorneys: []lpadata.Attorney{{ @@ -564,9 +564,9 @@ func TestClientLpa(t *testing.T) { Postcode: "F1 1FF", Country: "GB", }, - OtherNames: "JJ", - Channel: lpadata.ChannelOnline, - IdentityCheck: lpadata.IdentityCheck{ + OtherNamesKnownBy: "JJ", + Channel: lpadata.ChannelOnline, + IdentityCheck: &lpadata.IdentityCheck{ CheckedAt: time.Date(2002, time.January, 2, 12, 13, 14, 1, time.UTC), Type: "one-login", }, @@ -687,7 +687,7 @@ func TestClientLpa(t *testing.T) { Country: "GB", }, Channel: lpadata.ChannelOnline, - IdentityCheck: lpadata.IdentityCheck{ + IdentityCheck: &lpadata.IdentityCheck{ CheckedAt: time.Date(2002, time.January, 1, 13, 14, 15, 16, time.UTC), Type: "one-login", }, @@ -714,7 +714,7 @@ func TestClientLpa(t *testing.T) { UID: independentWitnessUID, FirstNames: "Indiana", LastName: "Witness", - Mobile: "0777777777", + Phone: "0777777777", Address: place.Address{ Line1: "i-line-1", Line2: "i-line-2", @@ -738,12 +738,12 @@ func TestClientLpa(t *testing.T) { "attorneys":[ {"uid":"` + attorneyUID.String() + `","firstNames":"Adam","lastName":"Attorney","dateOfBirth":"1999-01-02","email":"adam@example.com","address":{"line1":"a-line-1","line2":"a-line-2","line3":"a-line-3","town":"a-town","postcode":"A1 1FF","country":"GB"},"status":"active","appointmentType":"original"}, {"uid":"` + attorney2UID.String() + `","firstNames":"Alice","lastName":"Attorney","dateOfBirth":"1998-01-02","email":"alice@example.com","address":{"line1":"aa-line-1","line2":"aa-line-2","line3":"aa-line-3","town":"aa-town","postcode":"A1 1AF","country":"GB"},"status":"active","appointmentType":"original"}, -{"uid":"` + replacementAttorneyUID.String() + `","firstNames":"Richard","lastName":"Attorney","dateOfBirth":"1999-11-12","email":"richard@example.com","address":{"line1":"r-line-1","line2":"r-line-2","line3":"r-line-3","town":"r-town","postcode":"R1 1FF","country":"GB"},"status":"replacement","appointmentType":"replacement"}, -{"uid":"` + replacementAttorney2UID.String() + `","firstNames":"Rachel","lastName":"Attorney","dateOfBirth":"1998-11-12","email":"rachel@example.com","address":{"line1":"rr-line-1","line2":"rr-line-2","line3":"rr-line-3","town":"rr-town","postcode":"R1 1RF","country":"GB"},"status":"replacement","appointmentType":"replacement"} +{"uid":"` + replacementAttorneyUID.String() + `","firstNames":"Richard","lastName":"Attorney","dateOfBirth":"1999-11-12","email":"richard@example.com","address":{"line1":"r-line-1","line2":"r-line-2","line3":"r-line-3","town":"r-town","postcode":"R1 1FF","country":"GB"},"status":"inactive","appointmentType":"replacement"}, +{"uid":"` + replacementAttorney2UID.String() + `","firstNames":"Rachel","lastName":"Attorney","dateOfBirth":"1998-11-12","email":"rachel@example.com","address":{"line1":"rr-line-1","line2":"rr-line-2","line3":"rr-line-3","town":"rr-town","postcode":"R1 1RF","country":"GB"},"status":"inactive","appointmentType":"replacement"} ], "trustCorporations":[ {"uid":"` + trustCorporationUID.String() + `","name":"Trusty","companyNumber":"55555","email":"trusty@example.com","address":{"line1":"a-line-1","line2":"a-line-2","line3":"a-line-3","town":"a-town","postcode":"A1 1FF","country":"GB"},"status":"active","channel":"online","appointmentType":"original"}, -{"uid":"` + replacementTrustCorporationUID.String() + `","name":"UnTrusty","companyNumber":"65555","address":{"line1":"a-line-1","line2":"a-line-2","line3":"a-line-3","town":"a-town","postcode":"A1 1FF","country":"GB"},"status":"replacement","channel":"paper","appointmentType":"replacement"} +{"uid":"` + replacementTrustCorporationUID.String() + `","name":"UnTrusty","companyNumber":"65555","address":{"line1":"a-line-1","line2":"a-line-2","line3":"a-line-3","town":"a-town","postcode":"A1 1FF","country":"GB"},"status":"inactive","channel":"paper","appointmentType":"replacement"} ], "certificateProvider":{"uid":"` + certificateProviderUID.String() + `","firstNames":"Carol","lastName":"Cert","email":"carol@example.com","phone":"0700009000","address":{"line1":"c-line-1","line2":"c-line-2","line3":"c-line-3","town":"c-town","postcode":"C1 1FF","country":"GB"},"channel":"online","identityCheck":{"checkedAt":"2002-01-01T13:14:15.000000016Z","type":"one-login"}}, "peopleToNotify":[{"uid":"` + personToNotifyUID.String() + `","firstNames":"Peter","lastName":"Notify","address":{"line1":"p-line-1","line2":"p-line-2","line3":"p-line-3","town":"p-town","postcode":"P1 1FF","country":"GB"}}], @@ -903,8 +903,8 @@ func TestClientLpas(t *testing.T) { TownOrCity: "town", Country: "GB", }, - OtherNames: "JJ", - Channel: lpadata.ChannelOnline, + OtherNamesKnownBy: "JJ", + Channel: lpadata.ChannelOnline, }, Attorneys: lpadata.Attorneys{ Attorneys: []lpadata.Attorney{{ @@ -967,8 +967,8 @@ func TestClientLpas(t *testing.T) { Postcode: "F1 1FF", Country: "GB", }, - OtherNames: "JJ", - Channel: lpadata.ChannelOnline, + OtherNamesKnownBy: "JJ", + Channel: lpadata.ChannelOnline, }, Attorneys: lpadata.Attorneys{ TrustCorporation: lpadata.TrustCorporation{ @@ -1114,8 +1114,8 @@ func TestClientLpas(t *testing.T) { "attorneys":[ {"uid":"` + attorneyUID.String() + `","firstNames":"Adam","lastName":"Attorney","dateOfBirth":"1999-01-02","email":"adam@example.com","address":{"line1":"a-line-1","line2":"a-line-2","line3":"a-line-3","town":"a-town","postcode":"A1 1FF","country":"GB"},"status":"active","appointmentType":"original"}, {"uid":"` + attorney2UID.String() + `","firstNames":"Alice","lastName":"Attorney","dateOfBirth":"1998-01-02","email":"alice@example.com","address":{"line1":"aa-line-1","line2":"aa-line-2","line3":"aa-line-3","town":"aa-town","postcode":"A1 1AF","country":"GB"},"status":"removed","appointmentType":"original"}, -{"uid":"` + replacementAttorneyUID.String() + `","firstNames":"Richard","lastName":"Attorney","dateOfBirth":"1999-11-12","email":"richard@example.com","address":{"line1":"r-line-1","line2":"r-line-2","line3":"r-line-3","town":"r-town","postcode":"R1 1FF","country":"GB"},"status":"replacement","appointmentType":"replacement"}, -{"uid":"` + replacementAttorney2UID.String() + `","firstNames":"Rachel","lastName":"Attorney","dateOfBirth":"1998-11-12","email":"rachel@example.com","address":{"line1":"rr-line-1","line2":"rr-line-2","line3":"rr-line-3","town":"rr-town","postcode":"R1 1RF","country":"GB"},"status":"replacement","appointmentType":"replacement"} +{"uid":"` + replacementAttorneyUID.String() + `","firstNames":"Richard","lastName":"Attorney","dateOfBirth":"1999-11-12","email":"richard@example.com","address":{"line1":"r-line-1","line2":"r-line-2","line3":"r-line-3","town":"r-town","postcode":"R1 1FF","country":"GB"},"status":"inactive","appointmentType":"replacement"}, +{"uid":"` + replacementAttorney2UID.String() + `","firstNames":"Rachel","lastName":"Attorney","dateOfBirth":"1998-11-12","email":"rachel@example.com","address":{"line1":"rr-line-1","line2":"rr-line-2","line3":"rr-line-3","town":"rr-town","postcode":"R1 1RF","country":"GB"},"status":"inactive","appointmentType":"replacement"} ], "trustCorporations":[ {"uid":"` + trustCorporationUID.String() + `","name":"Trusty","companyNumber":"55555","email":"trusty@example.com","address":{"line1":"a-line-1","line2":"a-line-2","line3":"a-line-3","town":"a-town","postcode":"A1 1FF","country":"GB"},"status":"active","appointmentType":"original"}, diff --git a/internal/lpastore/lpadata/appointment_type.go b/internal/lpastore/lpadata/appointment_type.go new file mode 100644 index 0000000000..024494e46b --- /dev/null +++ b/internal/lpastore/lpadata/appointment_type.go @@ -0,0 +1,9 @@ +package lpadata + +//go:generate enumerator -type AppointmentType -trimprefix -linecomment +type AppointmentType uint8 + +const ( + AppointmentTypeOriginal AppointmentType = iota // original + AppointmentTypeReplacement // replacement +) diff --git a/internal/lpastore/lpadata/attorney.go b/internal/lpastore/lpadata/attorney.go index 3fc279c27d..afc02329c6 100644 --- a/internal/lpastore/lpadata/attorney.go +++ b/internal/lpastore/lpadata/attorney.go @@ -10,17 +10,24 @@ import ( ) type Attorney struct { - UID actoruid.UID - FirstNames string - LastName string - DateOfBirth date.Date - Email string - Address place.Address - Mobile string - SignedAt time.Time - ContactLanguagePreference localize.Lang - Channel Channel - Removed bool + UID actoruid.UID `json:"uid"` + FirstNames string `json:"firstNames"` + LastName string `json:"lastName"` + DateOfBirth date.Date `json:"dateOfBirth"` + Email string `json:"email,omitempty"` + Address place.Address `json:"address"` + Channel Channel `json:"channel"` + Status AttorneyStatus `json:"status"` + AppointmentType AppointmentType `json:"appointmentType"` + + // Mobile may be given by the attorney, or a paper donor + Mobile string `json:"mobile,omitempty"` + + // These are given by the attorney, so will not be present on creation. + SignedAt *time.Time `json:"signedAt,omitempty"` + ContactLanguagePreference localize.Lang `json:"contactLanguagePreference,omitempty"` + + Removed bool `json:"-"` } func (a Attorney) FullName() string { diff --git a/internal/lpastore/lpadata/attorney_status.go b/internal/lpastore/lpadata/attorney_status.go new file mode 100644 index 0000000000..4259a588c4 --- /dev/null +++ b/internal/lpastore/lpadata/attorney_status.go @@ -0,0 +1,10 @@ +package lpadata + +//go:generate enumerator -type AttorneyStatus -trimprefix -linecomment +type AttorneyStatus uint8 + +const ( + AttorneyStatusActive AttorneyStatus = iota // active + AttorneyStatusInactive // inactive + AttorneyStatusRemoved // removed +) diff --git a/internal/lpastore/lpadata/authorised_signatory.go b/internal/lpastore/lpadata/authorised_signatory.go index 04b03ffc1d..88f884c22a 100644 --- a/internal/lpastore/lpadata/authorised_signatory.go +++ b/internal/lpastore/lpadata/authorised_signatory.go @@ -3,9 +3,9 @@ package lpadata import "github.com/ministryofjustice/opg-modernising-lpa/internal/actor/actoruid" type AuthorisedSignatory struct { - UID actoruid.UID - FirstNames string - LastName string + UID actoruid.UID `json:"uid"` + FirstNames string `json:"firstNames"` + LastName string `json:"lastName"` } func (a AuthorisedSignatory) FullName() string { diff --git a/internal/lpastore/lpadata/certificate_provider.go b/internal/lpastore/lpadata/certificate_provider.go index 3b27835358..61877476f1 100644 --- a/internal/lpastore/lpadata/certificate_provider.go +++ b/internal/lpastore/lpadata/certificate_provider.go @@ -9,21 +9,24 @@ import ( ) type CertificateProvider struct { - UID actoruid.UID `json:"uid"` - FirstNames string `json:"firstNames"` - LastName string `json:"lastName"` - Email string `json:"email,omitempty"` - Phone string `json:"phone,omitempty"` - Address place.Address `json:"address"` - Channel Channel `json:"channel"` - SignedAt time.Time `json:"signedAt"` - ContactLanguagePreference localize.Lang `json:"contactLanguagePreference"` - IdentityCheck IdentityCheck `json:"identityCheck"` + UID actoruid.UID `json:"uid"` + FirstNames string `json:"firstNames"` + LastName string `json:"lastName"` + Email string `json:"email,omitempty"` + Phone string `json:"phone,omitempty"` + Address place.Address `json:"address"` + Channel Channel `json:"channel"` + + // These are given by the certificate provider, so will not be present when + // creating. + SignedAt *time.Time `json:"signedAt,omitempty"` + ContactLanguagePreference localize.Lang `json:"contactLanguagePreference,omitempty"` + IdentityCheck *IdentityCheck `json:"identityCheck,omitempty"` // Relationship is not stored in the lpa-store so is defaulted to // Professional. We require it to determine whether to show the home address // page to a certificate provider. - Relationship CertificateProviderRelationship + Relationship CertificateProviderRelationship `json:"-"` } func (c CertificateProvider) FullName() string { diff --git a/internal/lpastore/lpadata/donor.go b/internal/lpastore/lpadata/donor.go index f3d834d0f2..191211c5c3 100644 --- a/internal/lpastore/lpadata/donor.go +++ b/internal/lpastore/lpadata/donor.go @@ -8,19 +8,20 @@ import ( ) type Donor struct { - UID actoruid.UID - FirstNames string - LastName string - Email string - OtherNames string - DateOfBirth date.Date - Address place.Address - Channel Channel - ContactLanguagePreference localize.Lang - IdentityCheck IdentityCheck + UID actoruid.UID `json:"uid"` + FirstNames string `json:"firstNames"` + LastName string `json:"lastName"` + Email string `json:"email"` + OtherNamesKnownBy string `json:"otherNamesKnownBy,omitempty"` + DateOfBirth date.Date `json:"dateOfBirth"` + Address place.Address `json:"address"` + ContactLanguagePreference localize.Lang `json:"contactLanguagePreference"` + IdentityCheck *IdentityCheck `json:"identityCheck,omitempty"` // Mobile is only set for online donors who have provided one - Mobile string + Mobile string `json:"mobile,omitempty"` + + Channel Channel `json:"-"` } func (d Donor) FullName() string { diff --git a/internal/lpastore/lpadata/enum_appointmenttype.go b/internal/lpastore/lpadata/enum_appointmenttype.go new file mode 100644 index 0000000000..80de4d023e --- /dev/null +++ b/internal/lpastore/lpadata/enum_appointmenttype.go @@ -0,0 +1,70 @@ +// Code generated by "enumerator -type AppointmentType -trimprefix -linecomment"; DO NOT EDIT. + +package lpadata + +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[AppointmentTypeOriginal-0] + _ = x[AppointmentTypeReplacement-1] +} + +const _AppointmentType_name = "originalreplacement" + +var _AppointmentType_index = [...]uint8{0, 8, 19} + +func (i AppointmentType) String() string { + if i >= AppointmentType(len(_AppointmentType_index)-1) { + return "AppointmentType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _AppointmentType_name[_AppointmentType_index[i]:_AppointmentType_index[i+1]] +} + +func (i AppointmentType) MarshalText() ([]byte, error) { + return []byte(i.String()), nil +} + +func (i *AppointmentType) UnmarshalText(text []byte) error { + val, err := ParseAppointmentType(string(text)) + if err != nil { + return err + } + + *i = val + return nil +} + +func (i AppointmentType) IsOriginal() bool { + return i == AppointmentTypeOriginal +} + +func (i AppointmentType) IsReplacement() bool { + return i == AppointmentTypeReplacement +} + +func ParseAppointmentType(s string) (AppointmentType, error) { + switch s { + case "original": + return AppointmentTypeOriginal, nil + case "replacement": + return AppointmentTypeReplacement, nil + default: + return AppointmentType(0), fmt.Errorf("invalid AppointmentType '%s'", s) + } +} + +type AppointmentTypeOptions struct { + Original AppointmentType + Replacement AppointmentType +} + +var AppointmentTypeValues = AppointmentTypeOptions{ + Original: AppointmentTypeOriginal, + Replacement: AppointmentTypeReplacement, +} diff --git a/internal/lpastore/lpadata/enum_attorneystatus.go b/internal/lpastore/lpadata/enum_attorneystatus.go new file mode 100644 index 0000000000..7dae5be65f --- /dev/null +++ b/internal/lpastore/lpadata/enum_attorneystatus.go @@ -0,0 +1,79 @@ +// Code generated by "enumerator -type AttorneyStatus -trimprefix -linecomment"; DO NOT EDIT. + +package lpadata + +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[AttorneyStatusActive-0] + _ = x[AttorneyStatusInactive-1] + _ = x[AttorneyStatusRemoved-2] +} + +const _AttorneyStatus_name = "activeinactiveremoved" + +var _AttorneyStatus_index = [...]uint8{0, 6, 14, 21} + +func (i AttorneyStatus) String() string { + if i >= AttorneyStatus(len(_AttorneyStatus_index)-1) { + return "AttorneyStatus(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _AttorneyStatus_name[_AttorneyStatus_index[i]:_AttorneyStatus_index[i+1]] +} + +func (i AttorneyStatus) MarshalText() ([]byte, error) { + return []byte(i.String()), nil +} + +func (i *AttorneyStatus) UnmarshalText(text []byte) error { + val, err := ParseAttorneyStatus(string(text)) + if err != nil { + return err + } + + *i = val + return nil +} + +func (i AttorneyStatus) IsActive() bool { + return i == AttorneyStatusActive +} + +func (i AttorneyStatus) IsInactive() bool { + return i == AttorneyStatusInactive +} + +func (i AttorneyStatus) IsRemoved() bool { + return i == AttorneyStatusRemoved +} + +func ParseAttorneyStatus(s string) (AttorneyStatus, error) { + switch s { + case "active": + return AttorneyStatusActive, nil + case "inactive": + return AttorneyStatusInactive, nil + case "removed": + return AttorneyStatusRemoved, nil + default: + return AttorneyStatus(0), fmt.Errorf("invalid AttorneyStatus '%s'", s) + } +} + +type AttorneyStatusOptions struct { + Active AttorneyStatus + Inactive AttorneyStatus + Removed AttorneyStatus +} + +var AttorneyStatusValues = AttorneyStatusOptions{ + Active: AttorneyStatusActive, + Inactive: AttorneyStatusInactive, + Removed: AttorneyStatusRemoved, +} diff --git a/internal/lpastore/lpadata/independent_witness.go b/internal/lpastore/lpadata/independent_witness.go index 4c7996c54d..1858daa5dc 100644 --- a/internal/lpastore/lpadata/independent_witness.go +++ b/internal/lpastore/lpadata/independent_witness.go @@ -6,11 +6,11 @@ import ( ) type IndependentWitness struct { - UID actoruid.UID - FirstNames string - LastName string - Mobile string - Address place.Address + UID actoruid.UID `json:"uid"` + FirstNames string `json:"firstNames"` + LastName string `json:"lastName"` + Phone string `json:"phone"` + Address place.Address `json:"address"` } func (w IndependentWitness) FullName() string { diff --git a/internal/lpastore/lpadata/lpa.go b/internal/lpastore/lpadata/lpa.go index eb725c9f31..782cdd557c 100644 --- a/internal/lpastore/lpadata/lpa.go +++ b/internal/lpastore/lpadata/lpa.go @@ -99,7 +99,7 @@ func (l Lpa) AllAttorneysSigned() bool { for _, attorneys := range []Attorneys{l.Attorneys, l.ReplacementAttorneys} { for _, a := range attorneys.Attorneys { - if a.SignedAt.IsZero() { + if a.SignedAt == nil || a.SignedAt.IsZero() { return false } } @@ -199,22 +199,22 @@ func (l Lpa) Actors() iter.Seq[actor.Actor] { } } -func (l *Lpa) Attorney(uid actoruid.UID) (string, actor.Type) { +func (l *Lpa) Attorney(uid actoruid.UID) (string, string, actor.Type) { if t := l.ReplacementAttorneys.TrustCorporation; t.UID == uid { - return t.Name, actor.TypeReplacementTrustCorporation + return t.Name, t.Mobile, actor.TypeReplacementTrustCorporation } if t := l.Attorneys.TrustCorporation; t.UID == uid { - return t.Name, actor.TypeTrustCorporation + return t.Name, t.Mobile, actor.TypeTrustCorporation } if a, ok := l.ReplacementAttorneys.Get(uid); ok { - return a.FullName(), actor.TypeReplacementAttorney + return a.FullName(), a.Mobile, actor.TypeReplacementAttorney } if a, ok := l.Attorneys.Get(uid); ok { - return a.FullName(), actor.TypeAttorney + return a.FullName(), a.Mobile, actor.TypeAttorney } - return "", actor.TypeNone + return "", "", actor.TypeNone } diff --git a/internal/lpastore/lpadata/lpa_test.go b/internal/lpastore/lpadata/lpa_test.go index 9c0da7605c..8eee8bfc5b 100644 --- a/internal/lpastore/lpadata/lpa_test.go +++ b/internal/lpastore/lpadata/lpa_test.go @@ -56,22 +56,22 @@ func TestAllAttorneysSigned(t *testing.T) { }, "need attorney to sign": { lpa: Lpa{ - Attorneys: Attorneys{Attorneys: []Attorney{{SignedAt: attorneySigned}, {}}}, - ReplacementAttorneys: Attorneys{Attorneys: []Attorney{{SignedAt: attorneySigned}}}, + Attorneys: Attorneys{Attorneys: []Attorney{{SignedAt: &attorneySigned}, {}}}, + ReplacementAttorneys: Attorneys{Attorneys: []Attorney{{SignedAt: &attorneySigned}}}, }, expected: false, }, "need replacement attorney to sign": { lpa: Lpa{ - Attorneys: Attorneys{Attorneys: []Attorney{{SignedAt: attorneySigned}}}, - ReplacementAttorneys: Attorneys{Attorneys: []Attorney{{}, {SignedAt: attorneySigned}}}, + Attorneys: Attorneys{Attorneys: []Attorney{{SignedAt: &attorneySigned}}}, + ReplacementAttorneys: Attorneys{Attorneys: []Attorney{{}, {SignedAt: &attorneySigned}}}, }, expected: false, }, "all attorneys signed": { lpa: Lpa{ - Attorneys: Attorneys{Attorneys: []Attorney{{SignedAt: attorneySigned}, {SignedAt: attorneySigned}}}, - ReplacementAttorneys: Attorneys{Attorneys: []Attorney{{SignedAt: attorneySigned}}}, + Attorneys: Attorneys{Attorneys: []Attorney{{SignedAt: &attorneySigned}, {SignedAt: &attorneySigned}}}, + ReplacementAttorneys: Attorneys{Attorneys: []Attorney{{SignedAt: &attorneySigned}}}, }, expected: true, }, @@ -238,23 +238,25 @@ func TestAttorney(t *testing.T) { lpa := &Lpa{ Attorneys: Attorneys{ - Attorneys: []Attorney{{UID: attorneyUID, FirstNames: "A", LastName: "B"}}, + Attorneys: []Attorney{{UID: attorneyUID, FirstNames: "A", LastName: "B", Mobile: "0777"}}, TrustCorporation: TrustCorporation{UID: trustCorporationUID, Name: "C"}, }, ReplacementAttorneys: Attorneys{ Attorneys: []Attorney{{UID: replacementAttorneyUID, FirstNames: "D", LastName: "E"}}, - TrustCorporation: TrustCorporation{UID: replacementTrustCorporationUID, Name: "F"}, + TrustCorporation: TrustCorporation{UID: replacementTrustCorporationUID, Name: "F", Mobile: "0778"}, }, } testcases := map[string]struct { uid actoruid.UID name string + mobile string actorType actor.Type }{ "attorney": { uid: attorneyUID, name: "A B", + mobile: "0777", actorType: actor.TypeAttorney, }, "replacement attorney": { @@ -270,6 +272,7 @@ func TestAttorney(t *testing.T) { "replacement trust corporation": { uid: replacementTrustCorporationUID, name: "F", + mobile: "0778", actorType: actor.TypeReplacementTrustCorporation, }, "missing": { @@ -280,9 +283,10 @@ func TestAttorney(t *testing.T) { for name, tc := range testcases { t.Run(name, func(t *testing.T) { - name, actorType := lpa.Attorney(tc.uid) + name, mobile, actorType := lpa.Attorney(tc.uid) assert.Equal(t, tc.name, name) + assert.Equal(t, tc.mobile, mobile) assert.Equal(t, tc.actorType, actorType) }) } diff --git a/internal/lpastore/lpadata/person_to_notify.go b/internal/lpastore/lpadata/person_to_notify.go index 88f317ac87..4f1b1bdfe7 100644 --- a/internal/lpastore/lpadata/person_to_notify.go +++ b/internal/lpastore/lpadata/person_to_notify.go @@ -6,10 +6,10 @@ import ( ) type PersonToNotify struct { - UID actoruid.UID - FirstNames string - LastName string - Address place.Address + UID actoruid.UID `json:"uid"` + FirstNames string `json:"firstNames"` + LastName string `json:"lastName"` + Address place.Address `json:"address"` } func (p PersonToNotify) FullName() string { diff --git a/internal/lpastore/lpadata/trust_corporation.go b/internal/lpastore/lpadata/trust_corporation.go index af451e20ed..8c10720162 100644 --- a/internal/lpastore/lpadata/trust_corporation.go +++ b/internal/lpastore/lpadata/trust_corporation.go @@ -7,14 +7,22 @@ import ( ) type TrustCorporation struct { - UID actoruid.UID - Name string - CompanyNumber string - Email string - Address place.Address - Mobile string - Signatories []TrustCorporationSignatory - ContactLanguagePreference localize.Lang - Channel Channel - Removed bool + UID actoruid.UID `json:"uid"` + Name string `json:"name"` + CompanyNumber string `json:"companyNumber"` + Email string `json:"email,omitempty"` + Address place.Address `json:"address"` + Channel Channel `json:"channel"` + Status AttorneyStatus `json:"status"` + AppointmentType AppointmentType `json:"appointmentType"` + + // Mobile may be given by the trust corporation, or a paper donor + Mobile string `json:"mobile,omitempty"` + + // These are given by the trust corporation, so will not be present on + // creation. + ContactLanguagePreference localize.Lang `json:"contactLanguagePreference,omitempty"` + Signatories []TrustCorporationSignatory `json:"signatories,omitempty"` + + Removed bool `json:"-"` } diff --git a/internal/lpastore/resolving_service.go b/internal/lpastore/resolving_service.go index 817011f5f8..6b23fccbd2 100644 --- a/internal/lpastore/resolving_service.go +++ b/internal/lpastore/resolving_service.go @@ -36,12 +36,12 @@ func (s *ResolvingService) Get(ctx context.Context) (*lpadata.Lpa, error) { } if donor.LpaUID == "" { - return s.merge(FromDonorProvidedDetails(donor), donor), nil + return s.merge(LpaFromDonorProvided(donor), donor), nil } lpa, err := s.client.Lpa(ctx, donor.LpaUID) if errors.Is(err, ErrNotFound) { - lpa = FromDonorProvidedDetails(donor) + lpa = LpaFromDonorProvided(donor) } else if err != nil { return nil, err } @@ -70,7 +70,7 @@ func (s *ResolvingService) ResolveList(ctx context.Context, donors []*donordata. if lpa, ok := lpaMap[donor.LpaUID]; ok { result[i] = s.merge(lpa, donor) } else { - result[i] = s.merge(FromDonorProvidedDetails(donor), donor) + result[i] = s.merge(LpaFromDonorProvided(donor), donor) } } diff --git a/internal/lpastore/resolving_service_test.go b/internal/lpastore/resolving_service_test.go index 292025cacd..7690fa05b6 100644 --- a/internal/lpastore/resolving_service_test.go +++ b/internal/lpastore/resolving_service_test.go @@ -106,7 +106,7 @@ func TestResolvingServiceGet(t *testing.T) { }, Donor: lpadata.Donor{ Channel: lpadata.ChannelOnline, - IdentityCheck: lpadata.IdentityCheck{ + IdentityCheck: &lpadata.IdentityCheck{ CheckedAt: time.Date(2020, time.January, 2, 12, 13, 14, 5, time.UTC), Type: "one-login", }, diff --git a/internal/lpastore/update.go b/internal/lpastore/update.go index cec8de4f40..eeb6c359ab 100644 --- a/internal/lpastore/update.go +++ b/internal/lpastore/update.go @@ -146,13 +146,13 @@ func (c *Client) SendAttorney(ctx context.Context, lpa *lpadata.Lpa, attorney *a body := updateRequest{ Type: "ATTORNEY_SIGN", Changes: []updateRequestChange{ - {Key: attorneyKey + "/mobile", New: attorney.Phone}, {Key: attorneyKey + "/contactLanguagePreference", New: attorney.ContactLanguagePreference.String()}, }, } if attorney.IsTrustCorporation { body.Type = "TRUST_CORPORATION_SIGN" + body.Changes = append(body.Changes, updateRequestChange{Key: attorneyKey + "/mobile", New: attorney.Phone, Old: lpaTrustCorp.Mobile}) if lpaTrustCorp.Email != attorney.Email { body.Changes = append(body.Changes, updateRequestChange{Key: attorneyKey + "/email", New: attorney.Email, Old: lpaTrustCorp.Email}) @@ -178,6 +178,8 @@ func (c *Client) SendAttorney(ctx context.Context, lpa *lpadata.Lpa, attorney *a ) } } else { + body.Changes = append(body.Changes, updateRequestChange{Key: attorneyKey + "/mobile", New: attorney.Phone, Old: lpaAttorney.Mobile}) + if attorney.Email != lpaAttorney.Email { body.Changes = append(body.Changes, updateRequestChange{Key: attorneyKey + "/email", New: attorney.Email, Old: lpaAttorney.Email}) } diff --git a/internal/lpastore/update_test.go b/internal/lpastore/update_test.go index ffbd5004d3..f69efceb17 100644 --- a/internal/lpastore/update_test.go +++ b/internal/lpastore/update_test.go @@ -207,7 +207,7 @@ func TestClientSendAttorney(t *testing.T) { }, }, }, - json: `{"type":"ATTORNEY_SIGN","changes":[{"key":"/attorneys/1/mobile","old":null,"new":"07777"},{"key":"/attorneys/1/contactLanguagePreference","old":null,"new":"cy"},{"key":"/attorneys/1/email","old":"a@example.com","new":"b@example.com"},{"key":"/attorneys/1/channel","old":"paper","new":"online"},{"key":"/attorneys/1/signedAt","old":null,"new":"2000-01-02T03:04:05.000000006Z"}]}`, + json: `{"type":"ATTORNEY_SIGN","changes":[{"key":"/attorneys/1/contactLanguagePreference","old":null,"new":"cy"},{"key":"/attorneys/1/mobile","old":"","new":"07777"},{"key":"/attorneys/1/email","old":"a@example.com","new":"b@example.com"},{"key":"/attorneys/1/channel","old":"paper","new":"online"},{"key":"/attorneys/1/signedAt","old":null,"new":"2000-01-02T03:04:05.000000006Z"}]}`, }, "replacement attorney": { attorney: &attorneydata.Provided{ @@ -231,7 +231,7 @@ func TestClientSendAttorney(t *testing.T) { }, }, }, - json: `{"type":"ATTORNEY_SIGN","changes":[{"key":"/attorneys/3/mobile","old":null,"new":"07777"},{"key":"/attorneys/3/contactLanguagePreference","old":null,"new":"cy"},{"key":"/attorneys/3/email","old":"a@example.com","new":"b@example.com"},{"key":"/attorneys/3/channel","old":"paper","new":"online"},{"key":"/attorneys/3/signedAt","old":null,"new":"2000-01-02T03:04:05.000000006Z"}]}`, + json: `{"type":"ATTORNEY_SIGN","changes":[{"key":"/attorneys/3/contactLanguagePreference","old":null,"new":"cy"},{"key":"/attorneys/3/mobile","old":"","new":"07777"},{"key":"/attorneys/3/email","old":"a@example.com","new":"b@example.com"},{"key":"/attorneys/3/channel","old":"paper","new":"online"},{"key":"/attorneys/3/signedAt","old":null,"new":"2000-01-02T03:04:05.000000006Z"}]}`, }, "trust corporation": { attorney: &attorneydata.Provided{ @@ -258,7 +258,7 @@ func TestClientSendAttorney(t *testing.T) { TrustCorporation: lpadata.TrustCorporation{Channel: lpadata.ChannelPaper}, }, }, - json: `{"type":"TRUST_CORPORATION_SIGN","changes":[{"key":"/trustCorporations/0/mobile","old":null,"new":"07777"},{"key":"/trustCorporations/0/contactLanguagePreference","old":null,"new":"en"},{"key":"/trustCorporations/0/email","old":"","new":"a@example.com"},{"key":"/trustCorporations/0/channel","old":"paper","new":"online"},{"key":"/trustCorporations/0/signatories/0/firstNames","old":null,"new":"John"},{"key":"/trustCorporations/0/signatories/0/lastName","old":null,"new":"Signer"},{"key":"/trustCorporations/0/signatories/0/professionalTitle","old":null,"new":"Director"},{"key":"/trustCorporations/0/signatories/0/signedAt","old":null,"new":"2000-01-02T03:04:05.000000006Z"},{"key":"/trustCorporations/0/signatories/1/firstNames","old":null,"new":"Dave"},{"key":"/trustCorporations/0/signatories/1/lastName","old":null,"new":"Signer"},{"key":"/trustCorporations/0/signatories/1/professionalTitle","old":null,"new":"Assistant to the Director"},{"key":"/trustCorporations/0/signatories/1/signedAt","old":null,"new":"2000-01-02T03:04:05.000000007Z"}]}`, + json: `{"type":"TRUST_CORPORATION_SIGN","changes":[{"key":"/trustCorporations/0/contactLanguagePreference","old":null,"new":"en"},{"key":"/trustCorporations/0/mobile","old":"","new":"07777"},{"key":"/trustCorporations/0/email","old":"","new":"a@example.com"},{"key":"/trustCorporations/0/channel","old":"paper","new":"online"},{"key":"/trustCorporations/0/signatories/0/firstNames","old":null,"new":"John"},{"key":"/trustCorporations/0/signatories/0/lastName","old":null,"new":"Signer"},{"key":"/trustCorporations/0/signatories/0/professionalTitle","old":null,"new":"Director"},{"key":"/trustCorporations/0/signatories/0/signedAt","old":null,"new":"2000-01-02T03:04:05.000000006Z"},{"key":"/trustCorporations/0/signatories/1/firstNames","old":null,"new":"Dave"},{"key":"/trustCorporations/0/signatories/1/lastName","old":null,"new":"Signer"},{"key":"/trustCorporations/0/signatories/1/professionalTitle","old":null,"new":"Assistant to the Director"},{"key":"/trustCorporations/0/signatories/1/signedAt","old":null,"new":"2000-01-02T03:04:05.000000007Z"}]}`, }, "replacement trust corporation": { attorney: &attorneydata.Provided{ @@ -283,7 +283,7 @@ func TestClientSendAttorney(t *testing.T) { TrustCorporation: lpadata.TrustCorporation{Channel: lpadata.ChannelPaper}, }, }, - json: `{"type":"TRUST_CORPORATION_SIGN","changes":[{"key":"/trustCorporations/1/mobile","old":null,"new":"07777"},{"key":"/trustCorporations/1/contactLanguagePreference","old":null,"new":"en"},{"key":"/trustCorporations/1/channel","old":"paper","new":"online"},{"key":"/trustCorporations/1/signatories/0/firstNames","old":null,"new":"John"},{"key":"/trustCorporations/1/signatories/0/lastName","old":null,"new":"Signer"},{"key":"/trustCorporations/1/signatories/0/professionalTitle","old":null,"new":"Director"},{"key":"/trustCorporations/1/signatories/0/signedAt","old":null,"new":"2000-01-02T03:04:05.000000006Z"}]}`, + json: `{"type":"TRUST_CORPORATION_SIGN","changes":[{"key":"/trustCorporations/1/contactLanguagePreference","old":null,"new":"en"},{"key":"/trustCorporations/1/mobile","old":"","new":"07777"},{"key":"/trustCorporations/1/channel","old":"paper","new":"online"},{"key":"/trustCorporations/1/signatories/0/firstNames","old":null,"new":"John"},{"key":"/trustCorporations/1/signatories/0/lastName","old":null,"new":"Signer"},{"key":"/trustCorporations/1/signatories/0/professionalTitle","old":null,"new":"Director"},{"key":"/trustCorporations/1/signatories/0/signedAt","old":null,"new":"2000-01-02T03:04:05.000000006Z"}]}`, }, "replacement trust corporation when also attorney trust corporation": { attorney: &attorneydata.Provided{ @@ -303,7 +303,7 @@ func TestClientSendAttorney(t *testing.T) { LpaUID: "lpa-uid", Attorneys: lpadata.Attorneys{TrustCorporation: lpadata.TrustCorporation{Name: "a"}}, }, - json: `{"type":"TRUST_CORPORATION_SIGN","changes":[{"key":"/trustCorporations/1/mobile","old":null,"new":"07777"},{"key":"/trustCorporations/1/contactLanguagePreference","old":null,"new":"en"},{"key":"/trustCorporations/1/signatories/0/firstNames","old":null,"new":"John"},{"key":"/trustCorporations/1/signatories/0/lastName","old":null,"new":"Signer"},{"key":"/trustCorporations/1/signatories/0/professionalTitle","old":null,"new":"Director"},{"key":"/trustCorporations/1/signatories/0/signedAt","old":null,"new":"2000-01-02T03:04:05.000000006Z"}]}`, + json: `{"type":"TRUST_CORPORATION_SIGN","changes":[{"key":"/trustCorporations/1/contactLanguagePreference","old":null,"new":"en"},{"key":"/trustCorporations/1/mobile","old":"","new":"07777"},{"key":"/trustCorporations/1/signatories/0/firstNames","old":null,"new":"John"},{"key":"/trustCorporations/1/signatories/0/lastName","old":null,"new":"Signer"},{"key":"/trustCorporations/1/signatories/0/professionalTitle","old":null,"new":"Director"},{"key":"/trustCorporations/1/signatories/0/signedAt","old":null,"new":"2000-01-02T03:04:05.000000006Z"}]}`, }, } diff --git a/internal/page/fixtures/attorney.go b/internal/page/fixtures/attorney.go index 1fe5844381..def059ef18 100644 --- a/internal/page/fixtures/attorney.go +++ b/internal/page/fixtures/attorney.go @@ -14,6 +14,7 @@ import ( "github.com/ministryofjustice/opg-modernising-lpa/internal/attorney/attorneydata" "github.com/ministryofjustice/opg-modernising-lpa/internal/certificateprovider/certificateproviderdata" "github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata" + "github.com/ministryofjustice/opg-modernising-lpa/internal/dynamo" "github.com/ministryofjustice/opg-modernising-lpa/internal/event" "github.com/ministryofjustice/opg-modernising-lpa/internal/form" "github.com/ministryofjustice/opg-modernising-lpa/internal/localize" @@ -57,6 +58,7 @@ func Attorney( organisationStore OrganisationStore, memberStore MemberStore, shareCodeStore ShareCodeStore, + dynamoClient DynamoClient, ) page.Handler { progressValues := []string{ "signedByCertificateProvider", @@ -76,6 +78,8 @@ func Attorney( isReplacement = r.FormValue("is-replacement") == "1" isTrustCorporation = r.FormValue("is-trust-corporation") == "1" isSupported = r.FormValue("is-supported") == "1" + isPaperDonor = r.FormValue("is-paper-donor") == "1" + hasPhoneNumber = r.FormValue("has-phone-number") == "1" lpaType = r.FormValue("lpa-type") progress = slices.Index(progressValues, r.FormValue("progress")) email = r.FormValue("email") @@ -109,36 +113,60 @@ func Attorney( return err } - createFn := donorStore.Create - createSession := &appcontext.Session{SessionID: donorSessionID} - if isSupported { - createFn = organisationStore.CreateLPA + var donorDetails *donordata.Provided + if isPaperDonor { + lpaID := random.UuidString() + + donorDetails = &donordata.Provided{ + PK: dynamo.LpaKey(lpaID), + SK: dynamo.LpaOwnerKey(dynamo.DonorKey("PAPER")), + LpaID: lpaID, + LpaUID: makeUID(), + CreatedAt: time.Now(), + Version: 1, + } - supporterCtx := appcontext.ContextWithSession(r.Context(), &appcontext.Session{SessionID: donorSessionID, Email: testEmail}) + transaction := dynamo.NewTransaction(). + Create(donorDetails). + Create(dynamo.Keys{PK: dynamo.UIDKey(donorDetails.LpaUID), SK: dynamo.MetadataKey("")}). + Create(dynamo.Keys{PK: donorDetails.PK, SK: dynamo.ReservedKey(dynamo.DonorKey)}) - member, err := memberStore.Create(supporterCtx, random.String(12), random.String(12)) - if err != nil { - return err + if err := dynamoClient.WriteTransaction(r.Context(), transaction); err != nil { + return fmt.Errorf("could not write paper donor %s: %w", lpaID, err) } + } else { + createFn := donorStore.Create + createSession := &appcontext.Session{SessionID: donorSessionID} + if isSupported { + createFn = organisationStore.CreateLPA + + supporterCtx := appcontext.ContextWithSession(r.Context(), &appcontext.Session{SessionID: donorSessionID, Email: testEmail}) + + member, err := memberStore.Create(supporterCtx, random.String(12), random.String(12)) + if err != nil { + return err + } + + org, err := organisationStore.Create(supporterCtx, member, random.String(12)) + if err != nil { + return err + } - org, err := organisationStore.Create(supporterCtx, member, random.String(12)) + createSession.OrganisationID = org.ID + } + var err error + donorDetails, err = createFn(appcontext.ContextWithSession(r.Context(), createSession)) if err != nil { return err } - createSession.OrganisationID = org.ID - } - donorDetails, err := createFn(appcontext.ContextWithSession(r.Context(), createSession)) - if err != nil { - return err - } - - if isSupported { - if err := donorStore.Link(appcontext.ContextWithSession(r.Context(), createSession), sharecodedata.Link{ - LpaKey: donorDetails.PK, - LpaOwnerKey: donorDetails.SK, - }, donorDetails.Donor.Email); err != nil { - return err + if isSupported { + if err := donorStore.Link(appcontext.ContextWithSession(r.Context(), createSession), sharecodedata.Link{ + LpaKey: donorDetails.PK, + LpaOwnerKey: donorDetails.SK, + }, donorDetails.Donor.Email); err != nil { + return err + } } } @@ -174,7 +202,7 @@ func Attorney( }); err != nil { return err } - } else { + } else if donorDetails.LpaUID == "" { donorDetails.LpaUID = makeUID() } @@ -215,6 +243,7 @@ func Attorney( donorDetails.AttorneyDecisions = donordata.AttorneyDecisions{How: lpadata.JointlyAndSeverally} donorDetails.ReplacementAttorneyDecisions = donordata.AttorneyDecisions{How: lpadata.JointlyAndSeverally} donorDetails.HowShouldReplacementAttorneysStepIn = lpadata.ReplacementAttorneysStepInWhenAllCanNoLongerAct + donorDetails.Tasks.PayForLpa = task.PaymentStateCompleted certificateProvider, err := createCertificateProvider(certificateProviderCtx, shareCodeStore, certificateProviderStore, donorDetails.CertificateProvider.UID, donorDetails.SK, donorDetails.CertificateProvider.Email) if err != nil { @@ -355,8 +384,29 @@ func Attorney( registered = true } - if err := donorStore.Put(donorCtx, donorDetails); err != nil { - return err + if !isPaperDonor { + if err := donorStore.Put(donorCtx, donorDetails); err != nil { + return err + } + } + if donorDetails.LpaUID != "" { + body := lpastore.CreateLpaFromDonorProvided(donorDetails) + + if hasPhoneNumber { + if isTrustCorporation && isReplacement { + body.TrustCorporations[1].Mobile = testMobile + } else if isTrustCorporation { + body.TrustCorporations[0].Mobile = testMobile + } else if isReplacement { + body.Attorneys[1].Mobile = testMobile + } else { + body.Attorneys[0].Mobile = testMobile + } + } + + if err := lpaStoreClient.SendLpa(donorCtx, donorDetails.LpaUID, body); err != nil { + return fmt.Errorf("problem sending lpa: %w", err) + } } if err := certificateProviderStore.Put(certificateProviderCtx, certificateProvider); err != nil { return err @@ -366,10 +416,6 @@ func Attorney( } if donorDetails.LpaUID != "" { - if err := lpaStoreClient.SendLpa(donorCtx, donorDetails); err != nil { - return fmt.Errorf("problem sending lpa: %w", err) - } - lpa, err := lpaStoreClient.Lpa(donorCtx, donorDetails.LpaUID) if err != nil { return fmt.Errorf("problem getting lpa: %w", err) diff --git a/internal/page/fixtures/certificate_provider.go b/internal/page/fixtures/certificate_provider.go index 5f81a8c6fa..0556e8e6e8 100644 --- a/internal/page/fixtures/certificate_provider.go +++ b/internal/page/fixtures/certificate_provider.go @@ -206,7 +206,7 @@ func CertificateProvider( } if !donorDetails.SignedAt.IsZero() && donorDetails.LpaUID != "" { - if err := lpaStoreClient.SendLpa(donorCtx, donorDetails); err != nil { + if err := lpaStoreClient.SendLpa(donorCtx, donorDetails.LpaUID, lpastore.CreateLpaFromDonorProvided(donorDetails)); err != nil { return err } } diff --git a/internal/page/fixtures/donor.go b/internal/page/fixtures/donor.go index 57afc5708a..14155ca22b 100644 --- a/internal/page/fixtures/donor.go +++ b/internal/page/fixtures/donor.go @@ -19,6 +19,7 @@ import ( "github.com/ministryofjustice/opg-modernising-lpa/internal/document" "github.com/ministryofjustice/opg-modernising-lpa/internal/donor" "github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata" + "github.com/ministryofjustice/opg-modernising-lpa/internal/dynamo" "github.com/ministryofjustice/opg-modernising-lpa/internal/event" "github.com/ministryofjustice/opg-modernising-lpa/internal/form" "github.com/ministryofjustice/opg-modernising-lpa/internal/identity" @@ -37,6 +38,7 @@ import ( type DynamoClient interface { OneByUID(ctx context.Context, uid string, v interface{}) error Create(ctx context.Context, v interface{}) error + WriteTransaction(ctx context.Context, transaction *dynamo.Transaction) error } type DocumentStore interface { @@ -148,7 +150,7 @@ func Donor( } if !donorDetails.SignedAt.IsZero() && donorDetails.LpaUID != "" { - if err := lpaStoreClient.SendLpa(donorCtx, donorDetails); err != nil { + if err := lpaStoreClient.SendLpa(donorCtx, donorDetails.LpaUID, lpastore.CreateLpaFromDonorProvided(donorDetails)); err != nil { return err } diff --git a/internal/page/fixtures/supporter.go b/internal/page/fixtures/supporter.go index e92a622fc9..83eed4ac84 100644 --- a/internal/page/fixtures/supporter.go +++ b/internal/page/fixtures/supporter.go @@ -206,7 +206,7 @@ func Supporter( return err } if !donor.SignedAt.IsZero() && donor.LpaUID != "" { - if err := lpaStoreClient.SendLpa(donorCtx, donor); err != nil { + if err := lpaStoreClient.SendLpa(donorCtx, donor.LpaUID, lpastore.CreateLpaFromDonorProvided(donor)); err != nil { return err } diff --git a/internal/page/fixtures/voucher.go b/internal/page/fixtures/voucher.go index 5846865376..b7329cf1bb 100644 --- a/internal/page/fixtures/voucher.go +++ b/internal/page/fixtures/voucher.go @@ -104,7 +104,7 @@ func Voucher( } if lpaSigned { - if err := lpaStoreClient.SendLpa(donorCtx, donorDetails); err != nil { + if err := lpaStoreClient.SendLpa(donorCtx, donorDetails.LpaUID, lpastore.CreateLpaFromDonorProvided(donorDetails)); err != nil { return err } } diff --git a/internal/task/progress.go b/internal/task/progress.go index 6a215c8f83..3e9e83e137 100644 --- a/internal/task/progress.go +++ b/internal/task/progress.go @@ -59,13 +59,13 @@ func (pt ProgressTracker) Progress(lpa *lpadata.Lpa) Progress { Label: pt.Localizer.T("lpaPaidFor"), }, ConfirmedID: ProgressTask{ - Done: !lpa.Donor.IdentityCheck.CheckedAt.IsZero(), + Done: lpa.Donor.IdentityCheck != nil && !lpa.Donor.IdentityCheck.CheckedAt.IsZero(), }, DonorSigned: ProgressTask{ Done: lpa.SignedForDonor(), }, CertificateProviderSigned: ProgressTask{ - Done: !lpa.CertificateProvider.SignedAt.IsZero(), + Done: lpa.CertificateProvider.SignedAt != nil && !lpa.CertificateProvider.SignedAt.IsZero(), }, AttorneysSigned: ProgressTask{ Done: lpa.AllAttorneysSigned(), diff --git a/internal/task/progress_test.go b/internal/task/progress_test.go index 6bd1b6883f..bc9f2130df 100644 --- a/internal/task/progress_test.go +++ b/internal/task/progress_test.go @@ -10,6 +10,10 @@ import ( "github.com/stretchr/testify/assert" ) +func pt[T any](value T) *T { + return &value +} + func TestProgressToSlice(t *testing.T) { progress := Progress{ Paid: ProgressTask{Label: "Paid translation"}, @@ -87,7 +91,7 @@ func TestProgressTrackerProgress(t *testing.T) { CertificateProvider: lpadata.CertificateProvider{ FirstNames: "c", LastName: "d", - SignedAt: lpaSignedAt, + SignedAt: &lpaSignedAt, }, SignedAt: lpaSignedAt, WitnessedByCertificateProviderAt: lpaSignedAt, @@ -108,9 +112,9 @@ func TestProgressTrackerProgress(t *testing.T) { CertificateProvider: lpadata.CertificateProvider{ FirstNames: "c", LastName: "d", - SignedAt: lpaSignedAt, + SignedAt: &lpaSignedAt, }, - Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid1, SignedAt: lpaSignedAt.Add(time.Minute)}, {UID: uid2, SignedAt: lpaSignedAt.Add(time.Minute)}}}, + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid1, SignedAt: pt(lpaSignedAt.Add(time.Minute))}, {UID: uid2, SignedAt: pt(lpaSignedAt.Add(time.Minute))}}}, SignedAt: lpaSignedAt, WitnessedByCertificateProviderAt: lpaSignedAt, }, @@ -131,9 +135,9 @@ func TestProgressTrackerProgress(t *testing.T) { CertificateProvider: lpadata.CertificateProvider{ FirstNames: "c", LastName: "d", - SignedAt: lpaSignedAt, + SignedAt: &lpaSignedAt, }, - Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid1, SignedAt: lpaSignedAt}}}, + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid1, SignedAt: &lpaSignedAt}}}, SignedAt: lpaSignedAt, WitnessedByCertificateProviderAt: lpaSignedAt, Submitted: true, @@ -155,9 +159,9 @@ func TestProgressTrackerProgress(t *testing.T) { CertificateProvider: lpadata.CertificateProvider{ FirstNames: "c", LastName: "d", - SignedAt: lpaSignedAt, + SignedAt: &lpaSignedAt, }, - Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid1, SignedAt: lpaSignedAt}}}, + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid1, SignedAt: &lpaSignedAt}}}, SignedAt: lpaSignedAt, WitnessedByCertificateProviderAt: lpaSignedAt, Submitted: true, @@ -180,11 +184,11 @@ func TestProgressTrackerProgress(t *testing.T) { Donor: lpadata.Donor{FirstNames: "a", LastName: "b"}, SignedAt: lpaSignedAt, WitnessedByCertificateProviderAt: lpaSignedAt, - Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid1, SignedAt: lpaSignedAt.Add(time.Minute)}}}, + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid1, SignedAt: pt(lpaSignedAt.Add(time.Minute))}}}, CertificateProvider: lpadata.CertificateProvider{ FirstNames: "c", LastName: "d", - SignedAt: lpaSignedAt, + SignedAt: &lpaSignedAt, }, Submitted: true, StatutoryWaitingPeriodAt: lpaSignedAt, @@ -308,7 +312,7 @@ func TestLpaProgressAsSupporter(t *testing.T) { FirstNames: "a", LastName: "b", DateOfBirth: dateOfBirth, - IdentityCheck: lpadata.IdentityCheck{CheckedAt: time.Now()}, + IdentityCheck: &lpadata.IdentityCheck{CheckedAt: time.Now()}, }, CertificateProvider: lpadata.CertificateProvider{ FirstNames: "c", @@ -338,7 +342,7 @@ func TestLpaProgressAsSupporter(t *testing.T) { FirstNames: "a", LastName: "b", DateOfBirth: dateOfBirth, - IdentityCheck: lpadata.IdentityCheck{CheckedAt: time.Now()}, + IdentityCheck: &lpadata.IdentityCheck{CheckedAt: time.Now()}, }, CertificateProvider: lpadata.CertificateProvider{ FirstNames: "c", @@ -371,13 +375,13 @@ func TestLpaProgressAsSupporter(t *testing.T) { FirstNames: "a", LastName: "b", DateOfBirth: dateOfBirth, - IdentityCheck: lpadata.IdentityCheck{CheckedAt: time.Now()}, + IdentityCheck: &lpadata.IdentityCheck{CheckedAt: time.Now()}, }, Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{}}}, CertificateProvider: lpadata.CertificateProvider{ FirstNames: "c", LastName: "d", - SignedAt: lpaSignedAt, + SignedAt: &lpaSignedAt, }, Paid: true, SignedAt: lpaSignedAt, @@ -406,13 +410,13 @@ func TestLpaProgressAsSupporter(t *testing.T) { FirstNames: "a", LastName: "b", DateOfBirth: dateOfBirth, - IdentityCheck: lpadata.IdentityCheck{CheckedAt: time.Now()}, + IdentityCheck: &lpadata.IdentityCheck{CheckedAt: time.Now()}, }, - Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid, SignedAt: lpaSignedAt.Add(time.Minute)}}}, + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid, SignedAt: pt(lpaSignedAt.Add(time.Minute))}}}, CertificateProvider: lpadata.CertificateProvider{ FirstNames: "c", LastName: "d", - SignedAt: lpaSignedAt, + SignedAt: &lpaSignedAt, }, Paid: true, SignedAt: lpaSignedAt, @@ -442,13 +446,13 @@ func TestLpaProgressAsSupporter(t *testing.T) { FirstNames: "a", LastName: "b", DateOfBirth: dateOfBirth, - IdentityCheck: lpadata.IdentityCheck{CheckedAt: time.Now()}, + IdentityCheck: &lpadata.IdentityCheck{CheckedAt: time.Now()}, }, - Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid, SignedAt: lpaSignedAt.Add(time.Minute)}}}, + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid, SignedAt: pt(lpaSignedAt.Add(time.Minute))}}}, CertificateProvider: lpadata.CertificateProvider{ FirstNames: "c", LastName: "d", - SignedAt: lpaSignedAt, + SignedAt: &lpaSignedAt, }, Paid: true, SignedAt: lpaSignedAt, @@ -479,13 +483,13 @@ func TestLpaProgressAsSupporter(t *testing.T) { FirstNames: "a", LastName: "b", DateOfBirth: dateOfBirth, - IdentityCheck: lpadata.IdentityCheck{CheckedAt: time.Now()}, + IdentityCheck: &lpadata.IdentityCheck{CheckedAt: time.Now()}, }, - Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid, SignedAt: lpaSignedAt.Add(time.Minute)}}}, + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid, SignedAt: pt(lpaSignedAt.Add(time.Minute))}}}, CertificateProvider: lpadata.CertificateProvider{ FirstNames: "c", LastName: "d", - SignedAt: lpaSignedAt, + SignedAt: &lpaSignedAt, }, Paid: true, SignedAt: lpaSignedAt, @@ -518,13 +522,13 @@ func TestLpaProgressAsSupporter(t *testing.T) { FirstNames: "a", LastName: "b", DateOfBirth: dateOfBirth, - IdentityCheck: lpadata.IdentityCheck{CheckedAt: time.Now()}, + IdentityCheck: &lpadata.IdentityCheck{CheckedAt: time.Now()}, }, - Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid, SignedAt: lpaSignedAt.Add(time.Minute)}}}, + Attorneys: lpadata.Attorneys{Attorneys: []lpadata.Attorney{{UID: uid, SignedAt: pt(lpaSignedAt.Add(time.Minute))}}}, CertificateProvider: lpadata.CertificateProvider{ FirstNames: "c", LastName: "d", - SignedAt: lpaSignedAt, + SignedAt: &lpaSignedAt, }, Paid: true, SignedAt: lpaSignedAt, diff --git a/internal/templatefn/fn.go b/internal/templatefn/fn.go index f21ba06ee9..bb48c73ddb 100644 --- a/internal/templatefn/fn.go +++ b/internal/templatefn/fn.go @@ -499,7 +499,7 @@ func lpaDecisions(app appcontext.Data, lpa any, canChange bool) lpaDecisionsData case *lpadata.Lpa: data.Lpa = v case *donordata.Provided: - data.Lpa = lpastore.FromDonorProvidedDetails(v) + data.Lpa = lpastore.LpaFromDonorProvided(v) } return data diff --git a/lang/cy.json b/lang/cy.json index 748cb13d34..3f7279c852 100644 --- a/lang/cy.json +++ b/lang/cy.json @@ -701,6 +701,7 @@ "detailsTheDonorHasGivenAboutYou": "Manylion y mae’r rhoddwr wedi eu rhoi amdanoch", "whatToDoIfAnyDetailsAreIncorrect": "Beth i’w wneud os yw unrhyw rai o’r manylion a roddwyd amdanoch yn anghywir", "whatToDoIfAnyDetailsAreIncorrectAttorneyContent": "
Welsh {{.DonorFullName}}
", + "whatToDoIfAnyDetailsAreIncorrectAttorneyCanPhoneContent": "Welsh {{.DonorFullName}}
", "anyErrorsInYourDetailsCanDelay": "Gall unrhyw gamgymeriadau yn eich manylion achosi oedi cyn prosesu’r LPA.", "mobileNumber": "Rhif ffôn symudol", "anyErrorsInYourDetailsCanMakeLpaDifficultToUse": "Gall unrhyw wallau yn eich manylion wneud yr LPA yn anodd ei ddefnyddio. Mae’n bosibl na fydd sefydliadau’n derbyn yr LPA os nad yw’ch manylion yn cyfateb i’ch data adnabod.", diff --git a/lang/en.json b/lang/en.json index 0fa174a6e2..3e346f35fb 100644 --- a/lang/en.json +++ b/lang/en.json @@ -627,6 +627,7 @@ "whatToDoIfAnyDetailsAreIncorrectCertificateProviderContentLay": "If you notice a mistake in the name, address or mobile number the donor provided for you, you’ll need to let the donor know so they can change your details.
Once the donor has changed your details, you’ll need to log back in again and confirm your details are correct.
You should not complete the ‘Confirm your identity’ task until all of your information is correct.
", "whatToDoIfAnyDetailsAreIncorrectCertificateProviderContentProfessional": "If you notice a mistake in the name, work address or mobile number the donor provided for you, you’ll need to let the donor know so they can change your details.
Once the donor has changed your details, you’ll need to log back in again and confirm your details are correct.
You should not complete the ‘Confirm your identity’ task until all of your information is correct.
", "whatToDoIfAnyDetailsAreIncorrectAttorneyContent": "You can correct a mistake in your phone number.
However, if your name, date of birth or address are incorrect, do not continue.
Ask {{.DonorFullName}} to update your details. You must then log back into the service to confirm your details are correct.
", + "whatToDoIfAnyDetailsAreIncorrectAttorneyCanPhoneContent": "You can correct a mistake in your phone number.
However, if your name, date of birth or address are incorrect, do not continue.
Ask {{.DonorFullName}} to update your details. You must then log back into the service to confirm your details are correct.
", "anyErrorsInYourDetailsCanDelay": "Any errors in your details can cause delays in processing the LPA.", "mobileNumber": "Mobile number", "anyErrorsInYourDetailsCanMakeLpaDifficultToUse": "Any errors in your details can make the LPA difficult to use. Organisations might not accept the LPA if your details do not match your ID.", diff --git a/web/template/attorney/confirm_your_details.gohtml b/web/template/attorney/confirm_your_details.gohtml index 1c2a27b1b7..88c8249e37 100644 --- a/web/template/attorney/confirm_your_details.gohtml +++ b/web/template/attorney/confirm_your_details.gohtml @@ -3,56 +3,87 @@ {{ define "pageTitle" }}{{ tr .App "confirmYourDetails" }}{{ end }} {{ define "main" }} -{{ trFormat .App "youMustConfirmTheDetailsAboutYourCompany" "DonorFullName" .Lpa.Donor.FullName }}
- {{ else }} -{{ trFormat .App "youMustConfirmYourPhoneNumber" "DonorFullName" .Lpa.Donor.FullName }}
- {{ end }} - -{{ trFormat .App "youMustConfirmTheDetailsAboutYourCompany" "DonorFullName" .Lpa.Donor.FullName }}
+ {{ else }} +{{ trFormat .App "youMustConfirmYourPhoneNumber" "DonorFullName" .Lpa.Donor.FullName }}
+ {{ end }} + +