-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Initial code for us-enrichmemt-api. * Implement V1 enrichment sdk implemented full enrichment sdk functionality. --------- Co-authored-by: Bryan Amundson <[email protected]> Co-authored-by: Michael Whatcott <[email protected]>
- Loading branch information
1 parent
a3b88da
commit 4222c10
Showing
8 changed files
with
809 additions
and
1 deletion.
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,40 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"github.com/smartystreets/smartystreets-go-sdk/wireup" | ||
"log" | ||
"os" | ||
) | ||
|
||
func main() { | ||
log.SetFlags(log.Ltime | log.Llongfile) | ||
|
||
client := wireup.BuildUSEnrichmentAPIClient( | ||
//wireup.WebsiteKeyCredential(os.Getenv("SMARTY_AUTH_WEB"), os.Getenv("SMARTY_AUTH_REFERER")), | ||
wireup.SecretKeyCredential(os.Getenv("SMARTY_AUTH_ID"), os.Getenv("SMARTY_AUTH_TOKEN")), | ||
// The appropriate license values to be used for your subscriptions | ||
// can be found on the Subscriptions page the account dashboard. | ||
// https://www.smarty.com/docs/cloud/licensing | ||
wireup.WithLicenses("us-property-data-principal-cloud"), | ||
// wireup.DebugHTTPOutput(), // uncomment this line to see detailed HTTP request/response information. | ||
) | ||
|
||
// Documentation for input fields can be found at: | ||
// https://smartystreets.com/docs/cloud/us-reverse-geo-api#http-request-input-fields | ||
|
||
smartyKey := "1682393594" | ||
|
||
err, results := client.SendPropertyPrincipalLookup(smartyKey) | ||
|
||
if err != nil { | ||
log.Fatal("Error sending lookup:", err) | ||
} | ||
|
||
fmt.Printf("Results for input: (%s, %s)\n", smartyKey, "principal") | ||
for s, response := range results { | ||
fmt.Printf("#%d: %+v\n", s, response) | ||
} | ||
|
||
log.Println("OK") | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package us_enrichment | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
"strings" | ||
|
||
"github.com/smartystreets/smartystreets-go-sdk" | ||
) | ||
|
||
type Client struct { | ||
sender sdk.RequestSender | ||
} | ||
|
||
func NewClient(sender sdk.RequestSender) *Client { | ||
return &Client{sender: sender} | ||
} | ||
|
||
func (c *Client) SendPropertyFinancialLookup(smartyKey string) (error, []*FinancialResponse) { | ||
l := &financialLookup{ | ||
SmartyKey: smartyKey, | ||
} | ||
err := c.sendLookup(l) | ||
|
||
return err, l.Response | ||
} | ||
|
||
func (c *Client) SendPropertyPrincipalLookup(smartyKey string) (error, []*PrincipalResponse) { | ||
l := &principalLookup{ | ||
SmartyKey: smartyKey, | ||
} | ||
err := c.sendLookup(l) | ||
|
||
return err, l.Response | ||
} | ||
|
||
func (c *Client) sendLookup(lookup enrichmentLookup) error { | ||
return c.sendLookupWithContext(context.Background(), lookup) | ||
} | ||
|
||
func (c *Client) sendLookupWithContext(ctx context.Context, lookup enrichmentLookup) error { | ||
if lookup == nil { | ||
return nil | ||
} | ||
if len(lookup.GetSmartyKey()) == 0 { | ||
return nil | ||
} | ||
|
||
request := buildRequest(lookup) | ||
request = request.WithContext(ctx) | ||
|
||
response, err := c.sender.Send(request) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return lookup.UnmarshalResponse(response) | ||
} | ||
|
||
func buildRequest(lookup enrichmentLookup) *http.Request { | ||
request, _ := http.NewRequest("GET", buildLookupURL(lookup), nil) // We control the method and the URL. This is safe. | ||
query := request.URL.Query() | ||
request.URL.RawQuery = query.Encode() | ||
return request | ||
} | ||
|
||
func buildLookupURL(lookup enrichmentLookup) string { | ||
newLookupURL := strings.Replace(lookupURL, lookupURLSmartyKey, lookup.GetSmartyKey(), 1) | ||
newLookupURL = strings.Replace(newLookupURL, lookupURLDataSet, lookup.GetDataSet(), 1) | ||
return strings.Replace(newLookupURL, lookupURLDataSubSet, lookup.GetDataSubset(), 1) | ||
} | ||
|
||
const ( | ||
lookupURLSmartyKey = ":smartykey" | ||
lookupURLDataSet = ":dataset" | ||
lookupURLDataSubSet = ":datasubset" | ||
lookupURL = "/lookup/" + lookupURLSmartyKey + "/" + lookupURLDataSet + "/" + lookupURLDataSubSet // Remaining parts will be completed later by the sdk.BaseURLClient. | ||
) |
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,114 @@ | ||
package us_enrichment | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"net/http" | ||
"testing" | ||
|
||
"github.com/smarty/assertions/should" | ||
"github.com/smarty/gunit" | ||
) | ||
|
||
func TestClientFixture(t *testing.T) { | ||
gunit.Run(new(ClientFixture), t) | ||
} | ||
|
||
type ClientFixture struct { | ||
*gunit.Fixture | ||
|
||
sender *FakeSender | ||
client *Client | ||
|
||
input enrichmentLookup | ||
} | ||
|
||
func (f *ClientFixture) Setup() { | ||
f.sender = &FakeSender{} | ||
f.client = NewClient(f.sender) | ||
f.input = new(principalLookup) | ||
} | ||
|
||
func (f *ClientFixture) TestLookupSerializedAndSentWithContext__ResponseSuggestionsIncorporatedIntoLookup() { | ||
smartyKey := "123" | ||
f.sender.response = validFinancialResponse | ||
f.input = &financialLookup{ | ||
SmartyKey: smartyKey, | ||
} | ||
|
||
ctx := context.WithValue(context.Background(), "key", "value") | ||
err := f.client.sendLookupWithContext(ctx, f.input) | ||
|
||
f.So(err, should.BeNil) | ||
f.So(f.sender.request, should.NotBeNil) | ||
f.So(f.sender.request.Method, should.Equal, "GET") | ||
f.So(f.sender.request.URL.Path, should.Equal, "/lookup/"+smartyKey+"/"+f.input.GetDataSet()+"/"+f.input.GetDataSubset()) | ||
f.So(f.sender.request.Context(), should.Resemble, ctx) | ||
|
||
response := f.input.(*financialLookup).Response | ||
|
||
f.So(response, should.Resemble, []*FinancialResponse{ | ||
{ | ||
SmartyKey: "123", | ||
DataSetName: "property", | ||
DataSubsetName: "financial", | ||
Attributes: FinancialAttributes{ | ||
AssessedImprovementPercent: "Assessed_Improvement_Percent", | ||
VeteranTaxExemption: "Veteran_Tax_Exemption", | ||
WidowTaxExemption: "Widow_Tax_Exemption", | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func (f *ClientFixture) TestNilLookupNOP() { | ||
err := f.client.sendLookup(nil) | ||
f.So(err, should.BeNil) | ||
f.So(f.sender.request, should.BeNil) | ||
} | ||
|
||
func (f *ClientFixture) TestEmptyLookup_NOP() { | ||
err := f.client.sendLookup(new(principalLookup)) | ||
f.So(err, should.BeNil) | ||
f.So(f.sender.request, should.BeNil) | ||
} | ||
|
||
func (f *ClientFixture) TestSenderErrorPreventsDeserialization() { | ||
f.sender.err = errors.New("gophers") | ||
f.sender.response = validPrincipalResponse // would be deserialized if not for the err (above) | ||
f.input = &principalLookup{SmartyKey: "12345"} | ||
|
||
err := f.client.sendLookup(f.input) | ||
|
||
f.So(err, should.NotBeNil) | ||
f.So(f.input.(*principalLookup).Response, should.BeEmpty) | ||
} | ||
|
||
func (f *ClientFixture) TestDeserializationErrorPreventsDeserialization() { | ||
f.sender.response = `I can't haz JSON` | ||
f.input = &principalLookup{SmartyKey: "12345"} | ||
|
||
err := f.client.sendLookup(f.input) | ||
|
||
f.So(err, should.NotBeNil) | ||
f.So(f.input.(*principalLookup).Response, should.BeEmpty) | ||
} | ||
|
||
var validFinancialResponse = `[{"smarty_key":"123","data_set_name":"property","data_subset_name":"financial","attributes":{"assessed_improvement_percent":"Assessed_Improvement_Percent","veteran_tax_exemption":"Veteran_Tax_Exemption","widow_tax_exemption":"Widow_Tax_Exemption"}}]` | ||
var validPrincipalResponse = `[{"smarty_key":"123","data_set_name":"property","data_subset_name":"principal","attributes":{"1st_floor_sqft":"1st_Floor_Sqft",lender_name_2":"Lender_Name_2","lender_seller_carry_back":"Lender_Seller_Carry_Back","year_built":"Year_Built","zoning":"Zoning"}}]` | ||
|
||
/**************************************************************************/ | ||
|
||
type FakeSender struct { | ||
callCount int | ||
request *http.Request | ||
|
||
response string | ||
err error | ||
} | ||
|
||
func (f *FakeSender) Send(request *http.Request) ([]byte, error) { | ||
f.callCount++ | ||
f.request = request | ||
return []byte(f.response), f.err | ||
} |
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,61 @@ | ||
package us_enrichment | ||
|
||
import ( | ||
"encoding/json" | ||
) | ||
|
||
type enrichmentLookup interface { | ||
GetSmartyKey() string | ||
GetDataSet() string | ||
GetDataSubset() string | ||
|
||
UnmarshalResponse([]byte) error | ||
} | ||
|
||
type financialLookup struct { | ||
SmartyKey string | ||
Response []*FinancialResponse | ||
} | ||
|
||
func (f *financialLookup) GetSmartyKey() string { | ||
return f.SmartyKey | ||
} | ||
|
||
func (f *financialLookup) GetDataSet() string { | ||
return propertyDataSet | ||
} | ||
|
||
func (f *financialLookup) GetDataSubset() string { | ||
return financialDataSubset | ||
} | ||
|
||
func (f *financialLookup) UnmarshalResponse(bytes []byte) error { | ||
return json.Unmarshal(bytes, &f.Response) | ||
} | ||
|
||
type principalLookup struct { | ||
SmartyKey string | ||
Response []*PrincipalResponse | ||
} | ||
|
||
func (p *principalLookup) GetSmartyKey() string { | ||
return p.SmartyKey | ||
} | ||
|
||
func (p *principalLookup) GetDataSet() string { | ||
return propertyDataSet | ||
} | ||
|
||
func (p *principalLookup) GetDataSubset() string { | ||
return principalDataSubset | ||
} | ||
|
||
func (p *principalLookup) UnmarshalResponse(bytes []byte) error { | ||
return json.Unmarshal(bytes, &p.Response) | ||
} | ||
|
||
const ( | ||
financialDataSubset = "financial" | ||
principalDataSubset = "principal" | ||
propertyDataSet = "property" | ||
) |
Oops, something went wrong.