logo
Welcome to our new AbleCommerce forums. As a guest, you may view the information here. To post to this forum, you must have a registered account with us, either as a new user evaluating AbleCommerce or an existing user of the application. For all questions related to the older version of Gold and earlier, please go to forums.ablecommerce.com. Please use your AbleCommerce username and password to Login. Forums Registration.

Notification

Icon
Error

Options
Go to last post Go to first unread
sweeperq1766875  
#1 Posted : Monday, June 15, 2020 11:19:53 AM(UTC)
sweeperq1766875

Rank: Newbie

Groups: Authorized User, Developers
Joined: 5/30/2020(UTC)
Posts: 0

I was just looking through the API documentation and saw that there is an EventManager we can tie into during specific events like OrderPlaced, OrderShipped, OrderCancelled, etc. Is there any chance OrderItem-level events like OrderItemAdded, OrderItemUpdated, and OrderItemDeleted can/will be added?

It is nice that AC has some basic inventory management features. However, it is a pretty basic implementation and doesn't include things like Warehouse/Pick Location, allocated inventory, etc. For instance, Pick Slips do not contain a warehouse bin location. If products are marked as being unable to order if out-of-stock, orders can still come through for an item until Payment is captured (this is where allocated / available inventory comes into play).

With a couple more events, a pretty full-featured inventory management system can be tied in without making a bunch of changes to the core code.

Wanna join the discussion?! Login to your AbleCommerce Forums forum account. Forums Registration.

katie_able_support  
#2 Posted : Monday, June 15, 2020 5:30:59 PM(UTC)
katie_able_support

Rank: Advanced Member

Groups: Administrators, Developers, Registered, HelpDesk, System
Joined: 10/29/2018(UTC)
Posts: 91

Thanks: 2 times
Was thanked: 6 time(s) in 5 post(s)
Quote:
With a couple more events, a pretty full-featured inventory management system can be tied in without making a bunch of changes to the core code.


This is definitely an area we want to improve. I had looked at this when version 9 was first developed, but there was an issue with the warehouse to product relationship (specifically, enforcement during fulfillment). I can't remember all the details at the moment, but we would love to get more feedback on everything we need to have a full-featured inventory system.

I'll try to have a developer look at the EventManager to see what it would take to include the order level events.

Thanks!
Katie
Thanks for your support!
Katie
sweeperq1766875  
#3 Posted : Friday, June 19, 2020 10:15:50 AM(UTC)
sweeperq1766875

Rank: Newbie

Groups: Authorized User, Developers
Joined: 5/30/2020(UTC)
Posts: 0

Katie, that would be awesome!
Naveed Ashraf  
#4 Posted : Wednesday, June 24, 2020 10:54:32 AM(UTC)
Naveed Ashraf

Rank: Advanced Member

Groups: Admin, Administrators, Developers, Registered, HelpDesk, Authorized User
Joined: 7/31/2019(UTC)
Posts: 49

Was thanked: 3 time(s) in 3 post(s)
We also a have couple of inventory management events:

InventoryDestocked: When a product (or its variant) is purchased and marked SHIPPED from order admin this event is fired.
InventoryRestocked: When a purchased product (or its variant) is RETURNED from order admin this event is fired.
LowInventoryItemPurchased : low inventory item (product/variant) purchased event

I am not sure if these are useful in your scenario?
Another very useful event with respect to order management is OrderStatusUpdated which can be useful in many scenarios. You can write your custom event handlers for these events and perform various tasks.

Quote:
If products are marked as being unable to order if out-of-stock, orders can still come through for an item until Payment is captured (this is where allocated / available inventory comes into play).


Please explain in details that what features you are looking for?
sweeperq1766875  
#5 Posted : Wednesday, June 24, 2020 11:15:42 AM(UTC)
sweeperq1766875

Rank: Newbie

Groups: Authorized User, Developers
Joined: 5/30/2020(UTC)
Posts: 0

I hadn't thought about using the built in inventory events. Do those fire when you add, update, or delete order lines?

We allocate inventory for the customer with a timestamp when an order is placed. This makes it so if there are any issues with the order (address validation, fraud hold, tax exempt, other items on backorder, etc), we can still process orders that came after without running the risk of taking the first customer's inventory and being unable to fill their order.

Customizing the checkout was easy. The painstaking part was tying into the AC7 admin everywhere the qty for an item can change, which is why we haven't upgraded yet. I want to avoid that with AC9 if at all possible by creating a plug-in and tying into the events.

Is there an event that is guaranteed to fire every time an order line is added, updated, or deleted? It doesn't have to be line-specific. I can loop over the order contents for changes. I'm not sure OrderStatusUpdated always fires.
Naveed Ashraf  
#6 Posted : Wednesday, June 24, 2020 12:44:20 PM(UTC)
Naveed Ashraf

Rank: Advanced Member

Groups: Admin, Administrators, Developers, Registered, HelpDesk, Authorized User
Joined: 7/31/2019(UTC)
Posts: 49

Was thanked: 3 time(s) in 3 post(s)
Quote:
Do those fire when you add, update, or delete order lines?


The inventory is actually de-stocked when order items are shipped, so the respective InventoryDestocked event fires when order item is shipped from admin.
Also the InventoryRestocked event is fired when order item is returned from order admin.

However LowInventoryItemPurchased event is fired when order is placed with a product line item for which the inventory is low on stock.
Quote:

Is there an event that is guaranteed to fire every time an order line is added, updated, or deleted? It doesn't have to be line-specific. I can loop over the order contents for changes. I'm not sure OrderStatusUpdated always fires.



No there is no such event which fires when order items are added/removed. OrderStatusUpdated only fires when order status is updated. In some cases when new order items are added the order status may change, but not always.
sweeperq1766875  
#7 Posted : Wednesday, June 24, 2020 3:28:42 PM(UTC)
sweeperq1766875

Rank: Newbie

Groups: Authorized User, Developers
Joined: 5/30/2020(UTC)
Posts: 0


  • OrderPlaced to make the initial allotment.
  • OrderShipped or OrderShippedPartial to convert allotment to destock.
  • ShipmentReturned or ShipmentReturnedPartial to handle returns for destocked inventory.
  • OrderStatusUpdated can be used to check for other changes.


Unfortunately, without an event that reliably fires on changes to the line items that occur between order placement and shipping, there isn't an automatic way to modify allocations and update available inventory (available = stock - allocated).

Is the NHibernate stuff in CommerceBuilder public, or internal? I'm not super familiar with NHibernate, but if the bits are public, might I be able to wire in PostInsert, PostUpdate, and PostDelete event handler as part of a plug-in? Probably requires a change to the NHibernate config, but that is better than modifying AC source code.

I just don't get how small/mid-sized stores are handling their inventory? 43% of small businesses are using spreadsheets or nothing at all?! We ship hundreds of orders each day; I can't even fathom doing things the way we did before we automated.
Naveed Ashraf  
#8 Posted : Monday, June 29, 2020 11:25:57 AM(UTC)
Naveed Ashraf

Rank: Advanced Member

Groups: Admin, Administrators, Developers, Registered, HelpDesk, Authorized User
Joined: 7/31/2019(UTC)
Posts: 49

Was thanked: 3 time(s) in 3 post(s)
Quote:
I just don't get how small/mid-sized stores are handling their inventory? 43% of small businesses are using spreadsheets or nothing at all?! We ship hundreds of orders each day; I can't even fathom doing things the way we did before we automated.


As I mentioned before, the inventory in AbleCommerce is updated when from order admin you SHIP an item, or RETURN an item. Both actions have events associated with those as well. Also when a Low Inventory item is purchased (order placed), the "LowInventoryItemPurchased" event is fired.

AbleCommerce application do not update inventory when order line item is added or remove to order. I think you should update your code to follow this, and update the inventory when order items are shipped from order admin.

If you have better approach to handle it, then we are open for ideas.

Thanks,
Naveed Ashraf
Joe Payne @ AbleMods LLC  
#9 Posted : Monday, June 29, 2020 12:29:22 PM(UTC)
Joe Payne @ AbleMods LLC

Rank: Advanced Member

Groups: Developers
Joined: 11/9/2018(UTC)
Posts: 84

Thanks: 11 times
Was thanked: 5 time(s) in 5 post(s)
Able has never been strong with inventory. It works at a basic level for basic purposes, but more advanced implementations are simply not possible without major work.

My clients who require advanced inventory do it outside of Able by pushing orders to Fishbowl, Finale or Quickbooks. Then they sync those (more accurate) inventory figures back to able using automated server side API integrations.

Having an all-in-one solution that comprises complete inventory management while accommodating both eCommerce and accounting requirements isn’t a $1,500 program. It’s a $50,000 program.
sweeperq1766875  
#10 Posted : Monday, June 29, 2020 12:57:23 PM(UTC)
sweeperq1766875

Rank: Newbie

Groups: Authorized User, Developers
Joined: 5/30/2020(UTC)
Posts: 0

Quote:
I think you should update your code to follow this, and update the inventory when order items are shipped from order admin. If you have better approach to handle it, then we are open for ideas.


I don't mean to be rude, but based on your posts in this thread it doesn't seem like you are open to ideas. The idea provided was to have events for when order items are inserted, updated, or deleted. You keep repeating the same answer, and I keep telling you it does not work for our business case. It didn't seem like an unreasonable suggestion since you already have an event manager and are trying to build out your Zapier integration. Not sure if the your concern is performance, or you aren't understanding our business case and why we're requesting it... but the need is definitely there!

We accept backorders. Customers place orders. We handle hundreds of orders each day across multiple stores. Customers can call or email to edit orders at any time before or after shipment. Orders get held up for fraud and address checks. We don't want to promise a customer delivery of an item, then ship it to a more recent order because the first customer has a backorder hold for another item, or we put the first customer's order on hold to check an address.

Our order management/inventory system allows us to handle all of that by reserving inventory when an order is placed. These reservations/allotments need to be updated when an order is modified (edited, shipped, cancelled, or returned). Period. The allotment values need to be correct because the pick/pack functionality checks allotments to make sure not to over-pick or bumping anyone that ordered first but may be on hold.

Your response was to essentially dumb down the functionality of our systems to ignore inventory allotments and use only the stock quantity field during shipping and returns. If that were good enough, we wouldn't need an inventory system, we'd just use AbleCommerce. We did that over a decade ago in our company's early stages and it didn't work for us. AC's inventory management is not robust enough.

There are a few open source shopping carts that provide Insert/Update/Delete event hooks for all business object/entity types. I provided another developer links to the repositories via BaseCamp so he could see how it was done in a generic manner which didn't require coding up custom events for everything.

We really like AbleCommerce. Having the ability to customize source code to meet our business needs has been extremely helpful over the years. But customizing source has also made it so that it is very difficult to apply patches and upgrade. With AC9's revamped plug-in system and Zapier integration, I thought it was worth bringing up suggestions for improving the flexibility.
sweeperq1766875  
#11 Posted : Monday, June 29, 2020 1:15:55 PM(UTC)
sweeperq1766875

Rank: Newbie

Groups: Authorized User, Developers
Joined: 5/30/2020(UTC)
Posts: 0

Quote:
Having an all-in-one solution that comprises complete inventory management while accommodating both eCommerce and accounting requirements isn’t a $1,500 program. It’s a $50,000 program.


Joe, completely understand... and $50k might be generous :)

Fortunately, we're not looking for AbleCommerce to provide all of that functionality. All we requested was 3 events for easier tie-ins with 3rd party systems.

There are a couple of other free open-source alternatives that provide these events. I could have probably written a plug-in for one of them with less effort than I've put into this thread, but shaping 15 years worth of data would require extensive effort.

The framework is already in place with the AC event manager. I don't know if the concern is performance, or our business case is unique and not worth the effort.

I will likely end up creating a base code repository with the original AC9 source, then go in an edit the Admin controllers like I've always done. When patches are release it will just take some effort with merging changes.
Joe Payne @ AbleMods LLC  
#12 Posted : Monday, June 29, 2020 1:57:48 PM(UTC)
Joe Payne @ AbleMods LLC

Rank: Advanced Member

Groups: Developers
Joined: 11/9/2018(UTC)
Posts: 84

Thanks: 11 times
Was thanked: 5 time(s) in 5 post(s)
Since Able already has the logic for allocating/de-allocating stock, why not just roll your own events in default event manager and hook them to the OrderItem class object via overrides of BeforeSave() or AfterSave() in the respective repository? You can identify if it's an add or edit simply by checking the entity Id. A value = 0 means the entity is a new instance while anything > 0 would be an edit.
sweeperq1766875  
#13 Posted : Monday, June 29, 2020 2:55:14 PM(UTC)
sweeperq1766875

Rank: Newbie

Groups: Authorized User, Developers
Joined: 5/30/2020(UTC)
Posts: 0

To be sure I'm understanding...

Are you suggesting I create a custom order item repository by inheriting from OrderItemRepository, override the BeforeSave() and BeforeDelete() methods, then register my repository as the default with the IoC container using AppData\Windsor.config? That makes some sense because I could then trigger whatever code I want on save and delete.

This may indeed work for us. The concerns with this approach I can think of:

1. Does AC only manipulate OrderItems via this repository? Or does it also cascade nested changes that won't be captured via OrderRepository, BasketRepository, etc?

2. A 3rd party makes an awesome accounting, shipping, or tax plug-in utilizing a custom order item repository. Now we are forced to choose between features because only one repository can be used.

The tax plug-in piece is not really hypothetical. Similar to inventory, we had to roll out tax features because Avalara plug-in does not handle order edits and the Recalculate Taxes button does not work. We will likely make use of Avalara's new API methods to submit tax document amendments. We probably won't link the amendments directly to order item changes, but will still need to mark the order as modified and in need of recalculation.
Joe Payne @ AbleMods LLC  
#14 Posted : Monday, June 29, 2020 4:00:19 PM(UTC)
Joe Payne @ AbleMods LLC

Rank: Advanced Member

Groups: Developers
Joined: 11/9/2018(UTC)
Posts: 84

Thanks: 11 times
Was thanked: 5 time(s) in 5 post(s)
Yes Able goes through the repo for all DAL behaviors.

As far as inheriting from OrderItemRepository, from what I understand, the answer is yes. Except you wouldn't register your repo as the default. You'd simply register it as another repo using the RegisterFor decorator and call base.BeforeSave() or base.AfterSave() at the end of your code in your own class. From what I understand, all containers registered as IOC containers get called. So (theoretically) you could register 15 IOC containers all inheriting from the OrderItem repo and they would all get called because they're all registered with the decorator. You just can't control the sequence in which each one is called which obviously creates a few (or more) concerns.

Mazhar could probably clarify that for you better than I, I don't go this route when I code heavy customizations.

My projects all have full source, so I just modify existing Able class files using comments to make merges easy with future updates and recompile the CommerceBuilder project. Much faster, much easier that way. Of course when possible, I always put my custom classes in a separate folder, but still always a part of the CommerceBuilder project. Sometimes my code uses an Able namespace, sometimes I use my own.

Often I need to modify existing behavior rather than extend it, so modifying Able source is the most time-effective approach. YMMV.

If you're trying to do all of this via the plug-in system, I'm the wrong guy to help. I have yet to figure out how to make even a simple plugin work with the new plugin system mostly due to my inexperience with MVC.

Naveed Ashraf  
#15 Posted : Tuesday, June 30, 2020 6:29:02 AM(UTC)
Naveed Ashraf

Rank: Advanced Member

Groups: Admin, Administrators, Developers, Registered, HelpDesk, Authorized User
Joined: 7/31/2019(UTC)
Posts: 49

Was thanked: 3 time(s) in 3 post(s)
Hi,

Quote:
The framework is already in place with the AC event manager. I don't know if the concern is performance, or our business case is unique and not worth the effort.


Thanks for posting the details about your use cases. No, its not the case that your business case is unique, I just wanted to get more detailed requirements to understand it properly.


About the Joe's Comment:
Quote:
Since Able already has the logic for allocating/de-allocating stock, why not just roll your own events in default event manager and hook them to the OrderItem class object via overrides of BeforeSave() or AfterSave() in the respective repository? You can identify if it's an add or edit simply by checking the entity Id. A value = 0 means the entity is a new instance while anything > 0 would be an edit.


If you have the source code, new events for "OrderItemAdded", "OrderItemRemoved" can be easily added to our event manager, and can be triggered from AfterSave() function in OrderItemRepository. You can check there if the order item is added by merchant user, and its not a new order, and whatever conditions that meet your requirements.

Quote:
1. Does AC only manipulate OrderItems via this repository? Or does it also cascade nested changes that won't be captured via OrderRepository, BasketRepository, etc?


All database related changes will go through our respective Repository classes.

Now lets get back to original requirements.

Quote:
We accept backorders. Customers place orders. We handle hundreds of orders each day across multiple stores. Customers can call or email to edit orders at any time before or after shipment. Orders get held up for fraud and address checks. We don't want to promise a customer delivery of an item, then ship it to a more recent order because the first customer has a backorder hold for another item, or we put the first customer's order on hold to check an address.


You are right that our inventory system do not support up to this level. An inventory reservation feature is required for this, and we want to investigate and implement this. I think it can still be implemented as a Plugin and I will like get more feedback on this.


Thanks for all your feedback.
Naveed Ashraf  
#16 Posted : Wednesday, July 8, 2020 8:22:21 AM(UTC)
Naveed Ashraf

Rank: Advanced Member

Groups: Admin, Administrators, Developers, Registered, HelpDesk, Authorized User
Joined: 7/31/2019(UTC)
Posts: 49

Was thanked: 3 time(s) in 3 post(s)
Here is some sample code that demonstrates that how you can override the OrderItemRepository class to inject your own logic. For example triggering your own custom events:
Code:

    using CommerceBuilder.DomainModel;
    using CommerceBuilder.Orders;
    using Common;
    using Eventing;
    using Extensions;
    using NHibernate;
    using Utility;

    /// <summary>
    /// This class provides repository functionality for the OrderItem
    /// </summary>
    [RegisterFor(typeof(IOrderItemRepository))]
    [RegisterFor(typeof(IRepository<OrderItem>))]
    public class CustomOrderItemRepository : CommerceBuilder.Orders.OrderItemRepository
    {
        /// <inheritdoc />
        public override void BeforeSave(object entity)
        {
            OrderItem item = (OrderItem)entity;
            base.BeforeSave(item);

            // issue order item events only if the order is placed more then 10 seconds ago
            // this is to avoid order creation time save updates
            // also check for order item type for which we should trigger this event
            if (!item.Order.IsTransient() && item.Order.OrderDate < LocaleHelper.LocalNow.AddSeconds(-10)
                && item.OrderItemType == OrderItemType.Product)
            {
                ISession session = AbleContext.Current.Database.GetSession();
                bool isTransiant = item.IsTransient();
                
                // trigger the new product added/updated events as required
                if (isTransiant) CustomStoreEventEngine.OrderItemAdded(item);
                else if (AbleContext.Current.Database.GetSession().IsDirtyEntity(entity)) CustomStoreEventEngine.OrderItemUpdated(item);
            }
        }
        
        /// <inheritdoc />
        public override void AfterDelete(object entity)
        {
            base.AfterDelete(entity);

            // issue order item events only if the order is placed more then 10 seconds ago
            // this is to avoid order creation time save updates
            // also check for order item types settings for order item types for which we should trigger this event
            OrderItem item = (OrderItem)entity;
            if (!item.Order.IsTransient() && item.Order.OrderDate < LocaleHelper.LocalNow.AddSeconds(-10)
                && item.OrderItemType == OrderItemType.Product)
            {                
                int quantity = item.Quantity;
                decimal price = item.Price;

                CustomStoreEventEngine.OrderItemRemoved(item);
            }
        }
    }
Users browsing this topic
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.