diff --git a/.github/ISSUE_TEMPLATE/BUG-REPORT-V3.yml b/.github/ISSUE_TEMPLATE/BUG-REPORT-V3.yml index ddafcd4d47..5ef974b047 100644 --- a/.github/ISSUE_TEMPLATE/BUG-REPORT-V3.yml +++ b/.github/ISSUE_TEMPLATE/BUG-REPORT-V3.yml @@ -2,8 +2,9 @@ name: Bug Report – Commerce 3 description: Report an issue or unexpected behavior pertaining to Commerce 3 title: '[3.x]: ' labels: - - 🐞 bug - commerce3 + - Craft Commerce # Linear + - bug # Linear body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/BUG-REPORT-V4.yml b/.github/ISSUE_TEMPLATE/BUG-REPORT-V4.yml index c1e737e08e..89180561bf 100644 --- a/.github/ISSUE_TEMPLATE/BUG-REPORT-V4.yml +++ b/.github/ISSUE_TEMPLATE/BUG-REPORT-V4.yml @@ -2,8 +2,9 @@ name: Bug Report – Commerce 4 description: Report an issue or unexpected behavior pertaining to Commerce 4 title: '[4.x]: ' labels: - - 🐞 bug - commerce4 + - Craft Commerce # Linear + - bug # Linear body: - type: markdown attributes: diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b8eb695d7..6690daf3f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Release Notes for Craft Commerce +## 4.5.3 - 2024-04-02 + +- The “Postcode Condition Formula” condition rule now allows multi-line input. ([#3147](https://github.com/craftcms/commerce/issues/3147) +- Fixed a bug where order adjustments could be duplicated. ([#3438](https://github.com/craftcms/commerce/issues/3438)) +- Fixed a bug where successful refunds could show a failure notice. + +## 4.5.2 - 2024-03-06 + +- Fixed a bug where order status sources weren’t showing count badges on the Orders index page. ([#3397](https://github.com/craftcms/commerce/issues/3397)) +- Fixed a bug where discounts weren’t listing more than 128 related purchasables or categories. ([#3379](https://github.com/craftcms/commerce/issues/3379)) + ## 4.5.1.1 - 2024-03-01 - Fixed a bug where the “Share cart” order index action wasn’t working. diff --git a/src/Plugin.php b/src/Plugin.php index c38bcc2e4b..ef6a91363c 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -207,7 +207,7 @@ public static function editions(): array /** * @inheritDoc */ - public string $schemaVersion = '4.5.0'; + public string $schemaVersion = '4.5.1'; /** * @inheritdoc diff --git a/src/controllers/CartController.php b/src/controllers/CartController.php index 4e0eb14555..0407df92d7 100644 --- a/src/controllers/CartController.php +++ b/src/controllers/CartController.php @@ -24,6 +24,7 @@ use Throwable; use yii\base\Exception; use yii\base\InvalidConfigException; +use yii\mutex\Mutex; use yii\web\BadRequestHttpException; use yii\web\HttpException; use yii\web\NotFoundHttpException; @@ -52,6 +53,16 @@ class CartController extends BaseFrontEndController */ protected ?User $_currentUser = null; + /** + * @var Mutex|null + */ + private ?Mutex $_mutex = null; + + /** + * @var string|null + */ + private ?string $_mutexLockName = null; + /** * @throws InvalidConfigException */ @@ -92,10 +103,36 @@ public function actionUpdateCart(): ?Response { $this->requirePostRequest(); $isSiteRequest = $this->request->getIsSiteRequest(); + $isConsoleRequest = $this->request->getIsConsoleRequest(); $currentUser = Craft::$app->getUser()->getIdentity(); /** @var Plugin $plugin */ $plugin = Plugin::getInstance(); + $useMutex = (!$isConsoleRequest && Craft::$app->getRequest()->getBodyParam('number')) || (!$isConsoleRequest && $plugin->getCarts()->getHasSessionCartNumber()); + + if ($useMutex) { + $lockOrderNumber = null; + if ($bodyNumber = Craft::$app->getRequest()->getBodyParam('number')) { + $lockOrderNumber = $bodyNumber; + } elseif (!$isConsoleRequest) { + $request = Craft::$app->getRequest(); + $requestCookies = $request->getCookies(); + $cookieNumber = $requestCookies->getValue($plugin->getCarts()->cartCookie['name']); + + if ($cookieNumber) { + $lockOrderNumber = $cookieNumber; + } + } + + if ($lockOrderNumber) { + $this->_mutexLockName = "order:$lockOrderNumber"; + $this->_mutex = Craft::$app->getMutex(); + if (!$this->_mutex->acquire($this->_mutexLockName, 5)) { + throw new Exception('Unable to acquire a lock for saving of Order: ' . $lockOrderNumber); + } + } + } + // Get the cart from the request or from the session. // When we are about to update the cart, we consider it a real cart at this point, and want to actually create it in the DB. $this->_cart = $this->_getCart(true); @@ -489,6 +526,10 @@ private function _returnCart(): ?Response $error = Craft::t('commerce', 'Unable to update cart.'); $message = $this->request->getValidatedBodyParam('failMessage') ?? $error; + if ($this->_mutex && $this->_mutexLockName) { + $this->_mutex->release($this->_mutexLockName); + } + return $this->asModelFailure( $this->_cart, $message, @@ -509,6 +550,10 @@ private function _returnCart(): ?Response $this->_cartVariable => $this->_cart, ]); + if ($this->_mutex && $this->_mutexLockName) { + $this->_mutex->release($this->_mutexLockName); + } + return $this->asModelSuccess( $this->_cart, $message, diff --git a/src/controllers/OrdersController.php b/src/controllers/OrdersController.php index ee0a70b8ba..567543cf30 100644 --- a/src/controllers/OrdersController.php +++ b/src/controllers/OrdersController.php @@ -1039,7 +1039,7 @@ public function actionTransactionRefund(): Response $message = $child->message ? ' (' . $child->message . ')' : ''; - if ($child->status == TransactionRecord::STATUS_SUCCESS) { + if ($child->status == TransactionRecord::STATUS_SUCCESS || $child->status == TransactionRecord::STATUS_PROCESSING) { $child->order->updateOrderPaidInformation(); $this->setSuccessFlash(Craft::t('commerce', 'Transaction refunded successfully: {message}', [ 'message' => $message, @@ -1210,7 +1210,7 @@ private function _registerJavascript(array $variables): void $shippingCategories = Plugin::getInstance()->getShippingCategories()->getAllShippingCategoriesAsList(); Craft::$app->getView()->registerJs('window.orderEdit.shippingCategories = ' . Json::encode(ArrayHelper::toArray($shippingCategories)) . ';', View::POS_BEGIN); - + $currentUser = Craft::$app->getUser()->getIdentity(); $permissions = [ 'commerce-manageOrders' => $currentUser->can('commerce-manageOrders'), diff --git a/src/controllers/PaymentsController.php b/src/controllers/PaymentsController.php index e767fddc8d..be64544f8e 100644 --- a/src/controllers/PaymentsController.php +++ b/src/controllers/PaymentsController.php @@ -81,6 +81,32 @@ public function actionPay(): ?Response $number = $this->request->getParam('number'); + $useMutex = $number || (!$isCpRequest && $plugin->getCarts()->getHasSessionCartNumber()); + + if ($useMutex) { + $lockOrderNumber = null; + if ($number) { + $lockOrderNumber = $number; + } elseif (!$isCpRequest) { + $request = Craft::$app->getRequest(); + $requestCookies = $request->getCookies(); + $cookieNumber = $requestCookies->getValue($plugin->getCarts()->cartCookie['name']); + + if ($cookieNumber) { + $lockOrderNumber = $cookieNumber; + } + } + + if ($lockOrderNumber) { + $lockName = "order:$lockOrderNumber"; + $mutex = Craft::$app->getMutex(); + if (!$mutex->acquire($lockName, 5)) { + throw new Exception('Unable to acquire a lock for saving of Order: ' . $lockOrderNumber); + } + } + } + + if ($number !== null) { $order = $plugin->getOrders()->getOrderByNumber($number); @@ -375,6 +401,10 @@ public function actionPay(): ?Response $error = Craft::t('commerce', 'Something changed with the order before payment, please review your order and submit payment again.'); + if ($useMutex && isset($mutex, $lockName)) { + $mutex->release($lockName); + } + return $this->asModelFailure( $paymentForm, $error, @@ -390,6 +420,10 @@ public function actionPay(): ?Response } } + if ($useMutex && isset($mutex, $lockName)) { + $mutex->release($lockName); + } + $redirect = ''; $redirectData = []; $transaction = null; diff --git a/src/elements/Order.php b/src/elements/Order.php index 52e9ce6f9f..78250477d3 100644 --- a/src/elements/Order.php +++ b/src/elements/Order.php @@ -3399,6 +3399,12 @@ private function _saveAdjustments(): void $previousAdjustment->delete(); } } + + // Make sure all other adjustments have been cleaned up. + Db::delete( + Table::ORDERADJUSTMENTS, + ['and', ['orderId' => $this->id], ['not', ['id' => $newAdjustmentIds]]] + ); } diff --git a/src/elements/conditions/addresses/PostalCodeFormulaConditionRule.php b/src/elements/conditions/addresses/PostalCodeFormulaConditionRule.php index fee5391758..c320d3b6c2 100644 --- a/src/elements/conditions/addresses/PostalCodeFormulaConditionRule.php +++ b/src/elements/conditions/addresses/PostalCodeFormulaConditionRule.php @@ -22,11 +22,17 @@ */ class PostalCodeFormulaConditionRule extends BaseTextConditionRule implements ElementConditionRuleInterface { + /** + * @inheritdoc + */ public function getLabel(): string { return Craft::t('commerce', 'Postal Code Formula'); } + /** + * @inheritdoc + */ public function getExclusiveQueryParams(): array { return []; @@ -70,14 +76,14 @@ public function operators(): array public function inputHtml(): string { return Html::hiddenLabel($this->getLabel(), 'value') . - Cp::textHtml([ - 'type' => $this->inputType(), - 'id' => 'value', - 'name' => 'value', - 'code' => 'value', - 'value' => $this->value, - 'autocomplete' => false, - 'class' => 'fullwidth code', - ]); + Cp::textareaHtml([ + 'type' => $this->inputType(), + 'id' => 'value', + 'name' => 'value', + 'code' => 'value', + 'value' => $this->value, + 'autocomplete' => false, + 'class' => 'fullwidth code', + ]); } } diff --git a/src/elements/traits/OrderElementTrait.php b/src/elements/traits/OrderElementTrait.php index 7538661a54..c966de7a20 100644 --- a/src/elements/traits/OrderElementTrait.php +++ b/src/elements/traits/OrderElementTrait.php @@ -301,7 +301,6 @@ protected static function defineSources(string $context = null): array 'label' => Craft::t('commerce', 'All Orders'), 'criteria' => ['isCompleted' => true], 'defaultSort' => ['dateOrdered', 'desc'], - 'badgeCount' => 0, 'data' => [ 'date-attr' => 'dateOrdered', ], @@ -320,7 +319,6 @@ protected static function defineSources(string $context = null): array 'label' => Craft::t('site', $orderStatus->name), 'criteria' => $criteriaStatus, 'defaultSort' => ['dateOrdered', 'desc'], - 'badgeCount' => 0, 'data' => [ 'handle' => $orderStatus->handle, 'date-attr' => 'dateOrdered', diff --git a/src/migrations/Install.php b/src/migrations/Install.php index b1bf11f8f8..579a4af0f3 100644 --- a/src/migrations/Install.php +++ b/src/migrations/Install.php @@ -169,7 +169,9 @@ public function createTables(): void 'hasFreeShippingForMatchingItems' => $this->boolean()->notNull()->defaultValue(false), 'hasFreeShippingForOrder' => $this->boolean()->notNull()->defaultValue(false), 'allPurchasables' => $this->boolean()->notNull()->defaultValue(false), + 'purchasableIds' => $this->text(), 'allCategories' => $this->boolean()->notNull()->defaultValue(false), + 'categoryIds' => $this->text(), 'appliedTo' => $this->enum('appliedTo', ['matchingLineItems', 'allLineItems'])->notNull()->defaultValue('matchingLineItems'), 'categoryRelationshipType' => $this->enum('categoryRelationshipType', ['element', 'sourceElement', 'targetElement'])->notNull()->defaultValue('element'), 'orderConditionFormula' => $this->text(), diff --git a/src/migrations/m240306_091057_move_element_ids_on_discount_to_columns.php b/src/migrations/m240306_091057_move_element_ids_on_discount_to_columns.php new file mode 100644 index 0000000000..37f7622df3 --- /dev/null +++ b/src/migrations/m240306_091057_move_element_ids_on_discount_to_columns.php @@ -0,0 +1,63 @@ +addColumn($discountsTable, 'purchasableIds', $this->text()->after('allPurchasables')); + $this->addColumn($discountsTable, 'categoryIds', $this->text()->after('allCategories')); + + $purchasableIdsByDiscountId = (new Query()) + ->select(['discountId', 'purchasableId']) + ->from([$discountPurchasablesTables]) + ->collect(); + + $purchasableIdsByDiscountId = $purchasableIdsByDiscountId->groupBy('discountId')->map(function($row) { + return array_column($row->toArray(), 'purchasableId'); + }); + + $categoryIdsByDiscountId = (new Query()) + ->select(['discountId', 'categoryId']) + ->from([$discountCategoriesTable]) + ->collect(); + + $categoryIdsByDiscountId = $categoryIdsByDiscountId->groupBy('discountId')->map(function($row) { + return array_column($row->toArray(), 'categoryId'); + }); + + foreach ($purchasableIdsByDiscountId as $discountId => $purchasableIds) { + $this->update($discountsTable, ['purchasableIds' => Json::encode($purchasableIds)], ['id' => $discountId]); + } + + foreach ($categoryIdsByDiscountId as $discountId => $categoryIds) { + $this->update($discountsTable, ['categoryIds' => Json::encode($categoryIds)], ['id' => $discountId]); + } + + return true; + } + + /** + * @inheritdoc + */ + public function safeDown(): bool + { + echo "m240306_091057_move_element_ids_on_discount_to_columns cannot be reverted.\n"; + return false; + } +} diff --git a/src/records/Discount.php b/src/records/Discount.php index 3dcfaa9a05..bbf06f9605 100644 --- a/src/records/Discount.php +++ b/src/records/Discount.php @@ -18,7 +18,9 @@ * Discount record. * * @property bool $allCategories + * @property ?array $categoryIds * @property bool $allPurchasables + * @property ?array $purchasableIds * @property float $baseDiscount * @property float $purchaseTotal * @property string $baseDiscountType diff --git a/src/services/Discounts.php b/src/services/Discounts.php index 56a1e2575d..b65e19e02f 100644 --- a/src/services/Discounts.php +++ b/src/services/Discounts.php @@ -34,7 +34,7 @@ use craft\helpers\ArrayHelper; use craft\helpers\DateTimeHelper; use craft\helpers\Db; -use craft\helpers\StringHelper; +use craft\helpers\Json; use DateTime; use Throwable; use Twig\Error\LoaderError; @@ -741,6 +741,8 @@ public function saveDiscount(Discount $model, bool $runValidation = true): bool $record->totalDiscountUseLimit = $model->totalDiscountUseLimit; $record->ignoreSales = $model->ignoreSales; $record->appliedTo = $model->appliedTo; + $record->purchasableIds = $model->getPurchasableIds(); + $record->categoryIds = $model->getCategoryIds(); // If the discount is new, set the sort order to be at the top of the list. // We will ensure the sort orders are sequential when we save the discount. @@ -752,9 +754,11 @@ public function saveDiscount(Discount $model, bool $runValidation = true): bool $record->categoryRelationshipType = $model->categoryRelationshipType; if ($record->allCategories = $model->allCategories) { $model->setCategoryIds([]); + $record->categoryIds = null; } if ($record->allPurchasables = $model->allPurchasables) { $model->setPurchasableIds([]); + $record->purchasableIds = null; } $db = Craft::$app->getDb(); @@ -1234,9 +1238,10 @@ private function _populateDiscounts(array $discounts): array { foreach ($discounts as &$discount) { // @TODO remove this when we can widen the accepted params on the setters - $discount['purchasableIds'] = !empty($discount['purchasableIds']) ? StringHelper::split($discount['purchasableIds']) : []; + + $discount['purchasableIds'] = !empty($discount['purchasableIds']) ? Json::decodeIfJson($discount['purchasableIds'], true) : []; // IDs can be either category ID or entry ID due to the entryfication - $discount['categoryIds'] = !empty($discount['categoryIds']) ? StringHelper::split($discount['categoryIds']) : []; + $discount['categoryIds'] = !empty($discount['categoryIds']) ? Json::decodeIfJson($discount['categoryIds'], true) : []; $discount['orderCondition'] = $discount['orderCondition'] ?? ''; $discount['customerCondition'] = $discount['customerCondition'] ?? ''; $discount['billingAddressCondition'] = $discount['billingAddressCondition'] ?? ''; @@ -1294,6 +1299,8 @@ private function _createDiscountQuery(): Query '[[discounts.customerCondition]]', '[[discounts.shippingAddressCondition]]', '[[discounts.billingAddressCondition]]', + '[[discounts.purchasableIds]]', + '[[discounts.categoryIds]]', ]) ->from(['discounts' => Table::DISCOUNTS]) ->orderBy(['sortOrder' => SORT_ASC]) @@ -1301,18 +1308,6 @@ private function _createDiscountQuery(): Query ->leftJoin(Table::DISCOUNT_CATEGORIES . ' dpt', '[[dpt.discountId]]=[[discounts.id]]') ->groupBy(['discounts.id']); - if (Craft::$app->getDb()->getIsPgsql()) { - $query->addSelect([ - 'purchasableIds' => new Expression("STRING_AGG([[dp.purchasableId]]::text, ',')"), - 'categoryIds' => new Expression("STRING_AGG([[dpt.categoryId]]::text, ',')"), - ]); - } else { - $query->addSelect([ - 'purchasableIds' => new Expression('GROUP_CONCAT([[dp.purchasableId]])'), - 'categoryIds' => new Expression('GROUP_CONCAT([[dpt.categoryId]])'), - ]); - } - return $query; } } diff --git a/src/translations/en/commerce.php b/src/translations/en/commerce.php index 6e6b95da0c..9a5f6e4491 100644 --- a/src/translations/en/commerce.php +++ b/src/translations/en/commerce.php @@ -509,7 +509,6 @@ 'Invalid formula syntax' => 'Invalid formula syntax', 'Invalid gateway: {value}' => 'Invalid gateway: {value}', 'Invalid order condition syntax.' => 'Invalid order condition syntax.', - 'Invalid page number.' => 'Invalid page number.', 'Invalid payment or order. Please review.' => 'Invalid payment or order. Please review.', 'Invalid payment source ID: {value}' => 'Invalid payment source ID: {value}', 'Invoice amount' => 'Invoice amount', @@ -951,7 +950,6 @@ 'Switch' => 'Switch', 'System Settings' => 'System Settings', 'System' => 'System', - 'Tax & Shipping (Lite)' => 'Tax & Shipping (Lite)', 'Tax & Shipping' => 'Tax & Shipping', 'Tax (inc)' => 'Tax (inc)', 'Tax Categories' => 'Tax Categories', diff --git a/src/web/assets/commercecp/dist/commercecp.js b/src/web/assets/commercecp/dist/commercecp.js index 5ef033ae22..a15f50c7d5 100644 --- a/src/web/assets/commercecp/dist/commercecp.js +++ b/src/web/assets/commercecp/dist/commercecp.js @@ -1,2 +1,2 @@ -!function(){var t={528:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}!function(e){"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.initUnlimitedStockCheckbox=function(t){t.find("input.unlimited-stock:first").change(Craft.Commerce.handleUnlimitedStockCheckboxChange)},Craft.Commerce.handleUnlimitedStockCheckboxChange=function(t){var n=e(t.currentTarget),a=n.parent().prevAll(".textwrapper:first").children(".text:first");n.prop("checked")?a.prop("disabled",!0).addClass("disabled").val(""):a.prop("disabled",!1).removeClass("disabled").focus()}}(jQuery)},322:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.OrderEdit=Garnish.Base.extend({orderId:null,paymentForm:null,paymentAmount:null,paymentCurrency:null,$makePayment:null,init:function(t){this.setSettings(t),this.orderId=this.settings.orderId,this.paymentForm=this.settings.paymentForm,this.paymentAmount=this.settings.paymentAmount,this.paymentCurrency=this.settings.paymentCurrency,this.$makePayment=$("#make-payment"),this.addListener(this.$makePayment,"click","makePayment"),Object.keys(this.paymentForm.errors).length>0&&this.openPaymentModal()},openPaymentModal:function(){this.paymentModal?this.paymentModal.show():this.paymentModal=new Craft.Commerce.PaymentModal({orderId:this.orderId,paymentForm:this.paymentForm,paymentAmount:this.paymentAmount,paymentCurrency:this.paymentCurrency})},makePayment:function(t){t.preventDefault(),this.openPaymentModal()},_getCountries:function(){return window.countries}},{defaults:{orderId:null,paymentForm:null,paymentAmount:null,paymentCurrency:null,$makePayment:null}})},588:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.OrderIndex=Craft.BaseElementIndex.extend({startDate:null,endDate:null,init:function(t,e,n){if(this.on("selectSource",$.proxy(this,"updateSelectedSource")),this.base(t,e,n),Craft.ui.createDateRangePicker({onChange:function(t,e){this.startDate=t,this.endDate=e,this.updateElements()}.bind(this)}).appendTo(this.$toolbar),window.orderEdit&&window.orderEdit.currentUserPermissions["commerce-editOrders"]){var a=$("",{class:"btn submit icon add",href:Craft.getUrl("commerce/orders/create"),text:Craft.t("commerce","New Order")});this.addButton(a)}},updateSelectedSource:function(){var t="all"!==(this.$source?this.$source:"all")?this.$source.data("handle"):null;if("index"===this.settings.context&&"undefined"!=typeof history){var e="commerce/orders";t&&(e+="/"+t),history.replaceState({},"",Craft.getUrl(e))}},getDefaultSourceKey:function(){var t=window.defaultStatusHandle;if(t)for(var e=0;e="+this.startDate.getTime()/1e3),this.endDate&&t.criteria[e].push("<"+(this.endDate.getTime()/1e3+86400))}return t},updateSourcesBadgeCounts:function(){$.ajax({url:Craft.getActionUrl("commerce/orders/get-index-sources-badge-counts"),type:"GET",dataType:"json",success:$.proxy((function(t){if(t.counts){var e=this.$sidebar;$.each(t.counts,(function(t,n){var a=e.find('nav a[data-key="orderStatus:'+n.handle+'"]');a&&a.find(".badge").text(n.orderCount)}))}if(t.total){var n=this.$sidebar.find('nav a[data-key="*"]');n&&n.find(".badge").text(t.total)}}),this)})},setIndexAvailable:function(){this.updateSourcesBadgeCounts(),this.base()}}),Craft.registerElementIndexClass("craft\\commerce\\elements\\Order",Craft.Commerce.OrderIndex)},255:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.PaymentModal=Garnish.Modal.extend({$container:null,$body:null,init:function(t){var e=this;this.$container=$("",{id:"paymentmodal",class:"modal fitted loading"}).appendTo(Garnish.$bod),this.base(this.$container,$.extend({resizable:!1},t));var n={orderId:t.orderId,paymentForm:t.paymentForm,paymentAmount:t.paymentAmount,paymentCurrency:t.paymentCurrency};Craft.sendActionRequest("POST","commerce/orders/get-payment-modal",{data:n}).then((function(t){e.$container.removeClass("loading");var n=e;e.$container.append(t.data.modalHtml),Craft.appendHeadHtml(t.data.headHtml),Craft.appendFootHtml(t.data.footHtml);var a=$(".buttons",e.$container),s=$(''+Craft.t("commerce","Cancel")+"").prependTo(a);e.addListener(s,"click","cancelPayment"),$("select#payment-form-select").change($.proxy((function(t){var e=$(t.currentTarget).val();$(".gateway-form").addClass("hidden"),$("#gateway-"+e+"-form").removeClass("hidden"),setTimeout((function(){Craft.initUiElements(this.$container),n.updateSizeAndPosition()}),200)}),e)).trigger("change"),setTimeout((function(){Craft.initUiElements(this.$container),n.updateSizeAndPosition()}),200)})).catch((function(t){var n=t.response;e.$container.removeClass("loading");var a=Craft.t("commerce","An unknown error occurred.");n.data.message&&(a=n.data.message),e.$container.append(''+a+"")}))},cancelPayment:function(){this.hide()}},{})},166:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.ProductSalesModal=Garnish.Modal.extend({id:null,$newSale:null,$cancelBtn:null,$select:null,$saveBtn:null,$spinner:null,$purchasableCheckboxes:[],init:function(t,e){this.id=Math.floor(1e9*Math.random()),this.setSettings(e,this.defaults),this.$form=$('').appendTo(Garnish.$bod);var n=$('').appendTo(this.$form),a=$("",{class:"content"}).append($("",{class:"first",text:Craft.t("commerce","Add Product to Sale")})).append($("",{text:Craft.t("commerce","Add this product to an existing sale. This will change the conditions of the sale, please review the sale.")})).appendTo(n);if(this.settings.purchasables.length){var s=$('');$("",{class:"heading"}).append($("",{text:Craft.t("commerce","Select Variants")})).appendTo(s);var o=$('');$.each(this.settings.purchasables,$.proxy((function(t,e){var n=$("",{class:"checkbox",type:"checkbox",name:"ids[]",id:"add-to-sale-purchasable-"+e.id,value:e.id,checked:!0}),a=$("").append($("",{for:"add-to-sale-purchasable-"+e.id,text:e.title+" "}).append("",{class:"extralight",text:e.sku}));n.on("change",$.proxy((function(){this.updateNewSaleUrl()}),this)),this.$purchasableCheckboxes.push(n),n.prependTo(a),a.appendTo(o)}),this)),o.appendTo(s),s.appendTo(a)}if(t&&t.length){this.$select=$(''),$('----').appendTo(this.$select);for(var r=0;r=0&&(d=!0),this.$select.append($("",{disabled:d,text:Craft.escapeHtml(i.name),value:i.id}))}var l=$(''),c=$('');this.$select.appendTo(c),c.appendTo(l);var u=$('');$('').append($("",{text:Craft.t("commerce","Sale")})).appendTo(u),c.appendTo(u),u.appendTo(a),this.$select.on("change",$.proxy(this,"handleSaleChange"))}this.$error=$('').appendTo(a);var p=$('').appendTo(this.$form),f=$('').appendTo(p);this.$newSale=$("",{class:"btn icon add",target:"_blank",href:"",text:Craft.t("commerce","Create Sale")}).appendTo(f);var m=$('').appendTo(p),h=$('').appendTo(m);this.$cancelBtn=$("",{type:"button",class:"btn",value:Craft.t("commerce","Cancel")}).appendTo(h),this.$saveBtn=$("",{type:"button",class:"btn submit",value:Craft.t("commerce","Add")}).appendTo(h),this.$spinner=$('').appendTo(m),this.$saveBtn.addClass("disabled"),this.addListener(this.$cancelBtn,"click","hide"),this.addListener(this.$saveBtn,"click",$.proxy((function(t){t.preventDefault(),$(t.target).hasClass("disabled")||(this.$spinner.removeClass("hidden"),this.saveSale())}),this)),this.updateNewSaleUrl(),this.base(this.$form,this.settings)},updateNewSaleUrl:function(){var t=Craft.getUrl("commerce/promotions/sales/new");if(this.settings.id&&(t=Craft.getUrl("commerce/promotions/sales/new?purchasableIds="+this.settings.id)),this.$purchasableCheckboxes.length){var e=[];this.$purchasableCheckboxes.forEach((function(t){$(t).prop("checked")&&e.push($(t).val())})),e.length&&(t=Craft.getUrl("commerce/promotions/sales/new?purchasableIds="+e.join("|")))}this.$newSale.attr("href",t)},saveSale:function(){var t=this,e=this.$form.find('select[name="sale"]').val(),n=[];this.settings.purchasables.length?this.$form.find("input.checkbox:checked").each((function(t){n.push($(this).val())})):this.settings.id&&(n=[this.settings.id]);var a={ids:n,saleId:e};Craft.sendActionRequest("POST","commerce/sales/add-purchasable-to-sale",{data:a}).then((function(e){Craft.cp.displayNotice(Craft.t("commerce","Added to Sale.")),t.hide()})).catch((function(t){var e=t.response;Craft.cp.displayError(e.data&&e.data.message)})).finally((function(){t.$spinner.addClass("hidden")}))},handleSaleChange:function(t){""!=this.$select.val()?this.$saveBtn.removeClass("disabled"):this.$saveBtn.addClass("disabled")},defaults:{onSubmit:$.noop,id:null,productId:null,purchasables:[],existingSaleIds:[]}})},863:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.CommerceShippingItemRatesValuesInput=Craft.BaseInputGenerator.extend({startListening:function(){this.listening||(this.listening=!0,this.addListener(this.$source,"textchange","onSourceTextChange"),this.addListener(this.$form,"submit","onFormSubmit"))},updateTarget:function(){var t=this.$source.val(),e=this.generateTargetValue(t);this.$target.prop("placeholder",e)},onFormSubmit:function(){this.timeout&&clearTimeout(this.timeout)}})},341:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.SubscriptionsIndex=Craft.BaseElementIndex.extend({}),Craft.registerElementIndexClass("craft\\commerce\\elements\\Subscription",Craft.Commerce.SubscriptionsIndex)},607:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.UpdateOrderStatusModal=Garnish.Modal.extend({id:null,orderStatusId:null,originalStatus:null,currentStatus:null,originalStatusId:null,$statusSelect:null,$selectedStatus:null,$orderStatusIdInput:null,$message:null,$error:null,$updateBtn:null,$statusMenuBtn:null,$cancelBtn:null,$suppress:null,init:function(t,e,n){this.id=Math.floor(1e9*Math.random()),n.onHide=$.proxy((function(){this.destroy()}),this),this.setSettings(n,{resizable:!1}),this.originalStatusId=t.id,this.currentStatus=t;var a=$('').appendTo(Garnish.$bod),s=$('').appendTo(a),o=$("",{class:"content"}).append($("",{class:"first",text:Craft.t("commerce","Update Order Status")})).appendTo(s);this.$statusSelect=$("",{class:"btn menubtn",href:"#",html:$('')}).append(t.name).appendTo(o);for(var r=$('').appendTo(o),i=$('').appendTo(r),d="",l=0;l").append($("",{class:d,"data-id":e[l].id,"data-name":e[l].name,"data-color":e[l].color}).append('').append(e[l].name)).appendTo(i);this.$selectedStatus=$(".sel",i),this.$message=$("",{class:"field"}).append($("",{class:"heading"}).append($("",{text:Craft.t("commerce","Message")})).append($("",{class:"instructions",text:Craft.t("commerce","Status change message")}))).append($("",{class:"input ltr"}).append($("",{name:"message",rows:2,cols:50,maxlength:1e4,class:"text fullwidth"}))).appendTo(o);var c=$("",{class:"input"}).append($("",{id:"order-action-suppress-emails",name:"suppressEmails",type:"checkbox",class:"checkbox",value:"1"})).append($("",{for:"order-action-suppress-emails",text:Craft.t("commerce","Suppress emails")}));this.$suppress=$("",{class:"field"}).append(c).appendTo(o),this.$error=$('').appendTo(o);var u=$('').appendTo(a),p=$('').appendTo(u);this.$cancelBtn=$("",{type:"button",class:"btn",value:Craft.t("commerce","Cancel")}).appendTo(p),this.$updateBtn=$("",{type:"button",class:"btn submit",value:Craft.t("commerce","Update")}).appendTo(p),this.$updateBtn.addClass("disabled"),this.$statusMenuBtn=new Garnish.MenuBtn(this.$statusSelect,{onOptionSelect:$.proxy(this,"onSelectStatus")}),this.addListener(this.$cancelBtn,"click","onCancelClick"),this.addListener(this.$updateBtn,"click",(function(t){t.preventDefault(),$(t.target).hasClass("disabled")||this.updateStatus()})),this.base(a,n)},onCancelClick:function(){Craft.elementIndex.setIndexAvailable(),this.hide()},onSelectStatus:function(t){this.deselectStatus(),this.$selectedStatus=$(t),this.$selectedStatus.addClass("sel"),this.currentStatus={id:$(t).data("id"),name:$(t).data("name"),color:$(t).data("color")};var e=$("",{html:$('')}).append(Craft.uppercaseFirst(this.currentStatus.name));this.$statusSelect.html(e),this.originalStatusId===this.currentStatus.id?this.$updateBtn.addClass("disabled"):this.$updateBtn.removeClass("disabled")},deselectStatus:function(){this.$selectedStatus&&this.$selectedStatus.removeClass("sel")},updateStatus:function(){var t={orderStatusId:this.currentStatus.id,message:this.$message.find('textarea[name="message"]').val(),color:this.currentStatus.color,name:this.currentStatus.name,suppressEmails:this.$suppress.find('input[name="suppressEmails"]').is(":checked")};this.settings.onSubmit(t)},defaults:{onSubmit:$.noop}})},565:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.VariantValuesInput=Craft.BaseInputGenerator.extend({startListening:function(){this.listening||(this.listening=!0,this.addListener(this.$source,"textchange","onTextChange"),this.addListener(this.$form,"submit","onFormSubmit"))},updateTarget:function(){var t=this.$source.val();this.generateTargetValue(t),this.$target.prop("checked",!0)},onFormSubmit:function(){this.timeout&&clearTimeout(this.timeout)}})},645:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.DownloadOrderPdfAction=Garnish.Base.extend({$btn:null,$actionForm:null,hud:null,types:null,$hudBody:null,init:function(t,e,n){this.$btn=t,this.pdfs=e,this.types=n,this.$actionForm=this.$btn.closest("form"),this.$hudBody=$("",{class:"export-form"}),this.addListener(this.$btn,"click","showHud")},showHud:function(){var t=this;if(this.hud)this.hud.show();else{Craft.ui.createSelectField({label:Craft.t("commerce","PDF"),name:"pdfId",options:this.pdfs,class:"fullwidth"}).appendTo(this.$hudBody),Craft.ui.createSelectField({label:Craft.t("commerce","Download Type"),name:"type",options:this.types,class:"fullwidth"}).appendTo(this.$hudBody);var e=$("",{type:"submit",class:"btn submit fullwidth formsubmit",text:Craft.t("commerce","Download")}).appendTo(this.$hudBody);$("",{class:"spinner hidden"}).appendTo(this.$hudBody),this.hud=new Garnish.HUD(this.$btn,this.$hudBody,{hudClass:"hud"}),this.hud.on("hide",(function(){t.$btn.removeClass("active")}));var n=!1;e.on("click",$.proxy((function(t){if(t.preventDefault(),!n){n=!0;var e=this.$hudBody.find('[name="pdfId"]'),a=this.$hudBody.find('[name="type"]');this.$actionForm.find("input#pdf-id").val(e.val()),this.$actionForm.find("input#download-type").val(a.val()),this.$actionForm.submit(),n=!1,this.hud.hide()}}),this))}}})},237:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.TableRowAdditionalInfoIcon=Garnish.Base.extend({$icon:null,hud:null,init:function(t){this.$icon=$(t),this.addListener(this.$icon,"click","showHud")},showHud:function(){if(this.hud)this.hud.show();else{for(var t=this.$icon.closest(".infoRow"),e=$(""),n=($("Details").appendTo(e),$("").appendTo(e).find("tbody")),a=t.data("info"),s=0;s").appendTo(n),i=($("").append($("").text(Craft.t("commerce",a[s].label))).appendTo(r),a[s].value);switch(a[s].type){case"code":o=$(""+i+"");break;case"response":try{i=''+JSON.stringify(JSON.parse(i),void 0,4)+""}catch(t){i=''+$("").text(i).html()+""}o=$(''+i+""),Prism.highlightElement(o.find("code").get(0));break;default:o=$(""+i+"")}o.appendTo(r)}this.hud=new Garnish.HUD(this.$icon,e,{hudClass:"hud"})}}})},74:function(){},531:function(){},157:function(){},992:function(){},877:function(){},316:function(t,e,n){var a=n(74);a.__esModule&&(a=a.default),"string"==typeof a&&(a=[[t.id,a,""]]),a.locals&&(t.exports=a.locals),(0,n(673).Z)("354d7708",a,!0,{})},810:function(t,e,n){var a=n(531);a.__esModule&&(a=a.default),"string"==typeof a&&(a=[[t.id,a,""]]),a.locals&&(t.exports=a.locals),(0,n(673).Z)("c8f97f3c",a,!0,{})},714:function(t,e,n){var a=n(157);a.__esModule&&(a=a.default),"string"==typeof a&&(a=[[t.id,a,""]]),a.locals&&(t.exports=a.locals),(0,n(673).Z)("e69138b8",a,!0,{})},331:function(t,e,n){var a=n(992);a.__esModule&&(a=a.default),"string"==typeof a&&(a=[[t.id,a,""]]),a.locals&&(t.exports=a.locals),(0,n(673).Z)("7a191bbc",a,!0,{})},660:function(t,e,n){var a=n(877);a.__esModule&&(a=a.default),"string"==typeof a&&(a=[[t.id,a,""]]),a.locals&&(t.exports=a.locals),(0,n(673).Z)("135c0354",a,!0,{})},673:function(t,e,n){"use strict";function a(t,e){for(var n=[],a={},s=0;sn.parts.length&&(a.parts.length=n.parts.length)}else{var r=[];for(s=0;s0&&this.openPaymentModal()},openPaymentModal:function(){this.paymentModal?this.paymentModal.show():this.paymentModal=new Craft.Commerce.PaymentModal({orderId:this.orderId,paymentForm:this.paymentForm,paymentAmount:this.paymentAmount,paymentCurrency:this.paymentCurrency})},makePayment:function(t){t.preventDefault(),this.openPaymentModal()},_getCountries:function(){return window.countries}},{defaults:{orderId:null,paymentForm:null,paymentAmount:null,paymentCurrency:null,$makePayment:null}})},588:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.OrderIndex=Craft.BaseElementIndex.extend({startDate:null,endDate:null,init:function(t,e,n){if(this.on("selectSource",$.proxy(this,"updateSelectedSource")),this.base(t,e,n),Craft.ui.createDateRangePicker({onChange:function(t,e){this.startDate=t,this.endDate=e,this.updateElements()}.bind(this)}).appendTo(this.$toolbar),window.orderEdit&&window.orderEdit.currentUserPermissions["commerce-editOrders"]){var a=$("",{class:"btn submit icon add",href:Craft.getUrl("commerce/orders/create"),text:Craft.t("commerce","New Order")});this.addButton(a)}},updateSelectedSource:function(){var t="all"!==(this.$source?this.$source:"all")?this.$source.data("handle"):null;if("index"===this.settings.context&&"undefined"!=typeof history){var e="commerce/orders";t&&(e+="/"+t),history.replaceState({},"",Craft.getUrl(e))}},getDefaultSourceKey:function(){var t=window.defaultStatusHandle;if(t)for(var e=0;e="+this.startDate.getTime()/1e3),this.endDate&&t.criteria[e].push("<"+(this.endDate.getTime()/1e3+86400))}return t},updateSourcesBadgeCounts:function(){$.ajax({url:Craft.getActionUrl("commerce/orders/get-index-sources-badge-counts"),type:"GET",dataType:"json",success:$.proxy((function(t){if(t.counts){var e=this.$sidebar;$.each(t.counts,(function(t,n){var a=e.find('nav a[data-key="orderStatus:'+n.handle+'"]');if(a){var s=a.find(".badge");if(0===n.orderCount)return void(s.length&&s.remove());s.length||(s=$('').appendTo(a)),a.find(".badge").text(n.orderCount)}}))}if(t.total){var n=this.$sidebar.find('nav a[data-key="*"]');if(n){var a=n.find(".badge");if(0===t.total)return void(a.length&&a.remove());a.length||(a=$('').appendTo(n)),n.find(".badge").text(t.total)}}}),this)})},setIndexAvailable:function(){this.updateSourcesBadgeCounts(),this.base()}}),Craft.registerElementIndexClass("craft\\commerce\\elements\\Order",Craft.Commerce.OrderIndex)},255:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.PaymentModal=Garnish.Modal.extend({$container:null,$body:null,init:function(t){var e=this;this.$container=$("",{id:"paymentmodal",class:"modal fitted loading"}).appendTo(Garnish.$bod),this.base(this.$container,$.extend({resizable:!1},t));var n={orderId:t.orderId,paymentForm:t.paymentForm,paymentAmount:t.paymentAmount,paymentCurrency:t.paymentCurrency};Craft.sendActionRequest("POST","commerce/orders/get-payment-modal",{data:n}).then((function(t){e.$container.removeClass("loading");var n=e;e.$container.append(t.data.modalHtml),Craft.appendHeadHtml(t.data.headHtml),Craft.appendFootHtml(t.data.footHtml);var a=$(".buttons",e.$container),s=$(''+Craft.t("commerce","Cancel")+"").prependTo(a);e.addListener(s,"click","cancelPayment"),$("select#payment-form-select").change($.proxy((function(t){var e=$(t.currentTarget).val();$(".gateway-form").addClass("hidden"),$("#gateway-"+e+"-form").removeClass("hidden"),setTimeout((function(){Craft.initUiElements(this.$container),n.updateSizeAndPosition()}),200)}),e)).trigger("change"),setTimeout((function(){Craft.initUiElements(this.$container),n.updateSizeAndPosition()}),200)})).catch((function(t){var n=t.response;e.$container.removeClass("loading");var a=Craft.t("commerce","An unknown error occurred.");n.data.message&&(a=n.data.message),e.$container.append(''+a+"")}))},cancelPayment:function(){this.hide()}},{})},166:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.ProductSalesModal=Garnish.Modal.extend({id:null,$newSale:null,$cancelBtn:null,$select:null,$saveBtn:null,$spinner:null,$purchasableCheckboxes:[],init:function(t,e){this.id=Math.floor(1e9*Math.random()),this.setSettings(e,this.defaults),this.$form=$('').appendTo(Garnish.$bod);var n=$('').appendTo(this.$form),a=$("",{class:"content"}).append($("",{class:"first",text:Craft.t("commerce","Add Product to Sale")})).append($("",{text:Craft.t("commerce","Add this product to an existing sale. This will change the conditions of the sale, please review the sale.")})).appendTo(n);if(this.settings.purchasables.length){var s=$('');$("",{class:"heading"}).append($("",{text:Craft.t("commerce","Select Variants")})).appendTo(s);var o=$('');$.each(this.settings.purchasables,$.proxy((function(t,e){var n=$("",{class:"checkbox",type:"checkbox",name:"ids[]",id:"add-to-sale-purchasable-"+e.id,value:e.id,checked:!0}),a=$("").append($("",{for:"add-to-sale-purchasable-"+e.id,text:e.title+" "}).append("",{class:"extralight",text:e.sku}));n.on("change",$.proxy((function(){this.updateNewSaleUrl()}),this)),this.$purchasableCheckboxes.push(n),n.prependTo(a),a.appendTo(o)}),this)),o.appendTo(s),s.appendTo(a)}if(t&&t.length){this.$select=$(''),$('----').appendTo(this.$select);for(var r=0;r=0&&(d=!0),this.$select.append($("",{disabled:d,text:Craft.escapeHtml(i.name),value:i.id}))}var l=$(''),c=$('');this.$select.appendTo(c),c.appendTo(l);var u=$('');$('').append($("",{text:Craft.t("commerce","Sale")})).appendTo(u),c.appendTo(u),u.appendTo(a),this.$select.on("change",$.proxy(this,"handleSaleChange"))}this.$error=$('').appendTo(a);var p=$('').appendTo(this.$form),f=$('').appendTo(p);this.$newSale=$("",{class:"btn icon add",target:"_blank",href:"",text:Craft.t("commerce","Create Sale")}).appendTo(f);var m=$('').appendTo(p),h=$('').appendTo(m);this.$cancelBtn=$("",{type:"button",class:"btn",value:Craft.t("commerce","Cancel")}).appendTo(h),this.$saveBtn=$("",{type:"button",class:"btn submit",value:Craft.t("commerce","Add")}).appendTo(h),this.$spinner=$('').appendTo(m),this.$saveBtn.addClass("disabled"),this.addListener(this.$cancelBtn,"click","hide"),this.addListener(this.$saveBtn,"click",$.proxy((function(t){t.preventDefault(),$(t.target).hasClass("disabled")||(this.$spinner.removeClass("hidden"),this.saveSale())}),this)),this.updateNewSaleUrl(),this.base(this.$form,this.settings)},updateNewSaleUrl:function(){var t=Craft.getUrl("commerce/promotions/sales/new");if(this.settings.id&&(t=Craft.getUrl("commerce/promotions/sales/new?purchasableIds="+this.settings.id)),this.$purchasableCheckboxes.length){var e=[];this.$purchasableCheckboxes.forEach((function(t){$(t).prop("checked")&&e.push($(t).val())})),e.length&&(t=Craft.getUrl("commerce/promotions/sales/new?purchasableIds="+e.join("|")))}this.$newSale.attr("href",t)},saveSale:function(){var t=this,e=this.$form.find('select[name="sale"]').val(),n=[];this.settings.purchasables.length?this.$form.find("input.checkbox:checked").each((function(t){n.push($(this).val())})):this.settings.id&&(n=[this.settings.id]);var a={ids:n,saleId:e};Craft.sendActionRequest("POST","commerce/sales/add-purchasable-to-sale",{data:a}).then((function(e){Craft.cp.displayNotice(Craft.t("commerce","Added to Sale.")),t.hide()})).catch((function(t){var e=t.response;Craft.cp.displayError(e.data&&e.data.message)})).finally((function(){t.$spinner.addClass("hidden")}))},handleSaleChange:function(t){""!=this.$select.val()?this.$saveBtn.removeClass("disabled"):this.$saveBtn.addClass("disabled")},defaults:{onSubmit:$.noop,id:null,productId:null,purchasables:[],existingSaleIds:[]}})},863:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.CommerceShippingItemRatesValuesInput=Craft.BaseInputGenerator.extend({startListening:function(){this.listening||(this.listening=!0,this.addListener(this.$source,"textchange","onSourceTextChange"),this.addListener(this.$form,"submit","onFormSubmit"))},updateTarget:function(){var t=this.$source.val(),e=this.generateTargetValue(t);this.$target.prop("placeholder",e)},onFormSubmit:function(){this.timeout&&clearTimeout(this.timeout)}})},341:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.SubscriptionsIndex=Craft.BaseElementIndex.extend({}),Craft.registerElementIndexClass("craft\\commerce\\elements\\Subscription",Craft.Commerce.SubscriptionsIndex)},607:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.UpdateOrderStatusModal=Garnish.Modal.extend({id:null,orderStatusId:null,originalStatus:null,currentStatus:null,originalStatusId:null,$statusSelect:null,$selectedStatus:null,$orderStatusIdInput:null,$message:null,$error:null,$updateBtn:null,$statusMenuBtn:null,$cancelBtn:null,$suppress:null,init:function(t,e,n){this.id=Math.floor(1e9*Math.random()),n.onHide=$.proxy((function(){this.destroy()}),this),this.setSettings(n,{resizable:!1}),this.originalStatusId=t.id,this.currentStatus=t;var a=$('').appendTo(Garnish.$bod),s=$('').appendTo(a),o=$("",{class:"content"}).append($("",{class:"first",text:Craft.t("commerce","Update Order Status")})).appendTo(s);this.$statusSelect=$("",{class:"btn menubtn",href:"#",html:$('')}).append(t.name).appendTo(o);for(var r=$('').appendTo(o),i=$('').appendTo(r),d="",l=0;l").append($("",{class:d,"data-id":e[l].id,"data-name":e[l].name,"data-color":e[l].color}).append('').append(e[l].name)).appendTo(i);this.$selectedStatus=$(".sel",i),this.$message=$("",{class:"field"}).append($("",{class:"heading"}).append($("",{text:Craft.t("commerce","Message")})).append($("",{class:"instructions",text:Craft.t("commerce","Status change message")}))).append($("",{class:"input ltr"}).append($("",{name:"message",rows:2,cols:50,maxlength:1e4,class:"text fullwidth"}))).appendTo(o);var c=$("",{class:"input"}).append($("",{id:"order-action-suppress-emails",name:"suppressEmails",type:"checkbox",class:"checkbox",value:"1"})).append($("",{for:"order-action-suppress-emails",text:Craft.t("commerce","Suppress emails")}));this.$suppress=$("",{class:"field"}).append(c).appendTo(o),this.$error=$('').appendTo(o);var u=$('').appendTo(a),p=$('').appendTo(u);this.$cancelBtn=$("",{type:"button",class:"btn",value:Craft.t("commerce","Cancel")}).appendTo(p),this.$updateBtn=$("",{type:"button",class:"btn submit",value:Craft.t("commerce","Update")}).appendTo(p),this.$updateBtn.addClass("disabled"),this.$statusMenuBtn=new Garnish.MenuBtn(this.$statusSelect,{onOptionSelect:$.proxy(this,"onSelectStatus")}),this.addListener(this.$cancelBtn,"click","onCancelClick"),this.addListener(this.$updateBtn,"click",(function(t){t.preventDefault(),$(t.target).hasClass("disabled")||this.updateStatus()})),this.base(a,n)},onCancelClick:function(){Craft.elementIndex.setIndexAvailable(),this.hide()},onSelectStatus:function(t){this.deselectStatus(),this.$selectedStatus=$(t),this.$selectedStatus.addClass("sel"),this.currentStatus={id:$(t).data("id"),name:$(t).data("name"),color:$(t).data("color")};var e=$("",{html:$('')}).append(Craft.uppercaseFirst(this.currentStatus.name));this.$statusSelect.html(e),this.originalStatusId===this.currentStatus.id?this.$updateBtn.addClass("disabled"):this.$updateBtn.removeClass("disabled")},deselectStatus:function(){this.$selectedStatus&&this.$selectedStatus.removeClass("sel")},updateStatus:function(){var t={orderStatusId:this.currentStatus.id,message:this.$message.find('textarea[name="message"]').val(),color:this.currentStatus.color,name:this.currentStatus.name,suppressEmails:this.$suppress.find('input[name="suppressEmails"]').is(":checked")};this.settings.onSubmit(t)},defaults:{onSubmit:$.noop}})},565:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.VariantValuesInput=Craft.BaseInputGenerator.extend({startListening:function(){this.listening||(this.listening=!0,this.addListener(this.$source,"textchange","onTextChange"),this.addListener(this.$form,"submit","onFormSubmit"))},updateTarget:function(){var t=this.$source.val();this.generateTargetValue(t),this.$target.prop("checked",!0)},onFormSubmit:function(){this.timeout&&clearTimeout(this.timeout)}})},645:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.DownloadOrderPdfAction=Garnish.Base.extend({$btn:null,$actionForm:null,hud:null,types:null,$hudBody:null,init:function(t,e,n){this.$btn=t,this.pdfs=e,this.types=n,this.$actionForm=this.$btn.closest("form"),this.$hudBody=$("",{class:"export-form"}),this.addListener(this.$btn,"click","showHud")},showHud:function(){var t=this;if(this.hud)this.hud.show();else{Craft.ui.createSelectField({label:Craft.t("commerce","PDF"),name:"pdfId",options:this.pdfs,class:"fullwidth"}).appendTo(this.$hudBody),Craft.ui.createSelectField({label:Craft.t("commerce","Download Type"),name:"type",options:this.types,class:"fullwidth"}).appendTo(this.$hudBody);var e=$("",{type:"submit",class:"btn submit fullwidth formsubmit",text:Craft.t("commerce","Download")}).appendTo(this.$hudBody);$("",{class:"spinner hidden"}).appendTo(this.$hudBody),this.hud=new Garnish.HUD(this.$btn,this.$hudBody,{hudClass:"hud"}),this.hud.on("hide",(function(){t.$btn.removeClass("active")}));var n=!1;e.on("click",$.proxy((function(t){if(t.preventDefault(),!n){n=!0;var e=this.$hudBody.find('[name="pdfId"]'),a=this.$hudBody.find('[name="type"]');this.$actionForm.find("input#pdf-id").val(e.val()),this.$actionForm.find("input#download-type").val(a.val()),this.$actionForm.submit(),n=!1,this.hud.hide()}}),this))}}})},237:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}"undefined"===t(Craft.Commerce)&&(Craft.Commerce={}),Craft.Commerce.TableRowAdditionalInfoIcon=Garnish.Base.extend({$icon:null,hud:null,init:function(t){this.$icon=$(t),this.addListener(this.$icon,"click","showHud")},showHud:function(){if(this.hud)this.hud.show();else{for(var t=this.$icon.closest(".infoRow"),e=$(""),n=($("Details").appendTo(e),$("").appendTo(e).find("tbody")),a=t.data("info"),s=0;s").appendTo(n),i=($("").append($("").text(Craft.t("commerce",a[s].label))).appendTo(r),a[s].value);switch(a[s].type){case"code":o=$(""+i+"");break;case"response":try{i=''+JSON.stringify(JSON.parse(i),void 0,4)+""}catch(t){i=''+$("").text(i).html()+""}o=$(''+i+""),Prism.highlightElement(o.find("code").get(0));break;default:o=$(""+i+"")}o.appendTo(r)}this.hud=new Garnish.HUD(this.$icon,e,{hudClass:"hud"})}}})},74:function(){},531:function(){},157:function(){},992:function(){},877:function(){},316:function(t,e,n){var a=n(74);a.__esModule&&(a=a.default),"string"==typeof a&&(a=[[t.id,a,""]]),a.locals&&(t.exports=a.locals),(0,n(673).Z)("354d7708",a,!0,{})},810:function(t,e,n){var a=n(531);a.__esModule&&(a=a.default),"string"==typeof a&&(a=[[t.id,a,""]]),a.locals&&(t.exports=a.locals),(0,n(673).Z)("c8f97f3c",a,!0,{})},714:function(t,e,n){var a=n(157);a.__esModule&&(a=a.default),"string"==typeof a&&(a=[[t.id,a,""]]),a.locals&&(t.exports=a.locals),(0,n(673).Z)("e69138b8",a,!0,{})},331:function(t,e,n){var a=n(992);a.__esModule&&(a=a.default),"string"==typeof a&&(a=[[t.id,a,""]]),a.locals&&(t.exports=a.locals),(0,n(673).Z)("7a191bbc",a,!0,{})},660:function(t,e,n){var a=n(877);a.__esModule&&(a=a.default),"string"==typeof a&&(a=[[t.id,a,""]]),a.locals&&(t.exports=a.locals),(0,n(673).Z)("135c0354",a,!0,{})},673:function(t,e,n){"use strict";function a(t,e){for(var n=[],a={},s=0;sn.parts.length&&(a.parts.length=n.parts.length)}else{var r=[];for(s=0;s 0) {\n this.openPaymentModal();\n }\n },\n openPaymentModal: function () {\n if (!this.paymentModal) {\n this.paymentModal = new Craft.Commerce.PaymentModal({\n orderId: this.orderId,\n paymentForm: this.paymentForm,\n paymentAmount: this.paymentAmount,\n paymentCurrency: this.paymentCurrency,\n });\n } else {\n this.paymentModal.show();\n }\n },\n makePayment: function (ev) {\n ev.preventDefault();\n\n this.openPaymentModal();\n },\n\n _getCountries: function () {\n return window.countries;\n },\n },\n {\n defaults: {\n orderId: null,\n paymentForm: null,\n paymentAmount: null,\n paymentCurrency: null,\n $makePayment: null,\n },\n }\n);\n","/* jshint esversion: 6, strict: false */\n/* globals Craft, Garnish, $ */\nif (typeof Craft.Commerce === typeof undefined) {\n Craft.Commerce = {};\n}\n\n/**\n * Class Craft.Commerce.OrderIndex\n */\nCraft.Commerce.OrderIndex = Craft.BaseElementIndex.extend({\n startDate: null,\n endDate: null,\n\n init: function (elementType, $container, settings) {\n this.on('selectSource', $.proxy(this, 'updateSelectedSource'));\n this.base(elementType, $container, settings);\n\n Craft.ui\n .createDateRangePicker({\n onChange: function (startDate, endDate) {\n this.startDate = startDate;\n this.endDate = endDate;\n this.updateElements();\n }.bind(this),\n })\n .appendTo(this.$toolbar);\n\n if (\n window.orderEdit &&\n window.orderEdit.currentUserPermissions['commerce-editOrders']\n ) {\n // Add the New Order button\n var $btn = $('', {\n class: 'btn submit icon add',\n href: Craft.getUrl('commerce/orders/create'),\n text: Craft.t('commerce', 'New Order'),\n });\n this.addButton($btn);\n }\n },\n\n updateSelectedSource() {\n var source = this.$source ? this.$source : 'all';\n var handle = source !== 'all' ? this.$source.data('handle') : null;\n\n if (this.settings.context === 'index' && typeof history !== 'undefined') {\n var uri = 'commerce/orders';\n\n if (handle) {\n uri += '/' + handle;\n }\n\n history.replaceState({}, '', Craft.getUrl(uri));\n }\n },\n\n getDefaultSourceKey() {\n var defaultStatusHandle = window.defaultStatusHandle;\n\n if (defaultStatusHandle) {\n for (var i = 0; i < this.$sources.length; i++) {\n var $source = $(this.$sources[i]);\n\n if ($source.data('handle') === defaultStatusHandle) {\n return $source.data('key');\n }\n }\n }\n\n return this.base();\n },\n\n getViewParams: function () {\n var params = this.base();\n\n if (this.startDate || this.endDate) {\n var dateAttr = this.$source.data('date-attr') || 'dateUpdated';\n params.criteria[dateAttr] = ['and'];\n\n if (this.startDate) {\n params.criteria[dateAttr].push('>=' + this.startDate.getTime() / 1000);\n }\n\n if (this.endDate) {\n params.criteria[dateAttr].push(\n '<' + (this.endDate.getTime() / 1000 + 86400)\n );\n }\n }\n\n return params;\n },\n\n updateSourcesBadgeCounts: function () {\n $.ajax({\n url: Craft.getActionUrl('commerce/orders/get-index-sources-badge-counts'),\n type: 'GET',\n dataType: 'json',\n success: $.proxy(function (data) {\n if (data.counts) {\n var $sidebar = this.$sidebar;\n $.each(data.counts, function (key, row) {\n var $item = $sidebar.find(\n 'nav a[data-key=\"orderStatus:' + row.handle + '\"]'\n );\n if ($item) {\n $item.find('.badge').text(row.orderCount);\n }\n });\n }\n\n if (data.total) {\n var $total = this.$sidebar.find('nav a[data-key=\"*\"]');\n if ($total) {\n $total.find('.badge').text(data.total);\n }\n }\n }, this),\n });\n },\n\n setIndexAvailable: function () {\n this.updateSourcesBadgeCounts();\n this.base();\n },\n});\n\n// Register the Commerce order index class\nCraft.registerElementIndexClass(\n 'craft\\\\commerce\\\\elements\\\\Order',\n Craft.Commerce.OrderIndex\n);\n","/* jshint esversion: 6 */\n/* globals Craft, Garnish, $ */\nif (typeof Craft.Commerce === typeof undefined) {\n Craft.Commerce = {};\n}\n\n/**\n * Class Craft.Commerce.PaymentModal\n */\nCraft.Commerce.PaymentModal = Garnish.Modal.extend(\n {\n $container: null,\n $body: null,\n\n init: function (settings) {\n this.$container = $('', {\n id: 'paymentmodal',\n class: 'modal fitted loading',\n }).appendTo(Garnish.$bod);\n\n this.base(\n this.$container,\n $.extend(\n {\n resizable: false,\n },\n settings\n )\n );\n\n var data = {\n orderId: settings.orderId,\n paymentForm: settings.paymentForm,\n paymentAmount: settings.paymentAmount,\n paymentCurrency: settings.paymentCurrency,\n };\n\n Craft.sendActionRequest('POST', 'commerce/orders/get-payment-modal', {\n data,\n })\n .then((response) => {\n this.$container.removeClass('loading');\n var $this = this;\n this.$container.append(response.data.modalHtml);\n Craft.appendHeadHtml(response.data.headHtml);\n Craft.appendFootHtml(response.data.footHtml);\n\n var $buttons = $('.buttons', this.$container),\n $cancelBtn = $(\n '' + Craft.t('commerce', 'Cancel') + ''\n ).prependTo($buttons);\n\n this.addListener($cancelBtn, 'click', 'cancelPayment');\n\n $('select#payment-form-select')\n .change(\n $.proxy(function (ev) {\n var id = $(ev.currentTarget).val();\n $('.gateway-form').addClass('hidden');\n $('#gateway-' + id + '-form').removeClass('hidden');\n\n setTimeout(function () {\n Craft.initUiElements(this.$container);\n $this.updateSizeAndPosition();\n }, 200);\n }, this)\n )\n .trigger('change');\n\n setTimeout(function () {\n Craft.initUiElements(this.$container);\n $this.updateSizeAndPosition();\n }, 200);\n })\n .catch(({response}) => {\n this.$container.removeClass('loading');\n var error = Craft.t('commerce', 'An unknown error occurred.');\n\n if (response.data.message) {\n error = response.data.message;\n }\n\n this.$container.append('' + error + '');\n });\n },\n\n cancelPayment: function () {\n this.hide();\n },\n },\n {}\n);\n","/* jshint esversion: 6 */\n/* globals Craft, Garnish, $ */\nif (typeof Craft.Commerce === typeof undefined) {\n Craft.Commerce = {};\n}\n\nCraft.Commerce.ProductSalesModal = Garnish.Modal.extend({\n id: null,\n $newSale: null,\n $cancelBtn: null,\n $select: null,\n $saveBtn: null,\n $spinner: null,\n $purchasableCheckboxes: [],\n\n init: function (sales, settings) {\n this.id = Math.floor(Math.random() * 1000000000);\n\n this.setSettings(settings, this.defaults);\n this.$form = $(\n ''\n ).appendTo(Garnish.$bod);\n var $body = $('').appendTo(this.$form);\n var $inputs = $('', {class: 'content'})\n .append(\n $('', {\n class: 'first',\n text: Craft.t('commerce', 'Add Product to Sale'),\n })\n )\n .append(\n $('', {\n text: Craft.t(\n 'commerce',\n 'Add this product to an existing sale. This will change the conditions of the sale, please review the sale.'\n ),\n })\n )\n .appendTo($body);\n\n if (this.settings.purchasables.length) {\n var $checkboxField = $('');\n $('', {class: 'heading'})\n .append(\n $('', {\n text: Craft.t('commerce', 'Select Variants'),\n })\n )\n .appendTo($checkboxField);\n\n var $inputContainer = $('');\n $.each(\n this.settings.purchasables,\n $.proxy(function (key, purchasable) {\n var $pCheck = $('', {\n class: 'checkbox',\n type: 'checkbox',\n name: 'ids[]',\n id: 'add-to-sale-purchasable-' + purchasable.id,\n value: purchasable.id,\n checked: true,\n });\n\n var $checkboxContainer = $('').append(\n $('', {\n for: 'add-to-sale-purchasable-' + purchasable.id,\n text: purchasable.title + ' ',\n }).append('', {\n class: 'extralight',\n text: purchasable.sku,\n })\n );\n\n $pCheck.on(\n 'change',\n $.proxy(function () {\n this.updateNewSaleUrl();\n }, this)\n );\n this.$purchasableCheckboxes.push($pCheck);\n $pCheck.prependTo($checkboxContainer);\n $checkboxContainer.appendTo($inputContainer);\n }, this)\n );\n\n $inputContainer.appendTo($checkboxField);\n $checkboxField.appendTo($inputs);\n }\n\n if (sales && sales.length) {\n this.$select = $('');\n $('----').appendTo(this.$select);\n\n for (var i = 0; i < sales.length; i++) {\n var sale = sales[i];\n var disabled = false;\n\n if (\n this.settings.existingSaleIds &&\n this.settings.existingSaleIds.length &&\n this.settings.existingSaleIds.indexOf(sale.id) >= 0\n ) {\n disabled = true;\n }\n\n this.$select.append(\n $('', {\n disabled: disabled,\n text: Craft.escapeHtml(sale.name),\n value: sale.id,\n })\n );\n }\n var $field = $('');\n var $container = $('');\n this.$select.appendTo($container);\n $container.appendTo($field);\n\n var $fieldContainer = $('');\n $('')\n .append(\n $('', {\n text: Craft.t('commerce', 'Sale'),\n })\n )\n .appendTo($fieldContainer);\n\n $container.appendTo($fieldContainer);\n\n $fieldContainer.appendTo($inputs);\n\n this.$select.on('change', $.proxy(this, 'handleSaleChange'));\n }\n\n // Error notice area\n this.$error = $('').appendTo($inputs);\n\n // Footer and buttons\n var $footer = $('
"+i+"
'+JSON.stringify(JSON.parse(i),void 0,4)+"
'+$("").text(i).html()+"
'+i+"