How to correctly validate is all selected variants still available (when using Manage inventory)?
For example you have only 1 available quantity in stock, and customer A and B added it to their cart. Then both of them come to checkout page, and customer A faster filled checkout page and purchased this item. Customer B still filling data and click Purchase button. How to validate before processing payment is all of the items inside cart are available?
#How to validate is all items still available on the checkout process
24 messages · Page 1 of 1 (latest)
The purchase will fail for customer B with an error that item X is out of stock. So you don’t have to do the check, but it would make sense to handle the error gracefully, letting the customer know why their purchases failed, remove the item from their cart, etc. 😄
hm, for me it's not crashing. It should crash when you are calling medusaClient.carts.complete right?
Do you have allow_backorder enabled for the variant by any chance? 🙂
disabled, only Manage inventory enabled.
you can try to set quantity 1, then add it to cart, change quantity to 0 and complete order.
Just tested it and it does throw the error correctly:
{
code: "insufficient_inventory"
message: "Variant with id: variant_01GBWEF39VA2N7MMV35FSVJ5D9 does not have the required inventory"
type: "not_allowed"
}
can it be because of payment provider?
The issue is that cart completing usually happens after payment being processed. Hence I'm checking if everything in cart is available when customers clicks PAY
I have custom payment provider so I'm changing status to requires_more
I guess that's make sense to do at the beginning of completing cart. How exactly you are checking it? are you requesting to receive all this variants (to receive the latest state of variants)?
I have made a very sparse util function
I'm calling it like this in handleSubmit function
const [itemsAreNotAvailable, unavailableItems] = await checkForAvailability(
cart.items
);
if (itemsAreNotAvailable) {
// return error to customer and not continue
// loop through unavaibleItems and show which are unavailable.
The function itself could be written much better but it works. It probably needs a refactor with some Promise.all or whatever
import { medusaClient } from './client';
export const checkForAvailability = async (items) => {
const availabilityArray = [];
const unavailableItems = [];
for (const item of items) {
const { variant } = await medusaClient.products.variants.retrieve(
item.variant_id
);
const isAvailable =
variant?.inventory_quantity >= item.quantity || variant?.allow_backorder;
availabilityArray.push(isAvailable);
if (!isAvailable) {
unavailableItems.push({
...item,
available: variant?.inventory_quantity || 0,
});
}
}
return [availabilityArray.some((item) => item === false), unavailableItems];
};
I don't remember why I'm pushing there available to unavailableItems, hehe
@drifting timber I guess it's good work around, thx! But still @mint wagon would be nice if we will check availability before calling payment provider authorizePayment because in my opinion doesn't make sense to pay for products if they can be not available anymore.
ahh I know why, because customer might order 3 items of a variant and I have 2 in magazine
I'm showing to the customer how many are left if it fails
oh that's true, I was not thinking about such case 😅 nice catch!
Thinking about it, I'm gonna refactor it tommorow. You can just fetch the cart again to have fresh inventory state instead of requesting each variant
And just check each variant at cart.items.variant.inventory_quantity
@lavish bluff
also as possible solution 😉
I can’t really tell you why payment authorization occurs before checking the quantity, there might be some very good reason for it, but again can’t really answer that right now I would have to ask some of the guys that worked on the cart completion strategy. You could always overwrite the CartCompletion strategy to better fit your needs, we don’t have a specific guide for it, but it’s the same principle as outlined here for imports: https://docs.medusajs.com/advanced/backend/batch-jobs/customize-import. But I think it’s important to note that nothing is payed just because a cart is completed, you still need to capture the payment before any money ever leaves a customers account. 🙂
@mint wagon That might be true for Stripe card payments, but Przelewy24 or Blik payments are captured automatically anyway
I mean, they're not captured on medusa side, it's just how they work.
And in those cases you definitely should make sure to handle any potential issues like this before completing a cart, either as you are doing on the front end or by overwriting the completion strategy. But I will definitely try and asks the guys if there is a reason why the default strategy does it in that order or if it would make sense for us to change it 🙂