We've been making progress as far as refactoring the application goes as far as both reducing the number of end points, and moving domain logic from the end point handler into modules.
We've gotten to the point where invoices is the next logical step to tackle next. It's still a large ask, but we're in a much better position to address it now that we were previously.
Let's start with the goal. The goal is to reduce all of these end points down into three or four end points.
Effectively we only need four end points to accomplish what we're currently doing with a lot more.
- GET
/api/invoice
- POST
/api/invoice
- PUT
/api/invoice
- PATH
/api/invoice
The first step is to create a new draft. We can do this with a simple POST /api/invoice
. This will generate a GUID for that invoice resource on the server, along with poluating the table with the "from" information of the user, along with an empty list of details. To start the invoice will be in the "draft" state.
The next step is PUT /api/invoice
. This will update either the content of the invoice details. Or otherwise populate the "to" section of the invoice from a contact. The invoice is expected to be in the "draft" state at this time.
There are two actions that can be taken from the "draft" state. Either the invoice can be moved to the trash, or sent. These can be done with PATCH /api/invoice
to update the status of the invoice with a new action. In the case the invoice is "sent", the invoice is signed and sent to the buyer. From that point the contents of the invoice cannot be changed, and the status of the invoice must be negotiated between the two parties.
To quickly go over the status updates that can happen from that point, we have "return", "confirm", "unconfirm", "pay" on the buyer side. And "withdraw", and "complete" on the seller's side, in addition to "send". For any of these actions a PrivateInvoice node will need to connect to another node and update the status with a presentation.
There is another aspect of the second life of an invoice. Where a returned invoice can be recreated, fixed and sent again. In this case the two actions the seller can take are to "recreate" and "trash". Both of these actions will also result in a presentation being sent to the buyer to update the status of the invoice.
I think there is a weakness that we're only negotiating the state of the invoice between two parties. I don't know if this is where something like the Baseline Protocol or SCITT to be used. As two party approach only works with both actors are acting in good faith. There are any number of errors or intentional changes such as pretending not to exist which would interupt this flow.
For this first pass of API planning taking bad actors into considderation would be adding too much on the domain. So once we have a flow that works with two coorperating actors we can investigate options for how to mitigate or address the issue of bad actors. And how each of these options actually addresses that problem.
I think the approach to this would be to start at the beginning of the flow and update each step of the flow one function at a time until we have a decent amount of coverage.
Right now our postman collection only covers the draft to end state of the application from Alice to Bob. We could also add more requests to the tests where Bob returns and invoice, or where Alice withdraws and invoice. This would help with gaining confidence for test coverage for updates to the application going forward.
The current scope of changes includes the following.
- create draft
- update draft
- send, confirm, pay, complete
In the application followed by by fixing the postman collection. Followed by:
- Return, recreate
- Return, trash
- Create, send, withdraw
Which should cover more cases. From there we can look into more depth of what else can be approached with invoices. As it looks like this will start to get into cleaning up our modules for presentations, which include states out, and the states in for each one of these negotiations.