Skip to content

Conversation

@iamgabrielma
Copy link
Contributor

@iamgabrielma iamgabrielma commented Sep 19, 2022

Part of #7741

Description

For merchants to be able to see and choose existing customers from their store when creating or editing orders, we need to know who are these existing customers. At the moment we can only get partial customer data based on other API properties, like Orders.

This PR adds the initial networking layer that we need in order to fetch existing customers from a Store. We do so by performing a GET request to the /wp-json/wc/v3/customers/<id> API endpoint

Why don't we fetch the entirety of /customers/ endpoint?

We discovered that this endpoint does not search for first and last names, the proposed workaround is to use /wc-analytics/customers?search= instead, which returns the customer's ID, then use /customers/<id> to fetch the actual data.

For the moment, we're only modelling the Customer entity with a limited number of properties, the ones we actually use within the Order Creation screen (email, firstName, lastName, billing details, and shipping details), rather than all available properties. We can include more later as needed.

Changes

  • Added CustomerRemote, CustomerMapper, and Customer objects to the Networking layer. This retrieves, decodes, maps, and models an individual Customer entity from its JSON representation received from the API.
  • Modified Networking.generated and Models+Copiable.generated via rake generate, due adding GeneratedCopiable and GeneratedFakeable conformance to the model.
  • Added a customer.json file replicating a dummy /wp-json/wc/v3/customers/<id> API response, so we can Unit Test without hitting the actual network.

To avoid this PR to become too big, I'll add further Unit Tests on a different one.

Testing instructions

  • Make sure that Unit Tests pass

@iamgabrielma iamgabrielma mentioned this pull request Sep 19, 2022
15 tasks
@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Sep 19, 2022

You can test the changes from this Pull Request by:
  • Clicking here or scanning the QR code below to access App Center
  • Then installing the build number pr7746-32dfe2a on your iPhone

If you need access to App Center, please ask a maintainer to add you.

@iamgabrielma iamgabrielma changed the title Update Networking layer with GET /wp-json/wc/v3/customers Update Networking layer with GET /wp-json/wc/v3/customers/<id> Sep 20, 2022
@iamgabrielma iamgabrielma marked this pull request as ready for review September 20, 2022 10:15
@iamgabrielma iamgabrielma added feature: order details Related to order details. category: parity Match what's supported by the other platform. type: enhancement A request for an enhancement. feature: order creation All tasks related to creating an order and removed feature: order details Related to order details. labels Sep 20, 2022
@iamgabrielma iamgabrielma added this to the 10.5 milestone Sep 20, 2022
As Fakes is on a different framework, the Customer object cannot be found due to its default internal access control. Catched this when CI ran tests.
Copy link
Contributor

@joshheald joshheald left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, a few suggestions for reducing the amount of test code.

Comment on lines 50 to 51
let firstName = try container.decodeIfPresent(String.self, forKey: .firstName) ?? ""
let lastName = try container.decodeIfPresent(String.self, forKey: .lastName) ?? ""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the default strings here, given it's an optional property? I think you'd be best off with one or the other: make the property non-optional, or make it nil when we don't have the name.

Copy link
Contributor Author

@iamgabrielma iamgabrielma Sep 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh that's right! firstName and lastName are not required by the API so initially I made them optional, that said, without the name we won't be able to perform a search later on. For now I'll leave them Optional for simplicity, but most likely we'll have to loop back and modify this when we implement the actual search, once we know better what we need. Removed default values at f5c1c3e

Comment on lines 32 to 37
XCTAssertNotNil(customer?.customerID)
XCTAssertNotNil(customer?.email)
XCTAssertNotNil(customer?.firstName)
XCTAssertNotNil(customer?.lastName)
XCTAssertNotNil(customer?.billing)
XCTAssertNotNil(customer?.shipping)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove these asserts at least, or even this whole test, as they are covered by the correctly_parsed test

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha! Done at 2fe9688. I left the rest of the test so we can test the difference between if the data can be loaded from the local file vs if the values are correctly parsed. I see the correctly_parsed test also includes that the data must be loaded first in order to work, but it felt right to keep them separate. Happy to remove it entirely in any case 👍

// Then
XCTAssert(result.isSuccess)
let customer = try XCTUnwrap(result.get())
XCTAssertNotNil(customer)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this assert is unnecessary: the previous one will fail and throw if it's nil. You may want to check another property about the customer instead, or nothing at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you mean, done at 32dfe2a

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant the XCTAssertNotNil is unnecessary, though you're right that the XCTAssert(result.isSuccess) is also tested by the XCTUnwrap.

To be honest, and on second thoughts, since you never use the customer other than checking that it's there, unwrapping it isn't needed, I would consider simply doing XCTAssertNotNil(result.get()) in place of all three, though perhaps with the unwrap it's clearer that we're looking at a customer.

This is super trivial, no need to change it, I'm only commenting again because I'd not been clear the first time.

@iamgabrielma iamgabrielma merged commit 43597e2 into trunk Sep 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

category: parity Match what's supported by the other platform. feature: order creation All tasks related to creating an order type: enhancement A request for an enhancement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants