314 lines
14 KiB
C#
314 lines
14 KiB
C#
using Microsoft.AspNetCore.Mvc.Rendering;
|
|
using Nop.Core;
|
|
using Nop.Core.Domain.Catalog;
|
|
using Nop.Core.Domain.Common;
|
|
using Nop.Core.Domain.Customers;
|
|
using Nop.Core.Domain.Directory;
|
|
using Nop.Services.Attributes;
|
|
using Nop.Services.Common;
|
|
using Nop.Services.Directory;
|
|
using Nop.Services.Localization;
|
|
using Nop.Web.Models.Common;
|
|
|
|
namespace Nop.Web.Factories;
|
|
|
|
/// <summary>
|
|
/// Represents the address model factory
|
|
/// </summary>
|
|
public partial class AddressModelFactory : IAddressModelFactory
|
|
{
|
|
#region Fields
|
|
|
|
protected readonly AddressSettings _addressSettings;
|
|
protected readonly IAddressService _addressService;
|
|
protected readonly IAttributeFormatter<AddressAttribute, AddressAttributeValue> _addressAttributeFormatter;
|
|
protected readonly IAttributeParser<AddressAttribute, AddressAttributeValue> _addressAttributeParser;
|
|
protected readonly IAttributeService<AddressAttribute, AddressAttributeValue> _addressAttributeService;
|
|
protected readonly ICountryService _countryService;
|
|
protected readonly ILocalizationService _localizationService;
|
|
protected readonly IStateProvinceService _stateProvinceService;
|
|
protected readonly IWorkContext _workContext;
|
|
|
|
#endregion
|
|
|
|
#region Ctor
|
|
|
|
public AddressModelFactory(AddressSettings addressSettings,
|
|
IAddressService addressService,
|
|
IAttributeFormatter<AddressAttribute, AddressAttributeValue> addressAttributeFormatter,
|
|
IAttributeParser<AddressAttribute, AddressAttributeValue> addressAttributeParser,
|
|
IAttributeService<AddressAttribute, AddressAttributeValue> addressAttributeService,
|
|
ICountryService countryService,
|
|
ILocalizationService localizationService,
|
|
IStateProvinceService stateProvinceService,
|
|
IWorkContext workContext)
|
|
{
|
|
_addressSettings = addressSettings;
|
|
_addressService = addressService;
|
|
_addressAttributeFormatter = addressAttributeFormatter;
|
|
_addressAttributeParser = addressAttributeParser;
|
|
_addressAttributeService = addressAttributeService;
|
|
_countryService = countryService;
|
|
_localizationService = localizationService;
|
|
_stateProvinceService = stateProvinceService;
|
|
_workContext = workContext;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Utilities
|
|
|
|
/// <summary>
|
|
/// Prepare address attributes
|
|
/// </summary>
|
|
/// <param name="model">Address model</param>
|
|
/// <param name="address">Address entity</param>
|
|
/// <param name="overrideAttributesXml">Overridden address attributes in XML format; pass null to use CustomAttributes of address entity</param>
|
|
/// <returns>A task that represents the asynchronous operation</returns>
|
|
protected virtual async Task PrepareCustomAddressAttributesAsync(AddressModel model,
|
|
Address address, string overrideAttributesXml = "")
|
|
{
|
|
var attributes = await _addressAttributeService.GetAllAttributesAsync();
|
|
foreach (var attribute in attributes)
|
|
{
|
|
var attributeModel = new AddressAttributeModel
|
|
{
|
|
Id = attribute.Id,
|
|
ControlId = string.Format(NopCommonDefaults.AddressAttributeControlName, attribute.Id),
|
|
Name = await _localizationService.GetLocalizedAsync(attribute, x => x.Name),
|
|
IsRequired = attribute.IsRequired,
|
|
AttributeControlType = attribute.AttributeControlType,
|
|
};
|
|
|
|
if (attribute.ShouldHaveValues)
|
|
{
|
|
//values
|
|
var attributeValues = await _addressAttributeService.GetAttributeValuesAsync(attribute.Id);
|
|
foreach (var attributeValue in attributeValues)
|
|
{
|
|
var attributeValueModel = new AddressAttributeValueModel
|
|
{
|
|
Id = attributeValue.Id,
|
|
Name = await _localizationService.GetLocalizedAsync(attributeValue, x => x.Name),
|
|
IsPreSelected = attributeValue.IsPreSelected
|
|
};
|
|
attributeModel.Values.Add(attributeValueModel);
|
|
}
|
|
}
|
|
|
|
//set already selected attributes
|
|
var selectedAddressAttributes = !string.IsNullOrEmpty(overrideAttributesXml) ?
|
|
overrideAttributesXml :
|
|
address?.CustomAttributes;
|
|
switch (attribute.AttributeControlType)
|
|
{
|
|
case AttributeControlType.DropdownList:
|
|
case AttributeControlType.RadioList:
|
|
case AttributeControlType.Checkboxes:
|
|
{
|
|
if (!string.IsNullOrEmpty(selectedAddressAttributes))
|
|
{
|
|
//clear default selection
|
|
foreach (var item in attributeModel.Values)
|
|
item.IsPreSelected = false;
|
|
|
|
//select new values
|
|
var selectedValues = await _addressAttributeParser.ParseAttributeValuesAsync(selectedAddressAttributes);
|
|
foreach (var attributeValue in selectedValues)
|
|
foreach (var item in attributeModel.Values)
|
|
if (attributeValue.Id == item.Id)
|
|
item.IsPreSelected = true;
|
|
}
|
|
}
|
|
break;
|
|
case AttributeControlType.ReadonlyCheckboxes:
|
|
{
|
|
//do nothing
|
|
//values are already pre-set
|
|
}
|
|
break;
|
|
case AttributeControlType.TextBox:
|
|
case AttributeControlType.MultilineTextbox:
|
|
{
|
|
if (!string.IsNullOrEmpty(selectedAddressAttributes))
|
|
{
|
|
var enteredText = _addressAttributeParser.ParseValues(selectedAddressAttributes, attribute.Id);
|
|
if (enteredText.Any())
|
|
attributeModel.DefaultValue = enteredText[0];
|
|
}
|
|
}
|
|
break;
|
|
case AttributeControlType.ColorSquares:
|
|
case AttributeControlType.ImageSquares:
|
|
case AttributeControlType.Datepicker:
|
|
case AttributeControlType.FileUpload:
|
|
default:
|
|
//not supported attribute control types
|
|
break;
|
|
}
|
|
|
|
model.CustomAddressAttributes.Add(attributeModel);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
/// <summary>
|
|
/// Prepare address model
|
|
/// </summary>
|
|
/// <param name="model">Address model</param>
|
|
/// <param name="address">Address entity</param>
|
|
/// <param name="excludeProperties">Whether to exclude populating of model properties from the entity</param>
|
|
/// <param name="addressSettings">Address settings</param>
|
|
/// <param name="loadCountries">Countries loading function; pass null if countries do not need to load</param>
|
|
/// <param name="prePopulateWithCustomerFields">Whether to populate model properties with the customer fields (used with the customer entity)</param>
|
|
/// <param name="customer">Customer entity; required if prePopulateWithCustomerFields is true</param>
|
|
/// <param name="overrideAttributesXml">Overridden address attributes in XML format; pass null to use CustomAttributes of the address entity</param>
|
|
/// <returns>A task that represents the asynchronous operation</returns>
|
|
public virtual async Task PrepareAddressModelAsync(AddressModel model,
|
|
Address address, bool excludeProperties,
|
|
AddressSettings addressSettings,
|
|
Func<Task<IList<Country>>> loadCountries = null,
|
|
bool prePopulateWithCustomerFields = false,
|
|
Customer customer = null,
|
|
string overrideAttributesXml = "")
|
|
{
|
|
ArgumentNullException.ThrowIfNull(model);
|
|
|
|
ArgumentNullException.ThrowIfNull(addressSettings);
|
|
|
|
var languageId = customer != null ? (customer?.LanguageId ?? 0) : (await _workContext.GetWorkingLanguageAsync()).Id;
|
|
|
|
if (!excludeProperties && address != null)
|
|
{
|
|
model.Id = address.Id;
|
|
model.FirstName = address.FirstName;
|
|
model.LastName = address.LastName;
|
|
model.Email = address.Email;
|
|
model.Company = address.Company;
|
|
model.CountryId = address.CountryId;
|
|
model.CountryName = await _countryService.GetCountryByAddressAsync(address) is Country country ? await _localizationService.GetLocalizedAsync(country, x => x.Name) : null;
|
|
model.StateProvinceId = address.StateProvinceId;
|
|
model.StateProvinceName = await _stateProvinceService.GetStateProvinceByAddressAsync(address) is StateProvince stateProvince ? await _localizationService.GetLocalizedAsync(stateProvince, x => x.Name) : null;
|
|
model.County = address.County;
|
|
model.City = address.City;
|
|
model.Address1 = address.Address1;
|
|
model.Address2 = address.Address2;
|
|
model.ZipPostalCode = address.ZipPostalCode;
|
|
model.PhoneNumber = address.PhoneNumber;
|
|
model.FaxNumber = address.FaxNumber;
|
|
}
|
|
|
|
if (address == null && prePopulateWithCustomerFields)
|
|
{
|
|
if (customer == null)
|
|
throw new Exception("Customer cannot be null when prepopulating an address");
|
|
model.Email = customer.Email;
|
|
model.FirstName = customer.FirstName;
|
|
model.LastName = customer.LastName;
|
|
model.Company = customer.Company;
|
|
model.Address1 = customer.StreetAddress;
|
|
model.Address2 = customer.StreetAddress2;
|
|
model.ZipPostalCode = customer.ZipPostalCode;
|
|
model.City = customer.City;
|
|
model.County = customer.County;
|
|
model.PhoneNumber = customer.Phone;
|
|
model.FaxNumber = customer.Fax;
|
|
}
|
|
|
|
//countries and states
|
|
if (addressSettings.CountryEnabled && loadCountries != null)
|
|
{
|
|
var countries = await loadCountries();
|
|
|
|
if (_addressSettings.PreselectCountryIfOnlyOne && countries.Count == 1)
|
|
{
|
|
model.CountryId = countries[0].Id;
|
|
}
|
|
else
|
|
{
|
|
model.AvailableCountries.Add(new SelectListItem { Text = await _localizationService.GetResourceAsync("Address.SelectCountry"), Value = "0" });
|
|
}
|
|
|
|
if (addressSettings.DefaultCountryId != null)
|
|
model.CountryId = model.CountryId ?? addressSettings.DefaultCountryId;
|
|
|
|
foreach (var c in countries)
|
|
{
|
|
model.AvailableCountries.Add(new SelectListItem
|
|
{
|
|
Text = await _localizationService.GetLocalizedAsync(c, x => x.Name),
|
|
Value = c.Id.ToString(),
|
|
Selected = c.Id == model.CountryId
|
|
});
|
|
}
|
|
|
|
if (addressSettings.StateProvinceEnabled)
|
|
{
|
|
var states = (await _stateProvinceService
|
|
.GetStateProvincesByCountryIdAsync(model.CountryId ?? 0, languageId))
|
|
.ToList();
|
|
if (states.Any())
|
|
{
|
|
model.AvailableStates.Add(new SelectListItem { Text = await _localizationService.GetResourceAsync("Address.SelectState"), Value = "0" });
|
|
|
|
foreach (var s in states)
|
|
{
|
|
model.AvailableStates.Add(new SelectListItem
|
|
{
|
|
Text = await _localizationService.GetLocalizedAsync(s, x => x.Name),
|
|
Value = s.Id.ToString(),
|
|
Selected = (s.Id == model.StateProvinceId)
|
|
});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var anyCountrySelected = model.AvailableCountries.Any(x => x.Selected);
|
|
model.AvailableStates.Add(new SelectListItem
|
|
{
|
|
Text = await _localizationService.GetResourceAsync(anyCountrySelected ? "Address.Other" : "Address.SelectState"),
|
|
Value = "0"
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
//form fields
|
|
model.CompanyEnabled = addressSettings.CompanyEnabled;
|
|
model.CompanyRequired = addressSettings.CompanyRequired;
|
|
model.StreetAddressEnabled = addressSettings.StreetAddressEnabled;
|
|
model.StreetAddressRequired = addressSettings.StreetAddressRequired;
|
|
model.StreetAddress2Enabled = addressSettings.StreetAddress2Enabled;
|
|
model.StreetAddress2Required = addressSettings.StreetAddress2Required;
|
|
model.ZipPostalCodeEnabled = addressSettings.ZipPostalCodeEnabled;
|
|
model.ZipPostalCodeRequired = addressSettings.ZipPostalCodeRequired;
|
|
model.CityEnabled = addressSettings.CityEnabled;
|
|
model.CityRequired = addressSettings.CityRequired;
|
|
model.CountyEnabled = addressSettings.CountyEnabled;
|
|
model.CountyRequired = addressSettings.CountyRequired;
|
|
model.CountryEnabled = addressSettings.CountryEnabled;
|
|
model.StateProvinceEnabled = addressSettings.StateProvinceEnabled;
|
|
model.PhoneEnabled = addressSettings.PhoneEnabled;
|
|
model.PhoneRequired = addressSettings.PhoneRequired;
|
|
model.FaxEnabled = addressSettings.FaxEnabled;
|
|
model.FaxRequired = addressSettings.FaxRequired;
|
|
model.DefaultCountryId = addressSettings.DefaultCountryId;
|
|
|
|
//customer attribute services
|
|
if (_addressAttributeService != null && _addressAttributeParser != null)
|
|
{
|
|
await PrepareCustomAddressAttributesAsync(model, address, overrideAttributesXml);
|
|
}
|
|
if (_addressAttributeFormatter != null && address != null)
|
|
{
|
|
model.FormattedCustomAddressAttributes = await _addressAttributeFormatter.FormatAttributesAsync(address.CustomAttributes);
|
|
}
|
|
|
|
(model.AddressLine, model.AddressFields) = await _addressService.FormatAddressAsync(address, languageId);
|
|
}
|
|
|
|
#endregion
|
|
} |