526 lines
22 KiB
C#
526 lines
22 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using Nop.Core.Domain.Catalog;
|
|
using Nop.Core.Domain.Directory;
|
|
using Nop.Core.Domain.Orders;
|
|
using Nop.Services.Attributes;
|
|
using Nop.Services.Directory;
|
|
using Nop.Services.Localization;
|
|
using Nop.Services.Logging;
|
|
using Nop.Services.Messages;
|
|
using Nop.Services.Security;
|
|
using Nop.Services.Stores;
|
|
using Nop.Web.Areas.Admin.Factories;
|
|
using Nop.Web.Areas.Admin.Infrastructure.Mapper.Extensions;
|
|
using Nop.Web.Areas.Admin.Models.Orders;
|
|
using Nop.Web.Framework.Mvc;
|
|
using Nop.Web.Framework.Mvc.Filters;
|
|
|
|
namespace Nop.Web.Areas.Admin.Controllers;
|
|
|
|
public partial class CheckoutAttributeController : BaseAdminController
|
|
{
|
|
#region Fields
|
|
|
|
protected readonly CurrencySettings _currencySettings;
|
|
protected readonly IAttributeParser<CheckoutAttribute, CheckoutAttributeValue> _checkoutAttributeParser;
|
|
protected readonly IAttributeService<CheckoutAttribute, CheckoutAttributeValue> _checkoutAttributeService;
|
|
protected readonly ICheckoutAttributeModelFactory _checkoutAttributeModelFactory;
|
|
protected readonly ICurrencyService _currencyService;
|
|
protected readonly ICustomerActivityService _customerActivityService;
|
|
protected readonly ILocalizationService _localizationService;
|
|
protected readonly ILocalizedEntityService _localizedEntityService;
|
|
protected readonly INotificationService _notificationService;
|
|
protected readonly IMeasureService _measureService;
|
|
protected readonly IPermissionService _permissionService;
|
|
protected readonly IStoreMappingService _storeMappingService;
|
|
protected readonly IStoreService _storeService;
|
|
protected readonly MeasureSettings _measureSettings;
|
|
|
|
#endregion
|
|
|
|
#region Ctor
|
|
|
|
public CheckoutAttributeController(CurrencySettings currencySettings,
|
|
IAttributeParser<CheckoutAttribute, CheckoutAttributeValue> checkoutAttributeParser,
|
|
IAttributeService<CheckoutAttribute, CheckoutAttributeValue> checkoutAttributeService,
|
|
ICheckoutAttributeModelFactory checkoutAttributeModelFactory,
|
|
ICurrencyService currencyService,
|
|
ICustomerActivityService customerActivityService,
|
|
ILocalizationService localizationService,
|
|
ILocalizedEntityService localizedEntityService,
|
|
INotificationService notificationService,
|
|
IMeasureService measureService,
|
|
IPermissionService permissionService,
|
|
IStoreMappingService storeMappingService,
|
|
IStoreService storeService,
|
|
MeasureSettings measureSettings)
|
|
{
|
|
_currencySettings = currencySettings;
|
|
_checkoutAttributeParser = checkoutAttributeParser;
|
|
_checkoutAttributeService = checkoutAttributeService;
|
|
_checkoutAttributeModelFactory = checkoutAttributeModelFactory;
|
|
_currencyService = currencyService;
|
|
_customerActivityService = customerActivityService;
|
|
_localizationService = localizationService;
|
|
_localizedEntityService = localizedEntityService;
|
|
_notificationService = notificationService;
|
|
_measureService = measureService;
|
|
_permissionService = permissionService;
|
|
_storeMappingService = storeMappingService;
|
|
_storeService = storeService;
|
|
_measureSettings = measureSettings;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Utilities
|
|
|
|
protected virtual async Task UpdateAttributeLocalesAsync(CheckoutAttribute checkoutAttribute, CheckoutAttributeModel model)
|
|
{
|
|
foreach (var localized in model.Locales)
|
|
{
|
|
await _localizedEntityService.SaveLocalizedValueAsync(checkoutAttribute,
|
|
x => x.Name,
|
|
localized.Name,
|
|
localized.LanguageId);
|
|
|
|
await _localizedEntityService.SaveLocalizedValueAsync(checkoutAttribute,
|
|
x => x.TextPrompt,
|
|
localized.TextPrompt,
|
|
localized.LanguageId);
|
|
|
|
await _localizedEntityService.SaveLocalizedValueAsync(checkoutAttribute,
|
|
x => x.DefaultValue,
|
|
localized.DefaultValue,
|
|
localized.LanguageId);
|
|
}
|
|
}
|
|
|
|
protected virtual async Task UpdateValueLocalesAsync(CheckoutAttributeValue checkoutAttributeValue, CheckoutAttributeValueModel model)
|
|
{
|
|
foreach (var localized in model.Locales)
|
|
{
|
|
await _localizedEntityService.SaveLocalizedValueAsync(checkoutAttributeValue,
|
|
x => x.Name,
|
|
localized.Name,
|
|
localized.LanguageId);
|
|
}
|
|
}
|
|
|
|
protected virtual async Task SaveStoreMappingsAsync(CheckoutAttribute checkoutAttribute, CheckoutAttributeModel model)
|
|
{
|
|
checkoutAttribute.LimitedToStores = model.SelectedStoreIds.Any();
|
|
await _checkoutAttributeService.UpdateAttributeAsync(checkoutAttribute);
|
|
|
|
var existingStoreMappings = await _storeMappingService.GetStoreMappingsAsync(checkoutAttribute);
|
|
var allStores = await _storeService.GetAllStoresAsync();
|
|
foreach (var store in allStores)
|
|
{
|
|
if (model.SelectedStoreIds.Contains(store.Id))
|
|
{
|
|
//new store
|
|
if (!existingStoreMappings.Any(sm => sm.StoreId == store.Id))
|
|
await _storeMappingService.InsertStoreMappingAsync(checkoutAttribute, store.Id);
|
|
}
|
|
else
|
|
{
|
|
//remove store
|
|
var storeMappingToDelete = existingStoreMappings.FirstOrDefault(sm => sm.StoreId == store.Id);
|
|
if (storeMappingToDelete != null)
|
|
await _storeMappingService.DeleteStoreMappingAsync(storeMappingToDelete);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected virtual async Task SaveConditionAttributesAsync(CheckoutAttribute checkoutAttribute, CheckoutAttributeModel model)
|
|
{
|
|
string attributesXml = null;
|
|
|
|
if (model.ConditionModel.EnableCondition)
|
|
{
|
|
var attribute = await _checkoutAttributeService.GetAttributeByIdAsync(model.ConditionModel.SelectedAttributeId);
|
|
if (attribute != null)
|
|
{
|
|
switch (attribute.AttributeControlType)
|
|
{
|
|
case AttributeControlType.DropdownList:
|
|
case AttributeControlType.RadioList:
|
|
case AttributeControlType.ColorSquares:
|
|
case AttributeControlType.ImageSquares:
|
|
{
|
|
var selectedAttribute = model.ConditionModel.ConditionAttributes
|
|
.FirstOrDefault(x => x.Id == model.ConditionModel.SelectedAttributeId);
|
|
var selectedValue = selectedAttribute?.SelectedValueId;
|
|
|
|
//for conditions we should empty values save even when nothing is selected
|
|
//otherwise "attributesXml" will be empty
|
|
//hence we won't be able to find a selected attribute
|
|
attributesXml = _checkoutAttributeParser.AddAttribute(null, attribute, string.IsNullOrEmpty(selectedValue) ? string.Empty : selectedValue);
|
|
}
|
|
break;
|
|
|
|
case AttributeControlType.Checkboxes:
|
|
{
|
|
var selectedAttribute = model.ConditionModel.ConditionAttributes
|
|
.FirstOrDefault(x => x.Id == model.ConditionModel.SelectedAttributeId);
|
|
var selectedValues = selectedAttribute?.Values
|
|
.Where(x => x.Selected)
|
|
.Select(x => x.Value)
|
|
.ToList();
|
|
|
|
if (selectedValues?.Any() ?? false)
|
|
foreach (var value in selectedValues)
|
|
attributesXml = _checkoutAttributeParser.AddAttribute(attributesXml, attribute, value);
|
|
else
|
|
attributesXml = _checkoutAttributeParser.AddAttribute(null, attribute, string.Empty);
|
|
}
|
|
break;
|
|
|
|
case AttributeControlType.ReadonlyCheckboxes:
|
|
case AttributeControlType.TextBox:
|
|
case AttributeControlType.MultilineTextbox:
|
|
case AttributeControlType.Datepicker:
|
|
case AttributeControlType.FileUpload:
|
|
default:
|
|
//these attribute types are not supported as conditions
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
checkoutAttribute.ConditionAttributeXml = attributesXml;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Checkout attributes
|
|
|
|
public virtual IActionResult Index()
|
|
{
|
|
return RedirectToAction("List");
|
|
}
|
|
|
|
[CheckPermission(StandardPermission.Catalog.CHECKOUT_ATTRIBUTES_VIEW)]
|
|
public virtual async Task<IActionResult> List()
|
|
{
|
|
//prepare model
|
|
var model = await _checkoutAttributeModelFactory.PrepareCheckoutAttributeSearchModelAsync(new CheckoutAttributeSearchModel());
|
|
|
|
return View(model);
|
|
}
|
|
|
|
[HttpPost]
|
|
[CheckPermission(StandardPermission.Catalog.CHECKOUT_ATTRIBUTES_VIEW)]
|
|
public virtual async Task<IActionResult> List(CheckoutAttributeSearchModel searchModel)
|
|
{
|
|
//prepare model
|
|
var model = await _checkoutAttributeModelFactory.PrepareCheckoutAttributeListModelAsync(searchModel);
|
|
|
|
return Json(model);
|
|
}
|
|
|
|
[CheckPermission(StandardPermission.Catalog.CHECKOUT_ATTRIBUTES_CREATE_EDIT_DELETE)]
|
|
public virtual async Task<IActionResult> Create()
|
|
{
|
|
//prepare model
|
|
var model = await _checkoutAttributeModelFactory.PrepareCheckoutAttributeModelAsync(new CheckoutAttributeModel(), null);
|
|
|
|
return View(model);
|
|
}
|
|
|
|
[HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")]
|
|
[CheckPermission(StandardPermission.Catalog.CHECKOUT_ATTRIBUTES_CREATE_EDIT_DELETE)]
|
|
public virtual async Task<IActionResult> Create(CheckoutAttributeModel model, bool continueEditing)
|
|
{
|
|
if (ModelState.IsValid)
|
|
{
|
|
var checkoutAttribute = model.ToEntity<CheckoutAttribute>();
|
|
await _checkoutAttributeService.InsertAttributeAsync(checkoutAttribute);
|
|
|
|
//locales
|
|
await UpdateAttributeLocalesAsync(checkoutAttribute, model);
|
|
|
|
//stores
|
|
await SaveStoreMappingsAsync(checkoutAttribute, model);
|
|
|
|
//activity log
|
|
await _customerActivityService.InsertActivityAsync("AddNewCheckoutAttribute",
|
|
string.Format(await _localizationService.GetResourceAsync("ActivityLog.AddNewCheckoutAttribute"), checkoutAttribute.Name), checkoutAttribute);
|
|
|
|
_notificationService.SuccessNotification(await _localizationService.GetResourceAsync("Admin.Catalog.Attributes.CheckoutAttributes.Added"));
|
|
|
|
if (!continueEditing)
|
|
return RedirectToAction("List");
|
|
|
|
return RedirectToAction("Edit", new { id = checkoutAttribute.Id });
|
|
}
|
|
|
|
//prepare model
|
|
model = await _checkoutAttributeModelFactory.PrepareCheckoutAttributeModelAsync(model, null, true);
|
|
|
|
//if we got this far, something failed, redisplay form
|
|
return View(model);
|
|
}
|
|
|
|
[CheckPermission(StandardPermission.Catalog.CHECKOUT_ATTRIBUTES_VIEW)]
|
|
public virtual async Task<IActionResult> Edit(int id)
|
|
{
|
|
//try to get a checkout attribute with the specified id
|
|
var checkoutAttribute = await _checkoutAttributeService.GetAttributeByIdAsync(id);
|
|
if (checkoutAttribute == null)
|
|
return RedirectToAction("List");
|
|
|
|
//prepare model
|
|
var model = await _checkoutAttributeModelFactory.PrepareCheckoutAttributeModelAsync(null, checkoutAttribute);
|
|
|
|
return View(model);
|
|
}
|
|
|
|
[HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")]
|
|
[CheckPermission(StandardPermission.Catalog.CHECKOUT_ATTRIBUTES_CREATE_EDIT_DELETE)]
|
|
public virtual async Task<IActionResult> Edit(CheckoutAttributeModel model, bool continueEditing)
|
|
{
|
|
//try to get a checkout attribute with the specified id
|
|
var checkoutAttribute = await _checkoutAttributeService.GetAttributeByIdAsync(model.Id);
|
|
if (checkoutAttribute == null)
|
|
return RedirectToAction("List");
|
|
|
|
if (ModelState.IsValid)
|
|
{
|
|
checkoutAttribute = model.ToEntity(checkoutAttribute);
|
|
await SaveConditionAttributesAsync(checkoutAttribute, model);
|
|
await _checkoutAttributeService.UpdateAttributeAsync(checkoutAttribute);
|
|
|
|
//locales
|
|
await UpdateAttributeLocalesAsync(checkoutAttribute, model);
|
|
|
|
//stores
|
|
await SaveStoreMappingsAsync(checkoutAttribute, model);
|
|
|
|
//activity log
|
|
await _customerActivityService.InsertActivityAsync("EditCheckoutAttribute",
|
|
string.Format(await _localizationService.GetResourceAsync("ActivityLog.EditCheckoutAttribute"), checkoutAttribute.Name), checkoutAttribute);
|
|
|
|
_notificationService.SuccessNotification(await _localizationService.GetResourceAsync("Admin.Catalog.Attributes.CheckoutAttributes.Updated"));
|
|
|
|
if (!continueEditing)
|
|
return RedirectToAction("List");
|
|
|
|
return RedirectToAction("Edit", new { id = checkoutAttribute.Id });
|
|
}
|
|
|
|
//prepare model
|
|
model = await _checkoutAttributeModelFactory.PrepareCheckoutAttributeModelAsync(model, checkoutAttribute, true);
|
|
|
|
//if we got this far, something failed, redisplay form
|
|
return View(model);
|
|
}
|
|
|
|
[HttpPost]
|
|
[CheckPermission(StandardPermission.Catalog.CHECKOUT_ATTRIBUTES_CREATE_EDIT_DELETE)]
|
|
public virtual async Task<IActionResult> Delete(int id)
|
|
{
|
|
//try to get a checkout attribute with the specified id
|
|
var checkoutAttribute = await _checkoutAttributeService.GetAttributeByIdAsync(id);
|
|
if (checkoutAttribute == null)
|
|
return RedirectToAction("List");
|
|
|
|
await _checkoutAttributeService.DeleteAttributeAsync(checkoutAttribute);
|
|
|
|
//activity log
|
|
await _customerActivityService.InsertActivityAsync("DeleteCheckoutAttribute",
|
|
string.Format(await _localizationService.GetResourceAsync("ActivityLog.DeleteCheckoutAttribute"), checkoutAttribute.Name), checkoutAttribute);
|
|
|
|
_notificationService.SuccessNotification(await _localizationService.GetResourceAsync("Admin.Catalog.Attributes.CheckoutAttributes.Deleted"));
|
|
|
|
return RedirectToAction("List");
|
|
}
|
|
|
|
[HttpPost]
|
|
[CheckPermission(StandardPermission.Catalog.CHECKOUT_ATTRIBUTES_CREATE_EDIT_DELETE)]
|
|
public virtual async Task<IActionResult> DeleteSelected(ICollection<int> selectedIds)
|
|
{
|
|
if (selectedIds == null || !selectedIds.Any())
|
|
return NoContent();
|
|
|
|
var checkoutAttributes = await _checkoutAttributeService.GetAttributeByIdsAsync(selectedIds.ToArray());
|
|
await _checkoutAttributeService.DeleteAttributesAsync(checkoutAttributes);
|
|
|
|
foreach (var checkoutAttribute in checkoutAttributes)
|
|
{
|
|
//activity log
|
|
await _customerActivityService.InsertActivityAsync("DeleteCheckoutAttribute",
|
|
string.Format(await _localizationService.GetResourceAsync("ActivityLog.DeleteCheckoutAttribute"), checkoutAttribute.Name), checkoutAttribute);
|
|
}
|
|
|
|
return Json(new { Result = true });
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Checkout attribute values
|
|
|
|
[HttpPost]
|
|
[CheckPermission(StandardPermission.Catalog.CHECKOUT_ATTRIBUTES_VIEW)]
|
|
public virtual async Task<IActionResult> ValueList(CheckoutAttributeValueSearchModel searchModel)
|
|
{
|
|
//try to get a checkout attribute with the specified id
|
|
var checkoutAttribute = await _checkoutAttributeService.GetAttributeByIdAsync(searchModel.CheckoutAttributeId)
|
|
?? throw new ArgumentException("No checkout attribute found with the specified id");
|
|
|
|
//prepare model
|
|
var model = await _checkoutAttributeModelFactory.PrepareCheckoutAttributeValueListModelAsync(searchModel, checkoutAttribute);
|
|
|
|
return Json(model);
|
|
}
|
|
|
|
[CheckPermission(StandardPermission.Catalog.CHECKOUT_ATTRIBUTES_CREATE_EDIT_DELETE)]
|
|
public virtual async Task<IActionResult> ValueCreatePopup(int checkoutAttributeId)
|
|
{
|
|
//try to get a checkout attribute with the specified id
|
|
var checkoutAttribute = await _checkoutAttributeService.GetAttributeByIdAsync(checkoutAttributeId);
|
|
if (checkoutAttribute == null)
|
|
return RedirectToAction("List");
|
|
|
|
//prepare model
|
|
var model = await _checkoutAttributeModelFactory
|
|
.PrepareCheckoutAttributeValueModelAsync(new CheckoutAttributeValueModel(), checkoutAttribute, null);
|
|
|
|
return View(model);
|
|
}
|
|
|
|
[HttpPost]
|
|
[CheckPermission(StandardPermission.Catalog.CHECKOUT_ATTRIBUTES_CREATE_EDIT_DELETE)]
|
|
public virtual async Task<IActionResult> ValueCreatePopup(CheckoutAttributeValueModel model)
|
|
{
|
|
//try to get a checkout attribute with the specified id
|
|
var checkoutAttribute = await _checkoutAttributeService.GetAttributeByIdAsync(model.AttributeId);
|
|
if (checkoutAttribute == null)
|
|
return RedirectToAction("List");
|
|
|
|
model.PrimaryStoreCurrencyCode = (await _currencyService.GetCurrencyByIdAsync(_currencySettings.PrimaryStoreCurrencyId)).CurrencyCode;
|
|
model.BaseWeightIn = (await _measureService.GetMeasureWeightByIdAsync(_measureSettings.BaseWeightId)).Name;
|
|
|
|
if (checkoutAttribute.AttributeControlType == AttributeControlType.ColorSquares)
|
|
{
|
|
//ensure valid color is chosen/entered
|
|
if (string.IsNullOrEmpty(model.ColorSquaresRgb))
|
|
ModelState.AddModelError(string.Empty, "Color is required");
|
|
|
|
try
|
|
{
|
|
//ensure color is valid (can be instantiated)
|
|
System.Drawing.ColorTranslator.FromHtml(model.ColorSquaresRgb);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
ModelState.AddModelError(string.Empty, exc.Message);
|
|
}
|
|
}
|
|
|
|
if (ModelState.IsValid)
|
|
{
|
|
var checkoutAttributeValue = model.ToEntity<CheckoutAttributeValue>();
|
|
await _checkoutAttributeService.InsertAttributeValueAsync(checkoutAttributeValue);
|
|
|
|
await UpdateValueLocalesAsync(checkoutAttributeValue, model);
|
|
|
|
ViewBag.RefreshPage = true;
|
|
|
|
return View(model);
|
|
}
|
|
|
|
//prepare model
|
|
model = await _checkoutAttributeModelFactory.PrepareCheckoutAttributeValueModelAsync(model, checkoutAttribute, null, true);
|
|
|
|
//if we got this far, something failed, redisplay form
|
|
return View(model);
|
|
}
|
|
|
|
[CheckPermission(StandardPermission.Catalog.CHECKOUT_ATTRIBUTES_VIEW)]
|
|
public virtual async Task<IActionResult> ValueEditPopup(int id)
|
|
{
|
|
//try to get a checkout attribute value with the specified id
|
|
var checkoutAttributeValue = await _checkoutAttributeService.GetAttributeValueByIdAsync(id);
|
|
if (checkoutAttributeValue == null)
|
|
return RedirectToAction("List");
|
|
|
|
//try to get a checkout attribute with the specified id
|
|
var checkoutAttribute = await _checkoutAttributeService.GetAttributeByIdAsync(checkoutAttributeValue.AttributeId);
|
|
if (checkoutAttribute == null)
|
|
return RedirectToAction("List");
|
|
|
|
//prepare model
|
|
var model = await _checkoutAttributeModelFactory.PrepareCheckoutAttributeValueModelAsync(null, checkoutAttribute, checkoutAttributeValue);
|
|
|
|
return View(model);
|
|
}
|
|
|
|
[HttpPost]
|
|
[CheckPermission(StandardPermission.Catalog.CHECKOUT_ATTRIBUTES_CREATE_EDIT_DELETE)]
|
|
public virtual async Task<IActionResult> ValueEditPopup(CheckoutAttributeValueModel model)
|
|
{
|
|
//try to get a checkout attribute value with the specified id
|
|
var checkoutAttributeValue = await _checkoutAttributeService.GetAttributeValueByIdAsync(model.Id);
|
|
if (checkoutAttributeValue == null)
|
|
return RedirectToAction("List");
|
|
|
|
//try to get a checkout attribute with the specified id
|
|
var checkoutAttribute = await _checkoutAttributeService.GetAttributeByIdAsync(checkoutAttributeValue.AttributeId);
|
|
if (checkoutAttribute == null)
|
|
return RedirectToAction("List");
|
|
|
|
model.PrimaryStoreCurrencyCode = (await _currencyService.GetCurrencyByIdAsync(_currencySettings.PrimaryStoreCurrencyId)).CurrencyCode;
|
|
model.BaseWeightIn = (await _measureService.GetMeasureWeightByIdAsync(_measureSettings.BaseWeightId)).Name;
|
|
|
|
if (checkoutAttribute.AttributeControlType == AttributeControlType.ColorSquares)
|
|
{
|
|
//ensure valid color is chosen/entered
|
|
if (string.IsNullOrEmpty(model.ColorSquaresRgb))
|
|
ModelState.AddModelError(string.Empty, "Color is required");
|
|
|
|
try
|
|
{
|
|
//ensure color is valid (can be instantiated)
|
|
System.Drawing.ColorTranslator.FromHtml(model.ColorSquaresRgb);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
ModelState.AddModelError(string.Empty, exc.Message);
|
|
}
|
|
}
|
|
|
|
if (ModelState.IsValid)
|
|
{
|
|
checkoutAttributeValue = model.ToEntity(checkoutAttributeValue);
|
|
await _checkoutAttributeService.UpdateAttributeValueAsync(checkoutAttributeValue);
|
|
|
|
await UpdateValueLocalesAsync(checkoutAttributeValue, model);
|
|
|
|
ViewBag.RefreshPage = true;
|
|
|
|
return View(model);
|
|
}
|
|
|
|
//prepare model
|
|
model = await _checkoutAttributeModelFactory.PrepareCheckoutAttributeValueModelAsync(model, checkoutAttribute, checkoutAttributeValue, true);
|
|
|
|
//if we got this far, something failed, redisplay form
|
|
return View(model);
|
|
}
|
|
|
|
[HttpPost]
|
|
[CheckPermission(StandardPermission.Catalog.CHECKOUT_ATTRIBUTES_CREATE_EDIT_DELETE)]
|
|
public virtual async Task<IActionResult> ValueDelete(int id)
|
|
{
|
|
//try to get a checkout attribute value with the specified id
|
|
var checkoutAttributeValue = await _checkoutAttributeService.GetAttributeValueByIdAsync(id)
|
|
?? throw new ArgumentException("No checkout attribute value found with the specified id", nameof(id));
|
|
|
|
await _checkoutAttributeService.DeleteAttributeValueAsync(checkoutAttributeValue);
|
|
|
|
return new NullJsonResult();
|
|
}
|
|
|
|
#endregion
|
|
} |