/**
  * @param \Database_Result $records
  * @param string           $id
  * @param \DcaWizard       $dcaWizard
  *
  * @return string
  */
 public function generateWizardList($records, $id, $dcaWizard)
 {
     $return = '';
     $rows = $dcaWizard->getRows($records);
     // Alter the rows
     \System::loadLanguageFile('tl_iso_product_collection');
     $rows = array_map(function ($row) {
         // Force an algebraic sign for quantity
         $row['quantity'] = sprintf('%+d', $row['quantity']);
         // Make referenced product collection editable in a popup
         $row['product_collection_id'] = $row['product_collection_id'] ? sprintf('<a href="contao/main.php?do=iso_orders&amp;act=edit&amp;id=%1$u&amp;popup=1&amp;nb=1&amp;rt=%4$s" title="%3$s" onclick="Backend.openModalIframe({\'width\':768,\'title\':\'%3$s\',\'url\':this.href});return false">%2$s</a>', $row['product_collection_id'], \Image::getHtml('edit.gif') . $row['product_collection_id'], sprintf($GLOBALS['TL_LANG']['tl_iso_product_collection']['edit'][1], $row['product_collection_id']), REQUEST_TOKEN) : '-';
         return $row;
     }, $rows);
     if ($rows) {
         $template = new \BackendTemplate('be_widget_dcawizard');
         $template->headerFields = $dcaWizard->getHeaderFields();
         $template->hasRows = !empty($rows);
         $template->rows = $rows;
         $template->fields = $dcaWizard->fields;
         $template->showOperations = $dcaWizard->showOperations;
         if ($dcaWizard->showOperations) {
             $template->operations = $dcaWizard->getActiveRowOperations();
         }
         $template->generateOperation = function ($operation, $row) use($dcaWizard) {
             return $dcaWizard->generateRowOperation($operation, $row);
         };
         $dom = new \DOMDocument('1.0', 'utf-8');
         $dom->loadHTML($template->parse());
         $return = $dom->saveHTML($dom->getElementsByTagName('table')->item(0));
     }
     // Add the member's total bonus points
     $return .= sprintf('<strong style="display: inline-block; margin: 4px 0 2px 6px; border-bottom: 3px double">%s</strong>', Stock::getStockForProduct($dcaWizard->currentRecord));
     return $return;
 }
 /**
  * @category ISO_HOOKS: postCheckout
  *
  * @param ProductCollection\Order $order
  * @param array                   $tokens
  *
  */
 public function updateStockPostCheckout(ProductCollection\Order $order, array $tokens)
 {
     foreach ($order->getItems() as $item) {
         /** @var Product|\Model $product */
         $product = $item->getProduct();
         $productType = $product->getRelated('type');
         if ($productType->stockmanagement_active) {
             // Book stock change
             /** @var Stock|\Model $stockChange */
             $stockChange = new Stock();
             $stockChange->tstamp = time();
             $stockChange->pid = $product->id;
             $stockChange->product_collection_id = $order->id;
             $stockChange->quantity = -1 * (int) $item->quantity;
             $stockChange->source = Stock::STOCKMANAGEMENT_SOURCE_ORDER;
             $stockChange->save();
             // Fetch current stock
             $stock = Stock::getStockForProduct($product->id);
             // Disable product if necessary
             if ($productType->stockmanagement_disableProduct && false !== $stock && $stock < 1) {
                 $product->published = '';
                 $product->save();
             }
             // Send stock change notifications
             if ($productType->stockmanagement_notification) {
                 $notifications = deserialize($productType->stockmanagement_notifications);
                 foreach ($notifications as $notification) {
                     if ($stock <= $notification['threshold']) {
                         /** @noinspection PhpUndefinedMethodInspection */
                         /** @var Notification $notificationCenter */
                         $notificationCenter = Notification::findByPk($notification['nc_id']);
                         if (null !== $notificationCenter) {
                             $notificationCenter->send(self::createStockChangeNotifictionTokens($product, $order));
                         }
                         // Do not send multiple notifications
                         break;
                     }
                 }
             }
         }
     }
 }
<?php

/**
 * Isotope "simple stock management" for Contao Open Source CMS
 *
 * Copyright (c) 2016 Richard Henkenjohann
 *
 * @package Isotope
 * @author  Richard Henkenjohann <*****@*****.**>
 */
/**
 * Back end modules
 */
/** @noinspection PhpUndefinedMethodInspection */
$GLOBALS['BE_MOD']['isotope']['iso_products']['tables'][] = \Isotope\Model\Stock::getTable();
/**
 * Models
 */
/** @noinspection PhpUndefinedMethodInspection */
$GLOBALS['TL_MODELS'][Isotope\Model\Stock::getTable()] = 'Isotope\\Model\\Stock';
/**
 * Hooks
 */
$GLOBALS['ISO_HOOKS']['addProductToCollection'][] = ['Isotope\\SimpleStockmanagement\\Hooks', 'checkBeforeAddToCollection'];
$GLOBALS['ISO_HOOKS']['updateItemInCollection'][] = ['Isotope\\SimpleStockmanagement\\Hooks', 'checkBeforeUpdateCollection'];
$GLOBALS['ISO_HOOKS']['itemIsAvailable'][] = ['Isotope\\SimpleStockmanagement\\Hooks', 'checkItemIsAvailable'];
$GLOBALS['ISO_HOOKS']['preCheckout'][] = ['Isotope\\SimpleStockmanagement\\Hooks', 'checkBeforeCheckout'];
$GLOBALS['ISO_HOOKS']['postCheckout'][] = ['Isotope\\SimpleStockmanagement\\Hooks', 'updateStockPostCheckout'];
/**
 * Notification Center Notification Types
 */