-
Notifications
You must be signed in to change notification settings - Fork 0
Add RateOrder types #2
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
Conversation
This implements the additional types for RateOrder. There's more to be done here, but this is an initial commit for these changes since I am not entirely sure how to proceed with several different things.
This is the final dataype for the Request class for the Rate endpoint. Need to do more editing here, maybe sort the declarations so it's a bit more readable.
That's fine, do as thou wilt. I'd skip fussing over smart constructors too much for now. More of a capstone than a cornerstone. Focus on making something that can work and covers functionality, then clean up the "correct by construction" story. |
Got it, will do. Thanks! UPD: Issuing POST to the /rate endpoint now works. Added some scaffolding to the main function in |
Realized that it should be a list of SKUs and quantity values.
Sending the defaultRate returns the 200 status now.
This is a placeholder for now, used to check if the types I've been building work.
Figured out how to get rid of the record syntax by using the `unwrapUnaryRecords`.
This is still WIP, there are a lot more instances that need to be implemented for this endpoint. I wanted to make sure I am on the right track here. The client's main function now sends out an encoded Haskell datatype and decodes the response.
@bitemyapp I've added some initial FromJSON instances, if you could take a look at those, that would be much appreciated. There is still plenty to do, just want to make sure I am on the right track. Also, I know certain datatypes need to be stricter than just |
@alexeyzab looks fine so far to me. Let me know if you have questions :) |
@bitemyapp I have a question about the overall design of this library. From what I understand, after we write the ToJSON and FromJSON instances, we start writing functions inside the Is that overview correct or am I misunderstanding something? Thank you! |
@alexeyzab seems accurate to me, one thing I'd note is that the client interface in Bloodhound is pretty spare, however, we try to avoid users ever having to touch the URIs themselves beyond providing a host and in the case of Shipwire, it's just beta vs. prod. Example: https://github.com/bitemyapp/bloodhound/blob/master/src/Database/Bloodhound/Client.hs#L510-L515 note: Don't go out of your way to mimic Bloodhound literally, I'm just pointing it out as a guidepost. Keep it simple at first, whatever naturally makes sense to you as you proceed. Refinements can happen later. |
@bitemyapp got it, thanks! |
This should cover all of the JSON we get in response from this endpoint.
@bitemyapp Hey Chris! I've finished the datatypes for this endpoint's response. I have a couple of questions. I am using I am also not sure about the record syntax I've been using, specifically prefixing certain types and not prefixing others. For example:
vs.
Thank you! |
@alexeyzab usually we'll use Double instead of Float for the extra precision, but I think you're asking in regard to the costs/currencies. You never want to use a floating point type for that, instead you want fixed precision. I think you want E2 from Data.Fixed. re: prefixing - just prefix everything consistently. We can slap classy lenses on it if the prefixes start irritating you. |
@bitemyapp Gotcha, will do. What I had in mind was subweights stuff like: Alright, going to do that then. Thank you! |
Oh oh, weights. Right. Sorry. For that, I'd recommend |
Okay, I'll start with |
Also start using hindent for formatting the code.
@bitemyapp Hey Chris! I've added a rough draft of a |
@alexeyzab looks good so far to me, I'd recommend narrowing focus to getting tests passing against the beta/test API. I usually use Hspec. Can take cues from Bloodhound here as well if it's useful to you. |
Another next step would be to make a more "typed" API that takes a request/query datatype as input, performs the HTTP request, and returns a response type that has parsed the JSON and turned that into an explicit Haskell datatype already. I wouldn't necessarily do that next as I think tests are more important for now. I can save you time on the typed API return value thingy by showing you some tactics in Bloodhound and stripe-haskell. |
Right, I'll start working on tests then. I see, that's what I had in mind as well, the JSON response for this particular endpoint should be parsed properly into a |
That's the bit I thought I'd save you time on, give you a few suggestions/options. When can you hop into a vid call? |
Ahh, got it. I can do that now, if you are free. |
@alexeyzab sent you link in DMs |
First draft of the "/rate" endpoint test.
I've added one hspec test so far. It makes sure the decoded |
Change the single spec to use the new `dispatch` function. The spec is not returning the fullest JSON possible because of the ShipWire account limitations. Emailed the support about that.
@bitemyapp Hey Chris! I am starting to use the type families the way they are done in the Stripe API wrapper. Got a question though. What's the purpose of this empty datatype? I couldn't get a similar setup work with my
Not sure if that's a right solution. As for the hspec tests, I think I need to get my sandbox approved so I can get the full JSON response from ShipWire, I've emailed their support, this hasn't been resolved yet. |
It be a request type that points at Usually the argument type is an empty data decl and the result should be representational. So it would be something like: data DateRequest
type instance ShipWireReturn RateRequest = RateResponse
-- then RateResponse is a real datatype with a FromJSON |
This is more inline with stripe-haskell now.
I think I get it now. Thanks, Chris! |
@alexeyzab a request: could you add a link in the comments to the Shipwire API being implemented next to each request type? |
@bitemyapp will do. |
@bitemyapp something like this? |
Also, should we merge this so I can move on to other endpoints or is there anything I should add here first? |
@alexeyzab there are some ways in which I'd amend it. One is that I'd not make the endpoint the client uses accept a Line 29 in 7836aca
For a contrary example, there's the But the part the user directly uses is stuff like this: http://hackage.haskell.org/package/stripe-core-2.1.0/docs/Web-Stripe-Card.html#v:createCustomerCardByToken where they pass in structured data and something you can submit to Stripe via the Stripe client comes out the other side. Be very suspicious of any raw text or bytestring types exposed to your user. Another is that I'd change the name of request type: Does all this make sense? I agree this should get merged soon. If you're alright making these changes, we'll move to a merge and I'll look at the testing story this weekend. |
Ah, so instead of doing Will change the names too. Yeah, it makes sense, I'll go ahead and try implementing all of that now. Thank you! |
@alexeyzab sounds like you're on the right track. I hate nitpicking over names, but they can guide people to the right intuition without needing to check the docs, so I do care a bit. for The name nitpicking is because it's not clear just from |
@bitemyapp I understand it's important to have decent names, I'll try to be more descriptive in the future. Thank you! Think I've done what you've mentioned. Along the way I realized that |
Also get rid of passing a Maybe Lazy Bytestring straight to `createRateRequest` and instead pass in a non-optional GetRate.
Turns out despite having a `type` field inside the `warnings` array we can actually have a separate array altogether called `errors`.
@bitemyapp Hey Chris! Is there anything else I should add to this pull request? I've started working on another endpoint in a different branch, should we merge this one in? |
@alexeyzab I'll merge it, you start work in a new branch, I'll give this another look this weekend. |
Yep, thank you! |
Hi there!
Making this pull request early because I have a bunch of questions about how to do certain things.
I've been looking at bazaari and how the types are implemented there and was wondering if I should add the "un-" accessors to the dataypes, like here:
newtype PostalCode = PostalCode { unPostalCode :: T.Text } deriving (Eq, Show)
Beyond that I am also not sure if I should add similar functions to
PostalCode
,AddressLine
and so on:makeAddressLine :: T.Text -> Either T.Text AddressLine
makeAddressLine line
| T.length line == 0 = Left "Empty line"
| T.length line > 180 = Left "line is too long"
| T.length line <= 180 = Right $ AddressLine line
I couldn't find any specific information on what the limits are for those fields for Shipwire. Are those supposed to be arbitrary, "common sense" values or is it actually stated somewhere?
As you can see in the
defaultShipTo
I useT.pack
everywhere to convert Strings to Text.Is that normal? Feels dirty.
Another thing that confuses me a bit is the API restrictions on what is required and what isn't.
For example, if we look at the model schema of the Request class, we'll see this:
"required": [ "country" ],
Does this mean that all the other things inside
shipTo
are actually not required?A bit below that I also found another required clause:
"required": [ "shipTo", "items" ],
It's nested one level above the country one. If
shipTo
is required here, does that mean all the nested fields inshipTo
are required as well? Doesn't seem to be that way, otherwise what's the point of specifying thecountry
separately? I might be wrong, of course.Thank you!
UPD: Ignore the question about the accessors, just realized that the
SKU
datatype you've made had one. I'll add them to all the other ones in a later commit. My bad.UPD2: TIR (Today I Remembered) that
OverLoadedStrings
allows you to writeText
without the need ofT.pack
everywhere. That covers another question.P.S. One of my vim plugins aligns the imports and things like that which adds additional changes in git. If that's too annoying, I will turn it off.