DEV Community

Sales Igniter
Sales Igniter

Posted on

Multi Vendor Inventory and Rental Bookings in Magento 2

What Multi Location Inventory Features Are Available in Magento

If you are comparing Magento 2 vs other open source shopping carts there really is no comparison if you need to have Multi Location or Multi Store features. The reason being that the next closest competitor WooCommerce does not have any sort of multi location or multi store feature built in. While WordPress does have multi site, this is not really feasible for WooCommerce multi store features for a number of reasons such as that it doesn't support store by store or location by location inventory syncing, it can't set product pricing by store, and the plugins that do exist for this cost extra nd since there is no standard for it you'll have issues if you ever want to integrate "plugins on top of plugins" as far as multi inventory is concerned. For a full breakdown of WooCommerce vs Magento 2 when it comes to multi store and multi inventory please check out our article.

How To Integrate Multi Location with Rentals

First you'll need to make a reservations table, and in this reservations table you'll want as a minimum to have the start date, end date, order item id, order id, and inventory source.

Here is what this would look like in your etc/db_schema.xml file:

<table name="sirental_reservationorders" resource="default" engine="innodb" comment="sirental_reservationorders">
    <column xsi:type="int" name="reservationorder_id" padding="10" unsigned="true" nullable="false" identity="true" comment="Reservationorder_id"/>
    <column xsi:type="int" name="order_id" padding="10" unsigned="true" nullable="false" identity="false" default="0"/>
    <column xsi:type="int" name="product_id" padding="11" unsigned="false" nullable="false" identity="false" comment="Product_id"/>
    <column xsi:type="int" name="qty" padding="11" unsigned="false" nullable="false" identity="false" comment="Qty"/>
    <column xsi:type="int" name="qty_cancel" padding="11" unsigned="false" nullable="false" identity="false" default="0" comment="Cancelled Quantity"/>
    <column xsi:type="int" name="order_item_id" padding="11" unsigned="false" nullable="true" identity="false" comment="Order_item_id"/>
    <column xsi:type="datetime" name="start_date" on_update="false" nullable="true" comment="Start_date"/>
    <column xsi:type="datetime" name="end_date" on_update="false" nullable="true" comment="End_date"/>
    <column  name="source_code"  comment="Inventory Source Code" xsi:type="text"/>
  </table>
Enter fullscreen mode Exit fullscreen mode

After that create the model, resourcemodel, and collection for this table. We recommend the https://mage2gen.com/ for generating the base code for that, and then customizing it after.

Finally you'll want to create a async style processor once the order is placed. Please checkout the official document for how to make async calls. Or you could also make this as a cron that runs periodicall to process the rental orders. Here is a sample using the cron method:

    public function updateIsReserved()
    {
        if ($this->stock->reserveInventoryWithoutOrderInvoiced()) {

            $this->searchCriteriaBuilder->addFilter('is_reserved', 0);
            $criteria = $this->searchCriteriaBuilder->create();
            $Orders = $this->orderRepository->getList($criteria)->getItems();

            foreach ($Orders as $order) {
                $this->emulation->startEnvironmentEmulation($order->getStoreId(), 'frontend');
                $this->stockManagement->reserveQuoteOrOrder($order);
                $order->setIsReserved(1);
                $order->save();
                $this->emulation->stopEnvironmentEmulation();
            }
        }
    }

    public function execute()
    {
        $this->updateIsReserved();
    }
Enter fullscreen mode Exit fullscreen mode

Integrating Multi Vendor with Multi Location Inventory and Rental Inventory

This involves making sure the admin rental inventory report is compatible with vendors, and that the vendors can only see their products.

Multi Vendor Commission Payouts

Vendors will usually be paid out using Stripe or Paypal, but the method can vary for how you pay them. The main methods are:

  • Pay based on a percentage of the order that is placed
  • Vendor pays a membership fee to list products on your web site
  • No payment, rather the site is monetized via advertising

Adding Rental Order Notes Based On The Vendor ID

This can be accomplished by using an Observer setup like this. First make a file at etc/events.xml with this code:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="sales_order_place_after">
    <observer name="purchaseorder_place_order_after" instance="SalesIgniter\Purchaserentals\Observer\PurchaseRentalsComment" />
</config>
Enter fullscreen mode Exit fullscreen mode

and then in the Model/Observer/PurchaseRentalsComment.php file you would have:

    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $order = $observer->getEvent()->getOrder();
        $orderitems = $order->getItems();
        foreach($orderitems as $item) {
            if ($item->getParentItem()) {
                $originalBuyRequest = $item->getParentItem()->getBuyRequest();
            } else {
                $originalBuyRequest = $item->getBuyRequest();
            }
            if($originalBuyRequest->getPurchaseRentals() != null){
                $originalOrder = $this->orderRepository->get($originalBuyRequest->getOriginalOrderid());
                $orignalOrderInc = $originalOrder->getIncrementId();
                $order->addCommentToStatusHistory('Rental Purchase for Order #: ' . $orignalOrderInc, $status = false, $isVisibleOnFront = true)->setIsCustomerNotified(false);
                break;
            }
        }
    }
Enter fullscreen mode Exit fullscreen mode

Preventing Deducting Inventory for Rentals

Since rentals are returned, you'll want to make sure that Magento 2 does not deduct inventory when orders are placed. You'll need to calculate your inventory instead using an inventory array built from the start and end dates. Here's how to prevent inventory deductions. Make a file at etc/di.xml and add this code:

    <type name="Magento\InventorySourceDeductionApi\Model\SourceDeductionService">
        <plugin name="prevent_source_deduction_for_rental" type="SalesIgniter\Rentalinventory\Plugin\InventorySourceDeductionApi\PreventStockDeductionForRentalPlugin" sortOrder="100"/>
    </type>
Enter fullscreen mode Exit fullscreen mode

Here is the code for the actual plugin at Plugin/PreventAppendReservationForRentalPlugin.php

    public function aroundExecute(AppendReservationsInterface $subject, \Closure $proceed, array $reservations)
    {
        if (!$this->stockConfiguration->canSubtractQty()) {
            return;
        }

        $reservationToAppend = [];
        foreach ($reservations as $reservation) {
            $stockItemConfiguration = $this->getStockItemConfiguration->execute(
                $reservation->getSku(),
                $reservation->getStockId()
            );

            // don't add inventory reservations for rental products
            if(!$this->rentalHelper->isRentalTypeSimple($this->productRepository->get($reservation->getSku()))){
                $reservationToAppend[] = $reservation;
            }
        }

        if (!empty($reservationToAppend)) {
            $proceed($reservationToAppend);
        }
    }
Enter fullscreen mode Exit fullscreen mode

Further Information

For further information about multi vendor and multi store setups with rental bookings please visit our web site.

Top comments (0)