Skip to content

Commit

Permalink
Send notification to donor when certificate provider signs
Browse files Browse the repository at this point in the history
  • Loading branch information
hawx committed Jan 3, 2025
1 parent 303a205 commit df8f4ba
Show file tree
Hide file tree
Showing 4 changed files with 367 additions and 0 deletions.
53 changes: 53 additions & 0 deletions cmd/event-received/lpastore_event_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,24 @@ func (h *lpastoreEventHandler) Handle(ctx context.Context, factory factory, clou

return handleCreate(ctx, factory.DynamoClient(), lpaStoreClient, notifyClient, bundle, v)

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

bundle, err := factory.Bundle()
if err != nil {
return fmt.Errorf("could not load Bundle: %w", err)
}

notifyClient, err := factory.NotifyClient(ctx)
if err != nil {
return fmt.Errorf("could not create NotifyClient: %w", err)
}

return handleCertificateProviderSign(ctx, factory.DynamoClient(), lpaStoreClient, notifyClient, bundle, v)

case "REGISTER":
lpaStoreClient, err := factory.LpaStoreClient()
if err != nil {
Expand Down Expand Up @@ -102,6 +120,41 @@ func handleCreate(ctx context.Context, client dynamodbClient, lpaStoreClient Lpa
return nil
}

func handleCertificateProviderSign(ctx context.Context, client dynamodbClient, lpaStoreClient LpaStoreClient, notifyClient NotifyClient, bundle Bundle, v lpaUpdatedEvent) error {
lpa, err := lpaStoreClient.Lpa(ctx, v.UID)
if err != nil {
return fmt.Errorf("error getting lpa: %w", err)
}

localizer := bundle.For(lpa.Donor.ContactLanguagePreference)

if lpa.Donor.Channel.IsPaper() {
if err := notifyClient.SendActorSMS(ctx, notify.ToLpaDonor(lpa), v.UID, notify.PaperDonorCertificateProvidedSMS{
CertificateProviderFullName: lpa.CertificateProvider.FullName(),
LpaType: localizer.T(lpa.Type.String()),
}); err != nil {
return fmt.Errorf("error sending sms: %w", err)
}

return nil
}

donor, err := getDonorByLpaUID(ctx, client, v.UID)
if err != nil {
return fmt.Errorf("error getting donor: %w", err)
}

if err := notifyClient.SendActorEmail(ctx, notify.ToDonor(donor), v.UID, notify.DigitalDonorCertificateProvidedEmail{
Greeting: notifyClient.EmailGreeting(lpa),
CertificateProviderFullName: lpa.CertificateProvider.FullName(),
LpaType: localizer.T(lpa.Type.String()),
}); err != nil {
return fmt.Errorf("error sending email: %w", err)
}

return nil
}

func handleRegister(ctx context.Context, client dynamodbClient, lpaStoreClient LpaStoreClient, eventClient EventClient, v lpaUpdatedEvent) error {
lpa, err := lpaStoreClient.Lpa(ctx, v.UID)
if err != nil {
Expand Down
287 changes: 287 additions & 0 deletions cmd/event-received/lpastore_event_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,293 @@ func TestLpaStoreEventHandlerHandleLpaUpdatedCreateWhenNotifyErrors(t *testing.T
assert.ErrorIs(t, err, expectedError)
}

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

lpa := &lpadata.Lpa{
Type: lpadata.LpaTypePersonalWelfare,
Donor: lpadata.Donor{
ContactLanguagePreference: localize.Cy,
},
CertificateProvider: lpadata.CertificateProvider{
FirstNames: "a",
LastName: "b",
},
}

donor := &donordata.Provided{
PK: dynamo.LpaKey("an-lpa"),
Correspondent: donordata.Correspondent{Email: "[email protected]"},
}

lpaStoreClient := newMockLpaStoreClient(t)
lpaStoreClient.EXPECT().
Lpa(ctx, "M-1111-2222-3333").
Return(lpa, nil)

client := newMockDynamodbClient(t)
client.EXPECT().
OneByUID(ctx, "M-1111-2222-3333", mock.Anything).
Return(nil).
SetData(&donordata.Provided{
PK: dynamo.LpaKey("an-lpa"),
SK: dynamo.LpaOwnerKey(dynamo.DonorKey("a-donor")),
})
client.EXPECT().
One(ctx, dynamo.LpaKey("an-lpa"), dynamo.DonorKey("a-donor"), mock.Anything).
Return(nil).
SetData(donor)

notifyClient := newMockNotifyClient(t)
notifyClient.EXPECT().
EmailGreeting(lpa).
Return("hello")
notifyClient.EXPECT().
SendActorEmail(ctx, notify.ToDonor(donor), "M-1111-2222-3333", notify.DigitalDonorCertificateProvidedEmail{
Greeting: "hello",
CertificateProviderFullName: "a b",
LpaType: "personal-welfare",
}).
Return(nil)

bundle := newMockBundle(t)
bundle.EXPECT().
For(localize.Cy).
Return(&localize.Localizer{})

factory := newMockFactory(t)
factory.EXPECT().DynamoClient().Return(client)
factory.EXPECT().LpaStoreClient().Return(lpaStoreClient, nil)
factory.EXPECT().NotifyClient(ctx).Return(notifyClient, nil)
factory.EXPECT().Bundle().Return(bundle, nil)

handler := &lpastoreEventHandler{}

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

func TestLpaStoreEventHandlerHandleLpaUpdatedCertificateProviderSignWhenFactoryErrors(t *testing.T) {
testcases := map[string]func(*mockFactory){
"LpaStoreClient": func(factory *mockFactory) {
factory.EXPECT().LpaStoreClient().Return(nil, expectedError)
},
"Bundle": func(factory *mockFactory) {
factory.EXPECT().LpaStoreClient().Return(nil, nil)
factory.EXPECT().Bundle().Return(nil, expectedError)
},
"NotifyClient": func(factory *mockFactory) {
factory.EXPECT().LpaStoreClient().Return(nil, nil)
factory.EXPECT().Bundle().Return(nil, nil)
factory.EXPECT().NotifyClient(ctx).Return(nil, expectedError)
},
}

for name, setupFactory := range testcases {
t.Run(name, func(t *testing.T) {
v := &events.CloudWatchEvent{
DetailType: "lpa-updated",
Detail: json.RawMessage(`{"uid":"M-1111-2222-3333","changeType":"CERTIFICATE_PROVIDER_SIGN"}`),
}

factory := newMockFactory(t)
setupFactory(factory)

handler := &lpastoreEventHandler{}

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

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

lpa := &lpadata.Lpa{
Type: lpadata.LpaTypePersonalWelfare,
Donor: lpadata.Donor{
Channel: lpadata.ChannelPaper,
ContactLanguagePreference: localize.Cy,
},
CertificateProvider: lpadata.CertificateProvider{
FirstNames: "a",
LastName: "b",
},
}

lpaStoreClient := newMockLpaStoreClient(t)
lpaStoreClient.EXPECT().
Lpa(ctx, "M-1111-2222-3333").
Return(lpa, nil)

notifyClient := newMockNotifyClient(t)
notifyClient.EXPECT().
SendActorSMS(ctx, notify.ToLpaDonor(lpa), "M-1111-2222-3333", notify.PaperDonorCertificateProvidedSMS{
LpaType: "personal-welfare",
CertificateProviderFullName: "a b",
}).
Return(nil)

bundle := newMockBundle(t)
bundle.EXPECT().
For(localize.Cy).
Return(&localize.Localizer{})

factory := newMockFactory(t)
factory.EXPECT().DynamoClient().Return(nil)
factory.EXPECT().LpaStoreClient().Return(lpaStoreClient, nil)
factory.EXPECT().NotifyClient(ctx).Return(notifyClient, nil)
factory.EXPECT().Bundle().Return(bundle, nil)

handler := &lpastoreEventHandler{}

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

func TestLpaStoreEventHandlerHandleLpaUpdatedCertificateProviderSignWhenPaperDonorAndNotifyErrors(t *testing.T) {
lpa := &lpadata.Lpa{
Type: lpadata.LpaTypePersonalWelfare,
Donor: lpadata.Donor{
Channel: lpadata.ChannelPaper,
ContactLanguagePreference: localize.Cy,
},
}

lpaStoreClient := newMockLpaStoreClient(t)
lpaStoreClient.EXPECT().
Lpa(mock.Anything, mock.Anything).
Return(lpa, nil)

notifyClient := newMockNotifyClient(t)
notifyClient.EXPECT().
SendActorSMS(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
Return(expectedError)

bundle := newMockBundle(t)
bundle.EXPECT().
For(mock.Anything).
Return(&localize.Localizer{})

err := handleCertificateProviderSign(ctx, nil, lpaStoreClient, notifyClient, bundle, lpaUpdatedEvent{})
assert.ErrorIs(t, err, expectedError)
}

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

err := handleCertificateProviderSign(ctx, nil, lpaStoreClient, nil, nil, lpaUpdatedEvent{})
assert.ErrorIs(t, err, expectedError)
}

func TestLpaStoreEventHandlerHandleLpaUpdatedCertificateProviderSignWhenDonorStoreErrors(t *testing.T) {
testcases := map[string]func(*mockDynamodbClient){
"first": func(client *mockDynamodbClient) {
client.EXPECT().
OneByUID(mock.Anything, mock.Anything, mock.Anything).
Return(expectedError)
},
"second": func(client *mockDynamodbClient) {
client.EXPECT().
OneByUID(mock.Anything, mock.Anything, mock.Anything).
Return(nil).
SetData(&donordata.Provided{
PK: dynamo.LpaKey("an-lpa"),
SK: dynamo.LpaOwnerKey(dynamo.DonorKey("a-donor")),
})
client.EXPECT().
One(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
Return(expectedError)
},
}

for name, setupDynamodbClient := range testcases {
t.Run(name, func(t *testing.T) {

lpa := &lpadata.Lpa{
Type: lpadata.LpaTypePersonalWelfare,
Donor: lpadata.Donor{
ContactLanguagePreference: localize.Cy,
},
}

lpaStoreClient := newMockLpaStoreClient(t)
lpaStoreClient.EXPECT().
Lpa(mock.Anything, mock.Anything).
Return(lpa, nil)

bundle := newMockBundle(t)
bundle.EXPECT().
For(mock.Anything).
Return(&localize.Localizer{})

client := newMockDynamodbClient(t)
setupDynamodbClient(client)

err := handleCertificateProviderSign(ctx, client, lpaStoreClient, nil, bundle, lpaUpdatedEvent{})
assert.ErrorIs(t, err, expectedError)
})
}
}

func TestLpaStoreEventHandlerHandleLpaUpdatedCertificateProviderSignWhenNotifyErrors(t *testing.T) {
lpa := &lpadata.Lpa{
Type: lpadata.LpaTypePersonalWelfare,
Donor: lpadata.Donor{
ContactLanguagePreference: localize.Cy,
},
}

donor := &donordata.Provided{
PK: dynamo.LpaKey("an-lpa"),
Correspondent: donordata.Correspondent{Email: "[email protected]"},
}

lpaStoreClient := newMockLpaStoreClient(t)
lpaStoreClient.EXPECT().
Lpa(mock.Anything, mock.Anything).
Return(lpa, nil)

client := newMockDynamodbClient(t)
client.EXPECT().
OneByUID(mock.Anything, mock.Anything, mock.Anything).
Return(nil).
SetData(&donordata.Provided{
PK: dynamo.LpaKey("an-lpa"),
SK: dynamo.LpaOwnerKey(dynamo.DonorKey("a-donor")),
})
client.EXPECT().
One(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
Return(nil).
SetData(donor)

notifyClient := newMockNotifyClient(t)
notifyClient.EXPECT().
EmailGreeting(mock.Anything).
Return("hello")
notifyClient.EXPECT().
SendActorEmail(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
Return(expectedError)

bundle := newMockBundle(t)
bundle.EXPECT().
For(mock.Anything).
Return(&localize.Localizer{})

err := handleCertificateProviderSign(ctx, client, lpaStoreClient, notifyClient, bundle, lpaUpdatedEvent{})
assert.ErrorIs(t, err, expectedError)
}

func TestLpaStoreEventHandlerHandleLpaUpdatedRegister(t *testing.T) {
v := &events.CloudWatchEvent{
DetailType: "lpa-updated",
Expand Down
14 changes: 14 additions & 0 deletions internal/notify/email.go
Original file line number Diff line number Diff line change
Expand Up @@ -568,3 +568,17 @@ func (e DigitalDonorLpaSubmittedEmail) emailID(isProduction bool, _ localize.Lan

return "cd02bc22-41be-4e2c-94c2-055d6cba6466"
}

type DigitalDonorCertificateProvidedEmail struct {
Greeting string
CertificateProviderFullName string
LpaType string
}

func (e DigitalDonorCertificateProvidedEmail) emailID(isProduction bool, _ localize.Lang) string {
if isProduction {
return "9db20b35-8728-434b-8090-52cf704bc5a9"
}

return "9baaeb36-f1c6-44ba-840d-14914c18a455"
}
13 changes: 13 additions & 0 deletions internal/notify/sms.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,16 @@ func (e PaperDonorLpaSubmittedSMS) smsID(isProduction bool, lang localize.Lang)

return "e7476d24-6d37-4137-b4a0-de14d3a977ed"
}

type PaperDonorCertificateProvidedSMS struct {
CertificateProviderFullName string
LpaType string
}

func (e PaperDonorCertificateProvidedSMS) smsID(isProduction bool, lang localize.Lang) string {
if isProduction {
return "6b3d9a6c-5103-4c16-8c09-6ebaaec58f93"
}

return "ecdfef3e-cdc0-4393-add5-571bd9cd5c9f"
}

0 comments on commit df8f4ba

Please sign in to comment.