Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MLPAB-2731: handle change confirmed events and add banners #1764

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,23 @@ emit-object-tags-added-without-virus: ##@events emits a ObjectTagging:Put event
--function-name event-received text \
--payload '{"Records":[{"eventSource":"aws:s3","eventTime":"2023-10-23T15:58:33.081Z","eventName":"ObjectTagging:Put","s3":{"bucket":{"name":"uploads-opg-modernising-lpa-eu-west-1"},"object":{"key":"$(key)"}}}]}'

emit-immaterial-change-confirmed: ##@events emits a immaterial-change-confirmed event with the given LpaUID, actor type an actor UID e.g. emit-immaterial-change-confirmed uid=abc-123 actorType=donor actorUid=def-456
$(eval BODY := $(shell echo '{"version":"0","id":"63eb7e5f-1f10-4744-bba9-e16d327c3b98","detail-type":"immaterial-change-confirmed","source":"opg.poas.sirius","account":"653761790766","time":"2023-08-30T13:40:30Z","region":"eu-west-1","resources":[],"detail":{"uid":"$(uid)","actorType":"$(actorType)","actorUid":"$(actorUid)","sentDate":"2024-01-02T12:13:14.000006Z"}}' | sed 's/"/\\"/g'))

docker compose -f docker/docker-compose.yml exec localstack awslocal lambda invoke \
--endpoint-url=http://localhost:4566 \
--region eu-west-1 \
--function-name event-received text \
--payload '{"Records": [{"messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78", "body": "$(BODY)"}]}'

emit-material-change-confirmed: ##@events emits a material-change-confirmed event with the given LpaUID, actor type an actor UID e.g. emit-material-change-confirmed uid=abc-123 actorType=donor actorUid=def-456
$(eval BODY := $(shell echo '{"version":"0","id":"63eb7e5f-1f10-4744-bba9-e16d327c3b98","detail-type":"material-change-confirmed","source":"opg.poas.sirius","account":"653761790766","time":"2023-08-30T13:40:30Z","region":"eu-west-1","resources":[],"detail":{"uid":"$(uid)","actorType":"$(actorType)","actorUid":"$(actorUid)","sentDate":"2024-01-02T12:13:14.000006Z"}}' | sed 's/"/\\"/g'))

docker compose -f docker/docker-compose.yml exec localstack awslocal lambda invoke \
--endpoint-url=http://localhost:4566 \
--region eu-west-1 \
--function-name event-received text \
--payload '{"Records": [{"messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78", "body": "$(BODY)"}]}'

set-uploads-clean: ##@events calls emit-object-tags-added-without-virus for all documents on a given lpa e.g. set-uploads-clean lpaId=abc
for k in $$(docker compose -f docker/docker-compose.yml exec localstack awslocal dynamodb --region eu-west-1 query --table-name lpas --key-condition-expression 'PK = :pk and begins_with(SK, :sk)' --expression-attribute-values '{":pk": {"S": "LPA#$(lpaId)"}, ":sk": {"S": "DOCUMENT#"}}' | jq -c -r '.Items[] | .Key[]'); do \
Expand Down
25 changes: 25 additions & 0 deletions cmd/event-received/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

"github.com/aws/aws-lambda-go/events"
"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"
)
Expand Down Expand Up @@ -78,3 +79,27 @@ func getDonorByLpaUID(ctx context.Context, client dynamodbClient, uid string) (*

return &donor, nil
}

func putCertificateProvider(ctx context.Context, certificateProvider *certificateproviderdata.Provided, now func() time.Time, client dynamodbClient) error {
certificateProvider.UpdatedAt = now()

return client.Put(ctx, certificateProvider)
}

func getCertificateProviderByLpaUID(ctx context.Context, client dynamodbClient, uid string) (*certificateproviderdata.Provided, error) {
var key dynamo.Keys
if err := client.OneByUID(ctx, uid, &key); err != nil {
return nil, fmt.Errorf("failed to resolve uid: %w", err)
}

if key.PK == nil {
return nil, fmt.Errorf("PK missing from LPA in response")
}

var certificateProvider certificateproviderdata.Provided
if err := client.OneByPartialSK(ctx, key.PK, dynamo.CertificateProviderKey(""), &certificateProvider); err != nil {
return nil, fmt.Errorf("failed to get certificate provider: %w", err)
}

return &certificateProvider, nil
}
11 changes: 9 additions & 2 deletions cmd/event-received/mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,21 @@ func (c *mockDynamodbClient_OneByUID_Call) SetData(data any) {
}

func (c *mockDynamodbClient_One_Call) SetData(data any) {
c.Run(func(_ context.Context, _ dynamo.PK, _ dynamo.SK, v interface{}) {
c.Run(func(_ context.Context, _ dynamo.PK, _ dynamo.SK, v any) {
b, _ := attributevalue.Marshal(data)
attributevalue.Unmarshal(b, v)
})
}

func (c *mockDynamodbClient_AllByLpaUIDAndPartialSK_Call) SetData(data any) {
c.Run(func(_ context.Context, _ string, _ dynamo.SK, v interface{}) {
c.Run(func(_ context.Context, _ string, _ dynamo.SK, v any) {
b, _ := attributevalue.Marshal(data)
attributevalue.Unmarshal(b, v)
})
}

func (c *mockDynamodbClient_OneByPartialSK_Call) SetData(data any) {
c.Run(func(_ context.Context, _ dynamo.PK, _ dynamo.SK, v any) {
b, _ := attributevalue.Marshal(data)
attributevalue.Unmarshal(b, v)
})
Expand Down
71 changes: 66 additions & 5 deletions cmd/event-received/sirius_event_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

"github.com/aws/aws-lambda-go/events"
"github.com/ministryofjustice/opg-modernising-lpa/internal/actor"
"github.com/ministryofjustice/opg-modernising-lpa/internal/appcontext"
"github.com/ministryofjustice/opg-modernising-lpa/internal/certificateprovider/certificateproviderdata"
"github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata"
Expand Down Expand Up @@ -76,6 +77,12 @@ func (h *siriusEventHandler) Handle(ctx context.Context, factory factory, cloudW
case "priority-correspondence-sent":
return handlePriorityCorrespondenceSent(ctx, factory.DynamoClient(), cloudWatchEvent, factory.Now())

case "immaterial-change-confirmed":
return handleChangeConfirmed(ctx, factory.DynamoClient(), cloudWatchEvent, factory.Now(), false)

case "material-change-confirmed":
return handleChangeConfirmed(ctx, factory.DynamoClient(), cloudWatchEvent, factory.Now(), true)

default:
return fmt.Errorf("unknown sirius event")
}
Expand Down Expand Up @@ -120,7 +127,7 @@ func handleFeeApproved(

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

if donor.Tasks.PayForLpa.IsCompleted() || donor.Tasks.PayForLpa.IsApproved() {
Expand Down Expand Up @@ -168,7 +175,7 @@ func handleFurtherInfoRequested(ctx context.Context, client dynamodbClient, even

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

if donor.Tasks.PayForLpa.IsMoreEvidenceRequired() {
Expand All @@ -193,7 +200,7 @@ func handleFeeDenied(ctx context.Context, client dynamodbClient, event *events.C

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

if donor.Tasks.PayForLpa.IsDenied() {
Expand Down Expand Up @@ -333,13 +340,67 @@ func handlePriorityCorrespondenceSent(ctx context.Context, client dynamodbClient

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

donor.PriorityCorrespondenceSentAt = v.SentDate

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

return nil
}

type changeConfirmedEvent struct {
UID string `json:"uid"`
ActorType actor.Type `json:"actorType"`
ActorUID string `json:"actorUID"`
}

func handleChangeConfirmed(ctx context.Context, client dynamodbClient, event *events.CloudWatchEvent, now func() time.Time, materialChange bool) error {
var v changeConfirmedEvent
if err := json.Unmarshal(event.Detail, &v); err != nil {
return fmt.Errorf("failed to unmarshal detail: %w", err)
}

switch v.ActorType {
case actor.TypeDonor:
donor, err := getDonorByLpaUID(ctx, client, v.UID)
if err != nil {
return fmt.Errorf("failed to get donor: %w", err)
}

if donor.Tasks.ConfirmYourIdentity.IsProblem() {
if materialChange {
donor.MaterialChangeConfirmedAt = now()
} else {
donor.Tasks.ConfirmYourIdentity = task.IdentityStateCompleted
}

if err := putDonor(ctx, donor, now, client); err != nil {
return fmt.Errorf("failed to update donor: %w", err)
}
}
case actor.TypeCertificateProvider:
certificateProvider, err := getCertificateProviderByLpaUID(ctx, client, v.UID)
if err != nil {
return fmt.Errorf("failed to get certificate provider: %w", err)
}

if certificateProvider.Tasks.ConfirmYourIdentity.IsProblem() {
if materialChange {
certificateProvider.MaterialChangeConfirmedAt = now()
} else {
certificateProvider.Tasks.ConfirmYourIdentity = task.IdentityStateCompleted
}

if err := putCertificateProvider(ctx, certificateProvider, now, client); err != nil {
return fmt.Errorf("failed to update certificate provider: %w", err)
}
}
default:
return fmt.Errorf("invalid actorType, got %s, want donor or certificateProvider", v.ActorType.String())
}

return nil
Expand Down
Loading
Loading