Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warehouse management and product availability. #621

Closed
maltitco opened this issue Jul 21, 2017 · 21 comments
Closed

Warehouse management and product availability. #621

maltitco opened this issue Jul 21, 2017 · 21 comments

Comments

@maltitco
Copy link
Contributor

Hi, I have a question about managing the available product quantity.
I have reviewed the documentation and have not found any information about product stock management, as well status informing of product availability (Out in stock, Available, Waiting for delivery).

Are these solutions planned to be introduced at django-shop?

@jrief
Copy link
Member

jrief commented Jul 21, 2017

Where stock management is an issue, we have added an in_stock field to our product model. It then is quite easy to override the AddProductToCart serializer and to decrease the quantity in stock, whenever one purchases that item.

I agree, that there should be a howto and/or some sample code explaining how to handle this.

In django-SHOP the base product model does intentionally not offer stock management to keep that part separately from the framework.

@jrief
Copy link
Member

jrief commented Jul 21, 2017

This is from one of my merchant implementations:

class AddProductToCartSerializer(AddToCartSerializer):
    amount_in_stock = serializers.IntegerField(read_only=True)

    def get_instance(self, context, data, extra_args):
        product = context['product']
        product.refresh_from_db()
        if data != empty:
            quantity = data.get('quantity', self.fields['quantity'].default)
            data['quantity'] = min(int(quantity), product.amount_in_stock)
        instance = super().get_instance(context, data, extra_args)
        instance.update(
            amount_in_stock=product.amount_in_stock,
        )
        return instance

The merchant's product models contains this field:

class Product(BaseProduct):
    ....
    amount_in_stock = models.IntegerField(
        blank=False,
        default=1,
        help_text=_("Amount in stock")
    )

Inside your product's detail views you can use <ANY ng-bind="data.amount_in_stock"></ANY> to render the current amount in stock. This is updated whenever an item is removed from stock.

@maltitco
Copy link
Contributor Author

@jrief Thanks for the quick answer and implementation example.
Will this example also work for polymorphic products? Where in the case of t-shirts we will have to manage the stock for each size.

Could you put this information in the documentation.

@jrief
Copy link
Member

jrief commented Jul 21, 2017

Will this example also work for polymorphic products? Where in the case of t-shirts we will have to manage the stock for each size.

Sure. You can add the amount_in_stock to the base (polymorphic) product, to the product itself, or even to the class describing the variation. In your situation I would use the latter proposal. Then adopt your Add...ToCartSerializer appropriately.

@jrief
Copy link
Member

jrief commented Aug 25, 2017

We have a working implementation for it. In version 0.12 this might be published.
I'd like to use some websocket technology, so that the number of available items decreases as soon, as someone else adds it to his cart.

@maltitco
Copy link
Contributor Author

Super information that this feature will be in the core.
I'm waiting for version 0.12 - I will be happy to test the development versions.

@Aiky30
Copy link

Aiky30 commented Oct 4, 2017

@jrief

We have a working implementation for it. In version 0.12 this might be published.
I'd like to use some websocket technology, so that the number of available items decreases as soon, as someone else adds it to his cart.

The stock amount decreasing functionality would need to release the number of available items once the cart has been inactive for a period of time, maybe even limiting the amount that can be sold per transaction. There could be issues where a merchants competitors / hackers could add a large number of stock in a cart which would cause the item to become unavailable / out of stock.

Slightly off topic:
I'm currently using Django Oscar which I have lightly bound to Django CMS via my own bindings / scripts. I've recently ran an example of the new Django Shop (0.11) and I'm pretty impressed with the integration of Django Shop and CMS. I'm considering creating new sites with Django Shop but I'm a little cautious that early adoption could affect any early effort causing me to constantly go back to sites in production to keep them up to date. I would also be willing to push any improvements, bugfixes or plugins that I believe are relevant.

@jrief
Copy link
Member

jrief commented Oct 4, 2017

@Aiky30 sounds great.
If you want to get in touch with me personally to discuss about the roadmap of django-SHOP, please contact me by email.

@maltitco
Copy link
Contributor Author

maltitco commented Oct 4, 2017

When it comes to booking quantities in the basket, until the order is placed, products in the same quantity are available to everyone.

@jrief Can I request access to the roadmap for the next version?

@Aiky30
Copy link

Aiky30 commented Oct 4, 2017

@maltitco What would happen if two different customers added the same product to their carts but you can only full fill one of the orders (limited stock) at checkout time?

@maltitco
Copy link
Contributor Author

maltitco commented Oct 4, 2017

When the customer clicks on the order button, the available quantity should be checked.

In my experience customers often add products to the basket just as they add web pages to their favorites in the browser. And in this situation also creates an additional option of abandoned baskets.

@Aiky30
Copy link

Aiky30 commented Oct 4, 2017

@maltitco That keeps it simple which in most cases is better. I guess there could still be a small chance that an order can still be processing i.e. the order button could have been clicked by customer one, that order is now being processed but the quantity level hasn't yet been updated when customer 2 clicks and the same check is done but the first order hasn't updated the quantity yet. I know that we're talking a very, very small chance of this happening but at busy periods and popular products this could be a common scenario. Locking at a table level could prevent this but that will hit performance. Think updating multiple product quantity rows here, locking on a row level to update many items from order one whilst order two has been queued.

The concerns highlighted above wouldn't be an issue at add to cart time as the row will be locked whilst updating forcing any queries to wait.

@maltitco
Copy link
Contributor Author

maltitco commented Oct 4, 2017

@Aiky30 See how the dynamic basket update works when you change the quantity.
In the same way, you should check the available quantity at the time of order confirmation.

@jrief Can you say how it was planned?

@Aiky30
Copy link

Aiky30 commented Oct 4, 2017

@maltitco Not necessarily as on an order you are changing the quantity of many items at once which is multiple queries where as the one update stock reserves it immediately and locks that one row so it can't be read at the same time! The two are very different scenarios and definitely not the same.

May be better to see how other e-commerce applications currently do it as It's not something I've been involved with.

I would suggest creating tests that try to simulate the examples touched.

@maltitco
Copy link
Contributor Author

maltitco commented Oct 4, 2017

@Aiky30 The solution I described above I know from the platforms I worked on (Magento, Prestashop, virtuemart, opencart, oscommerce).

@Aiky30
Copy link

Aiky30 commented Oct 4, 2017

@maltitco Personally I would have mentioned previously if I knew how other projects accomplish this. Also consider that just because others do it it doesn't necessarily mean it's the right way. I am merely trying to cover all bases for the benefit of the project. If you have any hard evidence to back this up then by all means add the information rather than speculating what you think is the best solution.

I only know Django Oscar but I have never looked deeply into the stock allocation procedures until now. You are indeed correct that the quantity is reserved at order time. The following code in Oscar accomplishes that: http://django-oscar.readthedocs.io/en/releases-1.4/_modules/oscar/apps/order/processing.html#EventHandler.consume_stock_allocations

I would from this still investigate what the procedure is if there is stock that has been "allocated" but others still have it in their cart. What should happen? I guess the best solution is to check when the order button is clicked which I believe you mentioned earlier, this would require a check before proceeding that all of the stock is available, this would have to be done at the same time as reserving the allocation and lock the entries from being updated. We're talking milli seconds but its a gap in time where another simultaneous order could take the allocation.

@maltitco
Copy link
Contributor Author

maltitco commented Oct 4, 2017

@Aiky30 I do not speculate what would have been better, but I can not imagine the situation when the available quantity is reserved after inserting into the cart. The well-known B2B systems I use always contain clauses that inserting a product into a shopping cart is not equivalent to booking a quantity.
Our discussion will not bring...

@jrief I'm waiting for your opinion on this topic.

@jrief
Copy link
Member

jrief commented Oct 4, 2017

If you create your product model, and unless you have ∞ items of that product, then you keep track of your stock. This normally is an integer field, I'll name it amount_in_stock.

It's important to remember that this is your canonical information. Therefore I would not decrease that value, as soon as someone adds that item to the cart. This number shall only be decreased during the purchase operation.

Therefore, if you want to decrease the number of available items, override the CartItem model and add a timestamp added_to_cart to it.
Additionally add a method to your Product model which tells the exact number of items available. This can easily be computed using the amount_in_stock and filtering the Cart Items on the current product.

The reason doing so, is that carts can be "lost" much easier, and it would be quite error-prone, having to remember, when to re-add the amount of items from the cart to the product.

This of course is a matter of taste, but that would be my preferred solution.

@Aiky30
Copy link

Aiky30 commented Oct 5, 2017

@maltitco You should learn the meaning of being open to others opinions / solutions and contribute in a constructive way rather than barking your opinion over and over and stating why you are right rather than considering other angles / solutions. You may notice that I stated that you were right in my previous response! You mention that you cannot imagine another way, I can imagine other ways and I'm expressing them. That's what analysts do!

I would like to reiterate that I believe there could be an issue with allocated stock at order time where two customers are checking out simultaneously, the stock allocation could show as available when it's just been taken in the order processing stage.

@markusmo
Copy link

is there an update on this?
I am new to this framework and I quite like it.
We decided to use it for our webshop solution and this feature would help me a lot :-)

@jrief
Copy link
Member

jrief commented May 19, 2019

@maltitco @Aiky30 @markusmo
Yes upcoming version 1.1 handles this. Please read the documentation inventory.rst. Check out the releases/1.1.x branch for now.

Just to add my 2 cents to the discussion: It still is possible to work without any inventory management, but now there are other options which can be plugged in. This is to remain with django-SHOP's mindset be keep product models as lean as necessary.

I'm closing this, because this feature is solved for now.

@jrief jrief closed this as completed May 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants