{% extends "commerce/_layouts/cp" %}
{% set selectedSubnavItem = "promotions" %}
{% set crumbs = [
{ label: "Promotions"|t('commerce'), url: url('commerce/promotions') },
{ label: "Discounts"|t('commerce'), url: url('commerce/promotions/discounts') },
] %}
{% set fullPageForm = true %}
{% import "_includes/forms" as forms %}
{% import "commerce/_includes/forms/commerceForms" as commerceForms %}
{% set discountClasses = "" %}
{% if (discount.getErrors('name')) %}
{% set discountClasses = "error" %}
{% endif %}
{% set matchingItemsClasses = "" %}
{% if false %}
{% set matchingItemsClasses = "error" %}
{% endif %}
{% set conditionsClasses = "" %}
{% if(discount.getErrors('startDate') or discount.getErrors('endDate')) %}
{% set conditionsClasses = "error" %}
{% endif %}
{% set couponClasses = "" %}
{% if(discount.getErrors('code')) %}
{% set couponClasses = "error" %}
{% endif %}
{% set tabs = {
0: {'label':'Discount'|t('commerce'),'url':'#discount','class':discountClasses},
1: {'label':'Coupon'|t('commerce'),'url':'#coupon','class':couponClasses},
2: {'label':'Matching Items'|t('commerce'),'url':'#matching-items','class':matchingItemsClasses},
3: {'label':'Conditions'|t('commerce'),'url':'#conditions','class':conditionsClasses},
4: {'label':'Actions'|t('commerce'),'url':'#actions'}
} %}
{% block content %}
{{ redirectInput('commerce/promotions/discounts') }}
{% if discount.id %}
{% endif %}
{{ forms.textField({
first: true,
label: "Name"|t('commerce'),
instructions: "What this discount will be called in the control panel."|t('commerce'),
id: 'name',
name: 'name',
value: discount.name,
errors: discount.getErrors('name'),
autofocus: true,
required: true,
}) }}
{{ forms.textField({
label: "Description"|t('commerce'),
instructions: "Discount description."|t('commerce'),
id: 'description',
name: 'description',
value: discount.description,
errors: discount.getErrors('description'),
}) }}
{{ forms.lightSwitchField({
label: "Enable this discount"|t('commerce'),
id: 'enabled',
name: 'enabled',
value: 1,
on: discount.enabled,
checked: discount.enabled,
errors: discount.getErrors('enabled')
}) }}
{% hook "cp.commerce.discount.edit" %}
{% for purchasableType in purchasableTypes %}
{% set instruction = "for which this discount will be applicable to. Leave all purchasable fields blank for any purchasable."|t('commerce') %}
{{ forms.elementSelectField({
id: 'purchasables-'~purchasableType.elementType|id,
label: purchasableType.name ~ ' ' ~ '(Purchasable)'|t('commerce'),
name: 'purchasables['~purchasableType.elementType~']',
elements: purchasables[purchasableType.elementType] ?? null,
elementType: purchasableType.elementType,
limit: null,
instructions: purchasableType.name~" "~instruction,
errors: discount.getErrors('purchasables-'~purchasableType.elementType|replace('\\','-')),
}) }}
{% endfor %}
{{ forms.elementSelectField({
id: 'categories',
label: 'Categories'|t('commerce'),
name: 'categories',
elements: categories ? categories : null,
elementType: categoryElementType,
limit: null,
instructions: "Categories that the matching purchasables must be related to. Leave blank to ignore category matching."|t('commerce'),
errors: discount.getErrors('categories'),
}) }}
Advanced
{{ forms.selectField({
id: 'categoryRelationshipType',
name: 'categoryRelationshipType',
label: 'Categories Relationship Type'|t('commerce'),
instructions: "How the Purchasables and Categories are related, which determines the matching items. See [Relations Terminology]({link})."|t('commerce', {
link: 'https://craftcms.com/docs/3.x/relations.html#terminology',
}),
options: categoryRelationshipTypeOptions,
value: discount.categoryRelationshipType,
errors: discount.getErrors('categoryRelationshipType')
}) }}
{{ forms.textField({
label: "Coupon Code"|t('commerce'),
instructions: "A user will have to enter this code to activate this discount. A blank coupon code here will always match this discount."|t('commerce'),
id: 'code',
name: 'code',
value: discount.code,
errors: discount.getErrors('code'),
}) }}
{{ forms.dateTimeField({
label: "Start Date"|t('commerce'),
instructions: "Date from which the discount will be active. Leave blank for unlimited start date"|t('commerce'),
id: 'dateFrom',
name: 'dateFrom',
value: discount.dateFrom,
errors: discount.getErrors('dateFrom'),
}) }}
{{ forms.dateTimeField({
label: "End Date"|t('commerce'),
instructions: "Date when the discount will be finished. Leave blank for unlimited end date"|t('commerce'),
id: 'dateTo',
name: 'dateTo',
value: discount.dateTo,
errors: discount.getErrors('dateTo'),
}) }}
{% embed '_includes/forms/field' with {
label: 'Order Condition Formula'|t('commerce'),
id: 'orderConditionFormula',
rows: 5,
instructions: 'Use a formula to match this discount to the order. Leave this blank to match all orders. Use the `order` variable.',
tip: 'This field uses the Twig expression syntax. Learn More',
errors: discount is defined ? discount.getErrors('orderConditionFormula'),
} %}
{% block input %}
{% import "_includes/forms" as forms %}
{{ forms.textarea({
value: discount is defined ? discount.orderConditionFormula,
name: 'orderConditionFormula',
class: 'code',
rows: 5,
placeholder: 'Example'|t('commerce') ~ ': \'@apple.com\' in order.email'
}) }}
{% endblock %}
{% endembed %}
{% if groups|length %}
{{ forms.multiselectField({
label: 'User Groups'|t('commerce'),
instructions: "Groups for which this discount will be applicable to. Leave blank for all groups"|t('commerce'),
id: 'groups',
name: 'groups',
options: groups,
values: discount.getUserGroupIds(),
errors: discount.getErrors('groups'),
class: 'selectize fullwidth',
}) }}
{% endif %}
{{ commerceForms.numberField({
label: "Purchase Total"|t('commerce'),
instructions: "Restrict the discount to only those orders where the customer has purchased a minimum total value of matching items."|t('commerce'),
id: 'purchaseTotal',
name: 'purchaseTotal',
value: discount.purchaseTotal ? discount.purchaseTotal : 0,
type: 'number',
step: 'any',
errors: discount.getErrors('purchaseTotal'),
}) }}
{{ forms.textField({
label: "Minimum Purchase Quantity"|t('commerce'),
instructions: "Minimum number of matching items that need to be ordered for this discount to apply."|t('commerce'),
id: 'purchaseQty',
name: 'purchaseQty',
value: discount.purchaseQty,
type: 'number',
errors: discount.getErrors('purchaseQty'),
}) }}
{{ forms.textField({
label: "Maximum Purchase Quantity"|t('commerce'),
instructions: "Maximum number of matching items that can be ordered for this discount to apply. A zero value here will skip this condition."|t('commerce'),
id: 'maxPurchaseQty',
name: 'maxPurchaseQty',
value: discount.maxPurchaseQty,
type: 'number',
errors: discount.getErrors('maxPurchaseQty'),
}) }}
{% set customerUsage = customerUsage and customerUsage|length ? customerUsage : {uses: 0, customers: 0} %}
{% set customerCounterMarkup %}
{% endset %}
{{ forms.field({
label: "Per User Discount Limit"|t('commerce'),
instructions: "How many times one user is allowed to use this discount. Setting this requires a user to be logged in to use the discount. Setting this will not allow guests to use the discount. Set to zero for unlimited use by guests or users."|t('commerce'),
}, customerCounterMarkup) }}
{% set emailUsage = emailUsage and emailUsage|length ? emailUsage : {uses: 0, emails: 0} %}
{% set emailCounterMarkup %}
{% endset %}
{{ forms.field({
label: 'Per Email Address Discount Limit'|t('commerce'),
instructions: 'How many times one email address is allowed to use this discount. This applies to all previous orders, whether guest or user. Set to zero for unlimited use by guests or users.'|t('commerce'),
}, emailCounterMarkup) }}
{% set totalDiscountUsesWording = discount.totalDiscountUses != 1 ? '{count} times' : '{count} time' %}
{% set totalDiscountLimitMarkup %}
{% endset %}
{{ forms.field({
'label': 'Total Discount Use Limit'|t('commerce'),
'instructions': "How many times this discount can be used in total by guests or logged in users. Set zero for unlimited use."|t('commerce'),
}, totalDiscountLimitMarkup) }}
{{ forms.checkboxField({
label: "Exclude this discount for products that are already on sale"|t('commerce'),
id: 'excludeOnSale',
name: 'excludeOnSale',
value: 1,
checked: discount.excludeOnSale,
errors: discount.getErrors('excludeOnSale')
}) }}
Per Item Discount
{{ forms.selectField({
label: "Applied Scope"|t('commerce'),
instructions: "Choose whether the all line items or just matching line items get the 'Per Item' amounts off."|t('commerce'),
id: 'appliedTo',
name: 'appliedTo',
options: appliedTo,
value: discount.appliedTo,
'tip': "Matching items are those items that are used to match this discount’s conditions. Those on the 'Matching Items' tab."|t('commerce')
}) }}
{{ commerceForms.numberField({
label: "Per Item Amount Off"|t('commerce'),
instructions: "The flat value which should discount each item. i.e “3” for $3 off each item."|t('commerce'),
id: 'perItemDiscount',
name: 'perItemDiscount',
value: discount.perItemDiscount ? discount.perItemDiscount : 0,
type: 'number',
step: 'any',
errors: discount.getErrors('perItemDiscount'),
}) }}
{% set pctDiscountInput %}
{{ forms.select({
id: 'percentageOffSubject',
name: 'percentageOffSubject',
options: [
{label: "(%) off the discounted item price"|t('commerce'), value: 'discounted'},
{label: "(%) off the original item price"|t('commerce'), value: 'original'}
],
value: discount.percentageOffSubject
}) }}
{% endset %}
{{ forms.field({
label: "Per Item Percentage Off"|t('commerce'),
instructions: "The percentile value which should discount each item. i.e. “4%” for 4% off. Percentages are rounded to 2 decimal places."|t('commerce'),
id: 'percentDiscount',
errors: discount.getErrors('percentDiscount'),
tip: 'If you select the percentage to be “off the discounted item price”, this will include the “Per Item Amount” as well as any other discounts that applied before this one.'|t('commerce')
}, pctDiscountInput) }}
{{ forms.checkboxField({
label: "Ignore sales when this discount is applied to matching line items"|t('commerce'),
id: 'ignoreSales',
name: 'ignoreSales',
value: 1,
checked: discount.ignoreSales
}) }}
{% endset %}
{% set showWarning = false %}
{% if discount.baseDiscountType in ['percentTotal','percentTotalDiscounted','percentItems','percentItemsDiscounted'] %}
{% set showWarning = true %}
{% endif %}
{{ forms.field({
label: "Flat Order Discount Amount Off"|t('commerce'),
instructions: "The amount of discount that is applied to the whole order. This amount is spread across line items in order of highest price to lowest price, until the discount is used up."|t('commerce'),
id: 'baseDiscount',
errors: discount.getErrors('baseDiscount'),
warning: showWarning ? 'You have selected an option that will be removed in the next release of Craft Commerce. Use the “Per Item Discount” options to take a percentage off the whole order, or change this option to “Value”'|t('commerce') : null,
tip: 'The base discount can only discount items in the cart to down to zero until it is used up, it can not make the order negative.'|t('commerce')
}, baseDiscountInput) }}
Additional Actions
{{ forms.checkboxField({
label: "Remove all shipping costs from the order"|t('commerce'),
id: 'hasFreeShippingForOrder',
name: 'hasFreeShippingForOrder',
value: 1,
checked: discount.hasFreeShippingForOrder
}) }}
{{ forms.checkboxField({
label: "Remove shipping costs for matching items only"|t('commerce'),
id: 'hasFreeShippingForMatchingItems',
name: 'hasFreeShippingForMatchingItems',
value: 1,
checked: discount.hasFreeShippingForMatchingItems,
disabled: discount.hasFreeShippingForOrder
}) }}
{{ forms.checkboxField({
label: "Don’t apply any subsequent discounts to an order if this discount is applied"|t('commerce'),
id: 'stopProcessing',
name: 'stopProcessing',
value: 1,
checked: discount.stopProcessing,
errors: discount.getErrors('stopProcessing')
}) }}
{% endblock %}
{% js %}
$(function() {
$('#groups').selectize({
plugins: ['remove_button'],
dropdownParent: 'body'
});
$('#code').on('keyup blur', function(event) {
if (this.value.length === 0) {
$('#coupon-fields').addClass('hidden');
} else {
$('#coupon-fields').removeClass('hidden');
}
});
$("#hasFreeShippingForOrder").click(function (){
if ($("#hasFreeShippingForOrder").prop("checked")){
$("#hasFreeShippingForMatchingItems").prop("checked", false);
$("#hasFreeShippingForMatchingItems").prop("disabled", true);
}else{
$("#hasFreeShippingForMatchingItems").prop("disabled", false);
}
});
$('.clear-btn').click(function(event) {
var $this = $(this);
var $spinner = $($this.data('spinner'));
var $field = $($this.data('field'));
var type = $this.data('type');
var r = confirm(Craft.t('commerce', 'Are you sure you want to clear this discount usage counter?'));
if (r == true) {
$spinner.toggleClass('hidden');
$.ajax({
type: "POST",
dataType: 'json',
headers: {
"X-CSRF-Token" : '{{ craft.app.request.csrfToken }}',
},
url: '',
data: {
'action' : 'commerce/discounts/clear-discount-uses',
'id': '{{ discount.id ?? '' }}',
'type': type
},
success: function(data){
$spinner.toggleClass('hidden');
$field.val('');
Craft.cp.displayNotice(Craft.t('commerce', 'Counter has been cleared.'));
$this.attr('disabled', 'disabled').prop('disabled', 'disabled');
}
});
}
});
});
{% endjs %}