#How to validate is all items still available on the checkout process

24 messages · Page 1 of 1 (latest)

lavish bluff
#

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?

mint wagon
lavish bluff
mint wagon
lavish bluff
#

you can try to set quantity 1, then add it to cart, change quantity to 0 and complete order.

mint wagon
#

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"
}
lavish bluff
drifting timber
#

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

lavish bluff
#

I have custom payment provider so I'm changing status to requires_more

lavish bluff
drifting timber
#

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

lavish bluff
#

@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.

drifting timber
#

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

lavish bluff
drifting timber
#

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

mint wagon
#

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. 🙂

drifting timber
#

@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.

mint wagon