Multi Vendor Inventory and Rental Bookings in Magento 2
Tags: rental, calendar, magento2, multivendor
Published: 2022-04-19 09:16:23

### 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](https://rentalbookingsoftware.com/multi-source-inventory-warehouses-and-multi-store-magento-2-vs-woocommerce/) 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>
```

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](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/async-operations.html). 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();
    }
```

### 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>
```
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;
            }
        }
    }
```

### 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>
```

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);
        }
    }
```

### Further Information
For further information about [multi vendor and multi store setups with rental bookings](https://rentalbookingsoftware.com) please visit our web site.