Architecture question for state evolution - blockchain

I have a sample loan usecase, where I have two states:
Invoice State, and
Loan State.
Loan State is created by passing Invoice State as input.
Now as Corda follows UTXO model, when I do the default vault query, the Invoice state is not showed as it's consumed now.
To solve this, there are two possible ways:
Either, I query on all states i.e consumed and unconsumed.
Or, I
can maintain a status at Invoice state and mark the status to
something as Invoice paid after consuming it to create Loan State (So this is more like evolving state, something like bitcoin where balance is always getting transferred.).
Something like this:
Can anybody please recommend what would be the correct architecture decision?

Your Invoice should have a 'state' field with and enum of at least 'UNPAID' and 'PAID'
Your 'payInvoice' command should have the following inputs and outputs:
inputs:
Invoice - state=UNPAID
outputs
Invoice - state=PAID
Loan
The verify function should check that the inputs and outputs for this command are as above.
After which the 'UNPAID' invoice state is spent and cannot be used again.
I hope that makes sense.
Check out the 'MeteringInvoiceCommands.Pay' method in the following code. This is similar to what you need, but in this case, it is checking that a payment is produced as well as the input state is 'ISSUED' and output state is 'PAID'
https://gitlab.com/cordite/cordite/blob/master/cordapps/metering-contracts-states/src/main/kotlin/io/cordite/metering/contract/MeteringInvoiceContract.kt

I agree with bartman250. The second example makes the most sense in my view as it keeps options open in a more obvious way.
Let's say for example, for some reason the invoice needs to be reset to unpaid because there is a chargeback on a credit card, having the invoice as unconsumed works well.
The issue of worrying about it being consumed again can be handled by ensuring that the loan contract only consumes invoices that are marked as unpaid. We do something very similar with a purchase order in the letter of credit demo found here.
Having the invoice available to be queried from the vault as unconsumed is also the default query mode. It also provides the advantage of ensuring we're dealing with the latest version of the state by default.

The second example above is the best in my view.
Basically, if you hold an Enum on the Invoice with all the different states - i.e. UNPAID, PAID, REJECTED etc. You can then evolve this state in your flows.
You can then use the contract verify function for the 'paid command to check that a loan state has been created.

Related

How do you give negative feedback to amazon personalize? i.e. tell personalize that a user doesn't really like a certain item?

I did the amazon personalize deep dive series on youtube. At the timestamp 8:33 in the video, it was mentioned that 'Personalize does not understand negative feedback.' and that any interaction you submit is assumed to be a positive one.
But I think that giving negative feedback could improve the recommendations that we give on a whole. Personalize knowing that a user does not like a given item 'A' would help ensure that it does not recommend items similar to 'A' in the future.
Is there any way in which we can give negative feedback(ex. user doesn't like items x,y,z) to amazon personalize?
A possible way to give negative feedback that I thought of:
Let's say users can give ratings out of 5 for movies. Every time a user gives a rating >= 3 in the interactions dataset, we add an additional interaction in the dataset (i.e we have two interactions saying that a user rated a movie >=3 in the interactions.csv instead of just one). However, if he gives a rating <=2 (meaning he probably doesn't like the movie), we just keep the single interaction of that in the interactions dataset (i.e. we only have one interaction saying that a user rated a movie <=2 in the interactions.csv file)
Would this in any way help to convey to personalize that ratings <=2
are not as important/that the user did not like them?
Negative feedback, where the user explicitly indicates that they dislike an item, is currently not supported as training input for Amazon Personalize. Furthermore, there is currently no way to add weight/reward to specific interactions by event type or event value (see this answer for details).
With that said, you can use impressions with your interactions to indicate items that were seen by the user but that they chose not to interact with. Impressions are only supported by the User-Personalization recipe. From the docs:
Unlike other recipes, which solely use positive interactions (clicking, watching, or purchasing), the User-Personalization recipe can also use impressions data. Impressions are lists of items that were visible to a user when they interacted with (clicked, watched, purchased, and so on) a particular item.
Using this information, a solution created with the User-Personalization recipe can calculate the suitability of new items based on how frequently an item has been ignored, and change recommendations accordingly. For more information see Impressions data.
Impressions are not the same as an explicitly negative interaction but they do imply that the impressed items were considered less relevant/important to the user than the item that they chose to interact with.
Another approach that can be used to consider negative interactions when making recommendations is to have two event types: one event type for positive intent (e.g., "like", "watch", or "purchase") and one event type for dislike (e.g., "dislike"). Then create a Personalize solution that only trains on the positive event type. Finally, at inference time, use a Personalize filter to exclude items that the user has recently disliked.
EXCLUDE ItemID WHERE Interactions.EVENT_TYPE IN ("dislike")
In this case, Personalize is still training only on positive interactions but with the filter you won't recommend items that the user disliked.

Django: Handling discount codes

I am currently building a Django application where visitors can buy an online course. I now want to implement the possibility to provide discount codes. As these discount codes should be limited by quantity I now have the following implementation idea:
Guest visits www.page.com?discount=TEST
The model discount contains the fields discount_codes & max qty. I will check here, if the code exists. Also, I have to count all entries in my order model that used the discount code TEST. My order model contains the foreign_key field 'redeemed_discounts').
As soon the user clicks on Pay (via Stripe) I'll once again count all the orders in my order model which contain 'TEST' to make sure, the 'max_qty' is not reached meanwhile.
Now I can charge the visitor.
Would you consider this as good implemented or do you see any problems with the way I am planning to do it?
instead of using max_qty why don't you use something like use_left and max_use
so whenever someone uses that code you can reduce the count accordingly and when count hits zero you can stop using that with this approach you don't have to scan order table every time to see if the coupon code is still available.

NoSQL Race Condition

I'm trying to figure out how companies that use nosql database solve this general nosql race condition issue:
Lucky example: User and Product. Product has quantity of 1 and there are 2 users. When the first user tries to buy this product, system first checks whether quantity is > 0 and it is indeed > 0, proceeds to create a Transaction object and decrement quantity of product. The second user tries to buy the product, system rejects as quantity isn't > 0.
Unlucky: Both users try to buy the product simultaneously. For both, system confirmed quantity is > 0 and so created a Transaction object for both users, hence destroying the company image next day...
How to generally deal with this common scenario?
From similar cases i found on the net, one suggested solution is to use request queue, and process the request one by one. However, if all transactions are queued, and you're running business like Amazon (millions of transactions every now and then), how do we expect users to know whether or not their purchase succeeded shortly after they clicked that purchase now button?
One of the ways to solve this problem is to allow both users to order products simultaneously.
Then there are two possible situations:
One of the users doesn't finish a transaction (refuses to pay, closes a browser window etc). Then another one will have the requested amount of a product.
Both users finished their transactions. Then you will get a random user your product and say sorry to another one giving away a coupon with $10 to him/her.
The second situation should happen extremely rare. So you won't blow out all your money on coupons and your users will be happy whatever the outcome. But you still need to monitor the 2nd situation in order to react and make changes to your system if it happens more often than you expected.

SpreeCommerce: Mark order as pending

SpreeCommerce has an order overview, where it's possible to see all the orders and the states. Each day we open the order overview, and find the completed orders, pack them and ship them to the customer.
However, sometimes we don't have the goods for an order in stock, and want to mark the order as "pending", so we don't open the order each day by mistake.
What's the best way in SpreeCommerce to mark an order as "pending", so we only have to check the pending orders, when we get a new shipment of goods from our supplier?
It would be great, if we could use the state property, because SpreeCommerce allows us to filter orders by their state.
Spree supports inventory tracking as described here:
http://guides.spreecommerce.com/developer/inventory.html
This will allow you to flag a shipment as being backordered:
https://github.com/spree/spree/blob/v2.2.1/core/app/models/spree/shipment.rb#L79-L81
if any of its inventory units are backordered. An order is considered backordered if any of its shipments are considered backordered:
https://github.com/spree/spree/blob/master/core/app/models/spree/order.rb#L193-L195
Your best bets for putting an order in to a back ordered state would be:
Turn on inventory tracking in Spree and keep it up to date through synchronization or manual audits
Extend Spree to override what it means for shipment to be considered backordered and allow this to be set and unset by administrators as stock levels change
Which solution you should choose depends a great deal upon the specifics of your store and how you manage inventory. The specifics of your implementation could make either solution very easy, or very difficult.

shop scenario racing conditions

Imagine a little webshop which uses its own currency.
In the database, there is a table for items, which can be bought. The count of each item is limited. This limit is stored in a collumn in this table as integer.
Also, there is a table for the user's cash accounts, whereas for each account the current balance is saved.
If, for example, two users conduct their purchases at the same time and only one item is available, it could be possible that both users pay but only one receives the item due to racing conditions.
How can such racing conditions be resolved, without relying on entity framework throwing exceptions on saving?
How can I ensure the count of available items and the account balance of the buyer is correctly updated?
This isn't really a problem specific to Entity Framework, it's applicable to just about any shop scenario. It comes down to a question of policy - the only way to ensure that two customers do not purchase the same item is to allow a temporary lock to be placed on that item when they add the item to the cart, or begin the checkout process, similar to how concert tickets or flights are sold. This lock would expire if the purchase is not completed within a set amount of time, and the item would be released back for other customers to purchase.
In an e-commerce setting, this is not as suitable, since people may add an item to their cart and not check out, or spend extra time choosing additional items. This may lead to the scenario where you have items for sale but they can't be bought because they're in someone's cart who's not planning on checking out. Instead, duplicate orders are allowed, but payments are typically only pre-authorised and then completed at the time of shipping or order confirmation, so even if the second customer enters all their details and presses Buy, their card wouldn't be charged since the item wouldn't be shippable.
You can implement checks at different stages during the Checkout process to ensure the items in the cart are still available, or at the simplest level, leave it for the final "Pay Now" button on the last page. Ultimately though, this just reduces the potential for the race condition, rather than eliminating it.