shopify transaction api GET all transactions - rest

since shopify's transaction reporting is broken, I'm trying to use the API to get transaction fees for orders and basic accounting. In their API docs, they have their endpoints and parameters listed for getting/posting transactions. To "Receive a list of all Transactions", the docs say
GET /admin/orders/#{id}/transactions.json
but don't explain what the #{id} is for. The call will only work if I put a transaction ID in, but then it only shows a single transaction, rather than a list. The docs state that to "Get the Representation of a specific transaction":
GET /admin/orders/#{id}/transactions/#{id}.json
Which has the id in there twice. I can't use a single transaction, I need all of them for a specific range. I've tried /admin/orders/transactions.json, or putting in all or * in for the id, and it returns errors unless the id is a valid transaction id. Any ideas?

Transactions belong to an order. So the ID you are wondering about is for one specific order. So if you want transactions for your accounting system, the important thing you're basing your API work on will be orders. So setup your code to first off download the orders of interest. Say for a month. Now for each order ask for the transactions, and produce your report.

Related

XRPL: How to get the history of the balance of an account?

I would like to query the history of the balance of an XRPL account with the new WebSocket API.
For example, how do I check the balance of an account on a particular day?
I know with the v2 api, there was a possibility to query balance_changes. But this doesn't seem to be part of the new version.
For example:
https://data.ripple.com/v2/accounts/rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn/balance_changes?start=2018-01-01T00:00:00Z
How is this done with the new Websocket API's?
There's no convenient API call that the WebSocket API can do to get this. I assume you want the XRP balance, not token/issued currency balances, which are in a different place.
One way to go about it is to make an account_tx call and then iterate through the metadata. Many, but not all, transactions will have a ModifiedNode entry of type AccountRoot—if that transaction changed the account's XRP balance, you can see the difference in the PreviousFields vs. FinalFields for that entry. The Look Up Transaction Results tutorial has some details on how to parse out metadata this way. There are some kind of tricky edge cases here: for example, if you send a transaction that buys 10 drops of XRP in the exchange but burns 10 drops of XRP as a transaction cost, then the metadata won't show a balance change because the net change was zero (+10, -10).
Another approach could be to estimate what ledger_index was most recently closed at a given time, then use account_info to look up the account's balance as of that time. The hard part there is figuring out what the latest ledger index was at a given time. This is one of the places where the Data API was just more convenient than the WebSocket API—there's no way to look up by date in WebSocket so you have to try a ledger index, see what the close time of the ledger was, try another ledger index, see what the date is, etc.

Sort Order of Shopify REST Collections

Trying to nail down what the sort order is for Shopify's REST collections. Specifically I'm working with orders and customers at the moment.
I found this closed thread discussing the ability to sort collections, and the API docs don't mention it at all for either orders or customers.
However, customers have a documented search API, which does have an order parameter as an option. I'm not sure whether I can use it as a sort of substitute for the regular list API call. This doesn't seem to work properly for example - it returns more than one result.
/admin/customers/search.json?query=&limit=1
Orders don't have a documented search endpoint, but I do get a response when hitting
/admin/orders/search.json?query=&limit=1
Although it has the same issues as the customer search endpoint. I found this thread saying that orders are always returned most recent to newest by date - and inspecting the response I'm getting now that seems to be true although I could have sworn I've seen them come back in a different orders, it almost seems indeterminate.
Would like to know if that's the case for sure, and the same for customers. I seem to be getting them returned back in created_at order ascending for customers. Is that always the case?
Also, ID's for both customers and orders don't seem to be in created_at order, which is bizzare given that the have the since_id parameter in pretty much all their collections (which I found and promptly built my incremental pulling strategy on top of). I guess I'll have to use created_at instead.
The thread you linked to (apart from being really old) is referring to Collections (with a capital C), which are how groups of products are defined in Shopify (e.g. Shoes, Coats, Hats, etc.).
The 'collections' you're referring to (Customers, Products, Orders, etc.) are returned in descending date order (i.e. newest first) if the since_id parameter is not supplied, and in ascending order if it is supplied. Note that this should correspond with a descending id ordering, that's the idea at any rate as it allows you to use since_id to paginate properly (as you're doing).
Double check that you're getting wonky id ordering and if you are, please post the store domain you're seeing it on as well as a sample of order ids so that we can look into it.

How to get list of aggregates using JOliviers's CommonDomain and EventStore?

The repository in the CommonDomain only exposes the "GetById()". So what to do if my Handler needs a list of Customers for example?
On face value of your question, if you needed to perform operations on multiple aggregates, you would just provide the ID's of each aggregate in your command (which the client would obtain from the query side), then you get each aggregate from the repository.
However, looking at one of your comments in response to another answer I see what you are actually referring to is set based validation.
This very question has raised quite a lot debate about how to do this, and Greg Young has written an blog post on it.
The classic question is 'how do I check that the username hasn't already been used when processing my 'CreateUserCommand'. I believe the suggested approach is to assume that the client has already done this check by asking the query side before issuing the command. When the user aggregate is created the UserCreatedEvent will be raised and handled by the query side. Here, the insert query will fail (either because of a check or unique constraint in the DB), and a compensating command would be issued, which would delete the newly created aggregate and perhaps email the user telling them the username is already taken.
The main point is, you assume that the client has done the check. I know this is approach is difficult to grasp at first - but it's the nature of eventual consistency.
Also you might want to read this other question which is similar, and contains some wise words from Udi Dahan.
In the classic event sourcing model, queries like get all customers would be carried out by a separate query handler which listens to all events in the domain and builds a query model to satisfy the relevant questions.
If you need to query customers by last name, for instance, you could listen to all customer created and customer name change events and just update one table of last-name to customer-id pairs. You could hold other information relevant to the UI that is showing the data, or you could simply hold IDs and go to the repository for the relevant customers in order to work further with them.
You don't need list of customers in your handler. Each aggregate MUST be processed in its own transaction. If you want to show this list to user - just build appropriate view.
Your command needs to contain the id of the aggregate root it should operate on.
This id will be looked up by the client sending the command using a view in your readmodel. This view will be populated with data from the events that your AR emits.

What is a good strategy for adding additional information in a GET query over REST?

Given that we provide a restful api that serves book entities listening at
/books
And a client can get a book at the usual
GET /books/{id}
Suppose that we want to begin offering discounts on books to only our most vigilant buyers. These buyers would be given a discount code, and that code will reduce the price of the book.
Thus, a generic response may be
GET /books/4
{"id":4, "price":"24.95"}
Where a response to a query with a discount code may be
GET /books/4
{"id":4, "price":"24.95", "yourPrice":"19.95"}
The back-end processing we can get figured out, but what is the best practice for a client submitting a discount code over a restful api?
Certain books will be eligible for discounts while others will not. Discounts will not be broad (20% off everything), but instead will map to a specific price for that particular code (or client/code combo).
We've considered:
kludging the url
GET /codes/{someCode}/books/{id}
Adding the code in a header value
Using a query string
GET /books?code=myCode
anything else?
EDIT: Our goal is not to implement single-use codes. Instead, these discount codes could be used some fixed number of times for some fixed set of books.
I like using query variables. I just looked at the RESTful Web Services book, my main reference in this area, and they say:
Use query variables only to suggest
arguments being plugged into an
algorithm... If two URIs differ only
in their query variables, it implies
they're the different sets of inputs
into the same underlying algorithm.
It seems to me your discount codes are inputs to a discounting algorithm.
Charles
If you're going to be submitting anything that's not idempotent, I would suggest using POST instead of GET. You wouldn't want a client to be able to use their code more than once.
Anything you add in the URL or header values are open to be intercepted, and possibly allowing other users to 'fake' their discount ID. 1 approach would be to introduce a new POST call, that will allow the ID to be encrypted with simple HTTPS. The POSTed data could be as simple as the discountID or customerID.
Added - Sorry Michael, you already said that :)
You can register the code in a table so when the user retrieves that book automatically returns that book with the proper discount, for example:
The user can add some code
POST /register/{code}
This will add an entry to a table {user} - {code} so when the user retrieves by
GET /books/{id}
will use that entry to apply the discount. I'm guessing that you already have some relation between {code}-{book} so wont get into that.

Appending to a resource's attribute RESTfully

This is a follow up to Updating a value RESTfully with Post
How do I simply append to a resource's attribute using REST. Imagine I have customer.balance and balance is an int. Let' say I just want to tell the server to append 5 to whatever the current balance is. Can I do this restfully? If so, how?
Keep in mind that the client doesn't know the customer's existing balance, so it can't just
get customer
customer.balance += 5
post customer
(there would also be concurrency issues with the above.)
Simple, slightly ugly:
This is a simpler variation of my answer to your other question.
I think you're still within the constraints of REST if you do the following. However, I'm curious about what others think about this situation as well, so I hope to hear from others.
Your URI will be:
/customer/21/credits
You POST a credit resource (maybe <credit>5</credit>) to the URI, the server can then take the customer's balance and += it with the provided value. Additionally, you can support negative credits (e.g. <credit>-10</credit>);
Note that /customer/21/credits doesn't have to support all methods. Supporting POST only is perfectly acceptable.
However, this gets a little weird if credits aren't a true resource within your system. The HTTP spec says:
If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header.
Technically you're not creating a resource here, you're appending to the customer's balance (which is really an aggregate of all previous credits in the system). Since you're not keeping the credit around (presumably), you wouldn't really be able to return a reference to the newly "created" credit resource. You could probably return the customer's balance, or the <customer> itself, but that's a bit unintuitive to clients. This is why I think treating each credit as a new resource in the system is easier to work with (see below).
My preferred solution:
This is adapted from my answer in your other question. Here I'll try to approach it from the perspective of what the client/server are doing:
Client:
Builds a new credit resource:
<credit>
<amount>5</amount>
</credit>
POSTs resource to /customer/21/credits
POSTing here means, "append this new <credit> I'm providing to the list of <credit>s for this customer.
Server:
Receives POST to /customer/21/credits
Takes the amount from the request and +=s it to the customer's balance
Saves the credit and its information for later retrieval
Sends response to client:
<credit href="/customer/21/credits/credit-id-4321234">
<amount>5</amount>
<date>2009-10-16 12:00:23</date>
<ending-balance>45.03</ending-balance>
</credit>
This gives you the following advantages:
Credits can be accessed at a later date by id (with GET /customer/21/credits/[id])
You have a complete audit trail of credit history
Clients can, if you support it, update or remove credits by id (with PUT or DELETE)
Clients can retrieve an ordered list of credits, if you support it; e.g. GET /customer/21/credits might return:
<credits href="/customer/21/credits">
<credit href="/customer/21/credits/credit-id-7382134">
<amount>13</amount>
...
</credit>
<credit href="/customer/21/credits/credit-id-134u482">
...
</credit>
...
</credits>
Makes sense, since the customer's balance is really the end result of all credits applied to that customer.
To think about this in a REST-ful way, you would need to think about the action itself as a resource. For example, if this was banking, and you wanted to update the balance on an account, you would create a deposit resource, and then add one of those. The consequence of this would be to update the customer's balance
This also helps deal with concurrency issues, because you would be submitting a +5 action rather than requiring prior knowledge of the customer's balance. And, you would also be able to recall that resource (say deposit/51 for deposit with an ID of 51) and see other details about it (ie. Reason for deposit, date of deposit etc.).
EDIT: Realised that using an id of 5 for the deposit actually confuses the issue, so changed it to 51.
Well, there is alternative other than #Rob-Hruska 's solution.
The fundamental idea is the same: to think each credit/debit operation as a standalone transaction. However I once used a backend which supports storing schema-less data in json, so that I end up with defining the API as PUT with dynamic field names. Something like this:
PUT /customer/21
{"transaction_yyyymmddHHMMSS": 5}
I know this is NOT appropriate in the "credit/debit" context because an active account could have growing transaction records. But in my context I am using such tactics to store finite data (actually I was storing different batches of GPS way points during a driving trip).
Cons: This api style has heavy dependence on backend behavior's schema-less feature.
Pros: At least my approach is fully RESTful from the semantic point of view.
By contrast, #Rob-Hruska 's "Simple, slightly ugly" solution 1 does not have a valid Location header to return in the "201 Created" response, which is not a common RESTful behavior. (Or perhaps, we can let #Rob-Hruska's solution 1 to also return a dummy Location header, which points to a "410 Gone" or "404 Not Found" page. Is this more RESTful? Comments are welcome!)