diff --git a/README.md b/README.md index eb6f93e..aa1d69e 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ api.SearchCustomers(&cm.SearchCustomersParams{}) api.ListCustomers(&cm.ListCustomersParams{}) api.UpdateCustomer(&cm.NewCustomer{}, "customerUUID") api.MergeCustomers(&cm.MergeCustomersParams{}) +api.UnmergeCustomers(&cm.UnmergeCustomersParams{}) api.ConnectSubscriptions("customerUUID", []cm.Subscription{}) api.ListCustomersContact(&cm.ListContactsParams{}, "customerUUID") api.CreateCustomersContact(&cm.NewContact{}, "customerUUID") @@ -319,6 +320,7 @@ To work on the library: * add pre-commit hook `go test ./...` (in `.git/hooks/pre-commit`) to have a working state always. ### Testing +* Run test suite with `go test` * Use `net/http/httptest` for mocking HTTP server directly, see file `generic_test.go` for examples. * For `integration_tests` against real API use `github.com/dnaeon/go-vcr` library. Be careful to remove your API credentials from fixtures before committing! If Import API App changes, re-record the affected integration tests (by deleting fixtures). diff --git a/chartmogul.go b/chartmogul.go index 64348b3..5fe298d 100644 --- a/chartmogul.go +++ b/chartmogul.go @@ -91,6 +91,7 @@ type IApi interface { ListCustomers(ListCustomersParams *ListCustomersParams) (*Customers, error) SearchCustomers(SearchCustomersParams *SearchCustomersParams) (*Customers, error) MergeCustomers(MergeCustomersParams *MergeCustomersParams) error + UnmergeCustomers(UnmergeCustomersParams *UnmergeCustomersParams) error DeleteCustomer(customerUUID string) error DeleteCustomerInvoices(dataSourceUUID, customerUUID string) error DeleteCustomerInvoicesV2(dataSourceUUID, customerUUID string, DeleteCustomerInvoicesParams *DeleteCustomerInvoicesParams) error diff --git a/customers.go b/customers.go index 8bb4459..dd08b85 100644 --- a/customers.go +++ b/customers.go @@ -128,6 +128,14 @@ type MergeCustomersParams struct { Into CustID `json:"into"` } +// UnmergeCustomersParams - identify target for unmerging. +type UnmergeCustomersParams struct { + CustomerUUID string `json:"customer_uuid"` + ExternalID string `json:"external_id"` + DataSourceUUID string `json:"data_source_uuid"` + MoveToNewCustomer []string `json:"move_to_new_customer,omitempty"` +} + // CustID - use either DataSourceUUID & ExternalID or CustomerUUID type CustID struct { DataSourceUUID string `json:"data_source_uuid,omitempty"` @@ -146,6 +154,7 @@ const ( customersEndpoint = "customers" searchCustomersEndpoint = "customers/search" mergeCustomersEndpoint = "customers/merges" + unmergeCustomersEndpoint = "customers/unmerges" customerContactsEndpoint = "customers/:uuid/contacts" ) @@ -211,6 +220,13 @@ func (api API) MergeCustomers(mergeCustomersParams *MergeCustomersParams) error return api.merge(mergeCustomersEndpoint, *mergeCustomersParams) } +// UnmergeCustomers unmerges two cutomers. +// +// See https://dev.chartmogul.com/v1.0/reference#customers +func (api API) UnmergeCustomers(unmergeCustomersParams *UnmergeCustomersParams) error { + return api.unmerge(unmergeCustomersEndpoint, *unmergeCustomersParams) +} + // DeleteCustomer deletes one customer by UUID. // // See https://dev.chartmogul.com/v1.0/reference#customers diff --git a/generic.go b/generic.go index 55e7b2d..97dd553 100644 --- a/generic.go +++ b/generic.go @@ -110,6 +110,11 @@ func (api API) merge(path string, input interface{}) error { return wrapErrors(res, []byte(body), errs) } +// UPDATE +func (api API) unmerge(path string, input interface{}) error { + return api.merge(path, input) +} + // updateImpl adds another meta level, because this same pattern // uses multiple HTTP methods in API. func (api API) updateImpl(path string, uuid string, input interface{}, output interface{}, method string) error { diff --git a/integration_tests/customers_test.go b/integration_tests/customers_test.go index a16a487..843f7b0 100644 --- a/integration_tests/customers_test.go +++ b/integration_tests/customers_test.go @@ -40,6 +40,8 @@ func TestListCustomersIntegration(t *testing.T) { validateListCustomers(api, ds.UUID, t) validateSearchCustomers(api, "abc@123.com", t) + validateMergeCustomers(api, t) + validateUnmergeCustomers(api, t) validateCustomerRetrievalAndUpdate(api, customers[1], t) } @@ -113,6 +115,30 @@ func validateSearchCustomers(api *cm.API, email string, t *testing.T) { } } +// validateMergeCustomers validates that the specified customers can be correctly merged using the API. +func validateMergeCustomers(api *cm.API, t *testing.T) { + err := api.MergeCustomers(&cm.MergeCustomersParams{ + From: cm.CustID{CustomerUUID: "cus_2706d304-76b7-11ee-93d6-5b3d820d37cd"}, + Into: cm.CustID{CustomerUUID: "cus_23740208-2c7e-11ee-9ea2-ffd2435982bb"}, + }) + if err != nil { + t.Fatalf("Failed to merge customers: %v", err) + } +} + +// validateUnmergeCustomers validates that the specified customers can be correctly unmerged using the API. +func validateUnmergeCustomers(api *cm.API, t *testing.T) { + err := api.UnmergeCustomers(&cm.UnmergeCustomersParams{ + CustomerUUID: "cus_cd9e5f29-6299-40e5-b343-0bd1ed228b4f", + ExternalID: "cus_O075O8NH0LrtG8", + DataSourceUUID: "ds_788ec6ae-dd51-11ee-bd46-a3ec952dc041", + MoveToNewCustomer: []string{"tasks"}, + }) + if err != nil { + t.Fatalf("Failed to unmerge customers: %v", err) + } +} + // validatecustomerRetrievalAndUpdate checks that a given customer can be retrieved and updated // correctly through the API. func validateCustomerRetrievalAndUpdate(api *cm.API, customerToUpdate *cm.Customer, t *testing.T) {