Example #1
0
	private function commitProducts($orderId, $rawInput, $itemAddressMap, $editingExisting=false, $adjustInventory=true)
	{
		$orderId = (int)$orderId;
		if (!$orderId) {
			$this->setError("Invalid arguments passed to commitProducts");
			return false;
		}

		/** @var ISC_QUOTE */
		$quote = $rawInput['quote'];

		$existingOrder = false;
		$existingProducts = false;

		if ($editingExisting && $orderId) {
			$existingOrder = $this->get($orderId);
			if (!$existingOrder) {
				$this->setError("editingExisting specified in commitProducts but order " . $orderId . " not found");
				return false;
			}

			// prune products from the existing order which are no longer on the incoming edit (products tied to unused addresses should already be gone after commitAddresses())
			$this->deleteUnusedOrderProducts($orderId, $quote);

			$existingProducts = $this->getOrderProducts($orderId);
			$existingProducts = Interspire_Array::remapToSubkey($existingProducts, 'orderprodid'); // make existing products easier to find by id
		}

		$giftCertificates = array();
		foreach($quote->getItems() as /** @var ISC_QUOTE_ITEM */$item) {
			$itemType = 'physical';
			if($item->getType() == PT_DIGITAL) {
				$itemType = 'digital';
			}
			else if($item instanceof ISC_QUOTE_ITEM_GIFTCERTIFICATE) {
				// Gift certificates cannot be modified so continue if this is an existing order
				if($existingOrder) {
					continue;
				}
				$itemType = 'giftcertificate';
				$giftCertificates[] = $item;
			}

			$existingProduct = false;
			if (is_numeric($item->getId())) {
				// numeric quote_item id denotes existing order_product, but if it doesn't exist for some reason treat it as a new order_product I guess
				if (isset($existingProducts[$item->getId()])) {
					$existingProduct = $existingProducts[$item->getId()];
				}
			}

			// addresses are already stored in db and assigned real ids by commitAddresses()
			$addressId = 0;
			$itemAddressId = $item->getAddressId();
			if(isset($itemAddressMap[$itemAddressId])) {
				$addressId = $itemAddressMap[$itemAddressId];
			}

			$appliedDiscounts = $item->getDiscounts();
			if (empty($appliedDiscounts)) {
				$appliedDiscounts = '';
			} else {
				$appliedDiscounts = serialize($appliedDiscounts);
			}

			// build order_products data for upsert
			$newProduct = array(
				'orderorderid'				=> $orderId,
				'ordprodid'					=> $item->getProductId(),
				'ordprodsku'				=> $item->getSku(),
				'ordprodname'				=> $item->getName(),
				'ordprodtype'				=> $itemType,
				'ordprodqty'				=> $item->getQuantity(),

				'base_price'				=> $item->getBasePrice(),
				'price_ex_tax'				=> $item->getPrice(false),
				'price_inc_tax'				=> $item->getPrice(true),
				'price_tax'					=> $item->getTax(),

				'base_total'				=> $item->getBaseTotal(),
				'total_ex_tax'				=> $item->getTotal(false),
				'total_inc_tax'				=> $item->getTotal(true),
				'total_tax'					=> $item->getTaxTotal(),

				'base_cost_price'			=> $item->getBaseCostPrice(),
				'cost_price_inc_tax'		=> $item->getCostPrice(false),
				'cost_price_inc_tax'		=> $item->getCostPrice(true),
				'cost_price_tax'			=> $item->getCostPriceTax(),

				'ordprodweight'				=> $item->getWeight(),

				'ordprodoptions'			=> '',
				'ordprodvariationid'		=> $item->getVariationid(),

				'ordprodwrapid'				=> 0,
				'ordprodwrapname'			=> '',
				'base_wrapping_cost'		=> $item->getBaseWrappingCost(),
				'wrapping_cost_ex_tax'		=> $item->getWrappingCost(false),
				'wrapping_cost_inc_tax'		=> $item->getWrappingCost(true),
				'wrapping_cost_tax'			=> $item->getWrappingCost(true) - $item->getWrappingCost(false),
				'ordprodwrapmessage'		=> '',
				'ordprodeventname'			=> $item->getEventName(),
				'ordprodeventdate'			=> $item->getEventDate(true),
				'ordprodfixedshippingcost'	=> $item->getFixedShippingCost(),

				'order_address_id'			=> $addressId,

				'applied_discounts'			=> $appliedDiscounts,
			);

			$variationOptions = $item->getVariationOptions();
			if(!empty($variationOptions)) {
				$newProduct['ordprodoptions'] = serialize($variationOptions);
			}

			$wrapping = $item->getGiftWrapping();
			if(!empty($wrapping)) {
				$newProduct['ordprodwrapid'] = $wrapping['wrapid'];
				$newProduct['ordprodwrapname'] = $wrapping['wrapname'];
				$newProduct['ordprodwrapmessage'] = $wrapping['wrapmessage'];
			}

			// upsert to order_products
			if ($existingProduct) {
				if (!$this->db->UpdateQuery('order_products', $newProduct, "orderprodid = " . $existingProduct['orderprodid'])) {
					$this->setError("Failed to update existing order product");
					return false;
				}

				// remove existing configurable fields so they can be reinserted if needed
				$this->deleteOrderProductConfigurableFields($existingProduct['orderprodid']);
			} else {
				$orderProductId = $GLOBALS['ISC_CLASS_DB']->insertQuery('order_products', $newProduct);
				if(!$orderProductId) {
					$this->setError("Failed to insert new order product");
					return false;
				}
			}

			// adjust inventory levels for existing orders only (UpdateOrderStatus() seems to do it for new orders)
			if ($adjustInventory && $existingOrder && $existingOrder['ordinventoryupdated']) {
				$inventoryRequiresAdjustment = true;

				if ($existingProduct && $existingProduct['ordprodid']) {
					if ($existingProduct['ordprodid'] == $item->getProductId() && $existingProduct['ordprodvariationid'] == $item->getVariationId() && $existingProduct['ordprodqty'] == $item->getQuantity()) {
						// don't bother adjusting if the product, variation and qty details have not changed
						$inventoryRequiresAdjustment = false;
					}

					if ($inventoryRequiresAdjustment) {
						$product = $this->product->get($existingProduct['ordprodid']);
						if ($product) {
						// put old product inventory back to store
							if (!AdjustProductInventory($existingProduct['ordprodid'], $existingProduct['ordprodvariationid'], $product['prodinvtrack'], '+' . $existingProduct['ordprodqty'])) {
								$this->setError("Failed to adjust inventory for old order product");
								return false;
							}
						}
					}
				}

				// pull new product inventory from store
				if ($inventoryRequiresAdjustment && $item->getProductId()) {
					if (!AdjustProductInventory($item->getProductId(), $item->getVariationId(), $item->getInventoryTrackingMethod(), '-' . $item->getQuantity())) {
						$this->setError("Failed to adjust inventory for new order product");
						return false;
					}
				}
			}

			$configurableFields = $item->getConfiguration();
			foreach($configurableFields as $fieldId => $field) {
				if($field['type'] == 'file' && trim($field['value']) != '') {
					$filePath = ISC_BASE_PATH.'/'.GetConfig('ImageDirectory').'/configured_products/'.$field['value'];
					$fileTmpPath = ISC_BASE_PATH.'/'.GetConfig('ImageDirectory').'/configured_products_tmp/'.$field['value'];

					//do not remove the temp file here, because the payment may not successful
					//the file should still be viewable in in the cart,
					@copy($fileTmpPath, $filePath);
				}

				$newField = array(
					'ordprodid' => $orderProductId,
					'fieldid' => $fieldId,
					'orderid' => $orderId,
					'fieldname' => $field['name'],
					'fieldtype' => $field['type'],
					'fieldselectoptions' => '',
					'textcontents' => '',
					'filename' => '',
					'filetype' => '',
					'originalfilename' => '',
					'productid' => $item->getProductId(),
				);

				if($field['type'] == 'file' && trim($field['value']) != '') {
					$newField['filename'] = trim($field['value']);
					$newField['filetype'] = trim($field['fileType']);
					$newField['originalfilename'] = trim($field['fileOriginalName']);
				}
				elseif ($field['type'] == 'select') {
					$newField['fieldselectoptions'] = $field['selectOptions'];
					$newField['textcontents'] = trim($field['value']);
				}
				else {
					$newField['textcontents'] = trim($field['value']);
				}

				if(!$GLOBALS['ISC_CLASS_DB']->InsertQuery('order_configurable_fields', $newField)) {
					return false;
				}
			}
		}

		if(!empty($giftCertificates)) {
			getClass('ISC_GIFTCERTIFICATES')->createGiftCertificatesFromOrder(
				$orderId,
				$giftCertificates,
				1
			);
		}

		return true;
	}