Exemplo n.º 1
0
 /**
  * Edit coupons
  * @param   \Cx\Core\Html\Sigma   $objTemplate    The Template
  */
 static function edit($objTemplate)
 {
     global $_ARRAYLANG;
     //DBG::activate(DBG_ADODB|DBG_LOG_FIREPHP|DBG_PHP);
     $result = true;
     if (isset($_GET['delete'])) {
         list($code, $customer_id) = explode('-', $_GET['delete']);
         $result &= self::delete(contrexx_input2raw($code), intval($customer_id));
     }
     $edit = isset($_REQUEST['edit']) ? contrexx_input2raw($_REQUEST['edit']) : null;
     //DBG::log("Edit: ".($edit ? $edit : 'NULL'));
     $code = isset($_POST['code']) ? contrexx_input2raw($_POST['code']) : null;
     $payment_id = empty($_POST['payment_id']) ? 0 : intval($_POST['payment_id']);
     $start_time = empty($_POST['start_date']) ? 0 : strtotime(contrexx_input2raw($_POST['start_date']));
     $end_time = empty($_POST['end_date_unlimited']) ? empty($_POST['end_date']) ? 0 : strtotime(contrexx_input2raw($_POST['end_date'])) : 0;
     $coupon_type = empty($_POST['coupon_type']) ? null : contrexx_input2raw($_POST['coupon_type']);
     $discount_rate = intval(empty($_POST['discount_rate']) ? 0 : floatval($_POST['discount_rate']));
     $discount_amount = Currency::formatPrice(empty($_POST['discount_amount']) ? 0 : floatval($_POST['discount_amount']));
     if ($coupon_type == 'rate') {
         $discount_amount = 0;
     }
     if ($coupon_type == 'amount') {
         $discount_rate = 0;
     }
     $minimum_amount = Currency::formatPrice(empty($_POST['minimum_amount']) ? 0 : floatval($_POST['minimum_amount']));
     $uses = empty($_POST['unlimited']) ? empty($_POST['uses']) ? 1 : intval($_POST['uses']) : self::USES_UNLIMITED;
     $customer_id = empty($_POST['customer_id']) ? 0 : intval($_POST['customer_id']);
     $product_id = empty($_POST['product_id']) ? 0 : intval($_POST['product_id']);
     $global = !empty($_POST['global_or_customer']);
     //DBG::log("code $code, start_time $start_time, end_time $end_time, minimum amount $minimum_amount, discount_rate $discount_rate, discount_amount $discount_amount, uses $uses, customer_id $customer_id");
     if (isset($code)) {
         $result &= self::storeCode($code, $payment_id, $minimum_amount, $discount_rate, $discount_amount, $start_time, $end_time, $uses, $global, $customer_id, $product_id, $edit);
         if ($result) {
             $code = $edit = null;
         } else {
             if (empty($edit)) {
                 $edit = "{$code}-{$customer_id}";
             }
         }
     }
     // Reset the end time if it's in the past
     if ($end_time < time()) {
         $end_time = 0;
     }
     $uri = \Html::getRelativeUri();
     \Html::stripUriParam($uri, 'view');
     \Html::stripUriParam($uri, 'edit');
     \Html::stripUriParam($uri, 'order_coupon');
     $arrSortingFields = array('code' => $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_CODE'], 'start_time' => $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_START_TIME'], 'end_time' => $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_END_TIME'], 'minimum_amount' => sprintf($_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_MINIMUM_AMOUNT_FORMAT'], Currency::getDefaultCurrencyCode()), 'discount_rate' => $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_RATE'], 'discount_amount' => sprintf($_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_AMOUNT_FORMAT'], Currency::getDefaultCurrencyCode()), 'uses' => $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_USES'], 'global' => $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_SCOPE'], 'customer_id' => $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_CUSTOMER'], 'product_id' => $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_PRODUCT'], 'payment_id' => $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_PAYMENT']);
     $objSorting = new \Sorting($uri, $arrSortingFields, true, 'order_coupon');
     $objTemplate->setGlobalVariable($_ARRAYLANG + array('TXT_SHOP_DISCOUNT_COUPON_MINIMUM_AMOUNT_CURRENCY' => sprintf($_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_MINIMUM_AMOUNT_FORMAT'], Currency::getDefaultCurrencyCode()), 'TXT_SHOP_DISCOUNT_COUPON_AMOUNT_CURRENCY' => sprintf($_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_AMOUNT_FORMAT'], Currency::getDefaultCurrencyCode()), 'TXT_SHOP_DISCOUNT_COUPON_ADD_OR_EDIT' => $_ARRAYLANG[$edit ? 'TXT_SHOP_DISCOUNT_COUPON_EDIT' : 'TXT_SHOP_DISCOUNT_COUPON_ADD'], 'SHOP_DISCOUNT_COUPON_VIEW_ACTIVE' => $edit ? '' : 'active', 'SHOP_DISCOUNT_COUPON_EDIT_ACTIVE' => $edit ? 'active' : '', 'SHOP_DISCOUNT_COUPON_VIEW_DISPLAY' => $edit ? 'none' : 'block', 'SHOP_DISCOUNT_COUPON_EDIT_DISPLAY' => $edit ? 'block' : 'none', 'HEADER_SHOP_DISCOUNT_COUPON_CODE' => $objSorting->getHeaderForField('code'), 'HEADER_SHOP_DISCOUNT_COUPON_START_TIME' => $objSorting->getHeaderForField('start_time'), 'HEADER_SHOP_DISCOUNT_COUPON_END_TIME' => $objSorting->getHeaderForField('end_time'), 'HEADER_SHOP_DISCOUNT_COUPON_MINIMUM_AMOUNT_CURRENCY' => $objSorting->getHeaderForField('minimum_amount'), 'HEADER_SHOP_DISCOUNT_COUPON_RATE' => $objSorting->getHeaderForField('discount_rate'), 'HEADER_SHOP_DISCOUNT_COUPON_AMOUNT_CURRENCY' => $objSorting->getHeaderForField('discount_amount'), 'HEADER_SHOP_DISCOUNT_COUPON_USES' => $objSorting->getHeaderForField('uses'), 'HEADER_SHOP_DISCOUNT_COUPON_SCOPE' => $objSorting->getHeaderForField('global'), 'HEADER_SHOP_DISCOUNT_COUPON_CUSTOMER' => $objSorting->getHeaderForField('customer_id'), 'HEADER_SHOP_DISCOUNT_COUPON_PRODUCT' => $objSorting->getHeaderForField('product_id'), 'HEADER_SHOP_DISCOUNT_COUPON_PAYMENT' => $objSorting->getHeaderForField('payment_id')));
     $count = 0;
     $limit = \Cx\Core\Setting\Controller\Setting::getValue('numof_coupon_per_page_backend', 'Shop');
     if (empty($limit)) {
         self::errorHandler();
     }
     $arrCoupons = self::getArray(\Paging::getPosition(), $limit, $count, $objSorting->getOrder());
     $arrProductName = Products::getNameArray(true, $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_PRODUCT_FORMAT']);
     $arrPaymentName = Payment::getNameArray();
     $i = 0;
     $row = 0;
     $objCouponEdit = new Coupon();
     $objCouponEdit->code($code);
     $objCouponEdit->payment_id($payment_id);
     $objCouponEdit->minimum_amount($minimum_amount);
     $objCouponEdit->discount_rate($discount_rate);
     $objCouponEdit->discount_amount($discount_amount);
     $objCouponEdit->start_time($start_time);
     $objCouponEdit->end_time($end_time);
     $objCouponEdit->uses($uses);
     $objCouponEdit->is_global($global);
     $objCouponEdit->customer_id($customer_id);
     $objCouponEdit->product_id($product_id);
     global $_CONFIG;
     foreach ($arrCoupons as $index => $objCoupon) {
         $coupon_uri_id = 'coupon_uri_' . $index;
         $objTemplate->setVariable(array('SHOP_ROWCLASS' => 'row' . (++$row % 2 + 1), 'SHOP_DISCOUNT_COUPON_CODE' => $objCoupon->code, 'SHOP_DISCOUNT_COUPON_URI_ICON' => '<div class="icon_url"' . '>&nbsp;</div>', 'SHOP_DISCOUNT_COUPON_URI_INPUT' => '<div class="layer_url" id="' . $coupon_uri_id . '">' . \Html::getInputText('dummy', 'http://' . $_CONFIG['domainUrl'] . \Cx\Core\Core\Controller\Cx::instanciate()->getWebsiteOffsetPath() . '/' . CONTREXX_DIRECTORY_INDEX . '?section=Shop' . MODULE_INDEX . '&coupon_code=' . $objCoupon->code, false, 'readonly="readonly"' . ' style="width: 200px;"' . ' onfocus="this.select();"' . ' onblur="cx.jQuery(\'#' . $coupon_uri_id . '\').hide();"') . '</div>', 'SHOP_DISCOUNT_COUPON_START_TIME' => $objCoupon->start_time ? date(ASCMS_DATE_FORMAT_DATE, $objCoupon->start_time) : $_ARRAYLANG['TXT_SHOP_DATE_NONE'], 'SHOP_DISCOUNT_COUPON_END_TIME' => $objCoupon->end_time ? date(ASCMS_DATE_FORMAT_DATE, $objCoupon->end_time) : $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_END_TIME_UNLIMITED'], 'SHOP_DISCOUNT_COUPON_MINIMUM_AMOUNT' => $objCoupon->minimum_amount > 0 ? $objCoupon->minimum_amount : $_ARRAYLANG['TXT_SHOP_AMOUNT_NONE'], 'SHOP_DISCOUNT_COUPON_RATE' => $objCoupon->discount_rate > 0 ? $objCoupon->discount_rate : $_ARRAYLANG['TXT_SHOP_RATE_NONE'], 'SHOP_DISCOUNT_COUPON_AMOUNT' => $objCoupon->discount_amount > 0 ? $objCoupon->discount_amount : $_ARRAYLANG['TXT_SHOP_AMOUNT_NONE'], 'SHOP_DISCOUNT_COUPON_USES' => sprintf($_ARRAYLANG['TXT_SHOP_COUPON_USES_FORMAT'], $objCoupon->used, $objCoupon->uses < 1000000000.0 ? $objCoupon->uses : $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_USES_UNLIMITED']), 'SHOP_DISCOUNT_COUPON_SCOPE' => $objCoupon->global ? $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_GLOBALLY'] : $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_PER_CUSTOMER'], 'SHOP_DISCOUNT_COUPON_PER_CUSTOMER' => !$objCoupon->global ? \Html::getRadio('foo_' . ++$i, '', false, true, '', \Html::ATTRIBUTE_DISABLED) : '&nbsp;', 'SHOP_DISCOUNT_COUPON_CUSTOMER' => $objCoupon->customer_id ? Customers::getNameById($objCoupon->customer_id, '%4$s (%3$u)') : $_ARRAYLANG['TXT_SHOP_CUSTOMER_ANY'], 'SHOP_DISCOUNT_COUPON_PRODUCT' => $objCoupon->product_id ? isset($arrProductName[$objCoupon->product_id]) ? $arrProductName[$objCoupon->product_id] : $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_PRODUCT_INVALID'] : $_ARRAYLANG['TXT_SHOP_PRODUCT_ANY'], 'SHOP_DISCOUNT_COUPON_PAYMENT' => $objCoupon->payment_id ? sprintf($_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_PAYMENT_FORMAT'], $objCoupon->payment_id, $arrPaymentName[$objCoupon->payment_id]) : $_ARRAYLANG['TXT_SHOP_PAYMENT_ANY'], 'SHOP_DISCOUNT_COUPON_FUNCTIONS' => \Html::getBackendFunctions(array('edit' => ADMIN_SCRIPT_PATH . '?cmd=Shop&amp;act=settings&amp;tpl=coupon&amp;edit=' . urlencode($index), 'delete' => "javascript:delete_coupon('" . urlencode($index) . "');"))));
         $objTemplate->parse('shopDiscountCouponView');
         if ($index === $edit) {
             $objCouponEdit = $objCoupon;
         }
     }
     $objTemplate->replaceBlock('shopDiscountCouponView', '', true);
     $paging = \Paging::get($uri, $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_CODES'], $count, $limit);
     //DBG::log("Paging: $paging");
     $objTemplate->setVariable('SHOP_PAGING', $paging);
     $attribute_code = 'style="width: 230px; text-align: left;" maxlength="20"';
     $attribute_time = 'style="width: 230px; text-align: left;" maxlength="10"';
     $attribute_discount_rate = 'style="width: 230px; text-align: right;" maxlength="3"';
     $attribute_discount_amount = 'style="width: 230px; text-align: right;" maxlength="9"';
     $attribute_minimum_amount = 'style="width: 230px; text-align: right;" maxlength="9"';
     $attribute_uses = 'style="width: 230px; text-align: right;" maxlength="6"';
     // Superseded by the widget, see below
     //        $attribute_customer = 'style="width: 230px;"';
     $attribute_product = 'style="width: 230px;"';
     $attribute_payment = 'style="width: 230px;"';
     $type = $objCouponEdit->discount_rate > 0 ? 'rate' : 'amount';
     $customer_name = '';
     //reset the add view
     if (!$edit) {
         $objCouponEdit = new Coupon();
     }
     if ($objCouponEdit->customer_id) {
         $customer_name = Customers::getNameById($objCouponEdit->customer_id, '%4$s (%3$u)');
         //DBG::log("Customer ID ".$objCouponEdit->customer_id.": name $customer_name");
     }
     $objTemplate->setVariable(array('SHOP_ROWCLASS' => 'row' . (++$row % 2 + 1), 'SHOP_DISCOUNT_COUPON_INDEX' => $objCouponEdit->getIndex(), 'SHOP_DISCOUNT_COUPON_CODE' => \Html::getInputText('code', $objCouponEdit->code, '', $attribute_code), 'SHOP_DISCOUNT_COUPON_CODE_CREATE' => \Html::getInputButton('code_create', $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_CODE_NEW'], 'button', false, 'onclick="cx.jQuery(\'#code\').val(\'' . Coupon::getNewCode() . '\');' . 'cx.jQuery(this).css(\'display\', \'none\');"'), 'SHOP_DISCOUNT_COUPON_START_TIME' => \Html::getDatepicker('start_date', array('defaultDate' => date(ASCMS_DATE_FORMAT_DATE, $objCouponEdit->start_time ? $objCouponEdit->start_time : time())), $attribute_time), 'SHOP_DISCOUNT_COUPON_END_TIME' => \Html::getDatepicker('end_date', array('defaultDate' => $objCouponEdit->end_time ? date(ASCMS_DATE_FORMAT_DATE, $objCouponEdit->end_time) : ''), $attribute_time), 'SHOP_DISCOUNT_COUPON_END_TIME_UNLIMITED' => \Html::getCheckbox('end_time_unlimited', 1, '', $objCouponEdit->end_time ? '' : \Html::ATTRIBUTE_CHECKED) . \Html::getLabel('end_time_unlimited', $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_END_TIME_UNLIMITED']), 'SHOP_DISCOUNT_COUPON_MINIMUM_AMOUNT' => \Html::getInputText('minimum_amount', $objCouponEdit->minimum_amount, false, $attribute_minimum_amount), 'SHOP_DISCOUNT_COUPON_TYPE' => \Html::getRadioGroup('coupon_type', array('rate' => $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_TYPE_RATE'], 'amount' => $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_TYPE_AMOUNT']), $type), 'SHOP_DISCOUNT_COUPON_TYPE_SELECTED' => $type, 'SHOP_DISCOUNT_COUPON_RATE' => \Html::getInputText('discount_rate', $objCouponEdit->discount_rate, false, $attribute_discount_rate), 'SHOP_DISCOUNT_COUPON_AMOUNT' => \Html::getInputText('discount_amount', number_format($objCouponEdit->discount_amount, 2, '.', ''), false, $attribute_discount_amount), 'SHOP_DISCOUNT_COUPON_USES' => \Html::getInputText('uses', $objCouponEdit->uses < 1000000000.0 ? $objCouponEdit->uses : '', 'uses', $attribute_uses), 'SHOP_DISCOUNT_COUPON_USES_UNLIMITED' => \Html::getCheckbox('unlimited', 1, 'unlimited', $objCouponEdit->uses > 1000000000.0) . \Html::getLabel('unlimited', $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_USES_UNLIMITED']), 'SHOP_DISCOUNT_COUPON_GLOBALLY' => \Html::getRadio('global_or_customer', '1', 'global', $objCouponEdit->global) . \Html::getLabel('global', $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_GLOBALLY']), 'SHOP_DISCOUNT_COUPON_PER_CUSTOMER' => \Html::getRadio('global_or_customer', '0', 'customer', !$objCouponEdit->global) . \Html::getLabel('customer', $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_PER_CUSTOMER']), 'SHOP_DISCOUNT_COUPON_CUSTOMER_ID' => $objCouponEdit->customer_id, 'SHOP_DISCOUNT_COUPON_CUSTOMER_NAME' => $customer_name, 'SHOP_DISCOUNT_COUPON_PRODUCT' => \Html::getSelect('product_id', array(0 => $_ARRAYLANG['TXT_SHOP_PRODUCT_ANY']) + $arrProductName, $objCouponEdit->product_id, false, '', $attribute_product), 'SHOP_DISCOUNT_COUPON_PAYMENT' => \Html::getSelect('payment_id', array(0 => $_ARRAYLANG['TXT_SHOP_PAYMENT_ANY']) + $arrPaymentName, $objCouponEdit->payment_id, false, '', $attribute_payment), 'SHOP_DISCOUNT_COUPON_CUSTOMER_WIDGET_DISPLAY' => $objCouponEdit->global ? \Html::CSS_DISPLAY_NONE : \Html::CSS_DISPLAY_INLINE));
     $objTemplate->parse('shopDiscountCouponEdit');
     // Depends on, and thus implies loading jQuery as well!
     \FWUser::getUserLiveSearch(array('minLength' => 3, 'canCancel' => true, 'canClear' => true));
     return $result;
 }
Exemplo n.º 2
0
 /**
  * Returns an array with all placeholders and their values to be
  * replaced in any shop mailtemplate for the given order ID.
  *
  * You only have to set the 'substitution' index value of your MailTemplate
  * array to the array returned.
  * Customer data is not included here.  See {@see Customer::getSubstitutionArray()}.
  * Note that this method is now mostly independent of the current session.
  * The language of the mail template is determined by the browser
  * language range stored with the order.
  * @access  private
  * @static
  * @param   integer $order_id     The order ID
  * @param   boolean $create_accounts  If true, creates User accounts
  *                                    and Coupon codes.  Defaults to true
  * @return  array                 The array with placeholders as keys
  *                                and values from the order on success,
  *                                false otherwise
  */
 static function getSubstitutionArray($order_id, $create_accounts = true)
 {
     global $_ARRAYLANG;
     /*
                 $_ARRAYLANG['TXT_SHOP_URI_FOR_DOWNLOAD'].":\r\n".
                 'http://'.$_SERVER['SERVER_NAME'].
                 "/index.php?section=download\r\n";
     */
     $objOrder = Order::getById($order_id);
     if (!$objOrder) {
         // Order not found
         return false;
     }
     $lang_id = $objOrder->lang_id();
     if (!intval($lang_id)) {
         $lang_id = \FWLanguage::getLangIdByIso639_1($lang_id);
     }
     $status = $objOrder->status();
     $customer_id = $objOrder->customer_id();
     $customer = Customer::getById($customer_id);
     $payment_id = $objOrder->payment_id();
     $shipment_id = $objOrder->shipment_id();
     $arrSubstitution = array('CUSTOMER_COUNTRY_ID' => $objOrder->billing_country_id(), 'LANG_ID' => $lang_id, 'NOW' => date(ASCMS_DATE_FORMAT_DATETIME), 'TODAY' => date(ASCMS_DATE_FORMAT_DATE), 'ORDER_ID' => $order_id, 'ORDER_ID_CUSTOM' => ShopLibrary::getCustomOrderId($order_id), 'ORDER_DATE' => date(ASCMS_DATE_FORMAT_DATE, strtotime($objOrder->date_time())), 'ORDER_TIME' => date(ASCMS_DATE_FORMAT_TIME, strtotime($objOrder->date_time())), 'ORDER_STATUS_ID' => $status, 'ORDER_STATUS' => $_ARRAYLANG['TXT_SHOP_ORDER_STATUS_' . $status], 'MODIFIED' => date(ASCMS_DATE_FORMAT_DATETIME, strtotime($objOrder->modified_on())), 'REMARKS' => $objOrder->note(), 'ORDER_SUM' => sprintf('% 9.2f', $objOrder->sum()), 'CURRENCY' => Currency::getCodeById($objOrder->currency_id()));
     $arrSubstitution += $customer->getSubstitutionArray();
     if ($shipment_id) {
         $arrSubstitution += array('SHIPMENT' => array(0 => array('SHIPMENT_NAME' => sprintf('%-40s', Shipment::getShipperName($shipment_id)), 'SHIPMENT_PRICE' => sprintf('% 9.2f', $objOrder->shipment_amount()))), 'SHIPPING_ADDRESS' => array(0 => array('SHIPPING_COMPANY' => $objOrder->company(), 'SHIPPING_TITLE' => $_ARRAYLANG['TXT_SHOP_' . strtoupper($objOrder->gender())], 'SHIPPING_FIRSTNAME' => $objOrder->firstname(), 'SHIPPING_LASTNAME' => $objOrder->lastname(), 'SHIPPING_ADDRESS' => $objOrder->address(), 'SHIPPING_ZIP' => $objOrder->zip(), 'SHIPPING_CITY' => $objOrder->city(), 'SHIPPING_COUNTRY_ID' => $objOrder->country_id(), 'SHIPPING_COUNTRY' => \Cx\Core\Country\Controller\Country::getNameById($objOrder->country_id()), 'SHIPPING_PHONE' => $objOrder->phone())));
     }
     if ($payment_id) {
         $arrSubstitution += array('PAYMENT' => array(0 => array('PAYMENT_NAME' => sprintf('%-40s', Payment::getNameById($payment_id)), 'PAYMENT_PRICE' => sprintf('% 9.2f', $objOrder->payment_amount()))));
     }
     $arrItems = $objOrder->getItems();
     if (!$arrItems) {
         \Message::warning($_ARRAYLANG['TXT_SHOP_ORDER_WARNING_NO_ITEM']);
     }
     // Deduct Coupon discounts, either from each Product price, or
     // from the items total.  Mind that the Coupon has already been
     // stored with the Order, but not redeemed yet.  This is done
     // in this method, but only if $create_accounts is true.
     $coupon_code = NULL;
     $coupon_amount = 0;
     $objCoupon = Coupon::getByOrderId($order_id);
     if ($objCoupon) {
         $coupon_code = $objCoupon->code();
     }
     $orderItemCount = 0;
     $total_item_price = 0;
     // Suppress Coupon messages (see Coupon::available())
     \Message::save();
     foreach ($arrItems as $item) {
         $product_id = $item['product_id'];
         $objProduct = Product::getById($product_id);
         if (!$objProduct) {
             //die("Product ID $product_id not found");
             continue;
         }
         //DBG::log("Orders::getSubstitutionArray(): Item: Product ID $product_id");
         $product_name = substr($item['name'], 0, 40);
         $item_price = $item['price'];
         $quantity = $item['quantity'];
         // TODO: Add individual VAT rates for Products
         //            $orderItemVatPercent = $objResultItem->fields['vat_percent'];
         // Decrease the Product stock count,
         // applies to "real", shipped goods only
         $objProduct->decreaseStock($quantity);
         $product_code = $objProduct->code();
         // Pick the order items attributes
         $str_options = '';
         // Any attributes?
         if ($item['attributes']) {
             $str_options = '  ';
             // '[';
             $attribute_name_previous = '';
             foreach ($item['attributes'] as $attribute_name => $arrAttribute) {
                 //DBG::log("Attribute /$attribute_name/ => ".var_export($arrAttribute, true));
                 // NOTE: The option price is optional and may be left out
                 foreach ($arrAttribute as $arrOption) {
                     $option_name = $arrOption['name'];
                     $option_price = $arrOption['price'];
                     $item_price += $option_price;
                     // Recognize the names of uploaded files,
                     // verify their presence and use the original name
                     $option_name_stripped = ShopLibrary::stripUniqidFromFilename($option_name);
                     $path = Order::UPLOAD_FOLDER . $option_name;
                     if ($option_name != $option_name_stripped && \File::exists($path)) {
                         $option_name = $option_name_stripped;
                     }
                     if ($attribute_name != $attribute_name_previous) {
                         if ($attribute_name_previous) {
                             $str_options .= '; ';
                         }
                         $str_options .= $attribute_name . ': ' . $option_name;
                         $attribute_name_previous = $attribute_name;
                     } else {
                         $str_options .= ', ' . $option_name;
                     }
                     // TODO: Add proper formatting with sprintf() and language entries
                     if ($option_price != 0) {
                         $str_options .= ' ' . Currency::formatPrice($option_price) . ' ' . Currency::getActiveCurrencyCode();
                     }
                 }
             }
             //                $str_options .= ']';
         }
         // Product details
         $arrProduct = array('PRODUCT_ID' => $product_id, 'PRODUCT_CODE' => $product_code, 'PRODUCT_QUANTITY' => $quantity, 'PRODUCT_TITLE' => $product_name, 'PRODUCT_OPTIONS' => $str_options, 'PRODUCT_ITEM_PRICE' => sprintf('% 9.2f', $item_price), 'PRODUCT_TOTAL_PRICE' => sprintf('% 9.2f', $item_price * $quantity));
         //DBG::log("Orders::getSubstitutionArray($order_id, $create_accounts): Adding article: ".var_export($arrProduct, true));
         $orderItemCount += $quantity;
         $total_item_price += $item_price * $quantity;
         if ($create_accounts) {
             // Add an account for every single instance of every Product
             for ($instance = 1; $instance <= $quantity; ++$instance) {
                 $validity = 0;
                 // Default to unlimited validity
                 // In case there are protected downloads in the cart,
                 // collect the group IDs
                 $arrUsergroupId = array();
                 if ($objProduct->distribution() == 'download') {
                     $usergroupIds = $objProduct->usergroup_ids();
                     if ($usergroupIds != '') {
                         $arrUsergroupId = explode(',', $usergroupIds);
                         $validity = $objProduct->weight();
                     }
                 }
                 // create an account that belongs to all collected
                 // user groups, if any.
                 if (count($arrUsergroupId) > 0) {
                     // The login names are created separately for
                     // each product instance
                     $username = self::usernamePrefix . "_{$order_id}_{$product_id}_{$instance}";
                     $userEmail = $username . '-' . $arrSubstitution['CUSTOMER_EMAIL'];
                     $userpass = \User::make_password();
                     $objUser = new \User();
                     $objUser->setUsername($username);
                     $objUser->setPassword($userpass);
                     $objUser->setEmail($userEmail);
                     $objUser->setAdminStatus(false);
                     $objUser->setActiveStatus(true);
                     $objUser->setGroups($arrUsergroupId);
                     $objUser->setValidityTimePeriod($validity);
                     $objUser->setFrontendLanguage(FRONTEND_LANG_ID);
                     $objUser->setBackendLanguage(FRONTEND_LANG_ID);
                     $objUser->setProfile(array('firstname' => array(0 => $arrSubstitution['CUSTOMER_FIRSTNAME']), 'lastname' => array(0 => $arrSubstitution['CUSTOMER_LASTNAME']), 'company' => array(0 => $arrSubstitution['CUSTOMER_COMPANY']), 'address' => array(0 => $arrSubstitution['CUSTOMER_ADDRESS']), 'zip' => array(0 => $arrSubstitution['CUSTOMER_ZIP']), 'city' => array(0 => $arrSubstitution['CUSTOMER_CITY']), 'country' => array(0 => $arrSubstitution['CUSTOMER_COUNTRY_ID']), 'phone_office' => array(0 => $arrSubstitution['CUSTOMER_PHONE']), 'phone_fax' => array(0 => $arrSubstitution['CUSTOMER_FAX'])));
                     if (!$objUser->store()) {
                         \Message::error(implode('<br />', $objUser->getErrorMsg()));
                         return false;
                     }
                     if (empty($arrProduct['USER_DATA'])) {
                         $arrProduct['USER_DATA'] = array();
                     }
                     $arrProduct['USER_DATA'][] = array('USER_NAME' => $username, 'USER_PASS' => $userpass);
                 }
                 //echo("Instance $instance");
                 if ($objProduct->distribution() == 'coupon') {
                     if (empty($arrProduct['COUPON_DATA'])) {
                         $arrProduct['COUPON_DATA'] = array();
                     }
                     //DBG::log("Orders::getSubstitutionArray(): Getting code");
                     $code = Coupon::getNewCode();
                     //DBG::log("Orders::getSubstitutionArray(): Got code: $code, calling Coupon::addCode($code, 0, 0, 0, $item_price)");
                     Coupon::storeCode($code, 0, 0, 0, $item_price, 0, 0, 10000000000.0, true);
                     $arrProduct['COUPON_DATA'][] = array('COUPON_CODE' => $code);
                 }
             }
             // Redeem the *product* Coupon, if possible for the Product
             if ($coupon_code) {
                 $objCoupon = Coupon::available($coupon_code, $item_price * $quantity, $customer_id, $product_id, $payment_id);
                 if ($objCoupon) {
                     $coupon_code = NULL;
                     $coupon_amount = $objCoupon->getDiscountAmount($item_price, $customer_id);
                     if ($create_accounts) {
                         $objCoupon->redeem($order_id, $customer_id, $item_price * $quantity);
                     }
                 }
                 //\DBG::log("Orders::getSubstitutionArray(): Got Product Coupon $coupon_code");
             }
         }
         if (empty($arrSubstitution['ORDER_ITEM'])) {
             $arrSubstitution['ORDER_ITEM'] = array();
         }
         $arrSubstitution['ORDER_ITEM'][] = $arrProduct;
     }
     $arrSubstitution['ORDER_ITEM_SUM'] = sprintf('% 9.2f', $total_item_price);
     $arrSubstitution['ORDER_ITEM_COUNT'] = sprintf('% 4u', $orderItemCount);
     // Redeem the *global* Coupon, if possible for the Order
     if ($coupon_code) {
         $objCoupon = Coupon::available($coupon_code, $total_item_price, $customer_id, null, $payment_id);
         if ($objCoupon) {
             $coupon_amount = $objCoupon->getDiscountAmount($total_item_price, $customer_id);
             if ($create_accounts) {
                 $objCoupon->redeem($order_id, $customer_id, $total_item_price);
             }
         }
     }
     \Message::restore();
     // Fill in the Coupon block with proper discount and amount
     if ($objCoupon) {
         $coupon_code = $objCoupon->code();
         //\DBG::log("Orders::getSubstitutionArray(): Coupon $coupon_code, amount $coupon_amount");
     }
     if ($coupon_amount) {
         //\DBG::log("Orders::getSubstitutionArray(): Got Order Coupon $coupon_code");
         $arrSubstitution['DISCOUNT_COUPON'][] = array('DISCOUNT_COUPON_CODE' => sprintf('%-40s', $coupon_code), 'DISCOUNT_COUPON_AMOUNT' => sprintf('% 9.2f', -$coupon_amount));
     } else {
         //\DBG::log("Orders::getSubstitutionArray(): No Coupon for Order ID $order_id");
     }
     Products::deactivate_soldout();
     if (Vat::isEnabled()) {
         //DBG::log("Orders::getSubstitutionArray(): VAT amount: ".$objOrder->vat_amount());
         $arrSubstitution['VAT'] = array(0 => array('VAT_TEXT' => sprintf('%-40s', Vat::isIncluded() ? $_ARRAYLANG['TXT_SHOP_VAT_PREFIX_INCL'] : $_ARRAYLANG['TXT_SHOP_VAT_PREFIX_EXCL']), 'VAT_PRICE' => $objOrder->vat_amount()));
     }
     return $arrSubstitution;
 }