/** * "Close" the order for modifications and fix its state * * 1) fix current product prices and total (so the total doesn't change if product prices change) * 2) save created shipments * * @return CustomerOrder New order instance containing wishlist items */ public function finalize($options = array()) { if ($this->isFinalized->get() && empty($options['allowRefinalize'])) { return; } self::beginTransaction(); $this->event('before-finalize'); $this->loadAll(); $currency = $this->getCurrency(); foreach ($this->getShipments() as $shipment) { if ($shipment->isExistingRecord()) { $shipment->deleteRecordSet('ShipmentTax', new ARDeleteFilter()); } // clone shipping addresses if ($shipment->shippingAddress->get()) { $shippingAddress = clone $shipment->shippingAddress->get(); $shippingAddress->save(); $shipment->shippingAddress->set($shippingAddress); } $shipment->order->set($this); $shipment->save(); } $reserveProducts = self::getApplication()->isInventoryTracking(); foreach ($this->getShoppingCartItems() as $item) { if (empty($options['customPrice'])) { $item->price->set($item->getSubTotalBeforeTax() / $item->getCount()); } $item->name->set($item->getProduct()->getParent()->name->get()); $item->setValueByLang('name', 'sku', $item->getProduct()->sku->get()); $item->save(); // create sub-items for bundled products if ($item->getProduct()->isBundle()) { foreach ($item->getProduct()->getBundledProducts() as $bundled) { $bundledItem = OrderedItem::getNewInstance($this, $bundled->relatedProduct->get(), $bundled->getCount()); $bundledItem->parent->set($item); $bundledItem->save(); } } // reserve products if inventory is enabled if ($reserveProducts) { $item->reserve(); $item->save(); } } if (!$this->shippingAddress->get() && $this->user->get() && $this->user->get()->defaultShippingAddress->get() && $this->isShippingRequired()) { $this->shippingAddress->set($this->user->get()->defaultShippingAddress->get()->userAddress->get()); } if (!$this->billingAddress->get() && $this->user->get() && $this->user->get()->defaultBillingAddress->get()) { $this->billingAddress->set($this->user->get()->defaultBillingAddress->get()->userAddress->get()); } // clone billing/shipping addresses if (!$this->isFinalized->get()) { foreach (array('billingAddress', 'shippingAddress') as $address) { if ($this->{$address}->get()) { $this->{$address}->get()->load(); $this->{$address}->get()->getSpecification(); $cloned = clone $this->{$address}->get(); $cloned->save(); $cloned->loadEav(); $this->{$address}->set($cloned); } } } // move wish list items to a separate order if ($this->getWishListItems()) { $wishList = CustomerOrder::getNewInstance($this->user->get()); foreach ($this->getWishListItems() as $item) { $wishList->addItem($item); } $wishList->save(); } else { $wishList = null; } // set order total $this->totalAmount->set($this->getTotal(true)); // save shipment taxes foreach ($this->shipments as $shipment) { $shipment->save(); } // save discounts foreach ($this->orderDiscounts as $discount) { $discount->save(); } // @todo: remove the 0.99 multiplicator for currency conversion "tolerance" (a cent going missing when converting amounts between currencies back and forth) if (round($this->totalAmount->get(), 2) * 0.99 <= round($this->getPaidAmount(), 2)) { $this->isPaid->set(true); } $this->dateCompleted->set(new ARSerializableDateTime()); $this->isFinalized->set(true); // @todo: fix order total calculation $shipments = $this->shipments; unset($this->shipments); if (!$this->invoiceNumber->get()) { $generator = InvoiceNumberGenerator::getGenerator($this); $saved = false; while (!$saved) { try { $this->invoiceNumber->set($generator->getNumber()); $this->save(); $saved = true; } catch (SQLException $e) { } } } $this->event('after-finalize'); self::commit(); // @todo: see above $this->shipments = $shipments; // force updating array representation $this->resetArrayData(); return $wishList; }
/** * "Close" the order for modifications and fix its state * * 1) fix current product prices and total (so the total doesn't change if product prices change) * 2) save created shipments * * @return CustomerOrder New order instance containing wishlist items */ public function finalize($options = array()) { $rebillsLeft = 0; if ($this->isFinalized->get() && empty($options['allowRefinalize'])) { return; } self::beginTransaction(); $this->event('before-finalize'); $currency = $this->getCurrency(); $this->loadAll(); foreach ($this->getShipments() as $shipment) { if ($shipment->isExistingRecord()) { $shipment->deleteRecordSet('ShipmentTax', new ARDeleteFilter()); } $shipment->order->set($this); $shipment->save(); // clone shipping addresses if ($shipment->shippingAddress->get()) { $shippingAddress = clone $shipment->shippingAddress->get(); $shippingAddress->save(); $shipment->shippingAddress->set($shippingAddress); } } $reserveProducts = self::getApplication()->isInventoryTracking(); $rebillsLeft = 0; $groupedRebillsLeft = array(); $isFirstOrder = !$this->parentID->get(); foreach ($this->getShoppingCartItems() as $item) { // workround for failing tests. //if (!empty($options['customPrice'])) //{ $item->price->set($item->getSubTotalBeforeTax() / $item->getCount()); //} $item->name->set($item->getProduct()->getParent()->name->get()); $item->setValueByLang('name', 'sku', $item->getProduct()->sku->get()); $item->save(); // create sub-items for bundled products if ($item->getProduct()->isBundle()) { foreach ($item->getProduct()->getBundledProducts() as $bundled) { $bundledItem = OrderedItem::getNewInstance($this, $bundled->relatedProduct->get(), $bundled->getCount()); $bundledItem->parent->set($item); $bundledItem->save(); } } // reserve products if inventory is enabled if ($reserveProducts) { $item->reserve(); $item->save(); } if ($isFirstOrder) { $ri = RecurringItem::getInstanceByOrderedItem($item); if ($ri && $ri->isExistingRecord()) { $rebillCount = $ri->rebillCount->get(); // also here recurring item grouping $key = sprintf('%s_%s_%s', $ri->periodType->get(), $ri->periodLength->get(), $rebillCount === null ? 'NULL' : $rebillCount); if ($rebillCount !== null) { $groupedRebillsLeft[$key] = $rebillCount; } else { $groupedRebillsLeft[$key] = -1; // -1 means infinite rebill count } $this->isRecurring->set(true); // orders with at least one recurring billing plan must have isRecurring flag, if already not set. } } else { $rparentItem = $item->recurringParentID->get(); if ($rparentItem) { $ri = RecurringItem::getInstanceByOrderedItem($rparentItem, true); $ri->reload(); // if was bulk update, then cached data are outdated. if ($ri && $ri->isExistingRecord()) { // are RecurringItems grouped? // probably yes.. $rebillsLeft = $ri->rebillCount->get() - $ri->processedRebillCount->get(); } } } } if ($isFirstOrder) { foreach ($groupedRebillsLeft as $value) { if ($value == -1) { $rebillsLeft = -1; break; } else { $rebillsLeft += $value; } } } if (!$this->shippingAddress->get() && $this->user->get() && $this->user->get()->defaultShippingAddress->get() && $this->isShippingRequired()) { $this->shippingAddress->set($this->user->get()->defaultShippingAddress->get()->userAddress->get()); } if (!$this->billingAddress->get() && $this->user->get() && $this->user->get()->defaultBillingAddress->get()) { $this->billingAddress->set($this->user->get()->defaultBillingAddress->get()->userAddress->get()); } // clone billing/shipping addresses if (!$this->isFinalized->get()) { foreach (array('billingAddress', 'shippingAddress') as $address) { if ($this->{$address}->get()) { $this->{$address}->get()->load(); $this->{$address}->get()->getSpecification(); $cloned = clone $this->{$address}->get(); $cloned->save(); $cloned->loadEav(); $this->{$address}->set($cloned); } } } // move wish list items to a separate order if ($this->getWishListItems()) { $wishList = CustomerOrder::getNewInstance($this->user->get()); foreach ($this->getWishListItems() as $item) { $wishList->addItem($item); } $wishList->save(); } else { $wishList = null; } // set order total $this->totalAmount->set($this->getTotal(true)); // save shipment taxes foreach ($this->shipments as $shipment) { $shipment->save(); } // save discounts foreach ($this->orderDiscounts as $discount) { $discount->save(); } // @todo: remove the 0.99 multiplicator for currency conversion "tolerance" (a cent going missing when converting amounts between currencies back and forth) if (round($this->totalAmount->get(), 2) * 0.99 <= round($this->getPaidAmount(), 2)) { $this->isPaid->set(true); } $this->dateCompleted->set(new ARSerializableDateTime()); $this->isFinalized->set(true); // @todo: fix order total calculation $shipments = $this->shipments; unset($this->shipments); if (!$this->invoiceNumber->get()) { $generator = InvoiceNumberGenerator::getGenerator($this); $saved = false; while (!$saved) { try { $this->invoiceNumber->set($generator->getNumber()); $this->save(); $saved = true; } catch (SQLException $e) { } } } if ($this->isRecurring->get()) { $changed = false; if (!strlen($this->startDate->get())) { $this->startDate->set(date('Y-m-d H:i:s', time())); $changed = true; } if ($rebillsLeft != $this->rebillsLeft->get()) { $this->rebillsLeft->set($rebillsLeft); $changed = true; } if ($changed) { $this->save(); } } $this->event('after-finalize'); self::commit(); // @todo: see above $this->shipments = $shipments; // force updating array representation $this->resetArrayData(); return $wishList; }