/**
  * Saves the element and the purchasable. Use this function where you would usually
  * use `craft()->elements->saveElement()`
  *
  * @param BaseElementModel $model
  *
  * @return bool
  * @throws \Exception
  */
 public function saveElement(BaseElementModel $model)
 {
     if (!$model instanceof Purchasable) {
         throw new Exception('Trying to save a purchasable element that is not a purchasable.');
     }
     MarketDbHelper::beginStackedTransaction();
     try {
         if ($success = craft()->elements->saveElement($model)) {
             $id = $model->getPurchasableId();
             $price = $model->getPrice();
             $sku = $model->getSku();
             $purchasable = Market_PurchasableRecord::model()->findById($id);
             if (!$purchasable) {
                 $purchasable = new Market_PurchasableRecord();
             }
             $purchasable->id = $id;
             $purchasable->price = $price;
             $purchasable->sku = $sku;
             $success = $purchasable->save();
             if (!$success) {
                 $model->addErrors($purchasable->getErrors());
                 MarketDbHelper::rollbackStackedTransaction();
                 return $success;
             }
             MarketDbHelper::commitStackedTransaction();
         }
     } catch (\Exception $e) {
         MarketDbHelper::rollbackStackedTransaction();
         throw $e;
     }
     return $success;
 }
 public function save(Market_OrderSettingsModel $orderSettings)
 {
     if ($orderSettings->id) {
         $orderSettingsRecord = Market_OrderSettingsRecord::model()->findById($orderSettings->id);
         if (!$orderSettingsRecord) {
             throw new Exception(Craft::t('No order settings exists with the ID “{id}”', ['id' => $orderSettings->id]));
         }
         $oldOrderSettings = Market_OrderSettingsModel::populateModel($orderSettingsRecord);
         $isNewOrderSettings = false;
     } else {
         $orderSettingsRecord = new Market_OrderSettingsRecord();
         $isNewOrderSettings = true;
     }
     $orderSettingsRecord->name = $orderSettings->name;
     $orderSettingsRecord->handle = $orderSettings->handle;
     $orderSettingsRecord->validate();
     $orderSettings->addErrors($orderSettingsRecord->getErrors());
     if (!$orderSettings->hasErrors()) {
         MarketDbHelper::beginStackedTransaction();
         try {
             if (!$isNewOrderSettings && $oldOrderSettings->fieldLayoutId) {
                 // Drop the old field layout
                 craft()->fields->deleteLayoutById($oldOrderSettings->fieldLayoutId);
             }
             // Save the new one
             $fieldLayout = $orderSettings->getFieldLayout();
             craft()->fields->saveLayout($fieldLayout);
             // Update the calendar record/model with the new layout ID
             $orderSettings->fieldLayoutId = $fieldLayout->id;
             $orderSettingsRecord->fieldLayoutId = $fieldLayout->id;
             // Save it!
             $orderSettingsRecord->save(false);
             // Now that we have a calendar ID, save it on the model
             if (!$orderSettings->id) {
                 $orderSettings->id = $orderSettingsRecord->id;
             }
             MarketDbHelper::commitStackedTransaction();
         } catch (\Exception $e) {
             MarketDbHelper::rollbackStackedTransaction();
             throw $e;
         }
         return true;
     } else {
         return false;
     }
 }
 /**
  * @param Market_ProductModel $product
  *
  * @return bool
  * @throws Exception
  * @throws \Exception
  */
 public function save(Market_ProductModel $product)
 {
     if (!$product->id) {
         $record = new Market_ProductRecord();
     } else {
         $record = Market_ProductRecord::model()->findById($product->id);
         if (!$record) {
             throw new Exception(Craft::t('No product exists with the ID “{id}”', ['id' => $product->id]));
         }
     }
     $record->availableOn = $product->availableOn;
     $record->expiresOn = $product->expiresOn;
     $record->typeId = $product->typeId;
     $record->authorId = $product->authorId;
     $record->promotable = $product->promotable;
     $record->freeShipping = $product->freeShipping;
     $record->taxCategoryId = $product->taxCategoryId;
     $record->validate();
     $product->addErrors($record->getErrors());
     MarketDbHelper::beginStackedTransaction();
     try {
         if (!$product->hasErrors()) {
             if (craft()->elements->saveElement($product)) {
                 $record->id = $product->id;
                 $record->save(false);
                 MarketDbHelper::commitStackedTransaction();
                 return true;
             }
         }
     } catch (\Exception $e) {
         MarketDbHelper::rollbackStackedTransaction();
         throw $e;
     }
     MarketDbHelper::rollbackStackedTransaction();
     return false;
 }
 /**
  * Deleted a
  *
  * @param $id
  *
  * @return bool
  * @throws \CDbException
  * @throws \Exception
  */
 public function deleteById($id)
 {
     MarketDbHelper::beginStackedTransaction();
     try {
         $productType = $this->getById($id);
         $query = craft()->db->createCommand()->select('id')->from('market_products')->where(['typeId' => $productType->id]);
         $productIds = $query->queryColumn();
         foreach ($productIds as $id) {
             craft()->elements->deleteElementById($id);
         }
         $fieldLayoutId = $productType->asa('productFieldLayout')->getFieldLayout()->id;
         craft()->fields->deleteLayoutById($fieldLayoutId);
         if ($productType->hasVariants) {
             craft()->fields->deleteLayoutById($productType->asa('variantFieldLayout')->getFieldLayout()->id);
         }
         $productTypeRecord = Market_ProductTypeRecord::model()->findById($productType->id);
         $affectedRows = $productTypeRecord->delete();
         if ($affectedRows) {
             MarketDbHelper::commitStackedTransaction();
         }
         return (bool) $affectedRows;
     } catch (\Exception $e) {
         MarketDbHelper::rollbackStackedTransaction();
         throw $e;
     }
 }
 /**
  * @param Market_SaleModel $model
  * @param array            $groups       ids
  * @param array            $productTypes ids
  * @param array            $products     ids
  *
  * @return bool
  * @throws \Exception
  */
 public function save(Market_SaleModel $model, array $groups, array $productTypes, array $products)
 {
     if ($model->id) {
         $record = Market_SaleRecord::model()->findById($model->id);
         if (!$record) {
             throw new Exception(Craft::t('No sale exists with the ID “{id}”', ['id' => $model->id]));
         }
     } else {
         $record = new Market_SaleRecord();
     }
     $fields = ['id', 'name', 'description', 'dateFrom', 'dateTo', 'discountType', 'discountAmount', 'enabled'];
     foreach ($fields as $field) {
         $record->{$field} = $model->{$field};
     }
     $record->allGroups = $model->allGroups = empty($groups);
     $record->allProductTypes = $model->allProductTypes = empty($productTypes);
     $record->allProducts = $model->allProducts = empty($products);
     $record->validate();
     $model->addErrors($record->getErrors());
     MarketDbHelper::beginStackedTransaction();
     try {
         if (!$model->hasErrors()) {
             $record->save(false);
             $model->id = $record->id;
             Market_SaleUserGroupRecord::model()->deleteAllByAttributes(['saleId' => $model->id]);
             Market_SaleProductRecord::model()->deleteAllByAttributes(['saleId' => $model->id]);
             Market_SaleProductTypeRecord::model()->deleteAllByAttributes(['saleId' => $model->id]);
             foreach ($groups as $groupId) {
                 $relation = new Market_SaleUserGroupRecord();
                 $relation->attributes = ['userGroupId' => $groupId, 'saleId' => $model->id];
                 $relation->insert();
             }
             foreach ($productTypes as $productTypeId) {
                 $relation = new Market_SaleProductTypeRecord();
                 $relation->attributes = ['productTypeId' => $productTypeId, 'saleId' => $model->id];
                 $relation->insert();
             }
             foreach ($products as $productId) {
                 $relation = new Market_SaleProductRecord();
                 $relation->attributes = ['productId' => $productId, 'saleId' => $model->id];
                 $relation->insert();
             }
             MarketDbHelper::commitStackedTransaction();
             return true;
         }
     } catch (\Exception $e) {
         MarketDbHelper::rollbackStackedTransaction();
         throw $e;
     }
     MarketDbHelper::rollbackStackedTransaction();
     return false;
 }
 /**
  * Remove all items from a cart
  *
  * @param Market_OrderModel $cart
  *
  * @throws \Exception
  */
 public function clearCart(Market_OrderModel $cart)
 {
     MarketDbHelper::beginStackedTransaction();
     try {
         craft()->market_lineItem->deleteAllByOrderId($cart->id);
         craft()->market_order->save($cart);
     } catch (\Exception $e) {
         MarketDbHelper::rollbackStackedTransaction();
         throw $e;
     }
     MarketDbHelper::commitStackedTransaction();
 }
 /**
  * Save and set the given addresses to the current cart/order
  *
  * @param Market_OrderModel   $order
  * @param Market_AddressModel $shippingAddress
  * @param Market_AddressModel $billingAddress
  *
  * @return bool
  * @throws \Exception
  */
 public function setAddresses(Market_OrderModel $order, Market_AddressModel $shippingAddress, Market_AddressModel $billingAddress)
 {
     MarketDbHelper::beginStackedTransaction();
     try {
         $result1 = craft()->market_customer->saveAddress($shippingAddress);
         if ($billingAddress->id && $billingAddress->id == $shippingAddress->id) {
             $result2 = true;
         } else {
             $result2 = craft()->market_customer->saveAddress($billingAddress);
         }
         $order->setShippingAddress($shippingAddress);
         $order->setBillingAddress($billingAddress);
         if ($result1 && $result2) {
             $order->shippingAddressId = $shippingAddress->id;
             $order->billingAddressId = $billingAddress->id;
             $this->save($order);
             MarketDbHelper::commitStackedTransaction();
             return true;
         }
     } catch (\Exception $e) {
         MarketDbHelper::rollbackStackedTransaction();
         throw $e;
     }
     MarketDbHelper::rollbackStackedTransaction();
     return false;
 }
 /**
  * @param Market_TaxZoneModel $model
  * @param array               $countriesIds
  * @param array               $statesIds
  *
  * @return bool
  * @throws \Exception
  */
 public function save(Market_TaxZoneModel $model, $countriesIds, $statesIds)
 {
     if ($model->id) {
         $record = Market_TaxZoneRecord::model()->findById($model->id);
         if (!$record) {
             throw new Exception(Craft::t('No tax zone exists with the ID “{id}”', ['id' => $model->id]));
         }
     } else {
         $record = new Market_TaxZoneRecord();
     }
     //remembering which links should be clean
     $deleteOldCountries = $deleteOldStates = false;
     if ($record->id) {
         if ($record->countryBased) {
             $deleteOldCountries = true;
         } else {
             $deleteOldStates = true;
         }
     }
     //setting attributes
     $record->name = $model->name;
     $record->description = $model->description;
     $record->countryBased = $model->countryBased;
     $record->default = $model->default;
     $record->validate();
     $model->addErrors($record->getErrors());
     //validating given ids
     if ($record->countryBased) {
         $criteria = new \CDbCriteria();
         $criteria->addInCondition('id', $countriesIds);
         $exist = Market_CountryRecord::model()->exists($criteria);
         if (!$exist) {
             $model->addError('countries', 'Please select some countries');
         }
     } else {
         $criteria = new \CDbCriteria();
         $criteria->addInCondition('id', $statesIds);
         $exist = Market_StateRecord::model()->exists($criteria);
         if (!$exist) {
             $model->addError('states', 'Please select some states');
         }
     }
     //saving
     if (!$model->hasErrors()) {
         MarketDbHelper::beginStackedTransaction();
         try {
             // Save it!
             $record->save(false);
             // Now that we have a record ID, save it on the model
             $model->id = $record->id;
             //deleting old links
             if ($deleteOldCountries) {
                 Market_TaxZoneCountryRecord::model()->deleteAllByAttributes(['taxZoneId' => $record->id]);
             }
             if ($deleteOldStates) {
                 Market_TaxZoneStateRecord::model()->deleteAllByAttributes(['taxZoneId' => $record->id]);
             }
             //saving new links
             if ($model->countryBased) {
                 $rows = array_map(function ($id) use($model) {
                     return [$id, $model->id];
                 }, $countriesIds);
                 $cols = ['countryId', 'taxZoneId'];
                 $table = Market_TaxZoneCountryRecord::model()->getTableName();
             } else {
                 $rows = array_map(function ($id) use($model) {
                     return [$id, $model->id];
                 }, $statesIds);
                 $cols = ['stateId', 'taxZoneId'];
                 $table = Market_TaxZoneStateRecord::model()->getTableName();
             }
             craft()->db->createCommand()->insertAll($table, $cols, $rows);
             //If this was the default make all others not the default.
             if ($model->default) {
                 Market_TaxZoneRecord::model()->updateAll(['default' => 0], 'id != ?', [$record->id]);
             }
             MarketDbHelper::commitStackedTransaction();
         } catch (\Exception $e) {
             MarketDbHelper::rollbackStackedTransaction();
             throw $e;
         }
         return true;
     } else {
         return false;
     }
 }
 public function delete($model)
 {
     // Delete all rules first.
     MarketDbHelper::beginStackedTransaction();
     try {
         $rules = craft()->market_shippingRule->getAllByMethodId($model->id);
         foreach ($rules as $rule) {
             craft()->market_shippingRule->deleteById($rule->id);
         }
         Market_ShippingMethodRecord::model()->deleteByPk($model->id);
         MarketDbHelper::commitStackedTransaction();
         return true;
     } catch (\Exception $e) {
         MarketDbHelper::rollbackStackedTransaction();
         return false;
     }
     MarketDbHelper::rollbackStackedTransaction();
     return false;
 }
 /**
  * @param Market_OrderStatusModel $model
  * @param array $emailsIds
  *
  * @return bool
  * @throws Exception
  * @throws \CDbException
  * @throws \Exception
  */
 public function save(Market_OrderStatusModel $model, array $emailsIds)
 {
     if ($model->id) {
         $record = Market_OrderStatusRecord::model()->findById($model->id);
         if (!$record->id) {
             throw new Exception(Craft::t('No order status exists with the ID “{id}”', ['id' => $model->id]));
         }
     } else {
         $record = new Market_OrderStatusRecord();
     }
     $record->name = $model->name;
     $record->handle = $model->handle;
     $record->color = $model->color;
     $record->default = $model->default;
     $record->validate();
     $model->addErrors($record->getErrors());
     //validating emails ids
     $criteria = new \CDbCriteria();
     $criteria->addInCondition('id', $emailsIds);
     $exist = Market_EmailRecord::model()->exists($criteria);
     $hasEmails = (bool) count($emailsIds);
     if (!$exist && $hasEmails) {
         $model->addError('emails', 'One or more emails do not exist in the system.');
     }
     //saving
     if (!$model->hasErrors()) {
         MarketDbHelper::beginStackedTransaction();
         try {
             //only one default status can be among statuses of one order type
             if ($record->default) {
                 Market_OrderStatusRecord::model()->updateAll(['default' => 0]);
             }
             // Save it!
             $record->save(false);
             //Delete old links
             if ($model->id) {
                 Market_OrderStatusEmailRecord::model()->deleteAllByAttributes(['orderStatusId' => $model->id]);
             }
             //Save new links
             $rows = array_map(function ($id) use($record) {
                 return [$id, $record->id];
             }, $emailsIds);
             $cols = ['emailId', 'orderStatusId'];
             $table = Market_OrderStatusEmailRecord::model()->getTableName();
             craft()->db->createCommand()->insertAll($table, $cols, $rows);
             // Now that we have a calendar ID, save it on the model
             $model->id = $record->id;
             MarketDbHelper::commitStackedTransaction();
         } catch (\Exception $e) {
             MarketDbHelper::rollbackStackedTransaction();
             throw $e;
         }
         return true;
     } else {
         return false;
     }
 }
 /**
  * Save a new or existing product.
  */
 public function actionSaveProduct()
 {
     $this->requireAdmin();
     $this->requirePostRequest();
     $product = $this->_setProductFromPost();
     $implicitVariant = $this->_setImplicitVariantFromPost($product);
     $existingProduct = (bool) $product->id;
     MarketDbHelper::beginStackedTransaction();
     if (craft()->market_product->save($product)) {
         $implicitVariant->productId = $product->id;
         if (craft()->market_variant->save($implicitVariant)) {
             MarketDbHelper::commitStackedTransaction();
             craft()->userSession->setNotice(Craft::t('Product saved.'));
             if (craft()->request->getPost('redirectToVariant')) {
                 $this->redirect($product->getCpEditUrl() . '/variants/new');
             } else {
                 $this->redirectToPostedUrl($product);
             }
         }
     }
     MarketDbHelper::rollbackStackedTransaction();
     // Since Product may have been ok to save and an ID assigned,
     // but child model validation failed and the transaction rolled back.
     // Since action failed, lets remove the ID that was no persisted.
     if (!$existingProduct) {
         $product->id = null;
     }
     craft()->userSession->setNotice(Craft::t("Couldn't save product."));
     craft()->urlManager->setRouteVariables(['product' => $product, 'implicitVariant' => $implicitVariant]);
 }
 /**
  * Save a model into DB
  *
  * @param BaseElementModel $model
  *
  * @return bool
  * @throws \CDbException
  * @throws \Exception
  */
 public function save(BaseElementModel $model)
 {
     $productTypeId = craft()->db->createCommand()->select('typeId')->from('market_products')->where('id=:id', [':id' => $model->productId])->queryScalar();
     $productType = craft()->market_productType->getById($productTypeId);
     if ($model->id) {
         $record = Market_VariantRecord::model()->findById($model->id);
         if (!$record) {
             throw new HttpException(404);
         }
     } else {
         $record = new Market_VariantRecord();
     }
     /* @var Market_VariantModel $model */
     $record->isImplicit = $model->isImplicit;
     $record->productId = $model->productId;
     // We dont ask for a sku when dealing with a product with variants
     if ($model->isImplicit && $productType->hasVariants) {
         $model->sku = 'implicitSkuOfProductId' . $model->productId;
         $record->sku = $model->sku;
     } else {
         $record->sku = $model->sku;
     }
     if (!$productType->titleFormat) {
         $productType->titleFormat = "{sku}";
     }
     // implicit variant has no custom field data so play it safe and default it to sku.
     if ($model->isImplicit) {
         $productType->titleFormat = "{sku}";
     }
     $model->getContent()->title = craft()->templates->renderObjectTemplate($productType->titleFormat, $model);
     $record->price = $model->price;
     $record->width = $model->width;
     $record->height = $model->height;
     $record->length = $model->length;
     $record->weight = $model->weight;
     $record->minQty = $model->minQty;
     $record->maxQty = $model->maxQty;
     $record->stock = $model->stock;
     $record->unlimitedStock = $model->unlimitedStock;
     if ($model->unlimitedStock && $record->stock == "") {
         $model->stock = 0;
         $record->stock = 0;
     }
     $record->validate();
     $model->addErrors($record->getErrors());
     MarketDbHelper::beginStackedTransaction();
     try {
         if (!$model->hasErrors()) {
             if (craft()->market_purchasable->saveElement($model)) {
                 $record->id = $model->id;
                 $record->save(false);
                 MarketDbHelper::commitStackedTransaction();
                 return true;
             }
         }
     } catch (\Exception $e) {
         MarketDbHelper::rollbackStackedTransaction();
         throw $e;
     }
     MarketDbHelper::rollbackStackedTransaction();
     return false;
 }
 /**
  * @param Market_LineItemModel $lineItem
  *
  * @return bool
  * @throws \Exception
  */
 public function save(Market_LineItemModel $lineItem)
 {
     if ($lineItem->qty <= 0 && $lineItem->id) {
         $this->delete($lineItem);
         return true;
     }
     if (!$lineItem->id) {
         $lineItemRecord = new Market_LineItemRecord();
     } else {
         $lineItemRecord = Market_LineItemRecord::model()->findById($lineItem->id);
         if (!$lineItemRecord) {
             throw new Exception(Craft::t('No line item exists with the ID “{id}”', ['id' => $lineItem->id]));
         }
     }
     $lineItem->total = ($lineItem->price + $lineItem->saleAmount) * $lineItem->qty + $lineItem->tax + $lineItem->discount + $lineItem->shippingCost;
     $lineItemRecord->purchasableId = $lineItem->purchasableId;
     $lineItemRecord->orderId = $lineItem->orderId;
     $lineItemRecord->taxCategoryId = $lineItem->taxCategoryId;
     $lineItemRecord->qty = $lineItem->qty;
     $lineItemRecord->price = $lineItem->price;
     $lineItemRecord->weight = $lineItem->weight;
     $lineItemRecord->snapshot = $lineItem->snapshot;
     $lineItemRecord->note = $lineItem->note;
     $lineItemRecord->saleAmount = $lineItem->saleAmount;
     $lineItemRecord->salePrice = $lineItem->salePrice;
     $lineItemRecord->tax = $lineItem->tax;
     $lineItemRecord->discount = $lineItem->discount;
     $lineItemRecord->shippingCost = $lineItem->shippingCost;
     $lineItemRecord->total = $lineItem->total;
     // Cant have discounts making things less than zero.
     if ($lineItemRecord->total < 0) {
         $lineItemRecord->total = 0;
     }
     $lineItemRecord->validate();
     /** @var \Market\Interfaces\Purchasable $purchasable */
     $purchasable = craft()->elements->getElementById($lineItem->purchasableId);
     $purchasable->validateLineItem($lineItem);
     $lineItem->addErrors($lineItemRecord->getErrors());
     MarketDbHelper::beginStackedTransaction();
     try {
         if (!$lineItem->hasErrors()) {
             $lineItemRecord->save(false);
             $lineItemRecord->id = $lineItem->id;
             MarketDbHelper::commitStackedTransaction();
             return true;
         }
     } catch (\Exception $e) {
         MarketDbHelper::rollbackStackedTransaction();
         throw $e;
     }
     return false;
 }