-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
VEGA-2667 correction when changing donor details (#272)
* VEGA-2667 correction when changing donor details * Make fields optional as not all fields will have changes for correction * add correction test file * Add correction json file * Amend json file * Only allow lpa signed on date to change if paper channel, add test coverage * Stop registered LPAs from getting corrections
- Loading branch information
Showing
6 changed files
with
318 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
{ | ||
"type": "CORRECTION", | ||
"changes": [ | ||
{ | ||
"key": "/donor/firstNames", | ||
"new": "Sam", | ||
"old": "Sammy" | ||
}, | ||
{ | ||
"key": "/donor/lastName", | ||
"new": "Smith", | ||
"old": "Smithy" | ||
}, | ||
{ | ||
"key": "/donor/address/dateOfBirth", | ||
"new": "2000-01-01", | ||
"old": "1999-11-11" | ||
}, | ||
{ | ||
"key": "/donor/address/line1", | ||
"new": "Somewhere", | ||
"old": "Anywhere" | ||
}, | ||
{ | ||
"key": "/donor/address/town", | ||
"new": "London", | ||
"old": "Birmingham" | ||
}, | ||
{ | ||
"key": "/donor/address/postcode", | ||
"new": "E1 1AA", | ||
"old": "B1 1AA" | ||
}, | ||
{ | ||
"key": "/donor/address/country", | ||
"new": "GB", | ||
"old": "" | ||
}, | ||
{ | ||
"key": "/signedAt", | ||
"new": "2024-01-13T22:00:00Z", | ||
"old": "" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/ministryofjustice/opg-data-lpa-store/internal/shared" | ||
"github.com/ministryofjustice/opg-data-lpa-store/internal/validate" | ||
"github.com/ministryofjustice/opg-data-lpa-store/lambda/update/parse" | ||
"time" | ||
) | ||
|
||
type Correction struct { | ||
DonorFirstNames string | ||
DonorLastName string | ||
DonorOtherNames string | ||
DonorDob shared.Date | ||
DonorAddress shared.Address | ||
DonorEmail string | ||
LPASignedAt time.Time | ||
} | ||
|
||
func (c Correction) Apply(lpa *shared.Lpa) []shared.FieldError { | ||
if !c.LPASignedAt.IsZero() && lpa.Channel == shared.ChannelOnline { | ||
return []shared.FieldError{{Source: "/signedAt", Detail: "LPA Signed on date cannot be changed for online LPAs"}} | ||
} | ||
|
||
if lpa.Status == shared.LpaStatusRegistered { | ||
return []shared.FieldError{{Source: "/type", Detail: "Cannot make corrections to a Registered LPA"}} | ||
} | ||
|
||
lpa.Donor.FirstNames = c.DonorFirstNames | ||
lpa.Donor.LastName = c.DonorLastName | ||
lpa.Donor.OtherNamesKnownBy = c.DonorOtherNames | ||
lpa.Donor.DateOfBirth = c.DonorDob | ||
lpa.Donor.Address = c.DonorAddress | ||
lpa.Donor.Email = c.DonorEmail | ||
lpa.SignedAt = c.LPASignedAt | ||
|
||
return nil | ||
} | ||
|
||
func validateCorrection(changes []shared.Change, lpa *shared.Lpa) (Correction, []shared.FieldError) { | ||
var data Correction | ||
|
||
data.DonorFirstNames = lpa.LpaInit.Donor.FirstNames | ||
data.DonorLastName = lpa.LpaInit.Donor.LastName | ||
data.DonorOtherNames = lpa.LpaInit.Donor.OtherNamesKnownBy | ||
data.DonorDob = lpa.LpaInit.Donor.DateOfBirth | ||
data.DonorAddress = lpa.LpaInit.Donor.Address | ||
data.DonorEmail = lpa.LpaInit.Donor.Email | ||
data.LPASignedAt = lpa.LpaInit.SignedAt | ||
|
||
errors := parse.Changes(changes). | ||
Prefix("/donor/address", func(p *parse.Parser) []shared.FieldError { | ||
return p. | ||
Field("/line1", &data.DonorAddress.Line1, parse.Optional()). | ||
Field("/line2", &data.DonorAddress.Line2, parse.Optional()). | ||
Field("/line3", &data.DonorAddress.Line3, parse.Optional()). | ||
Field("/town", &data.DonorAddress.Town, parse.Optional()). | ||
Field("/postcode", &data.DonorAddress.Postcode, parse.Optional()). | ||
Field("/country", &data.DonorAddress.Country, parse.Validate(func() []shared.FieldError { | ||
return validate.Country("", data.DonorAddress.Country) | ||
}), parse.Optional()). | ||
Consumed() | ||
}, parse.Optional()). | ||
Field("/donor/firstNames", &data.DonorFirstNames, parse.Validate(func() []shared.FieldError { | ||
return validate.Required("", data.DonorFirstNames) | ||
}), parse.Optional()). | ||
Field("/donor/lastName", &data.DonorLastName, parse.Validate(func() []shared.FieldError { | ||
return validate.Required("", data.DonorLastName) | ||
}), parse.Optional()). | ||
Field("/donor/otherNamesKnownBy", &data.DonorOtherNames, parse.Optional()). | ||
Field("/donor/email", &data.DonorEmail, parse.Optional()). | ||
Field("/donor/dateOfBirth", &data.DonorDob, parse.Validate(func() []shared.FieldError { | ||
return validate.Date("", data.DonorDob) | ||
}), parse.Optional()). | ||
Field("/signedAt", &data.LPASignedAt, parse.Validate(func() []shared.FieldError { | ||
return validate.Time("", data.LPASignedAt) | ||
}), parse.Optional()). | ||
Consumed() | ||
|
||
return data, errors | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"testing" | ||
"time" | ||
|
||
"github.com/ministryofjustice/opg-data-lpa-store/internal/shared" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func createDate(date string) shared.Date { | ||
d := shared.Date{} | ||
_ = d.UnmarshalText([]byte(date)) | ||
return d | ||
} | ||
|
||
func TestCorrectionApply(t *testing.T) { | ||
now := time.Now() | ||
yesterday := now.Add(-24 * time.Hour) | ||
lpa := &shared.Lpa{ | ||
LpaInit: shared.LpaInit{ | ||
Donor: shared.Donor{ | ||
Person: shared.Person{ | ||
FirstNames: "donor-firstname", | ||
LastName: "donor-lastname", | ||
}, | ||
OtherNamesKnownBy: "donor-otherNames", | ||
DateOfBirth: createDate("1990-01-02"), | ||
Address: shared.Address{ | ||
Line1: "123 Main St", | ||
Town: "Anytown", | ||
Postcode: "A11 B22", | ||
Country: "IE", | ||
}, | ||
Email: "[email protected]", | ||
}, | ||
SignedAt: yesterday, | ||
}, | ||
} | ||
|
||
correction := Correction{ | ||
DonorFirstNames: "Jane", | ||
DonorLastName: "Smith", | ||
DonorOtherNames: "Janey", | ||
DonorDob: createDate("2000-11-11"), | ||
DonorAddress: shared.Address{ | ||
Line1: "456 Another St", | ||
Town: "Othertown", | ||
Postcode: "B22 A11", | ||
Country: "IE", | ||
}, | ||
DonorEmail: "[email protected]", | ||
LPASignedAt: now, | ||
} | ||
|
||
errors := correction.Apply(lpa) | ||
|
||
assert.Empty(t, errors) | ||
assert.Equal(t, correction.DonorFirstNames, lpa.Donor.FirstNames) | ||
assert.Equal(t, correction.DonorLastName, lpa.Donor.LastName) | ||
assert.Equal(t, correction.DonorOtherNames, lpa.Donor.OtherNamesKnownBy) | ||
assert.Equal(t, correction.DonorDob, lpa.Donor.DateOfBirth) | ||
assert.Equal(t, correction.DonorAddress, lpa.Donor.Address) | ||
assert.Equal(t, correction.DonorEmail, lpa.Donor.Email) | ||
assert.Equal(t, correction.LPASignedAt, lpa.SignedAt) | ||
} | ||
|
||
func TestCorrectionRegisteredLpa(t *testing.T) { | ||
lpa := &shared.Lpa{ | ||
Status: shared.LpaStatusRegistered, | ||
LpaInit: shared.LpaInit{ | ||
Channel: "paper", | ||
Donor: shared.Donor{ | ||
Person: shared.Person{ | ||
FirstNames: "donor-firstname", | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
correction := Correction{ | ||
DonorFirstNames: "Jane", | ||
} | ||
errors := correction.Apply(lpa) | ||
|
||
assert.Equal(t, errors, []shared.FieldError{{Source: "/type", Detail: "Cannot make corrections to a Registered LPA"}}) | ||
} | ||
|
||
func TestCorrectionLpaSignedOnlineChannel(t *testing.T) { | ||
now := time.Now() | ||
yesterday := now.Add(-24 * time.Hour) | ||
lpa := &shared.Lpa{ | ||
LpaInit: shared.LpaInit{ | ||
Channel: "online", | ||
SignedAt: yesterday, | ||
}, | ||
} | ||
|
||
correction := Correction{ | ||
LPASignedAt: now, | ||
} | ||
errors := correction.Apply(lpa) | ||
|
||
assert.Equal(t, errors, []shared.FieldError{{Source: "/signedAt", Detail: "LPA Signed on date cannot be changed for online LPAs"}}) | ||
} | ||
|
||
func TestValidateCorrection(t *testing.T) { | ||
now := time.Now() | ||
|
||
testcases := map[string]struct { | ||
changes []shared.Change | ||
lpa *shared.Lpa | ||
errors []shared.FieldError | ||
}{ | ||
"valid update": { | ||
changes: []shared.Change{ | ||
{Key: "/donor/firstNames", New: json.RawMessage(`"Jane"`), Old: jsonNull}, | ||
{Key: "/donor/lastName", New: json.RawMessage(`"Doe"`), Old: jsonNull}, | ||
{Key: "/donor/otherNamesKnownBy", New: json.RawMessage(`"Janey"`), Old: jsonNull}, | ||
{Key: "/donor/email", New: json.RawMessage(`"[email protected]"`), Old: jsonNull}, | ||
{Key: "/donor/dateOfBirth", New: json.RawMessage(`"2000-01-01"`), Old: jsonNull}, | ||
{Key: "/signedAt", New: json.RawMessage(`"` + now.Format(time.RFC3339Nano) + `"`), Old: jsonNull}, | ||
}, | ||
lpa: &shared.Lpa{ | ||
LpaInit: shared.LpaInit{ | ||
Donor: shared.Donor{}, | ||
}, | ||
}, | ||
}, | ||
"missing required fields": { | ||
changes: []shared.Change{ | ||
{Key: "/donor/firstNames", New: jsonNull, Old: jsonNull}, | ||
{Key: "/donor/lastName", New: jsonNull, Old: jsonNull}, | ||
}, | ||
lpa: &shared.Lpa{ | ||
LpaInit: shared.LpaInit{ | ||
Donor: shared.Donor{}, | ||
}, | ||
}, | ||
errors: []shared.FieldError{ | ||
{Source: "/changes/0/new", Detail: "field is required"}, | ||
{Source: "/changes/1/new", Detail: "field is required"}, | ||
}, | ||
}, | ||
"invalid country": { | ||
changes: []shared.Change{ | ||
{Key: "/donor/address/country", New: json.RawMessage(`"United Kingdom"`), Old: jsonNull}, | ||
}, | ||
lpa: &shared.Lpa{ | ||
LpaInit: shared.LpaInit{ | ||
Donor: shared.Donor{ | ||
Address: shared.Address{}, | ||
}, | ||
}, | ||
}, | ||
errors: []shared.FieldError{ | ||
{Source: "/changes/0/new", Detail: "must be a valid ISO-3166-1 country code"}, | ||
}, | ||
}, | ||
} | ||
|
||
for name, tc := range testcases { | ||
t.Run(name, func(t *testing.T) { | ||
_, errors := validateCorrection(tc.changes, tc.lpa) | ||
assert.ElementsMatch(t, tc.errors, errors) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters