This commit is contained in:
Andy Howard
2024-11-19 09:47:00 +00:00
parent c5ee285e27
commit 8b872cc8f3
214 changed files with 7924 additions and 5519 deletions
@@ -117,40 +117,40 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="association.caption.association" xml:space="preserve">
<data name="label.association" xml:space="preserve">
<value>Association</value>
</data>
<data name="association.caption.association.create" xml:space="preserve">
<data name="caption.association.create" xml:space="preserve">
<value>Create Association</value>
</data>
<data name="association.caption.association.update" xml:space="preserve">
<data name="caption.association.update" xml:space="preserve">
<value>Update Association</value>
</data>
<data name="association.caption.associations" xml:space="preserve">
<data name="label.associations" xml:space="preserve">
<value>Associations</value>
</data>
<data name="commodity.caption.commodities" xml:space="preserve">
<data name="caption.commodities" xml:space="preserve">
<value>Commodities</value>
</data>
<data name="commodity.caption.commodity" xml:space="preserve">
<data name="caption.commodity" xml:space="preserve">
<value>Commodity</value>
</data>
<data name="commodity.caption.commodity.create" xml:space="preserve">
<data name="caption.commodity.create" xml:space="preserve">
<value>Create Commodity</value>
</data>
<data name="commodity.caption.commodity.update" xml:space="preserve">
<value>UpdateCommodity</value>
<data name="caption.commodity.update" xml:space="preserve">
<value>Update Commodity</value>
</data>
<data name="contact.caption.contact" xml:space="preserve">
<data name="label.contact" xml:space="preserve">
<value>Contact</value>
</data>
<data name="contact.caption.contact.create" xml:space="preserve">
<data name="caption.contact.create" xml:space="preserve">
<value>Add Contact</value>
</data>
<data name="contact.caption.contact.update" xml:space="preserve">
<data name="caption.contact.update" xml:space="preserve">
<value>Update Contact</value>
</data>
<data name="contact.caption.contacts" xml:space="preserve">
<data name="label.contacts" xml:space="preserve">
<value>Contacts</value>
</data>
<data name="copyright.symbol.year.html" xml:space="preserve">
@@ -168,12 +168,6 @@
<data name="label.any" xml:space="preserve">
<value>Any</value>
</data>
<data name="label.association" xml:space="preserve">
<value>Association</value>
</data>
<data name="label.associations" xml:space="preserve">
<value>Associations</value>
</data>
<data name="label.calendar" xml:space="preserve">
<value>Calendar</value>
</data>
@@ -201,19 +195,16 @@
<data name="label.commodities" xml:space="preserve">
<value>Commodities</value>
</data>
<data name="label.contacts" xml:space="preserve">
<value>Contacts</value>
</data>
<data name="label.context" xml:space="preserve">
<value>Context</value>
</data>
<data name="label.create" xml:space="preserve">
<value>Create</value>
</data>
<data name="label.create.individual" xml:space="preserve">
<data name="caption.individual.create" xml:space="preserve">
<value>Create Individual</value>
</data>
<data name="label.create.organisation" xml:space="preserve">
<data name="caption.organisation.create" xml:space="preserve">
<value>Create Organisation</value>
</data>
<data name="label.customers" xml:space="preserve">
@@ -516,4 +507,88 @@
<data name="label.code.type" xml:space="preserve">
<value>Code type</value>
</data>
<data name="label.address" xml:space="preserve">
<value>Address</value>
</data>
<data name="label.phone" xml:space="preserve">
<value>Phone</value>
</data>
<data name="label.sales.price" xml:space="preserve">
<value>Sales price</value>
</data>
<data name="label.cost.price" xml:space="preserve">
<value>Cost price</value>
</data>
<data name="label.retail.price" xml:space="preserve">
<value>Retail price</value>
</data>
<data name="label.tax.code" xml:space="preserve">
<value>Tax code</value>
</data>
<data name="label.unit.of.sale" xml:space="preserve">
<value>Unit of sale</value>
</data>
<data name="label.pack.quantity" xml:space="preserve">
<value>Pack quantity</value>
</data>
<data name="label.target" xml:space="preserve">
<value>Target</value>
</data>
<data name="label.owner" xml:space="preserve">
<value>Owner</value>
</data>
<data name="label.id" xml:space="preserve">
<value>Id</value>
</data>
<data name="label.salutation" xml:space="preserve">
<value>Salutation</value>
</data>
<data name="label.initials" xml:space="preserve">
<value>Initials</value>
</data>
<data name="label.title" xml:space="preserve">
<value>Title</value>
</data>
<data name="caption.contact.group.create" xml:space="preserve">
<value>Create Contact Group</value>
</data>
<data name="label.options" xml:space="preserve">
<value>Options</value>
</data>
<data name="label.prospect" xml:space="preserve">
<value>Prospect</value>
</data>
<data name="label.abbreviation" xml:space="preserve">
<value>Abbreviation</value>
</data>
<data name="label.nature" xml:space="preserve">
<value>Nature</value>
</data>
<data name="label.phone.alt" xml:space="preserve">
<value>Alt. phone</value>
</data>
<data name="label.phone.direct" xml:space="preserve">
<value>Direct phone</value>
</data>
<data name="label.phone.fax" xml:space="preserve">
<value>Fax</value>
</data>
<data name="label.website" xml:space="preserve">
<value>Website</value>
</data>
<data name="label.company.no" xml:space="preserve">
<value>Company no.</value>
</data>
<data name="label.vat.reg" xml:space="preserve">
<value>VAT reg.</value>
</data>
<data name="label.phone.mobile" xml:space="preserve">
<value>Mobile phone</value>
</data>
<data name="label.phone.home" xml:space="preserve">
<value>Home phone</value>
</data>
<data name="label.email.domain" xml:space="preserve">
<value>Email domain</value>
</data>
</root>
@@ -10,12 +10,15 @@ using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
using Sarand.BusinessMgr.Net.Standard.Base.Core;
using Sarand.BusinessMgr.Net.Standard.Base.Mgr.Control;
using Sarand.BusinessMgr.Net.Standard.Dbas.Consoles;
using Sarand.BusinessMgr.Web.Portal.Consoles;
using Sarand.BusinessMgr.Web.Portal.Helpers;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.IO;
using Sarand.Net.Standard.Base.ReferenceData;
using Sarand.Net.Standard.Base.Utils;
using Sarand.Net.Standard.Dbas.Base;
using System;
@@ -31,7 +34,7 @@ namespace Sarand.BusinessMgr.Web.Portal.App
//-------------------------------------------------------------------
// Data members.
private PropertySet properties;
private Dictionary<String, SbmAppConfig> appConfigs = new Dictionary<string, SbmAppConfig>();
private Dictionary<String, Net.Core.Web.App.SbmAppConfig> appConfigs = new Dictionary<string, Net.Core.Web.App.SbmAppConfig>();
private Dictionary<String, SbmEmailConfig> emailConfigs = new Dictionary<string, SbmEmailConfig>();
private ISacsDatabase controlDatabase = null;
@@ -52,6 +55,23 @@ namespace Sarand.BusinessMgr.Web.Portal.App
public SysId ControlOwnerId { get; protected set; }
public SysId ControlRepositoryId { get; protected set; }
}
private class SessionContextData_Core : SessionContextData
{
// Instance configuration for core database instance without Control configuration.
public SessionContextData_Core(SbmSessionContext_Web sessionContext) : base(sessionContext)
{
}
private SbmInstanceConfig instanceConfig = null;
public override SbmInstanceConfig InstanceConfig
{
get
{
if (instanceConfig == null)
instanceConfig = new SbmInstanceConfig_Core(SessionContext);
return instanceConfig;
}
}
}
private class SessionContextData_Control : SessionContextData
{
public SessionContextData_Control(SbmSessionContext_Web sessionContext, SysId controlOwnerId, SysId controlRepositoryId) : base(sessionContext)
@@ -65,7 +85,7 @@ namespace Sarand.BusinessMgr.Web.Portal.App
get
{
if (instanceConfig == null)
instanceConfig = new SbmInstanceConfig_Web(ControlOwnerId, ControlRepositoryId);
instanceConfig = new SbmInstanceConfig_Portal(ControlOwnerId, ControlRepositoryId);
return instanceConfig;
}
}
@@ -97,7 +117,7 @@ namespace Sarand.BusinessMgr.Web.Portal.App
// Properties.
public static SbmApplication_Portal Instance { get; private set; }
// Application Configuration.
public override SbmAppConfig AppConfig { get { return appConfigs.Values.ToList().getConfigForApplication(); } }
public override Net.Core.Web.App.SbmAppConfig AppConfig { get { return appConfigs.Values.ToList().getConfigForApplication(); } }
// Session Configuration.
public override String SessionCookieName { get { return Sbm.Config.Portal.Session.Cookie.Name; } }
// Session Contexts - available BusMgr instances.
@@ -130,11 +150,20 @@ namespace Sarand.BusinessMgr.Web.Portal.App
{
return sessionContexts.GetValue(sessionContext.Index, null)?.BusMgrDatabase;
}
// Instance configuration.
public override SbmInstanceConfig GetInstanceConfig(SbmSessionContext sessionContext)
{
return sessionContexts.GetValue(sessionContext.Index, null)?.InstanceConfig;
}
// Email configuration.
public override SbmEmailConfig EmailConfig { get { return emailConfigs.Values.ToList().getConfigForSession(AppConfig); } }
//-------------------------------------------------------------------
// Create Consoles.
public override SaReferenceDataConsole CreateReferenceDataConsole(ISbmUserContext_Core userContext)
{
return new SbmReferenceDataConsole_Portal(userContext);
}
public override SbmEmailConsole CreateEmailConsole(ISbmUserContext_Core userContext)
{
return new SbmEmailConsole_Portal(EmailConfig);
@@ -198,21 +227,21 @@ namespace Sarand.BusinessMgr.Web.Portal.App
SaLogger.Warn($"{SysUtil.Fn} Control Database initialisation error: " + controlDatabase.ErrorStateMessage);
// Configure BusMgr database connections.
foreach (SbmAppConfig.DatabaseConfig dbConfig in AppConfig.BusMgrDatabases)
foreach (Net.Core.Web.App.SbmAppConfig.DatabaseConfig dbConfig in AppConfig.BusMgrDatabases)
{
SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig();
SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig();
config.location = dbConfig.Location;
config.user = dbConfig.User;
config.pword = dbConfig.Password;
SacsDatabase coreDatabase = SacsDatabaseConsole.OpenOdbcDatabase(config);
SacsDatabase coreDatabase = SacsDatabaseConsole.OpenOdbcDatabase(config);
if (!coreDatabase.HasErrorState())
{
// Session context.
ushort sessionContextIdx = sessionContextIdx_Next++;
SessionContextData sessionContextData = new SessionContextData(new SbmSessionContext_Web(sessionContextIdx, Sbm.Application.WebPortal));
SessionContextData sessionContextData = new SessionContextData_Core(new SbmSessionContext_Web(sessionContextIdx, Sbm.Application.WebPortal));
sessionContextData.BusMgrDatabase = coreDatabase;
sessionContextData.DbIdentifiers.UnionWith(dbConfig.Identifiers);
sessionContexts.Add(sessionContextData.SessionContext.Index, sessionContextData);
sessionContexts.Add(sessionContextData.SessionContext.Index, sessionContextData);
}
else SaLogger.Warn($"{SysUtil.Fn} Database: " + coreDatabase.DatabaseName + ". Initialisation error: " + coreDatabase.ErrorStateMessage);
}
@@ -0,0 +1,228 @@
using DocumentFormat.OpenXml.Drawing.Diagrams;
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
using Sarand.BusinessMgr.Net.Standard.Base.Mgr.Control;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Sarand.BusinessMgr.Web.Portal.App
{
//=======================================================================
public class SbmInstanceConfig_Portal : SbmInstanceConfig
{
//-------------------------------------------------------------------
// Definitions.
protected const String ParamContext_Config = "Config";
protected const String ParamContext_ConfigPrefix = "Config-";
protected const String ApplicationOptionValue_Allow = "Allow";
protected const String ApplicationOptionValue_Disallow = "Disallow";
//-------------------------------------------------------------------
// Data members.
private readonly SysId controlOwnerId;
private readonly SysId controlRepositoryId;
//-------------------------------------------------------------------
// Construction.
public SbmInstanceConfig_Portal(SysId controlOwnerId, SysId controlRepositoryId)
{
this.controlOwnerId = controlOwnerId;
this.controlRepositoryId = controlRepositoryId;
PopulateControlParams();
}
//-------------------------------------------------------------------
// Owner/Instance configuration parameters.
public enum ConfigParamType
{
// Affiliate types.
AllowedAffiliateTypes,
DisallowedAffiliateTypes,
// Association types.
AllowedAssociationTypes,
DisallowedAssociationTypes,
// Transaction types.
AllowedTransactionTypes,
DisallowedTransactionTypes,
// Application options.
ApplicationOption,
}
public class ConfigParamData
{
public ConfigParamType ConfigParam { get; set; }
public String Context { get; set; }
public String Name { get; set; }
public HashSet<String> Values { get; } = new HashSet<string>();
public bool Password { get; set; }
}
public bool IsConfigParamOfType(ConfigParamType configParam, SbmcItemParam itemParam)
{
switch (configParam)
{
// Affiliate types.
case ConfigParamType.AllowedAffiliateTypes:
case ConfigParamType.DisallowedAffiliateTypes:
// Association types.
case ConfigParamType.AllowedAssociationTypes:
case ConfigParamType.DisallowedAssociationTypes:
// Transaction types.
case ConfigParamType.AllowedTransactionTypes:
case ConfigParamType.DisallowedTransactionTypes:
return itemParam.Context.EqualsCI(ParamContext_Config) && itemParam.Name.EqualsCI(configParam.ToString());
// Application options.
case ConfigParamType.ApplicationOption:
return itemParam.Context.EqualsCI($"{ParamContext_ConfigPrefix}{ConfigParamType.ApplicationOption.ToString()}");
}
return false;
}
public ConfigParamData GetConfigParamData(ConfigParamType configParam)
{
switch (configParam)
{
// Affiliate types.
case ConfigParamType.AllowedAffiliateTypes:
case ConfigParamType.DisallowedAffiliateTypes:
// Association types.
case ConfigParamType.AllowedAssociationTypes:
case ConfigParamType.DisallowedAssociationTypes:
// Transaction types.
case ConfigParamType.AllowedTransactionTypes:
case ConfigParamType.DisallowedTransactionTypes:
return new ConfigParamData() { ConfigParam = configParam, Context = ParamContext_Config, Name = configParam.ToString() };
}
return null;
}
public ConfigParamData GetAllowOptionConfigParamData(Sbm.ConfigOption option)
{
ConfigParamData configParamData = new ConfigParamData() { ConfigParam = ConfigParamType.ApplicationOption, Context = $"{ParamContext_ConfigPrefix}{ConfigParamType.ApplicationOption.ToString()}", Name = option.ToString() };
configParamData.Values.UnionWith(new List<String>() { ApplicationOptionValue_Allow, ApplicationOptionValue_Disallow });
return configParamData;
}
//-------------------------------------------------------------------
// Populate Repository Configuration parameters.
private void PopulateControlParams()
{
using (DisposableCollection<SacsDisposable> disposables = new DisposableCollection<SacsDisposable>())
{
SbmcItemMgr controlItemMgr = SbmGlobals_Web.System.CreateControlItemMgr();
if (controlItemMgr != null)
{
disposables.Add(controlItemMgr);
PopulateControlParams(controlItemMgr, new ItemId((short)SbmcHierarchyItem.ItemType.Owner, controlOwnerId));
PopulateControlParams(controlItemMgr, new ItemId((short)SbmcHierarchyItem.ItemType.Repository, controlRepositoryId));
}
}
}
private void PopulateControlParams(SbmcItemMgr controlItemMgr, ItemId paramItemId)
{
if (!ItemId.IsValid(paramItemId)) return;
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
{
// Query item params.
SbmcItemParam.Params prmParam = new SbmcItemParam.Params();
prmParam.ItemIdsIncluded.Add(paramItemId);
prmParam.StatusCat = SbmcItemParam.StatusCat.ActiveOnly;
List<SbmcItemParam> itemParams = controlItemMgr.GetItemParamList(prmParam);
disposables.AddRange(itemParams);
foreach (SbmcItemParam itemParam in itemParams)
PopulateControlParam(itemParam);
}
}
private void PopulateControlParam(SbmcItemParam itemParam)
{
// Affiliate types.
if (IsConfigParamOfType(ConfigParamType.AllowedAffiliateTypes, itemParam))
AffiliateTypes_Allowed.UnionWith(EnumUtil.ParseEnums<Sbm.AffiliateType>(Regex.Split(itemParam.Value, "[\\s,;\\-]+")));
else if (IsConfigParamOfType(ConfigParamType.DisallowedAffiliateTypes, itemParam))
AffiliateTypes_Disallowed.UnionWith(EnumUtil.ParseEnums<Sbm.AffiliateType>(Regex.Split(itemParam.Value, "[\\s,;\\-]+")));
// Association types.
else if (IsConfigParamOfType(ConfigParamType.AllowedAssociationTypes, itemParam))
AssociationTypes_Allowed.UnionWith(EnumUtil.ParseEnums<Sbm.AssociationType>(Regex.Split(itemParam.Value, "[\\s,;\\-]+")));
else if (IsConfigParamOfType(ConfigParamType.DisallowedAssociationTypes, itemParam))
AssociationTypes_Disallowed.UnionWith(EnumUtil.ParseEnums<Sbm.AssociationType>(Regex.Split(itemParam.Value, "[\\s,;\\-]+")));
// Transaction types.
else if (IsConfigParamOfType(ConfigParamType.AllowedTransactionTypes, itemParam))
TransactionTypes_Allowed.UnionWith(EnumUtil.ParseEnums<Sbm.TransactionType>(Regex.Split(itemParam.Value, "[\\s,;\\-]+")));
else if (IsConfigParamOfType(ConfigParamType.DisallowedTransactionTypes, itemParam))
TransactionTypes_Disallowed.UnionWith(EnumUtil.ParseEnums<Sbm.TransactionType>(Regex.Split(itemParam.Value, "[\\s,;\\-]+")));
// Application options.
else if (IsConfigParamOfType(ConfigParamType.ApplicationOption, itemParam))
{
Sbm.ConfigOption option = EnumUtil.ParseEnum(itemParam.Name, Sbm.ConfigOption.Unknown);
if (option != Sbm.ConfigOption.Unknown)
{
if (itemParam.Value.EqualsCI(ApplicationOptionValue_Allow))
ApplicationOptions_Allowed.Add(option);
else if (itemParam.Value.EqualsCI(ApplicationOptionValue_Disallow))
ApplicationOptions_Disallowed.Add(option);
else
SaLogger.Warn($"{SysUtil.Fn} Unrecognised application option value: {itemParam.Value}. Option: {option}.");
}
else
SaLogger.Warn($"{SysUtil.Fn} Unrecognised application option: {itemParam.Name}.");
}
}
//-------------------------------------------------------------------
// Allowed data component types.
//-------------------------------------------------------------------
// Supported affiliate types.
private readonly HashSet<Sbm.AffiliateType> AffiliateTypes_Allowed = new HashSet<Sbm.AffiliateType>();
private readonly HashSet<Sbm.AffiliateType> AffiliateTypes_Disallowed = new HashSet<Sbm.AffiliateType>();
public override bool AllowAffiliateType(Sbm.AffiliateType affiliateType, bool defaultResponse)
{
if (AffiliateTypes_Disallowed.Contains(affiliateType)) return false;
if (AffiliateTypes_Allowed.Contains(affiliateType)) return true;
return defaultResponse;
}
// Supported affiliate types.
private readonly HashSet<Sbm.AssociationType> AssociationTypes_Allowed = new HashSet<Sbm.AssociationType>();
private readonly HashSet<Sbm.AssociationType> AssociationTypes_Disallowed = new HashSet<Sbm.AssociationType>();
public override bool AllowAssociationType(Sbm.AssociationType affiliateType, bool defaultResponse)
{
if (AssociationTypes_Disallowed.Contains(affiliateType)) return false;
if (AssociationTypes_Allowed.Contains(affiliateType)) return true;
return defaultResponse;
}
// Supported affiliate types.
private readonly HashSet<Sbm.TransactionType> TransactionTypes_Allowed = new HashSet<Sbm.TransactionType>();
private readonly HashSet<Sbm.TransactionType> TransactionTypes_Disallowed = new HashSet<Sbm.TransactionType>();
public override bool AllowTransactionType(Sbm.TransactionType affiliateType, bool defaultResponse)
{
if (TransactionTypes_Disallowed.Contains(affiliateType)) return false;
if (TransactionTypes_Allowed.Contains(affiliateType)) return true;
return defaultResponse;
}
//-------------------------------------------------------------------
// Supported application options.
private readonly HashSet<Sbm.ConfigOption> ApplicationOptions_Allowed = new HashSet<Sbm.ConfigOption>();
private readonly HashSet<Sbm.ConfigOption> ApplicationOptions_Disallowed = new HashSet<Sbm.ConfigOption>();
public override bool AllowApplicationOption(Sbm.ConfigOption option, bool defaultResponse)
{
if (ApplicationOptions_Disallowed.Contains(option)) return false;
if (ApplicationOptions_Allowed.Contains(option)) return true;
return defaultResponse;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -104,7 +104,9 @@ namespace Sarand.BusinessMgr.Web.Portal.App
//-------------------------------------------------------------------
// Security Profile.
[JsonProperty("SecurityProfile")]
private readonly SbmSecurityProfile securityProfile;
[JsonIgnore]
public ISbmSecurityProfile_Core SecurityProfile_Core { get { return securityProfile; } }
//-------------------------------------------------------------------
@@ -233,7 +235,7 @@ namespace Sarand.BusinessMgr.Web.Portal.App
public class FilterData
{
public uint PageNo { get; set; } = 1;
public ushort PageLength { get; set; } = 16;
public ushort PageLength { get; set; } = 200;
}
public FilterData Filter { get; } = new FilterData();
}
@@ -246,7 +248,7 @@ namespace Sarand.BusinessMgr.Web.Portal.App
public class FilterData
{
public uint PageNo { get; set; } = 1;
public ushort PageLength { get; set; } = 16;
public ushort PageLength { get; set; } = 200;
}
public FilterData Filter { get; } = new FilterData();
}
@@ -259,7 +261,7 @@ namespace Sarand.BusinessMgr.Web.Portal.App
public class FilterData
{
public uint PageNo { get; set; } = 1;
public ushort PageLength { get; set; } = 16;
public ushort PageLength { get; set; } = 200;
}
public FilterData Filter { get; } = new FilterData();
}
@@ -0,0 +1,35 @@
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Core;
using Sarand.BusinessMgr.Net.Standard.Dbas.Consoles;
using Sarand.Net.Standard.Base.UpdateLog;
namespace Sarand.BusinessMgr.Web.Portal.Consoles
{
//=======================================================================
public class SbmReferenceDataConsole_Portal : SbmReferenceDataConsole_Dbas
{
//-------------------------------------------------------------------
// Data members.
private SaUpdateLogConsole updateLogConsole;
//-------------------------------------------------------------------
// Construction.
public SbmReferenceDataConsole_Portal(ISbmUserContext_Core userContext) :
base(userContext)
{
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
}
base.Dispose(disposing);
}
//-------------------------------------------------------------------
// Properties.
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -12,7 +12,7 @@ using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets
{
//=======================================================================
partial class AssetCategoryController
@@ -9,10 +9,10 @@ using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets
{
//======================================================================
public partial class AssetCategoryController : SbmController_Portal
//======================================================================
public partial class AssetCategoryController : SbmController_Portal
{
//-------------------------------------------------------------------
// Data members.
@@ -12,7 +12,7 @@ using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets
{
//=======================================================================
partial class AssetController
@@ -9,7 +9,7 @@ using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets
{
//======================================================================
public partial class AssetController : SbmController_Portal
@@ -13,7 +13,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets
{
//=======================================================================
partial class VehicleClassController
@@ -9,10 +9,10 @@ using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets
{
//======================================================================
public partial class VehicleClassController : SbmController_Portal
//======================================================================
public partial class VehicleClassController : SbmController_Portal
{
//-------------------------------------------------------------------
// Data members.
@@ -1,397 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
using Sarand.BusinessMgr.Web.Portal.Models;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
using Sarand.BusinessMgr.Net.Standard.Base.Helpers;
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Email;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Security;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
namespace Sarand.BusinessMgr.Web.Portal.Controllers
{
//=======================================================================
// Portal Association Controller - Ajax actions.
//=======================================================================
partial class AssociationController
{
//-------------------------------------------------------------------
// Association data.
private class AssociationData_List : AjaxResponse_Data.ItemData_Base
{
public String OwnerId { get; set; }
public String OwnerName { get; set; }
public String TargetId { get; set; }
public String TargetName { get; set; }
public String TypeCode { get; set; }
public String TypeDesc { get; set; }
public String Code { get; set; }
public String ReferenceExt { get; set; }
public String Group { get; set; }
public String DescDetail { get; set; }
// Address.
public String AddressSummary { get; set; }
}
private class AssociationData_Full : AssociationData_List
{
// Association properties.
public String Location { get; set; }
public String Role { get; set; }
public String PhoneMain { get; set; }
public String Email { get; set; }
public String NominalCodeDefault { get; set; }
}
private void PopulateAssociationResponseData(SbmAssociation association, AssociationData_List data)
{
data.Id = SysId.ToString(association.Id);
data.TypeCode = Internals.AssociationTypeCodes.GetCodeForType(association.AssociationType);
data.TypeDesc = Internals.AssociationTypeCodes.GetDescForType(association.AssociationType);
data.Code = association.Code;
data.ReferenceExt = association.RefExt;
data.Group = association.Group;
data.DescDetail = association.DescDetail;
// Common properties.
data.Notes = association.Notes;
data.StatusCode = association.StatusCode;
data.StatusDesc = association.StatusDesc;
}
private void PopulateAssociationResponseData(SbmAssociation association, AssociationData_Full data)
{
PopulateAssociationResponseData(association, data as AssociationData_List);
// Association properties.
data.Location = association.Location;
data.Role = association.Role;
data.PhoneMain = association.PhoneMain;
data.Email = association.Email;
data.NominalCodeDefault = association.DefaultNominalCode;
}
//-------------------------------------------------------------------
// Association list.
//-------------------------------------------------------------------
private class AjaxResponse_AssociationList : AjaxResponse_Data
{
// Construction.
public AjaxResponse_AssociationList(SbmModel_Portal model) : base(model) { }
// Association list.
public List<AssociationData_List> Associations { get; } = new List<AssociationData_List>();
// Reference data.
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public String DefaultStatusCode { get; set; }
}
// Ajax request.
[HttpPost]
[Route("Association/Ajax/List")]
[Route("Association/Ajax/GetList")]
public IActionResult Ajax_AssociationList(Model_Association model)
{
AjaxResponse_AssociationList responseData = new AjaxResponse_AssociationList(model);
String messageTitle = Localiser["association.caption.associations"];
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Reference data - statuses.
foreach (SaStatus status in SbmAssociation.ValidStatuses.FindAll(item => item != SaStatus.Deleted))
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SbmAssociation.DefaultStatus);
// Item filter.
SbmAssociation.Params prmAssociation = new SbmAssociation.Params();
prmAssociation.AffiliateIdOwner = SessionData_Portal.Organisation.AffiliateId;
prmAssociation.Search = model.Filter.AssociationSearch;
prmAssociation.AssociationType = model.GetFilterAssociationType();
prmAssociation.StatusCat = SbmAssociation.StatusCat.NotDeleted;
prmAssociation.SortColumns.Add(AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Target_Name));
model.Paging.ItemTotal = (ulong)AccountMgr.GetAssociationCount(prmAssociation);
model.PopulatePagingTo(prmAssociation.ResultsPaging);
// Item columns.
ColumnDfn colId = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Id);
ColumnDfn colAffIdTarget = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.AffIdTarget);
ColumnDfn colTargetName = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Target_Name);
ColumnDfn colAssociationType = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Type_Desc);
ColumnDfn colCode = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Code);
ColumnDfn colExtRef = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.ExtRef);
ColumnDfn colGroup = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Group);
ColumnDfn colDescDetail = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.DescDetail);
ColumnDfn colNotes = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Notes);
ColumnDfn colStatus = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Status);
ColumnDfn colCreatedOn = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.CreateOn_Date);
ColumnDfn colUpdatedOn = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.UpdateOn_Date);
List<ColumnDfn> columns = new List<ColumnDfn>()
{
colId, colAffIdTarget, colTargetName, colAssociationType,
colCode, colExtRef, colGroup, colDescDetail,
colNotes, colStatus, colCreatedOn, colUpdatedOn
};
// Query items.
using (DbResultSet resultSet = AccountMgr.ExecuteAssociationQuery(columns, prmAssociation))
{
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
{
NamedValue.Map values = resultSet.GetRecordValues();
Sbm.AssociationType associationType = (Sbm.AssociationType)values.GetLong(colAssociationType.DataName);
AssociationData_List associationData = new AssociationData_List()
{
Id = values.GetString(colId.DataName),
TargetId = values.GetString(colAffIdTarget.DataName),
TargetName = values.GetString(colTargetName.DataName),
TypeCode = Internals.AssociationTypeCodes.GetCodeForType(associationType),
TypeDesc = Internals.AssociationTypeCodes.GetDescForType(associationType),
Code = values.GetString(colCode.DataName),
ReferenceExt = values.GetString(colExtRef.DataName),
Group = values.GetString(colGroup.DataName),
DescDetail = values.GetString(colDescDetail.DataName),
Notes = values.GetString(colNotes.DataName),
StatusCode = values.GetString(colStatus.DataName),
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName)),
CreatedOn = DateUtil.Format(values.GetDate(colCreatedOn.DataName), "yyyyMMdd"),
CreatedOnFmt = Localiser.FormatDate(values.GetDate(colCreatedOn.DataName)),
UpdatedOn = DateUtil.Format(values.GetDate(colUpdatedOn.DataName), "yyyyMMdd"),
UpdatedOnFmt = Localiser.FormatDate(values.GetDate(colUpdatedOn.DataName))
};
responseData.Associations.Add(associationData);
}
}
// Refresh paging info.
if (model.Paging.IsPaged)
model.Paging.ItemCount = (ushort)responseData.Associations.Count;
SessionData_Portal.Profile.Associations.Filter.PageNo = model.Paging.PageNo;
SessionData_Portal.Profile.Associations.Filter.PageLength = model.Paging.PageLength;
responseData.SetPaging(model);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
// Get Association ajax request.
//-------------------------------------------------------------------
private class AjaxResponse_Association : AjaxResponse_Data
{
// Construction.
public AjaxResponse_Association(SbmModel_Portal model) : base(model) { }
// Association details.
public AssociationData_Full association { get; } = new AssociationData_Full();
}
//-------------------------------------------------------------------
[HttpPost]
[Route("Association/Ajax/Item")]
[Route("Association/Ajax/GetItem")]
public IActionResult Ajax_GetItem(Model_Association model)
{
String messageTitle = Localiser["association.caption.association"];
AjaxResponse_Association responseData = new AjaxResponse_Association(model);
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Identify item.
SysId associationId = model.AssociationId.ToSysId();
if (!SysId.IsValid(associationId))
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
// Retrieve item.
SbmAssociation association = AccountMgr.GetAssociationById(associationId);
if (association == null)
{
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve association for Id: '" + model.AssociationId + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
}
// Construct response.
PopulateAssociationResponseData(association, responseData.association);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
// Store Association ajax request.
//-------------------------------------------------------------------
[HttpPost]
[Route("Association/Ajax/Store")]
[Route("Association/Ajax/StoreItem")]
public IActionResult Ajax_StoreItem(Model_Association model)
{
String messageTitle = Localiser["association.caption.association"];
AjaxResponse_Association responseData = new AjaxResponse_Association(model);
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Validate item properties.
model.ValidateAssociationData(responseData);
if (responseData.HasControlErrors())
return Json(responseData);
// Validate item Id against 'Exists' flag.
SysId associationId = model.AssociationId.ToSysId();
bool associationExists = StringUtil.ToBool(model.AssociationExists);
if (associationExists && !SysId.IsValid(associationId))
{
SaLogger.Warn($"{SysUtil.Fn} Id not specified for existing Association.");
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
if (!associationExists && SysId.IsValid(associationId))
{
SaLogger.Warn($"{SysUtil.Fn} Id specified for new Association: '" + model.AssociationId + "'");
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
// Retrieve existing item.
SbmAssociation association = AccountMgr.GetAssociationById(associationId);
if (association == null && SysId.IsValid(associationId))
{
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve association for Id: '" + model.AssociationId + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
}
// Create new item if required.
if (association == null)
{
association = AccountMgr.CreateAssociation(SessionData_Portal.Organisation.AffiliateId, model.GetAssociationType(), model.AffiliateIdTarget.ToSysId());
}
// Populate item properties.
if (model.AssociationCode != null)
association.Code = model.AssociationCode;
if (model.AssociationReferenceExt != null)
association.RefExt = model.AssociationReferenceExt;
if (model.AssociationLocation != null)
association.Location = model.AssociationLocation;
if (model.AssociationRole != null)
association.Role = model.AssociationRole;
if (model.AssociationPhoneMain != null)
association.PhoneMain = model.AssociationPhoneMain;
if (model.AssociationEmail != null)
association.Email = model.AssociationEmail;
if (model.AssociationGroup != null)
association.Group = model.AssociationGroup;
if (model.AssociationDescDetail != null)
association.DescDetail = model.AssociationDescDetail;
if (model.AssociationNominalCodeDefault != null)
association.DefaultNominalCode = model.AssociationNominalCodeDefault;
// Account.
if (model.AssociationAccountManagerCode != null)
association.AccountManagerCode = model.AssociationAccountManagerCode;
if (model.AssociationAccountHandlerCode != null)
association.AccountHandlerCode = model.AssociationAccountHandlerCode;
if (model.AssociationAccountTypeCode != null)
association.AccountTypeCode = model.AssociationAccountTypeCode;
if (model.AssociationAccountRatingCode != null)
association.AccountRatingCode = model.AssociationAccountRatingCode;
// Contact.
if (model.AssociationContactAreaCode != null)
association.ContactAreaCode = model.AssociationContactAreaCode;
if (model.AssociationContactHandlerCode != null)
association.ContactHandlerCode = model.AssociationContactHandlerCode;
if (model.AssociationContactMethodCode != null)
association.ContactMethodCode = model.AssociationContactMethodCode;
if (model.AssociationContactCallCycleCode != null)
association.ContactCallCycleCode = model.AssociationContactCallCycleCode;
if (model.AssociationCallsPerYear != null)
association.CallsPerYear = StringUtil.ToInt(model.AssociationCallsPerYear);
if (model.AssociationLastCallDate != null)
association.LastCall = model.ParseDateFromForm(model.AssociationLastCallDate);
// Customer.
if (model.AssociationCommodityIdSalesDefault != null)
association.CommodityIdSalesDefault = model.AssociationCommodityIdSalesDefault.ToSysId();
if (model.AssociationOrderLeadTimeCode != null)
association.OrderLeadTimeCode = model.AssociationOrderLeadTimeCode;
if (model.AssociationDeliveryTypeCode != null)
association.DeliveryTypeCode = model.AssociationDeliveryTypeCode;
if (model.AssociationDeliveryMethodCode != null)
association.DeliveryMethodCode = model.AssociationDeliveryMethodCode;
if (model.AssociationDeliveryCourierCode != null)
association.DeliveryCourierCode = model.AssociationDeliveryCourierCode;
if (model.AssociationDeliveryBookInCode != null)
association.DeliveryBookInCode = model.AssociationDeliveryBookInCode;
// Transactions.
if (model.AssociationAmountTransMax != null)
association.AmountTransMax = StringUtil.ToDecimal(model.AssociationAmountTransMax);
if (model.AssociationAnnualSalesTarget != null)
association.AnnualSalesTarget = StringUtil.ToDecimal(model.AssociationAnnualSalesTarget);
if (model.AssociationCreditLimit != null)
association.CreditLimit = StringUtil.ToDecimal(model.AssociationCreditLimit);
if (model.AssociationAccountBalance != null)
association.AccountBalance = StringUtil.ToDecimal(model.AssociationAccountBalance);
if (model.AssociationDiscountType != null)
association.DiscountType = model.GetAssociationDiscountType();
if (model.AssociationDiscountRate != null)
association.DiscountRate = StringUtil.ToDecimal(model.AssociationDiscountRate);
if (model.AssociationPriceSetId != null)
association.PriceSetId = model.AssociationPriceSetId.ToSysId();
if (model.AssociationTaxCodeId != null)
association.TaxCodeId = model.AssociationTaxCodeId.ToSysId();
if (model.AssociationPaymentTerms != null)
association.PaymentTerms = StringUtil.ToShort(model.AssociationPaymentTerms);
if (model.AssociationInvoiceDesc != null)
association.InvoiceDesc = model.AssociationInvoiceDesc;
if (model.AssociationTerminatedDate != null)
association.Terminated = model.ParseDateFromForm(model.AssociationTerminatedDate);
// Common properties.
if (model.AssociationNotes != null)
association.Notes = model.AssociationNotes;
if (model.AssociationStatusCode != null)
association.Status = model.AssociationStatus;
// Store item.
if (!SysId.IsValid(association.Id))
{
if (!AccountMgr.InsertAssociation(association, DbUpdateInfo))
{
SaLogger.Warn($"{SysUtil.Fn} Failed to insert association: " + AccountMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.created"]);
}
else
{
if (!AccountMgr.UpdateAssociation(association, DbUpdateInfo))
{
SaLogger.Warn($"{SysUtil.Fn} Failed to update association [Id:" + SysId.ToString(association.Id) + "]: " + AccountMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]);
}
// Construct response.
PopulateAssociationResponseData(association, responseData.association);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -14,7 +14,7 @@ using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes
{
//=======================================================================
partial class CodeController
@@ -9,7 +9,7 @@ using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes
{
//======================================================================
public partial class CodeController : SbmController_Portal
@@ -15,7 +15,7 @@ using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes
{
//=======================================================================
partial class CodeTypeController
@@ -10,10 +10,10 @@ using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes
{
//======================================================================
public partial class CodeTypeController : SbmController_Portal
//======================================================================
public partial class CodeTypeController : SbmController_Portal
{
//-------------------------------------------------------------------
// Data members.
@@ -0,0 +1,501 @@
using Microsoft.AspNetCore.Mvc;
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
using Sarand.BusinessMgr.Web.Portal.Models;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
using Sarand.BusinessMgr.Net.Standard.Base.Helpers;
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Email;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Security;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Sarand.BusinessMgr.Web.Portal.Models.Commodities;
using static Sarand.BusinessMgr.Net.Standard.Base.App.Sbm;
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
{
//=======================================================================
// Portal Commodity Controller - Ajax actions.
//=======================================================================
partial class CommodityController
{
//-------------------------------------------------------------------
// Commodity data.
private class CommodityListData : AjaxResponse_Data.ItemData_Base
{
public String TypeCode { get; set; }
public String TypeDesc { get; set; }
public String Code { get; set; }
public String Desc { get; set; }
public String SalesPriceFmt { get; set; }
public String SalesUnit { get; set; }
public String CostPriceFmt { get; set; }
}
private enum CommodityDataGroup
{
Sales, Purchasing, Specification, Production
}
private class CommodityItemData : CommodityListData
{
// Commodity properties.
public String DrawingIssue { get; set; }
public String AssocIdCustomer { get; set; }
public String AssocIdSupplier { get; set; }
// Sales.
public String SalesPrice { get; set; }
// Purchasing.
public String CostPrice { get; set; }
// Specification.
// Production.
}
private void PopulateCommodityResponseListData(SbmCommodity commodity, CommodityListData data)
{
data.Id = SysId.ToString(commodity.Id);
data.TypeCode = Internals.CommodityTypeCodes.GetCodeForType(commodity.CommodityType);
data.TypeDesc = Internals.CommodityTypeCodes.GetDescForType(commodity.CommodityType);
data.Code = commodity.Code;
data.Desc = commodity.DescBrief;
data.SalesPriceFmt = StringUtil.NullOnBlank(StringUtil.FormatNumeric(commodity.SalesPrice, SbmInternals.CurrencyDecimalsDefault, 0, ','));
data.SalesUnit = StringUtil.NullOnBlank(Internals.GetUnitOfMeasureCaption(commodity.UomIdSale));
data.CostPriceFmt = StringUtil.NullOnBlank(StringUtil.FormatNumeric(commodity.CostPrice, SbmInternals.CurrencyDecimalsDefault, 0, ','));
// Common properties.
data.Notes = commodity.Notes;
data.StatusCode = commodity.StatusCode;
data.StatusDesc = commodity.StatusDesc;
}
private void PopulateCommodityResponseItemData(SbmCommodity commodity, CommodityItemData data, HashSet<CommodityDataGroup> dataGroups = null)
{
PopulateCommodityResponseListData(commodity, data as CommodityListData);
// Commodity properties.
data.DrawingIssue = StringUtil.NullOnBlank(commodity.DrawingIssue);
data.AssocIdCustomer = StringUtil.NullOnBlank(SysId.ToString(commodity.AssociationIdCustomer));
data.AssocIdSupplier = StringUtil.NullOnBlank(SysId.ToString(commodity.AssociationIdSupplier));
if (dataGroups != null && dataGroups.Contains(CommodityDataGroup.Sales))
{
// Sales.
data.SalesPrice = StringUtil.NullOnBlank(StringUtil.FormatNumeric(commodity.SalesPrice, SbmInternals.CurrencyDecimalsDefault));
}
if (dataGroups != null && dataGroups.Contains(CommodityDataGroup.Purchasing))
{
// Purchasing.
data.CostPrice = StringUtil.NullOnBlank(StringUtil.FormatNumeric(commodity.CostPrice, SbmInternals.CurrencyDecimalsDefault));
}
if (dataGroups != null && dataGroups.Contains(CommodityDataGroup.Specification))
{
// Specification.
}
if (dataGroups != null && dataGroups.Contains(CommodityDataGroup.Production))
{
// Production.
}
}
//-------------------------------------------------------------------
// Commodity list.
//-------------------------------------------------------------------
private class AjaxResponse_CommodityList : AjaxResponse_Data
{
// Construction.
public AjaxResponse_CommodityList(SbmModel_Portal model) : base(model) { }
// Commodity list.
public List<CommodityListData> Commodities { get; } = new List<CommodityListData>();
// Commodity configuration.
public class ConfigData
{
// Optional columns to show.
public class ShowColumnData
{
public bool? CatalogRef { get; set; }
public bool? Weight { get; set; }
public bool? PackQtySale { get; set; }
public bool? StockAllocated { get; set; }
public bool? StockLevelSales { get; set; }
public bool? StockAvailable { get; set; }
}
public ShowColumnData ShowColumn { get; } = new ShowColumnData();
// Optional fields to show.
public class ShowFieldData
{
public bool? DrawingIssue { get; set; }
public bool? DrawingNo { get; set; }
public bool? Department { get; set; }
public bool? CatalogRef { get; set; }
public bool? Volume { get; set; }
public bool? Density { get; set; }
public bool? BoxQuantity { get; set; }
public bool? ICNTariffCode { get; set; }
public bool? PlaceOfOrigin { get; set; }
public bool? MaterialCost { get; set; }
public bool? ExWorksCost { get; set; }
public bool? RetailPricePlanned { get; set; }
public bool? CarriageCostIndicative { get; set; }
}
public ShowFieldData ShowField { get; } = new ShowFieldData();
// Configurable field label.
public class FieldLabelData
{
public String CatalogRef { get; set; }
public String Dimensions { get; set; }
public String ICNTariffCode { get; set; }
public String CostPrice { get; set; }
public String PlaceOfOrigin { get; set; }
public String MaterialCost { get; set; }
public String CurrencyIdMaterial { get; set; }
public String ExWorksCost { get; set; }
public String CurrencyIdExWorks { get; set; }
public String SpecSummary { get; set; }
public String MaterialCode { get; set; }
public String FinishCode { get; set; }
public String DescDetail { get; set; }
public String RetailPricePlanned { get; set; }
}
public FieldLabelData FieldLabel { get; } = new FieldLabelData();
}
public ConfigData Config { get; } = new ConfigData();
// Reference data.
public List<CodeDesc> CommodityTypes { get; } = new List<CodeDesc>();
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public String DefaultStatusCode { get; set; }
}
// Ajax request.
[HttpPost]
[Route("Commodity/Ajax/List")]
[Route("Commodity/Ajax/GetList")]
public IActionResult Ajax_CommodityList(Model_Commodity model)
{
String fn = GetType().Name + ".Ajax_CommodityList";
AjaxResponse_CommodityList responseData = new AjaxResponse_CommodityList(model);
String messageTitle = Localiser["caption.commodities"];
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Configuration.
PopulateConfigShow(responseData.Config.ShowField);
// Reference data - commodity types.
foreach (TypeCodeDesc commodityType in GetCodesOfType(Sbm.SystemCode.CommodityType))
responseData.CommodityTypes.Add(commodityType.Code, commodityType.Desc);
// Reference data - statuses.
foreach (SaStatus status in SbmCommodity.ValidStatuses.FindAll(item => item != SaStatus.Deleted))
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SbmCommodity.DefaultStatus);
// Item filter.
SbmCommodity.Params prmCommodity = new SbmCommodity.Params();
prmCommodity.Search = model.Filter.Search;
prmCommodity.CommodityType = model.GetFilterCommodityType();
prmCommodity.StatusCat = SbmCommodity.StatusCat.NotDeleted;
prmCommodity.SortColumns.Add(CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.Code));
prmCommodity.SortColumns.Add(CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.DescBrief));
model.Paging.ItemTotal = (ulong)CommodityMgr.GetCommodityCount(prmCommodity);
model.PopulatePagingTo(prmCommodity.ResultsPaging);
// Item columns.
ColumnDfn colId = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.Id);
ColumnDfn colCommodityType = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.Type_Desc);
ColumnDfn colCode = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.Code);
ColumnDfn colDescBrief = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.DescBrief);
ColumnDfn colSalesPrice = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.SalesPrice);
ColumnDfn colSalesUomId = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.UomIdSale);
ColumnDfn colCostPrice = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.CostPrice);
ColumnDfn colNotes = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.Notes);
ColumnDfn colStatus = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.Status);
ColumnDfn colCreatedOn = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.CreateOn_Date);
ColumnDfn colUpdatedOn = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.UpdateOn_Date);
List<ColumnDfn> columns = new List<ColumnDfn>()
{
colId, colCommodityType, colCode, colDescBrief,
colSalesPrice, colSalesUomId,colCostPrice,
colNotes, colStatus, colCreatedOn, colUpdatedOn
};
// Query items.
using (DbResultSet resultSet = CommodityMgr.ExecuteCommodityQuery(columns, prmCommodity))
{
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
{
NamedValue.Map values = resultSet.GetRecordValues();
Sbm.CommodityType commodityType = (Sbm.CommodityType)values.GetLong(colCommodityType.DataName);
CommodityListData commodityData = new CommodityListData()
{
Id = values.GetString(colId.DataName),
TypeCode = Internals.CommodityTypeCodes.GetCodeForType(commodityType),
TypeDesc = Internals.CommodityTypeCodes.GetDescForType(commodityType),
Code = values.GetString(colCode.DataName),
Desc = values.GetString(colDescBrief.DataName),
SalesPriceFmt = StringUtil.NullOnBlank(StringUtil.FormatNumeric(values.GetValue(colSalesPrice.DataName).ToDecimal(), SbmInternals.CurrencyDecimalsDefault, 0, ',')),
SalesUnit = Internals.GetUnitOfMeasureCaption(new SysId(values.GetLong(colSalesUomId.DataName))),
CostPriceFmt = StringUtil.NullOnBlank(StringUtil.FormatNumeric(values.GetValue(colCostPrice.DataName).ToDecimal(), SbmInternals.CurrencyDecimalsDefault, 0, ',')),
Notes = StringUtil.NullOnBlank(values.GetString(colNotes.DataName)),
StatusCode = values.GetString(colStatus.DataName),
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName)),
CreatedOn = DateUtil.Format(values.GetDate(colCreatedOn.DataName), "yyyyMMdd"),
CreatedOnFmt = Localiser.FormatDate(values.GetDate(colCreatedOn.DataName)),
UpdatedOn = DateUtil.Format(values.GetDate(colUpdatedOn.DataName), "yyyyMMdd"),
UpdatedOnFmt = Localiser.FormatDate(values.GetDate(colUpdatedOn.DataName))
};
responseData.Commodities.Add(commodityData);
}
}
// Refresh paging info.
if (model.Paging.IsPaged)
model.Paging.ItemCount = (ushort)responseData.Commodities.Count;
SessionData_Portal.Profile.Commodities.Filter.PageNo = model.Paging.PageNo;
SessionData_Portal.Profile.Commodities.Filter.PageLength = model.Paging.PageLength;
responseData.SetPaging(model);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
// Populate configuration.
private void PopulateConfigShow(AjaxResponse_CommodityList.ConfigData.ShowFieldData show)
{
// Ref. Sbm.OrgOption_ShowField.
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_DrawingIssue)) show.DrawingIssue = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_DrawingNo)) show.DrawingNo = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_Department)) show.Department = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_CatalogRef)) show.CatalogRef = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_Volume)) show.Volume = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_Density)) show.Density = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_BoxQuantity)) show.BoxQuantity = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_ICNTariffCode)) show.ICNTariffCode = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_PlaceOfOrigin)) show.PlaceOfOrigin = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_MaterialCost)) show.MaterialCost = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_ExWorksCost)) show.ExWorksCost = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_RetailPricePlanned)) show.RetailPricePlanned = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_CarriageCostIndicative)) show.CarriageCostIndicative = true;
}
//-------------------------------------------------------------------
// Get Commodity ajax request.
//-------------------------------------------------------------------
private class AjaxResponse_Commodity : AjaxResponse_Data
{
// Construction.
public AjaxResponse_Commodity(SbmModel_Portal model) : base(model) { }
// Commodity details.
public CommodityItemData commodity { get; } = new CommodityItemData();
}
//-------------------------------------------------------------------
[HttpPost]
[Route("Commodity/Ajax/Item")]
[Route("Commodity/Ajax/GetItem")]
public IActionResult Ajax_GetItem(Model_Commodity model)
{
String fn = GetType().Name + ".Ajax_GetItem";
String messageTitle = Localiser["caption.commodity"];
AjaxResponse_Commodity responseData = new AjaxResponse_Commodity(model);
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Identify item.
SysId commodityId = model.Commodity.Id.ToSysId();
if (!SysId.IsValid(commodityId))
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
// Retrieve item.
SbmCommodity commodity = CommodityMgr.GetCommodityById(commodityId);
if (commodity == null)
{
SaLogger.Warn(fn + " Failed to retrieve commodity for Id: '" + model.Commodity.Id + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
}
// Construct response.
PopulateCommodityResponseItemData(commodity, responseData.commodity);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
// Store Commodity ajax request.
//-------------------------------------------------------------------
[HttpPost]
[Route("Commodity/Ajax/Store")]
[Route("Commodity/Ajax/StoreItem")]
public IActionResult Ajax_StoreItem(Model_Commodity model)
{
String fn = GetType().Name + ".Ajax_StoreItem";
String messageTitle = Localiser["caption.commodity"];
AjaxResponse_Commodity responseData = new AjaxResponse_Commodity(model);
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Validate item properties.
model.ValidateCommodityData(responseData);
if (responseData.HasControlErrors())
return Json(responseData);
// Validate item Id against 'Exists' flag.
SysId commodityId = model.Commodity.Id.ToSysId();
bool commodityExists = StringUtil.ToBool(model.Commodity.Exists);
if (commodityExists && !SysId.IsValid(commodityId))
{
SaLogger.Warn(fn + " Id not specified for existing Commodity.");
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
if (!commodityExists && SysId.IsValid(commodityId))
{
SaLogger.Warn(fn + " Id specified for new Commodity: '" + model.Commodity.Id + "'");
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
// Retrieve existing item.
SbmCommodity commodity = CommodityMgr.GetCommodityById(commodityId);
if (commodity == null && SysId.IsValid(commodityId))
{
SaLogger.Warn(fn + " Failed to retrieve commodity for Id: '" + model.Commodity.Id + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
}
// Create new item if required.
if (commodity == null)
{
commodity = CommodityMgr.CreateCommodity(model.GetCommodityType(), model.Commodity.Code);
if (model.Commodity.Code != null)
commodity.Code = model.Commodity.Code;
}
// Populate item properties.
if (model.Commodity.Type != null)
commodity.CommodityType = model.GetCommodityType();
if (model.Commodity.Code != null)
commodity.Code = model.Commodity.Code;
if (model.Commodity.DescBrief != null)
commodity.DescBrief = model.Commodity.DescBrief;
// Common properties.
if (model.Commodity.Notes != null)
commodity.Notes = model.Commodity.Notes;
if (model.Commodity.StatusCode != null)
commodity.Status = model.GetCommodityStatus();
// Store item.
if (!SysId.IsValid(commodity.Id))
{
if (!CommodityMgr.InsertCommodity(commodity, DbUpdateInfo))
{
SaLogger.Warn(fn + " Failed to insert commodity: " + CommodityMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.created"]);
}
else
{
if (!CommodityMgr.UpdateCommodity(commodity, DbUpdateInfo))
{
SaLogger.Warn(fn + " Failed to update commodity [Id:" + SysId.ToString(commodity.Id) + "]: " + CommodityMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]);
}
UpdateAssociatedData(commodity);
// Construct response.
PopulateCommodityResponseItemData(commodity, responseData.commodity);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
/// <summary>
/// Bring associated data into line with the commodity.
/// </summary>
/// <param name="commodity"></param>
/// <returns></returns>
private bool UpdateAssociatedData(SbmCommodity commodity)
{
if (!UpdateRequirements(commodity))
{
return false;
}
// Cost Estimates and Processes likely not required here as will have their own update page/form/action.
if (!CommodityMgr.CommitCommodityCostEstimates(commodity))
{
SaLogger.Warn($"{SysUtil.Fn} Failed to commit cost estimates - {CommodityMgr.ErrorStateMessage}. Code: {commodity.Code}.");
return false;
}
if (!CommodityMgr.CommitCommodityProcesses(commodity))
{
SaLogger.Warn($"{SysUtil.Fn} Failed to commit processes - {CommodityMgr.ErrorStateMessage}. Code: {commodity.Code}.");
return false;
}
// Machine list - nothing to do.
// Associated Products.
if (associatedProducts != null && associatedProducts.ItemLinks != null)
{
DataItemMgr.UpdateLinkedItems(associatedProducts.ItemMode, associatedProducts.ItemLinkType, ref associatedProducts.ItemIdParent, ref associatedProducts.ItemIdChild, commodity.GetItemId(), associatedProducts.ItemLinks);
}
// Sales Budget.
if (!CommodityMgr.UpdateReferencesToSalesTemplate(commodity))
{
SaLogger.Warn($"{SysUtil.Fn} Failed to update sales template references - {CommodityMgr.ErrorStateMessage}. Code: {commodity.Code}.");
return false;
}
return true;
}
//-------------------------------------------------------------------
// Associated products.
// Oct24 Not yet implemented - may be in separate page/controller.
private class AssociatedProductsData
{
public Sbm.AssociatedItemMode ItemMode = AssociatedItemMode.Unknown;
public Sbm.ItemLinkType ItemLinkType = ItemLinkType.Unknown;
public ItemId ItemIdParent;
public ItemId ItemIdChild;
public List<SbmItemLink> ItemLinks { get; set; }
}
private AssociatedProductsData associatedProducts { get; set; }
//-------------------------------------------------------------------
private bool UpdateRequirements(SbmCommodity commodity)
{
if (!CommodityMgr.UpdateCommodityRequirements(commodity))
{
SaLogger.Warn($"{SysUtil.Fn} Failed to update commodity requirements - {CommodityMgr.ErrorStateMessage}. Code: {commodity.Code}.");
return false;
}
return true;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -16,7 +16,7 @@ using System.Linq;
using System.Threading.Tasks;
using Sarand.BusinessMgr.Web.Portal.Models.Commodities;
namespace Sarand.BusinessMgr.Web.Portal.Controllers
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
{
//=======================================================================
public partial class CommodityController : SbmController_Portal
@@ -33,7 +33,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
//-------------------------------------------------------------------
[HttpGet]
public IActionResult Index()
public IActionResult Index(Model_Commodity model)
{
if (!ValidUserSession)
AutoLoginUser();
@@ -46,7 +46,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
}
// Commodity page.
Model_Commodity model = new Model_Commodity(Localiser);
RefreshModel(model);
model.Paging.PageNo = SessionData_Portal.Profile.Commodities.Filter.PageNo;
model.Paging.PageLength = SessionData_Portal.Profile.Commodities.Filter.PageLength;
return View(model);
@@ -1,306 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
using Sarand.BusinessMgr.Web.Portal.Models;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
using Sarand.BusinessMgr.Net.Standard.Base.Helpers;
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Email;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Security;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Sarand.BusinessMgr.Web.Portal.Models.Commodities;
namespace Sarand.BusinessMgr.Web.Portal.Controllers
{
//=======================================================================
// Portal Commodity Controller - Ajax actions.
//=======================================================================
partial class CommodityController
{
//-------------------------------------------------------------------
// Commodity data.
private class CommodityData_List : AjaxResponse_Data.ItemData_Base
{
public String TypeCode { get; set; }
public String TypeDesc { get; set; }
public String Code { get; set; } = "";
public String Desc { get; set; } = "";
// Address.
public String AddressSummary { get; set; }
}
private class CommodityData_Full : CommodityData_List
{
// Commodity properties.
}
private void PopulateCommodityResponseData(SbmCommodity commodity, CommodityData_List data)
{
data.Id = SysId.ToString(commodity.Id);
data.TypeCode = Internals.CommodityTypeCodes.GetCodeForType(commodity.CommodityType);
data.TypeDesc = Internals.CommodityTypeCodes.GetDescForType(commodity.CommodityType);
data.Code = commodity.Code;
data.Desc = commodity.DescBrief;
// Common properties.
data.Notes = commodity.Notes;
data.StatusCode = commodity.StatusCode;
data.StatusDesc = commodity.StatusDesc;
}
private void PopulateCommodityResponseData(SbmCommodity commodity, CommodityData_Full data)
{
PopulateCommodityResponseData(commodity, data as CommodityData_List);
// Commodity properties.
}
//-------------------------------------------------------------------
// Commodity list.
//-------------------------------------------------------------------
private class AjaxResponse_CommodityList : AjaxResponse_Data
{
// Construction.
public AjaxResponse_CommodityList(SbmModel_Portal model) : base(model) { }
// Commodity list.
public List<CommodityData_List> Commodities { get; } = new List<CommodityData_List>();
// Reference data.
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public String DefaultStatusCode { get; set; }
}
// Ajax request.
[HttpPost]
[Route("Commodity/Ajax/List")]
[Route("Commodity/Ajax/GetList")]
public IActionResult Ajax_CommodityList(Model_Commodity model)
{
String fn = GetType().Name + ".Ajax_CommodityList";
AjaxResponse_CommodityList responseData = new AjaxResponse_CommodityList(model);
String messageTitle = Localiser["commodity.caption.commodities"];
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Reference data - statuses.
foreach (SaStatus status in SbmCommodity.ValidStatuses.FindAll(item => item != SaStatus.Deleted))
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SbmCommodity.DefaultStatus);
// Item filter.
SbmCommodity.Params prmCommodity = new SbmCommodity.Params();
prmCommodity.Search = model.Filter.CommoditySearch;
prmCommodity.CommodityType = model.GetFilterCommodityType();
prmCommodity.StatusCat = SbmCommodity.StatusCat.NotDeleted;
prmCommodity.SortColumns.Add(CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.Code));
prmCommodity.SortColumns.Add(CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.DescBrief));
model.Paging.ItemTotal = (ulong)CommodityMgr.GetCommodityCount(prmCommodity);
model.PopulatePagingTo(prmCommodity.ResultsPaging);
// Item columns.
ColumnDfn colId = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.Id);
ColumnDfn colCommodityType = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.Type_Desc);
ColumnDfn colCode = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.Code);
ColumnDfn colDescBrief = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.DescBrief);
ColumnDfn colNotes = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.Notes);
ColumnDfn colStatus = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.Status);
ColumnDfn colCreatedOn = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.CreateOn_Date);
ColumnDfn colUpdatedOn = CommodityMgr.GetCommodityColumnDfn(SbmCommodity.Column.UpdateOn_Date);
List<ColumnDfn> columns = new List<ColumnDfn>()
{
colId, colCommodityType, colCode, colDescBrief,
colNotes, colStatus, colCreatedOn, colUpdatedOn
};
// Query items.
using (DbResultSet resultSet = CommodityMgr.ExecuteCommodityQuery(columns, prmCommodity))
{
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
{
NamedValue.Map values = resultSet.GetRecordValues();
Sbm.CommodityType commodityType = (Sbm.CommodityType)values.GetLong(colCommodityType.DataName);
CommodityData_List commodityData = new CommodityData_List()
{
Id = values.GetString(colId.DataName),
TypeCode = Internals.CommodityTypeCodes.GetCodeForType(commodityType),
TypeDesc = Internals.CommodityTypeCodes.GetDescForType(commodityType),
Code = values.GetString(colCode.DataName),
Desc = values.GetString(colDescBrief.DataName),
Notes = values.GetString(colNotes.DataName),
StatusCode = values.GetString(colStatus.DataName),
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName)),
CreatedOn = DateUtil.Format(values.GetDate(colCreatedOn.DataName), "yyyyMMdd"),
CreatedOnFmt = Localiser.FormatDate(values.GetDate(colCreatedOn.DataName)),
UpdatedOn = DateUtil.Format(values.GetDate(colUpdatedOn.DataName), "yyyyMMdd"),
UpdatedOnFmt = Localiser.FormatDate(values.GetDate(colUpdatedOn.DataName))
};
responseData.Commodities.Add(commodityData);
}
}
// Refresh paging info.
if (model.Paging.IsPaged)
model.Paging.ItemCount = (ushort)responseData.Commodities.Count;
SessionData_Portal.Profile.Commodities.Filter.PageNo = model.Paging.PageNo;
SessionData_Portal.Profile.Commodities.Filter.PageLength = model.Paging.PageLength;
responseData.SetPaging(model);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
// Get Commodity ajax request.
//-------------------------------------------------------------------
private class AjaxResponse_Commodity : AjaxResponse_Data
{
// Construction.
public AjaxResponse_Commodity(SbmModel_Portal model) : base(model) { }
// Commodity details.
public CommodityData_Full commodity { get; } = new CommodityData_Full();
}
//-------------------------------------------------------------------
[HttpPost]
[Route("Commodity/Ajax/Item")]
[Route("Commodity/Ajax/GetItem")]
public IActionResult Ajax_GetItem(Model_Commodity model)
{
String fn = GetType().Name + ".Ajax_GetItem";
String messageTitle = Localiser["commodity.caption.commodity"];
AjaxResponse_Commodity responseData = new AjaxResponse_Commodity(model);
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Identify item.
SysId commodityId = model.CommodityId.ToSysId();
if (!SysId.IsValid(commodityId))
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
// Retrieve item.
SbmCommodity commodity = CommodityMgr.GetCommodityById(commodityId);
if (commodity == null)
{
SaLogger.Warn(fn + " Failed to retrieve commodity for Id: '" + model.CommodityId + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
}
// Construct response.
PopulateCommodityResponseData(commodity, responseData.commodity);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
// Store Commodity ajax request.
//-------------------------------------------------------------------
[HttpPost]
[Route("Commodity/Ajax/Store")]
[Route("Commodity/Ajax/StoreItem")]
public IActionResult Ajax_StoreItem(Model_Commodity model)
{
String fn = GetType().Name + ".Ajax_StoreItem";
String messageTitle = Localiser["commodity.caption.commodity"];
AjaxResponse_Commodity responseData = new AjaxResponse_Commodity(model);
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Validate item properties.
model.ValidateCommodityData(responseData);
if (responseData.HasControlErrors())
return Json(responseData);
// Validate item Id against 'Exists' flag.
SysId commodityId = model.CommodityId.ToSysId();
bool commodityExists = StringUtil.ToBool(model.CommodityExists);
if (commodityExists && !SysId.IsValid(commodityId))
{
SaLogger.Warn(fn + " Id not specified for existing Commodity.");
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
if (!commodityExists && SysId.IsValid(commodityId))
{
SaLogger.Warn(fn + " Id specified for new Commodity: '" + model.CommodityId + "'");
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
// Retrieve existing item.
SbmCommodity commodity = CommodityMgr.GetCommodityById(commodityId);
if (commodity == null && SysId.IsValid(commodityId))
{
SaLogger.Warn(fn + " Failed to retrieve commodity for Id: '" + model.CommodityId + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
}
// Create new item if required.
if (commodity == null)
{
commodity = CommodityMgr.CreateCommodity(model.GetCommodityType(), model.CommodityCode);
if (model.CommodityCode != null)
commodity.Code = model.CommodityCode;
}
// Populate item properties.
if (model.CommodityType != null)
commodity.CommodityType = model.GetCommodityType();
if (model.CommodityCode != null)
commodity.Code = model.CommodityCode;
if (model.CommodityDesc != null)
commodity.DescBrief = model.CommodityDesc;
// Common properties.
if (model.CommodityNotes != null)
commodity.Notes = model.CommodityNotes;
if (model.CommodityStatusCode != null)
commodity.Status = model.CommodityStatus;
// Store item.
if (!SysId.IsValid(commodity.Id))
{
if (!CommodityMgr.InsertCommodity(commodity, DbUpdateInfo))
{
SaLogger.Warn(fn + " Failed to insert commodity: " + CommodityMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.created"]);
}
else
{
if (!CommodityMgr.UpdateCommodity(commodity, DbUpdateInfo))
{
SaLogger.Warn(fn + " Failed to update commodity [Id:" + SysId.ToString(commodity.Id) + "]: " + CommodityMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]);
}
// Construct response.
PopulateCommodityResponseData(commodity, responseData.commodity);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -1,377 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
using Sarand.BusinessMgr.Web.Portal.Models;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
using Sarand.BusinessMgr.Net.Standard.Base.Helpers;
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Email;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Security;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
namespace Sarand.BusinessMgr.Web.Portal.Controllers
{
//=======================================================================
// Portal Contact Controller - Ajax actions.
//=======================================================================
partial class ContactController
{
//-------------------------------------------------------------------
// Affiliate data.
private class AffiliateData_List : AjaxResponse_Data.ItemData_Base
{
public String DisplayName { get; set; }
public String TypeCode { get; set; }
public String TypeDesc { get; set; }
public bool? Individual { get; set; }
// Address.
public String AddressSummary { get; set; }
}
private class AffiliateData_Full : AffiliateData_List
{
// Affiliate properties.
public String PhoneMain { get; set; } = "";
public String PhoneAlt { get; set; } = "";
public String PhoneFax { get; set; } = "";
public String Email { get; set; } = "";
public String Website { get; set; } = "";
// Ogranisation.
public SysId AffiliateIdParent { get; set; } = new SysId();
public String Name { get; set; } = "";
public String Abbr { get; set; } = "";
public String Nature { get; set; } = "";
public String Contact { get; set; } = "";
public String CompanyNo { get; set; } = "";
public String VatReg { get; set; } = "";
public String PhoneDirect { get; set; } = "";
// Individual.
public String Title { get; set; } = "";
public String Initials { get; set; } = "";
public String LastName { get; set; } = "";
public String FirstName { get; set; } = "";
public String Salutation { get; set; } = "";
public String PhoneMobile { get; set; } = "";
public byte BirthDay { get; set; } = 0;
public byte BirthMonth { get; set; } = 0;
public short BirthYear { get; set; } = 0;
public String MaritalStatus { get; set; } = "";
public String Spouse { get; set; } = "";
public String Children { get; set; } = "";
public String Hometown { get; set; } = "";
public SysId UserId { get; set; } = new SysId();
}
private void PopulateAffiliateResponseData(SbmAffiliate affiliate, AffiliateData_List data)
{
data.Id = SysId.ToString(affiliate.Id);
data.DisplayName = affiliate.GetDisplayName();
data.TypeCode = Internals.AffiliateTypeCodes.GetCodeForType(affiliate.AffiliateType);
data.TypeDesc = Internals.AffiliateTypeCodes.GetDescForType(affiliate.AffiliateType);
data.Individual = affiliate.AffiliateType == Sbm.AffiliateType.Individual ? true : (bool?)null;
// Common properties.
data.Notes = affiliate.Notes;
data.StatusCode = affiliate.StatusCode;
data.StatusDesc = affiliate.StatusDesc;
}
private void PopulateAffiliateResponseData(SbmAffiliate affiliate, AffiliateData_Full data)
{
PopulateAffiliateResponseData(affiliate, data as AffiliateData_List);
// Affiliate properties.
data.PhoneMain = affiliate.PhoneMain;
data.PhoneAlt = affiliate.PhoneAlt;
data.PhoneFax = affiliate.PhoneFax;
data.Email = affiliate.Email;
data.Website = affiliate.Website;
// Ogranisation.
data.AffiliateIdParent = affiliate.AffiliateIdParent;
data.Name = affiliate.Name;
data.Abbr = affiliate.Abbr;
data.Nature = affiliate.Nature;
data.Contact = affiliate.Contact;
data.CompanyNo = affiliate.CompanyNo;
data.VatReg = affiliate.VatReg;
data.PhoneDirect = affiliate.PhoneDirect;
// Individual.
data.Title = affiliate.Title;
data.Initials = affiliate.Initials;
data.LastName = affiliate.LastName;
data.FirstName = affiliate.FirstName;
data.Salutation = affiliate.Salutation;
data.PhoneMobile = affiliate.PhoneMobile;
data.BirthDay = affiliate.BirthDay;
data.BirthMonth = affiliate.BirthMonth;
data.BirthYear = affiliate.BirthYear;
data.MaritalStatus = affiliate.MaritalStatus;
data.Spouse = affiliate.Spouse;
data.Children = affiliate.Children;
data.Hometown = affiliate.Hometown;
data.UserId = affiliate.UserId;
}
//-------------------------------------------------------------------
// Contact list.
//-------------------------------------------------------------------
private class AjaxResponse_ContactList : AjaxResponse_Data
{
// Construction.
public AjaxResponse_ContactList(SbmModel_Portal model) : base(model) { }
// Affiliate list.
public List<AffiliateData_List> Affiliates { get; } = new List<AffiliateData_List>();
// Reference data.
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public String DefaultStatusCode { get; set; }
}
// Ajax request.
[HttpPost]
[Route("Contact/Ajax/List")]
[Route("Contact/Ajax/GetList")]
public IActionResult Ajax_ContactList(Model_Contact model)
{
String fn = GetType().Name + ".Ajax_ContactList";
AjaxResponse_ContactList responseData = new AjaxResponse_ContactList(model);
String messageTitle = Localiser["contact.caption.contacts"];
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Reference data - statuses.
foreach (SaStatus status in SbmAffiliate.ValidStatuses.FindAll(item => item != SaStatus.Deleted))
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SbmAffiliate.DefaultStatus);
// Item filter.
SbmAffiliate.Params prmAffiliate = new SbmAffiliate.Params();
prmAffiliate.Search = model.Filter.ContactSearch;
prmAffiliate.AffiliateType = model.GetFilterContactType();
prmAffiliate.StatusCat = SbmAffiliate.StatusCat.NotDeleted;
prmAffiliate.SortColumns.Add(AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Name));
prmAffiliate.SortColumns.Add(AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.LastName));
model.Paging.ItemTotal = (ulong)AccountMgr.GetAffiliateCount(prmAffiliate);
model.PopulatePagingTo(prmAffiliate.ResultsPaging);
// Item columns.
ColumnDfn colId = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Id);
ColumnDfn colName = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Name);
ColumnDfn colAffiliateType = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Type);
ColumnDfn colPhoneMain = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.PhoneMain);
ColumnDfn colPhoneAlt = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.PhoneAlt);
ColumnDfn colAddress = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Address_Summary);
ColumnDfn colNotes = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Notes);
ColumnDfn colStatus = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Status);
ColumnDfn colCreatedOn = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.CreateOn_Date);
ColumnDfn colUpdatedOn = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.UpdateOn_Date);
List<ColumnDfn> columns = new List<ColumnDfn>()
{
colId, colName, colAffiliateType,
colPhoneMain, colPhoneAlt,
colAddress,
colNotes, colStatus, colCreatedOn, colUpdatedOn
};
// Query items.
using (DbResultSet resultSet = AccountMgr.ExecuteAffiliateQuery(columns, prmAffiliate))
{
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
{
NamedValue.Map values = resultSet.GetRecordValues();
Sbm.AffiliateType affiliateType = (Sbm.AffiliateType)values.GetLong(colAffiliateType.DataName);
AffiliateData_List affiliateData = new AffiliateData_List()
{
Id = values.GetString(colId.DataName),
DisplayName = values.GetString(colName.DataName),
TypeCode = Internals.AffiliateTypeCodes.GetCodeForType(affiliateType),
TypeDesc = Internals.AffiliateTypeCodes.GetDescForType(affiliateType),
Individual = affiliateType == Sbm.AffiliateType.Individual ? true : (bool?)null,
AddressSummary = AccountMgr.GetAffiliateDataValue(colAddress, values).AsString(),
Notes = values.GetString(colNotes.DataName),
StatusCode = values.GetString(colStatus.DataName),
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName)),
CreatedOn = DateUtil.Format(values.GetDate(colCreatedOn.DataName), "yyyyMMdd"),
CreatedOnFmt = Localiser.FormatDate(values.GetDate(colCreatedOn.DataName)),
UpdatedOn = DateUtil.Format(values.GetDate(colUpdatedOn.DataName), "yyyyMMdd"),
UpdatedOnFmt = Localiser.FormatDate(values.GetDate(colUpdatedOn.DataName))
};
responseData.Affiliates.Add(affiliateData);
}
}
// Refresh paging info.
if (model.Paging.IsPaged)
model.Paging.ItemCount = (ushort)responseData.Affiliates.Count;
SessionData_Portal.Profile.Contacts.Filter.PageNo = model.Paging.PageNo;
SessionData_Portal.Profile.Contacts.Filter.PageLength = model.Paging.PageLength;
responseData.SetPaging(model);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
// Get Affiliate ajax request.
//-------------------------------------------------------------------
private class AjaxResponse_Affiliate : AjaxResponse_Data
{
// Construction.
public AjaxResponse_Affiliate(SbmModel_Portal model) : base(model) { }
// Affiliate details.
public AffiliateData_Full affiliate { get; } = new AffiliateData_Full();
}
//-------------------------------------------------------------------
[HttpPost]
[Route("Contact/Ajax/Item")]
[Route("Contact/Ajax/GetItem")]
public IActionResult Ajax_GetItem(Model_Contact model)
{
String fn = GetType().Name + ".Ajax_GetItem";
String messageTitle = Localiser["contact.caption.contact"];
AjaxResponse_Affiliate responseData = new AjaxResponse_Affiliate(model);
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Identify item.
SysId affiliateId = model.AffiliateId.ToSysId();
if (!SysId.IsValid(affiliateId))
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
// Retrieve item.
SbmAffiliate affiliate = AccountMgr.GetAffiliateById(affiliateId);
if (affiliate == null)
{
SaLogger.Warn(fn + " Failed to retrieve affiliate for Id: '" + model.AffiliateId + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
}
// Construct response.
PopulateAffiliateResponseData(affiliate, responseData.affiliate);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
// Store Affiliate ajax request.
//-------------------------------------------------------------------
[HttpPost]
[Route("Contact/Ajax/Store")]
[Route("Contact/Ajax/StoreItem")]
public IActionResult Ajax_StoreItem(Model_Contact model)
{
String fn = GetType().Name + ".Ajax_StoreItem";
String messageTitle = Localiser["contact.caption.contact"];
AjaxResponse_Affiliate responseData = new AjaxResponse_Affiliate(model);
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Validate item properties.
model.ValidateAffiliateData(responseData);
if (responseData.HasControlErrors())
return Json(responseData);
// Validate item Id against 'Exists' flag.
SysId affiliateId = model.AffiliateId.ToSysId();
bool contactExists = StringUtil.ToBool(model.ContactExists);
if (contactExists && !SysId.IsValid(affiliateId))
{
SaLogger.Warn(fn + " Id not specified for existing Affiliate.");
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
if (!contactExists && SysId.IsValid(affiliateId))
{
SaLogger.Warn(fn + " Id specified for new Affiliate: '" + model.AffiliateId + "'");
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
// Retrieve existing item.
SbmAffiliate affiliate = AccountMgr.GetAffiliateById(affiliateId);
if (affiliate == null && SysId.IsValid(affiliateId))
{
SaLogger.Warn(fn + " Failed to retrieve affiliate for Id: '" + model.AffiliateId + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
}
// Create new item if required.
if (affiliate == null)
{
affiliate = AccountMgr.CreateAffiliate(model.GetContactType());
}
else
{
if (model.ContactType != null)
affiliate.AffiliateType = model.GetContactType();
}
// Populate item properties.
if (affiliate.IsIndividual())
{
if (model.ContactFirstName != null)
affiliate.FirstName = model.ContactFirstName;
if (model.ContactLastName != null)
affiliate.LastName = model.ContactLastName;
}
else
{
if (model.ContactName != null)
affiliate.Name = model.ContactName;
}
// Common properties.
if (model.ContactNotes != null)
affiliate.Notes = model.ContactNotes;
if (model.ContactStatusCode != null)
affiliate.Status = model.ContactStatus;
// Store item.
if (!SysId.IsValid(affiliate.Id))
{
if (!AccountMgr.InsertAffiliate(affiliate, DbUpdateInfo))
{
SaLogger.Warn(fn + " Failed to insert affiliate: " + AccountMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.created"]);
}
else
{
if (!AccountMgr.UpdateAffiliate(affiliate, DbUpdateInfo))
{
SaLogger.Warn(fn + " Failed to update affiliate [Id:" + SysId.ToString(affiliate.Id) + "]: " + AccountMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]);
}
// Construct response.
PopulateAffiliateResponseData(affiliate, responseData.affiliate);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,431 @@
using Microsoft.AspNetCore.Mvc;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.BusinessMgr.Web.Portal.Models;
using Sarand.BusinessMgr.Web.Portal.Models.Contacts;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Security;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
{
//=======================================================================
// Portal Association Controller - Ajax actions.
//=======================================================================
partial class AssociationController
{
//-------------------------------------------------------------------
// Association data.
private class AssociationListData : AjaxResponse_Data.ItemData_Base
{
public String TargetName { get; set; }
public String TypeDesc { get; set; }
public String Code { get; set; }
// Address.
public String AddressSummary { get; set; }
}
private class AssociationItemData : AssociationListData
{
// Association properties.
public String OwnerId { get; set; }
public String OwnerName { get; set; }
public String TargetId { get; set; }
public String TypeCode { get; set; }
public String ReferenceExt { get; set; }
public String Group { get; set; }
public String DescDetail { get; set; }
public String Location { get; set; }
public String Role { get; set; }
public String PhoneMain { get; set; }
public String Email { get; set; }
public String NominalCodeDefault { get; set; }
}
private void PopulateAssociationResponseListData(SbmAssociation association, SbmAffiliate affiliateTarget, AssociationListData data)
{
data.Id = SysId.ToString(association.Id);
data.TargetName = affiliateTarget.GetDisplayName();
data.TypeDesc = Internals.AssociationTypeCodes.GetDescForType(association.AssociationType);
data.Code = association.Code;
// Common properties.
data.Notes = association.Notes;
data.StatusCode = association.StatusCode;
data.StatusDesc = association.StatusDesc;
}
private void PopulateAssociationResponseItemData(SbmAssociation association, SbmAffiliate affiliateTarget, AssociationItemData data)
{
// List data.
PopulateAssociationResponseListData(association, affiliateTarget, data as AssociationListData);
// Association properties.
data.TargetId = SysId.ToString(association.AffiliateIdTarget);
data.TypeCode = Internals.AssociationTypeCodes.GetCodeForType(association.AssociationType);
data.ReferenceExt = association.RefExt;
data.Group = association.Group;
data.DescDetail = association.DescDetail;
data.Location = association.Location;
data.Role = association.Role;
data.PhoneMain = association.PhoneMain;
data.Email = association.Email;
data.NominalCodeDefault = association.DefaultNominalCode;
// Address.
//data.AddressSummary = AccountMgr.GetAddressSummaryFor(new ItemId((short)Sbm.ItemType.Affiliate, association.AffiliateIdTarget));
}
//-------------------------------------------------------------------
// Association list.
//-------------------------------------------------------------------
private class AjaxResponse_AssociationList : AjaxResponse_Data
{
// Construction.
public AjaxResponse_AssociationList(SbmModel_Portal model) : base(model) { }
// Configuration.
public Model_Association.ListConfigData Config { get; } = new Model_Association.ListConfigData();
// Association list.
public List<AssociationListData> Associations { get; } = new List<AssociationListData>();
// Reference data.
public List<CodeDesc> AssociationTypes { get; } = new List<CodeDesc>();
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public String DefaultStatusCode { get; set; }
}
// Ajax request.
[HttpPost]
[Route("Association/Ajax/List")]
[Route("Association/Ajax/GetList")]
public IActionResult Ajax_AssociationList(Model_Association model)
{
AjaxResponse_AssociationList responseData = new AjaxResponse_AssociationList(model);
String messageTitle = Localiser["label.associations"];
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Configuration.
model.PopulateListConfig(responseData.Config);
// Reference data - types.
List<TypeCodeDesc> associationTypes = Internals.AssociationTypeCodes;
foreach (Sbm.AssociationType associationType in EnumUtil.GetValues<Sbm.AssociationType>())
{
if (associationType <= 0 || associationType == Sbm.AssociationType.Internal) continue;
if (!SessionConsole.AllowAssociationType(associationType)) continue;
responseData.AssociationTypes.Add(associationTypes.GetCodeForType(associationType), Localiser.GetAssociationTypeCaption(associationType));
}
// Reference data - statuses.
foreach (SaStatus status in SbmAssociation.ValidStatuses.FindAll(item => item != SaStatus.Deleted))
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SbmAssociation.DefaultStatus);
// Item filter.
SbmAssociation.Params prmAssociation = new SbmAssociation.Params();
prmAssociation.AffiliateIdOwner = SessionData_Portal.Organisation.AffiliateId;
prmAssociation.Search = model.Filter.Search;
prmAssociation.AssociationType = model.GetFilterAssociationType();
if (prmAssociation.AssociationType <= 0)
prmAssociation.AssociationType = Sbm.AssociationType.NotInternal;
prmAssociation.StatusCat = SbmAssociation.StatusCat.NotDeleted;
prmAssociation.SortColumns.Add(AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Target_Name));
model.Paging.ItemTotal = (ulong)AccountMgr.GetAssociationCount(prmAssociation);
model.PopulatePagingTo(prmAssociation.ResultsPaging);
// Item columns.
ColumnDfn colId = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Id);
ColumnDfn colTargetName = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Target_Name);
ColumnDfn colAssociationType = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Type_Desc);
ColumnDfn colCode = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Code);
ColumnDfn colAddress = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Target_Address_Summary);
ColumnDfn colNotes = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Notes);
ColumnDfn colStatus = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Status);
ColumnDfn colCreatedOn = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.CreateOn_Date);
ColumnDfn colUpdatedOn = AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.UpdateOn_Date);
List<ColumnDfn> columns = new List<ColumnDfn>()
{
colId, colTargetName, colAssociationType, colCode, colAddress,
colNotes, colStatus, colCreatedOn, colUpdatedOn
};
// Query items.
using (DbResultSet resultSet = AccountMgr.ExecuteAssociationQuery(columns, prmAssociation))
{
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
{
NamedValue.Map values = resultSet.GetRecordValues();
Sbm.AssociationType associationType = (Sbm.AssociationType)values.GetLong(colAssociationType.DataName);
AssociationListData associationData = new AssociationListData()
{
Id = values.GetString(colId.DataName),
TargetName = values.GetString(colTargetName.DataName),
TypeDesc = Internals.AssociationTypeCodes.GetDescForType(associationType),
Code = values.GetString(colCode.DataName),
AddressSummary = AccountMgr.GetAssociationDataValue(colAddress, values).ToString(),
Notes = values.GetString(colNotes.DataName),
StatusCode = values.GetString(colStatus.DataName),
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName)),
CreatedOn = DateUtil.Format(values.GetDate(colCreatedOn.DataName), "yyyyMMdd"),
CreatedOnFmt = Localiser.FormatDate(values.GetDate(colCreatedOn.DataName)),
UpdatedOn = DateUtil.Format(values.GetDate(colUpdatedOn.DataName), "yyyyMMdd"),
UpdatedOnFmt = Localiser.FormatDate(values.GetDate(colUpdatedOn.DataName))
};
responseData.Associations.Add(associationData);
}
}
// Refresh paging info.
if (model.Paging.IsPaged)
model.Paging.ItemCount = (ushort)responseData.Associations.Count;
SessionData_Portal.Profile.Associations.Filter.PageNo = model.Paging.PageNo;
SessionData_Portal.Profile.Associations.Filter.PageLength = model.Paging.PageLength;
responseData.SetPaging(model);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
// Get Association ajax request.
//-------------------------------------------------------------------
private class AjaxResponse_Association : AjaxResponse_Data
{
// Construction.
public AjaxResponse_Association(SbmModel_Portal model) : base(model) { }
// Configuration.
public Model_Association.ItemConfigData Config { get; } = new Model_Association.ItemConfigData();
// Association details.
public AssociationItemData association { get; } = new AssociationItemData();
}
//-------------------------------------------------------------------
[HttpPost]
[Route("Association/Ajax/Item")]
[Route("Association/Ajax/GetItem")]
public IActionResult Ajax_GetItem(Model_Association model)
{
String messageTitle = Localiser["label.association"];
AjaxResponse_Association responseData = new AjaxResponse_Association(model);
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Record disposable items as they are created so all can be disposed when needed.
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
{
// Identify item.
SysId associationId = model.Association.Id.ToSysId();
if (!SysId.IsValid(associationId))
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
// Retrieve item.
SbmAssociation association = AccountMgr.GetAssociationById(associationId);
disposables.Add(association);
if (association == null)
{
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve association for Id: '" + model.Association.Id + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
}
SbmAffiliate affiliateTarget = AccountMgr.GetAffiliateById(association.AffiliateIdTarget);
disposables.Add(affiliateTarget);
// Construct response.
model.PopulateItemConfig(responseData.Config, association, affiliateTarget);
PopulateAssociationResponseItemData(association, affiliateTarget, responseData.association);
// Complete response.
responseData.Success = true;
}
return Json(responseData);
}
//-------------------------------------------------------------------
// Store Association ajax request.
//-------------------------------------------------------------------
[HttpPost]
[Route("Association/Ajax/Store")]
[Route("Association/Ajax/StoreItem")]
public IActionResult Ajax_StoreItem(Model_Association model)
{
String messageTitle = Localiser["label.association"];
AjaxResponse_Association responseData = new AjaxResponse_Association(model);
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Validate item properties.
model.ValidateAssociationData(responseData);
if (responseData.HasControlErrors())
return Json(responseData);
// Record disposable items as they are created so all can be disposed when needed.
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
{
// Validate item Id against 'Exists' flag.
SysId associationId = model.Association.Id.ToSysId();
bool associationExists = StringUtil.ToBool(model.Association.Exists);
if (associationExists && !SysId.IsValid(associationId))
{
SaLogger.Warn($"{SysUtil.Fn} Id not specified for existing Association.");
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
if (!associationExists && SysId.IsValid(associationId))
{
SaLogger.Warn($"{SysUtil.Fn} Id specified for new Association: '" + model.Association.Id + "'");
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
// Retrieve existing item.
SbmAssociation association = AccountMgr.GetAssociationById(associationId);
disposables.Add(association);
if (association == null && SysId.IsValid(associationId))
{
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve association for Id: '" + model.Association.Id + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
}
// Create new item if required.
if (association == null)
{
Sbm.AssociationType associationType = model.GetAssociationType();
if (associationType < 0 || associationType == Sbm.AssociationType.Internal)
{
SaLogger.Warn($"{SysUtil.Fn} Invalid type for new Association: '" + model.Association.Type + "'");
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
// New item.
association = AccountMgr.CreateAssociation(SessionData_Portal.Organisation.AffiliateId, associationType, model.Association.AffiliateIdTarget.ToSysId());
disposables.Add(association);
}
// Populate item properties.
if (model.Association.Code != null)
association.Code = model.Association.Code;
if (model.Association.ReferenceExt != null)
association.RefExt = model.Association.ReferenceExt;
if (model.Association.Location != null)
association.Location = model.Association.Location;
if (model.Association.Role != null)
association.Role = model.Association.Role;
if (model.Association.PhoneMain != null)
association.PhoneMain = model.Association.PhoneMain;
if (model.Association.Email != null)
association.Email = model.Association.Email;
if (model.Association.Group != null)
association.Group = model.Association.Group;
if (model.Association.DescDetail != null)
association.DescDetail = model.Association.DescDetail;
if (model.Association.NominalCodeDefault != null)
association.DefaultNominalCode = model.Association.NominalCodeDefault;
// Account.
if (model.Association.AccountManagerCode != null)
association.AccountManagerCode = model.Association.AccountManagerCode;
if (model.Association.AccountHandlerCode != null)
association.AccountHandlerCode = model.Association.AccountHandlerCode;
if (model.Association.AccountTypeCode != null)
association.AccountTypeCode = model.Association.AccountTypeCode;
if (model.Association.AccountRatingCode != null)
association.AccountRatingCode = model.Association.AccountRatingCode;
// Contact.
if (model.Association.ContactAreaCode != null)
association.ContactAreaCode = model.Association.ContactAreaCode;
if (model.Association.ContactHandlerCode != null)
association.ContactHandlerCode = model.Association.ContactHandlerCode;
if (model.Association.ContactMethodCode != null)
association.ContactMethodCode = model.Association.ContactMethodCode;
if (model.Association.ContactCallCycleCode != null)
association.ContactCallCycleCode = model.Association.ContactCallCycleCode;
if (model.Association.CallsPerYear != null)
association.CallsPerYear = StringUtil.ToInt(model.Association.CallsPerYear);
if (model.Association.LastCallDate != null)
association.LastCall = model.ParseDateFromForm(model.Association.LastCallDate);
// Customer.
if (model.Association.CommodityIdSalesDefault != null)
association.CommodityIdSalesDefault = model.Association.CommodityIdSalesDefault.ToSysId();
if (model.Association.OrderLeadTimeCode != null)
association.OrderLeadTimeCode = model.Association.OrderLeadTimeCode;
if (model.Association.DeliveryTypeCode != null)
association.DeliveryTypeCode = model.Association.DeliveryTypeCode;
if (model.Association.DeliveryMethodCode != null)
association.DeliveryMethodCode = model.Association.DeliveryMethodCode;
if (model.Association.DeliveryCourierCode != null)
association.DeliveryCourierCode = model.Association.DeliveryCourierCode;
if (model.Association.DeliveryBookInCode != null)
association.DeliveryBookInCode = model.Association.DeliveryBookInCode;
// Transactions.
if (model.Association.AmountTransMax != null)
association.AmountTransMax = StringUtil.ToDecimal(model.Association.AmountTransMax);
if (model.Association.AnnualSalesTarget != null)
association.AnnualSalesTarget = StringUtil.ToDecimal(model.Association.AnnualSalesTarget);
if (model.Association.CreditLimit != null)
association.CreditLimit = StringUtil.ToDecimal(model.Association.CreditLimit);
if (model.Association.AccountBalance != null)
association.AccountBalance = StringUtil.ToDecimal(model.Association.AccountBalance);
if (model.Association.DiscountType != null)
association.DiscountType = model.GetAssociationDiscountType();
if (model.Association.DiscountRate != null)
association.DiscountRate = StringUtil.ToDecimal(model.Association.DiscountRate);
if (model.Association.PriceSetId != null)
association.PriceSetId = model.Association.PriceSetId.ToSysId();
if (model.Association.TaxCodeId != null)
association.TaxCodeId = model.Association.TaxCodeId.ToSysId();
if (model.Association.PaymentTerms != null)
association.PaymentTerms = StringUtil.ToShort(model.Association.PaymentTerms);
if (model.Association.InvoiceDesc != null)
association.InvoiceDesc = model.Association.InvoiceDesc;
if (model.Association.TerminatedDate != null)
association.Terminated = model.ParseDateFromForm(model.Association.TerminatedDate);
// Common properties.
if (model.Association.Notes != null)
association.Notes = model.Association.Notes;
if (model.Association.StatusCode != null)
association.Status = model.GetAssociationStatus();
// Store item.
if (!SysId.IsValid(association.Id))
{
if (!AccountMgr.InsertAssociation(association, DbUpdateInfo))
{
SaLogger.Warn($"{SysUtil.Fn} Failed to insert association: " + AccountMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.created"]);
}
else
{
if (!AccountMgr.UpdateAssociation(association, DbUpdateInfo))
{
SaLogger.Warn($"{SysUtil.Fn} Failed to update association [Id:" + SysId.ToString(association.Id) + "]: " + AccountMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]);
}
SbmAffiliate affiliateTarget = AccountMgr.GetAffiliateById(association.AffiliateIdTarget);
disposables.Add(affiliateTarget);
// Construct response.
model.PopulateItemConfig(responseData.Config, association, affiliateTarget);
PopulateAssociationResponseItemData(association, affiliateTarget, responseData.association);
// Complete response.
responseData.Success = true;
}
return Json(responseData);
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -2,7 +2,6 @@
using Microsoft.Extensions.Logging;
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
using Sarand.BusinessMgr.Web.Portal.Models;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
@@ -15,8 +14,9 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Sarand.BusinessMgr.Web.Portal.Models.Contacts;
namespace Sarand.BusinessMgr.Web.Portal.Controllers
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
{
//=======================================================================
public partial class AssociationController : SbmController_Portal
@@ -33,7 +33,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
//-------------------------------------------------------------------
[HttpGet]
public IActionResult Index()
public IActionResult Index(Model_Association model)
{
if (!ValidUserSession)
AutoLoginUser();
@@ -46,7 +46,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
}
// Association page.
Model_Association model = new Model_Association(Localiser);
RefreshModel(model);
model.PopulateListConfig();
model.Paging.PageNo = SessionData_Portal.Profile.Associations.Filter.PageNo;
model.Paging.PageLength = SessionData_Portal.Profile.Associations.Filter.PageLength;
return View(model);
@@ -0,0 +1,471 @@
using DocumentFormat.OpenXml.EMMA;
using Microsoft.AspNetCore.Mvc;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.BusinessMgr.Web.Portal.Models;
using Sarand.BusinessMgr.Web.Portal.Models.Contacts;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.CodeTypes;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Security;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
{
//=======================================================================
// Portal Contact Controller - Ajax actions.
//=======================================================================
partial class ContactController
{
//-------------------------------------------------------------------
// Affiliate data.
private class AffiliateListData : AjaxResponse_Data.ItemData_Base
{
public String DisplayName { get; set; }
public String TypeDesc { get; set; }
public bool? IsIndividual { get; set; }
public bool? IsGroup { get; set; }
public String AddressSummary { get; set; }
public String Contact { get; set; }
public String Phone { get; set; }
public String Email { get; set; }
public long? AssociationCount { get; set; }
}
private class AffiliateItemData : AffiliateListData
{
// Affiliate properties.
public String TypeCode { get; set; }
// Fields.
public class FieldData
{
public Dictionary<string, string> Value { get; } = new Dictionary<string, string>();
}
public FieldData Field { get; } = new FieldData();
}
private void PopulateAffiliateResponseListData(Model_Contact model, SbmAffiliate affiliate, AffiliateListData data)
{
data.Id = SysId.ToString(affiliate.Id);
data.DisplayName = affiliate.GetDisplayName();
data.TypeDesc = Internals.AffiliateTypeCodes.GetDescForType(affiliate.AffiliateType);
if (affiliate.IsIndividual()) data.IsIndividual = true;
if (affiliate.IsContactGroup()) data.IsGroup = true;
// Common properties.
data.StatusCode = affiliate.StatusCode;
data.StatusDesc = affiliate.StatusDesc;
}
private void PopulateAffiliateResponseItemData(Model_Contact model, SbmAffiliate affiliate, AffiliateItemData data)
{
PopulateAffiliateResponseListData(model, affiliate, data as AffiliateListData);
// Affiliate properties.
data.TypeCode = Internals.AffiliateTypeCodes.GetCodeForType(affiliate.AffiliateType);
// Ogranisation.
data.Field.Value.Add(Model_Contact.ItemField.Parent.ToString(), SysId.ToString(affiliate.AffiliateIdParent));
data.Field.Value.Add(Model_Contact.ItemField.Name.ToString(), affiliate.Name);
data.Field.Value.Add(Model_Contact.ItemField.Abbreviation.ToString(), affiliate.Abbr);
data.Field.Value.Add(Model_Contact.ItemField.Nature.ToString(), affiliate.Nature);
data.Field.Value.Add(Model_Contact.ItemField.Contact.ToString(), affiliate.Contact);
data.Field.Value.Add(Model_Contact.ItemField.PhoneMain.ToString(), affiliate.PhoneMain);
data.Field.Value.Add(Model_Contact.ItemField.PhoneAlt.ToString(), affiliate.PhoneAlt);
data.Field.Value.Add(Model_Contact.ItemField.PhoneDirect.ToString(), affiliate.PhoneDirect);
data.Field.Value.Add(Model_Contact.ItemField.PhoneFax.ToString(), affiliate.PhoneFax);
data.Field.Value.Add(Model_Contact.ItemField.Email.ToString(), affiliate.Email);
data.Field.Value.Add(Model_Contact.ItemField.Website.ToString(), affiliate.Website);
data.Field.Value.Add(Model_Contact.ItemField.CompanyNo.ToString(), affiliate.CompanyNo);
data.Field.Value.Add(Model_Contact.ItemField.VatReg.ToString(), affiliate.VatReg);
// Individual.
data.Field.Value.Add(Model_Contact.ItemField.Title.ToString(), affiliate.Title);
data.Field.Value.Add(Model_Contact.ItemField.Salutation.ToString(), affiliate.Salutation);
data.Field.Value.Add(Model_Contact.ItemField.FirstName.ToString(), affiliate.FirstName);
data.Field.Value.Add(Model_Contact.ItemField.Initials.ToString(), affiliate.Initials);
data.Field.Value.Add(Model_Contact.ItemField.LastName.ToString(), affiliate.LastName);
data.Field.Value.Add(Model_Contact.ItemField.PhoneMobile.ToString(), affiliate.PhoneMobile);
data.Field.Value.Add(Model_Contact.ItemField.BirthDay.ToString(), affiliate.BirthDay > 0 ? affiliate.BirthDay.ToString() : "");
data.Field.Value.Add(Model_Contact.ItemField.BirthMonth.ToString(), affiliate.BirthMonth > 0 ? affiliate.BirthMonth.ToString() : "");
data.Field.Value.Add(Model_Contact.ItemField.BirthYear.ToString(), affiliate.BirthYear > 0 ? affiliate.BirthYear.ToString() : "");
data.Field.Value.Add(Model_Contact.ItemField.MaritalStatus.ToString(), affiliate.MaritalStatus);
data.Field.Value.Add(Model_Contact.ItemField.Spouse.ToString(), affiliate.Spouse);
data.Field.Value.Add(Model_Contact.ItemField.Children.ToString(), affiliate.Children);
data.Field.Value.Add(Model_Contact.ItemField.Hometown.ToString(), affiliate.Hometown);
data.Field.Value.Add(Model_Contact.ItemField.UserId.ToString(), SysId.ToString(affiliate.UserId));
// Flags.
data.Field.Value.Add(Model_Contact.ItemField.Prospect.ToString(), affiliate.Prospect ? "1" : "");
// Common properties.
data.Field.Value.Add(Model_Contact.ItemField.Notes.ToString(), affiliate.Notes);
// Cleanse field values.
data.Field.Value.RemoveAll(item => StringUtil.IsBlank(item.Value));
}
//-------------------------------------------------------------------
// Contact configuration.
//-------------------------------------------------------------------
// Contact list and item configurations as well as reference data
// for pages other than Contact to search/create/update contacts.
private class AjaxResponse_ContactConfig : AjaxResponse_Data
{
// Construction.
public AjaxResponse_ContactConfig(SbmModel_Portal model) : base(model) { }
// Configuration.
public Model_Contact.ListConfigData Config { get; } = new Model_Contact.ListConfigData();
public Model_Contact.ItemConfigData ConfigInd { get; } = new Model_Contact.ItemConfigData();
public Model_Contact.ItemConfigData ConfigOrg { get; } = new Model_Contact.ItemConfigData();
public Model_Contact.ItemConfigData ConfigGrp { get; } = new Model_Contact.ItemConfigData();
// Reference data.
public List<AjaxResponse_Data.ItemCodeDesc> OrganisationTypes { get; } = new List<AjaxResponse_Data.ItemCodeDesc>();
public List<AjaxResponse_Data.ItemCodeDesc> Titles { get; } = new List<AjaxResponse_Data.ItemCodeDesc>();
public List<AjaxResponse_Data.ItemCodeDesc> Salutations { get; } = new List<AjaxResponse_Data.ItemCodeDesc>();
public List<AjaxResponse_Data.ItemCodeDesc> Statuses { get; } = new List<AjaxResponse_Data.ItemCodeDesc>();
public String DefaultStatusCode { get; set; }
}
// Ajax request.
[HttpPost]
[Route("Contact/Ajax/Config")]
[Route("Contact/Ajax/GetConfig")]
public IActionResult Ajax_ContactConfig(Model_Contact model)
{
String fn = GetType().Name + ".Ajax_ContactConfig";
AjaxResponse_ContactConfig responseData = new AjaxResponse_ContactConfig(model);
String messageTitle = Localiser["label.contacts"];
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Populate configuration data.
PopulateContactConfig(model, responseData);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
private void PopulateContactConfig(Model_Contact model, AjaxResponse_ContactConfig responseData)
{
// Configuration.
model.PopulateListConfig(responseData.Config);
model.PopulateItemConfig(responseData.ConfigInd, null, Sbm.AffiliateType.Individual);
model.PopulateItemConfig(responseData.ConfigOrg, null, Sbm.AffiliateType.Commercial);
model.PopulateItemConfig(responseData.ConfigGrp, null, Sbm.AffiliateType.ContactGroup);
// Reference data - Organisation types.
foreach (TypeCodeDesc affiliateType in GetCodesOfType(Sbm.SystemCode.AffiliateType).Where(item => item.Type != (short)Sbm.AffiliateType.Individual && item.Type != (short)Sbm.AffiliateType.ContactGroup))
responseData.OrganisationTypes.Add(new AjaxResponse_Data.ItemCodeDesc(affiliateType.Code, affiliateType.Desc));
// Reference data - titles.
foreach (SaCode title in CodeTypeConsole.GetCodesForCodeType(SbmSystem.GetCodeTypeCode(Sbm.ApplCodeType.ContactTitle)))
responseData.Titles.Add(new AjaxResponse_Data.ItemCodeDesc(title.Code, title.Description));
// Reference data - salutation.
responseData.Salutations.Add(new AjaxResponse_Data.ItemCodeDesc("Dear", "Dear"));
// Reference data - statuses.
foreach (SaStatus status in SbmAffiliate.ValidStatuses.FindAll(item => item != SaStatus.Deleted))
responseData.Statuses.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SbmAffiliate.DefaultStatus);
}
//-------------------------------------------------------------------
// Contact list.
//-------------------------------------------------------------------
private class AjaxResponse_ContactList : AjaxResponse_ContactConfig
{
// Construction.
public AjaxResponse_ContactList(SbmModel_Portal model) : base(model) { }
// Affiliate list.
public List<AffiliateListData> Contacts { get; } = new List<AffiliateListData>();
}
// Ajax request.
[HttpPost]
[Route("Contact/Ajax/List")]
[Route("Contact/Ajax/GetList")]
public IActionResult Ajax_ContactList(Model_Contact model)
{
String fn = GetType().Name + ".Ajax_ContactList";
AjaxResponse_ContactList responseData = new AjaxResponse_ContactList(model);
String messageTitle = Localiser["label.contacts"];
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Populate configuration data.
PopulateContactConfig(model, responseData);
// Item filter.
SbmAffiliate.Params prmAffiliate = new SbmAffiliate.Params();
prmAffiliate.Search = model.Filter.Search;
prmAffiliate.AffiliateType = model.GetFilterContactType();
prmAffiliate.StatusCat = SbmAffiliate.StatusCat.NotDeleted;
prmAffiliate.SortColumns.Add(AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Name));
prmAffiliate.SortColumns.Add(AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.LastName));
model.Paging.ItemTotal = (ulong)AccountMgr.GetAffiliateCount(prmAffiliate);
model.PopulatePagingTo(prmAffiliate.ResultsPaging);
// Item columns.
ColumnDfn colId = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Id);
ColumnDfn colName = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Name);
ColumnDfn colAffiliateType = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Type);
ColumnDfn colAddress = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Address_Summary);
ColumnDfn colContact = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Contact);
ColumnDfn colPhoneMain = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.PhoneMain);
ColumnDfn colPhoneAlt = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.PhoneAlt);
ColumnDfn colPhoneMobile = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.PhoneMobile);
ColumnDfn colPhoneDirect = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.PhoneDirect);
ColumnDfn colEmail = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Email);
ColumnDfn colAssocCount = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Association_Count);
ColumnDfn colNotes = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Notes);
ColumnDfn colStatus = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Status);
ColumnDfn colCreatedOn = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.CreateOn_Date);
ColumnDfn colUpdatedOn = AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.UpdateOn_Date);
List<ColumnDfn> columns = new List<ColumnDfn>()
{
colId, colName, colAffiliateType,
colAddress, colContact, colPhoneMain, colPhoneAlt, colPhoneMobile, colPhoneDirect, colEmail, colAssocCount,
colNotes, colStatus, colCreatedOn, colUpdatedOn
};
if (responseData.Config.Column.Hide.Contains(Model_Contact.ItemColumn.Address.ToString()))
columns.Remove(colAddress);
if (responseData.Config.Column.Hide.Contains(Model_Contact.ItemColumn.Email.ToString()))
columns.Remove(colEmail);
// Query items.
using (DbResultSet resultSet = AccountMgr.ExecuteAffiliateQuery(columns, prmAffiliate))
{
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
{
NamedValue.Map values = resultSet.GetRecordValues();
Sbm.AffiliateType affiliateType = (Sbm.AffiliateType)values.GetLong(colAffiliateType.DataName);
AffiliateListData affiliateData = new AffiliateListData()
{
Id = values.GetString(colId.DataName),
DisplayName = values.GetString(colName.DataName),
TypeDesc = Internals.AffiliateTypeCodes.GetDescForType(affiliateType),
AddressSummary = StringUtil.NullOnBlank(AccountMgr.GetAffiliateDataValue(colAddress, values).AsString()),
Contact = StringUtil.NullOnBlank(values.GetString(colContact.DataName)),
Phone = StringUtil.NullOnBlank(StringUtil.OnBlank(values.GetString(colPhoneMain.DataName), values.GetString(colPhoneAlt.DataName), values.GetString(colPhoneMobile.DataName), values.GetString(colPhoneDirect.DataName))),
Email = StringUtil.NullOnBlank(values.GetString(colEmail.DataName)),
Notes = StringUtil.NullOnBlank(AccountMgr.GetAffiliateDataValue(colNotes, values).ToString()),
StatusCode = values.GetString(colStatus.DataName),
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName)),
CreatedOn = DateUtil.Format(values.GetDate(colCreatedOn.DataName), "yyyyMMdd"),
CreatedOnFmt = Localiser.FormatDate(values.GetDate(colCreatedOn.DataName)),
UpdatedOn = DateUtil.Format(values.GetDate(colUpdatedOn.DataName), "yyyyMMdd"),
UpdatedOnFmt = Localiser.FormatDate(values.GetDate(colUpdatedOn.DataName))
};
if (SbmAffiliate.IsIndividual(affiliateType)) affiliateData.IsIndividual = true;
if (SbmAffiliate.IsContactGroup(affiliateType)) affiliateData.IsGroup = true;
long assocCount = values.GetLong(colAssocCount.DataName);
if (assocCount > 0)
affiliateData.AssociationCount = assocCount;
responseData.Contacts.Add(affiliateData);
}
}
// Refresh paging info.
if (model.Paging.IsPaged)
model.Paging.ItemCount = (ushort)responseData.Contacts.Count;
SessionData_Portal.Profile.Contacts.Filter.PageNo = model.Paging.PageNo;
SessionData_Portal.Profile.Contacts.Filter.PageLength = model.Paging.PageLength;
responseData.SetPaging(model);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
// Get Affiliate ajax request.
//-------------------------------------------------------------------
private class AjaxResponse_Affiliate : AjaxResponse_Data
{
// Construction.
public AjaxResponse_Affiliate(SbmModel_Portal model) : base(model) { }
// Configuration.
public Model_Contact.ItemConfigData Config { get; } = new Model_Contact.ItemConfigData();
// Affiliate details.
public AffiliateItemData Contact { get; } = new AffiliateItemData();
}
//-------------------------------------------------------------------
[HttpPost]
[Route("Contact/Ajax/Item")]
[Route("Contact/Ajax/GetItem")]
public IActionResult Ajax_GetItem(Model_Contact model)
{
String fn = GetType().Name + ".Ajax_GetItem";
String messageTitle = Localiser["label.contact"];
AjaxResponse_Affiliate responseData = new AjaxResponse_Affiliate(model);
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Identify item.
SysId affiliateId = model.Contact.Id.ToSysId();
if (!SysId.IsValid(affiliateId))
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
// Retrieve item.
SbmAffiliate affiliate = AccountMgr.GetAffiliateById(affiliateId);
if (affiliate == null)
{
SaLogger.Warn(fn + " Failed to retrieve affiliate for Id: '" + model.Contact.Id + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
}
// Construct response.
model.PopulateItemConfig(responseData.Config, affiliate);
PopulateAffiliateResponseItemData(model, affiliate, responseData.Contact);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
// Store Affiliate ajax request.
//-------------------------------------------------------------------
[HttpPost]
[Route("Contact/Ajax/Store")]
[Route("Contact/Ajax/StoreItem")]
public IActionResult Ajax_StoreItem(Model_Contact model)
{
String fn = GetType().Name + ".Ajax_StoreItem";
String messageTitle = Localiser["label.contact"];
AjaxResponse_Affiliate responseData = new AjaxResponse_Affiliate(model);
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Validate item properties.
model.ValidateAffiliateData(responseData);
if (responseData.HasControlErrors())
return Json(responseData);
// Validate item Id against 'Exists' flag.
SysId affiliateId = model.Contact.Id.ToSysId();
bool contactExists = StringUtil.ToBool(model.Contact.Exists);
if (contactExists && !SysId.IsValid(affiliateId))
{
SaLogger.Warn(fn + " Id not specified for existing Affiliate.");
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
if (!contactExists && SysId.IsValid(affiliateId))
{
SaLogger.Warn(fn + " Id specified for new Affiliate: '" + model.Contact.Id + "'");
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
// Retrieve existing item.
SbmAffiliate affiliate = AccountMgr.GetAffiliateById(affiliateId);
if (affiliate == null && SysId.IsValid(affiliateId))
{
SaLogger.Warn(fn + " Failed to retrieve affiliate for Id: '" + model.Contact.Id + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
}
// Create new item if required.
if (affiliate == null)
{
affiliate = AccountMgr.CreateAffiliate(model.GetContactType());
}
else
{
if (model.Contact.Type != null)
affiliate.AffiliateType = model.GetContactType();
}
// Populate item properties.
// Organisation.
if (model.Contact.Name != null)
affiliate.Name = model.Contact.Name;
if (model.Contact.Abbreviation != null)
affiliate.Abbr = model.Contact.Abbreviation;
if (model.Contact.Nature != null)
affiliate.Nature = model.Contact.Nature;
if (model.Contact.Contact != null)
affiliate.Contact = model.Contact.Contact;
if (model.Contact.PhoneMain != null)
affiliate.PhoneMain = model.Contact.PhoneMain;
if (model.Contact.PhoneAlt != null)
affiliate.PhoneAlt = model.Contact.PhoneAlt;
if (model.Contact.PhoneDirect != null)
affiliate.PhoneDirect = model.Contact.PhoneDirect;
if (model.Contact.PhoneFax != null)
affiliate.PhoneFax = model.Contact.PhoneFax;
if (model.Contact.Email != null)
affiliate.Email = model.Contact.Email;
if (model.Contact.Website != null)
affiliate.Website = model.Contact.Website;
if (model.Contact.CompanyNo != null)
affiliate.CompanyNo = model.Contact.CompanyNo;
if (model.Contact.VatReg != null)
affiliate.VatReg = model.Contact.VatReg;
// Individual.
if (model.Contact.Title != null)
affiliate.Title = model.Contact.Title;
if (model.Contact.Salutation != null)
affiliate.Salutation = model.Contact.Salutation;
if (model.Contact.FirstName != null)
affiliate.FirstName = model.Contact.FirstName;
if (model.Contact.Initials != null)
affiliate.Initials = model.Contact.Initials;
if (model.Contact.LastName != null)
affiliate.LastName = model.Contact.LastName;
if (model.Contact.PhoneMobile != null)
affiliate.PhoneMobile = model.Contact.PhoneMobile;
// Flags.
if (model.Contact.IsProspectSumbitted())
affiliate.Prospect = model.Contact.Prospect;
// Common properties.
if (model.Contact.Notes != null)
affiliate.Notes = model.Contact.Notes;
if (model.Contact.StatusCode != null)
affiliate.Status = model.GetAffiliateStatus();
// Store item.
if (!SysId.IsValid(affiliate.Id))
{
if (!AccountMgr.InsertAffiliate(affiliate, DbUpdateInfo))
{
SaLogger.Warn(fn + " Failed to insert affiliate: " + AccountMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.created"]);
}
else
{
if (!AccountMgr.UpdateAffiliate(affiliate, DbUpdateInfo))
{
SaLogger.Warn(fn + " Failed to update affiliate [Id:" + SysId.ToString(affiliate.Id) + "]: " + AccountMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]);
}
// Construct response.
model.PopulateItemConfig(responseData.Config, affiliate);
PopulateAffiliateResponseItemData(model, affiliate, responseData.Contact);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -2,7 +2,6 @@
using Microsoft.Extensions.Logging;
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
using Sarand.BusinessMgr.Web.Portal.Models;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
@@ -15,8 +14,9 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Sarand.BusinessMgr.Web.Portal.Models.Contacts;
namespace Sarand.BusinessMgr.Web.Portal.Controllers
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
{
//=======================================================================
public partial class ContactController : SbmController_Portal
@@ -33,7 +33,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
//-------------------------------------------------------------------
[HttpGet]
public IActionResult Index()
public IActionResult Index(Model_Contact model)
{
if (!ValidUserSession)
AutoLoginUser();
@@ -46,7 +46,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
}
// Contact page.
Model_Contact model = new Model_Contact(Localiser);
RefreshModel(model);
model.PopulateListConfig();
model.Paging.PageNo = SessionData_Portal.Profile.Contacts.Filter.PageNo;
model.Paging.PageLength = SessionData_Portal.Profile.Contacts.Filter.PageLength;
return View(model);
@@ -26,6 +26,8 @@ using Sarand.BusinessMgr.Net.Core.Web.Helpers;
namespace Sarand.BusinessMgr.Web.Portal.Controllers
{
//=======================================================================
// Portal Controller - Utils.
//=======================================================================
public class SbmController_Portal : SbmController_Web
{
@@ -150,6 +152,9 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
// Create session.
OpenUserSession(userContext.SessionContext, dbIdentifier, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation);
// Configure security profile.
SessionData_Portal.SecurityProfile_Core.RefreshProfile(SessionConsole, SecurityConsole, securityItemUser.Id, SecurityConsole.GetRegisteredRights());
// Send the 'Keep Logged In' cookie if requested.
if (affiliateUser.KeepLoggedIn_Portal)
SetKeepLoggedInCookie();
@@ -288,7 +293,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
String keepLoggedInCookieValue = GenerateKeepLoggedInCookieValue();
int cookieExpiresDays = Math.Max(Sbm.Config.Security.SignIn.KeepLoggedIn.CookieExpiresDays_Min, Math.Min(Sbm.Config.Security.SignIn.KeepLoggedIn.CookieExpiresDays_Max, AppConfig.Security.SignIn.KeepLoggedIn.CookieExpiresDays));
SetResponseCookie(KeepLoggedIn.CookieName, keepLoggedInCookieValue, DateTime.Now.AddDays(cookieExpiresDays), true);
SaLogger.Info($"{SysUtil.Fn} 'Keep Logged In' cookie set. Name: {KeepLoggedIn.CookieName}. Value: {keepLoggedInCookieValue}");
SaLogger.Debug($"{SysUtil.Fn} 'Keep Logged In' cookie set. Name: {KeepLoggedIn.CookieName}. Value: {keepLoggedInCookieValue}");
}
/// <summary>Set the 'Keep Logged In' response cookie to expired with no data.</summary>
@@ -297,7 +302,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
if (StringUtil.IsEmpty(GetRequestCookie(KeepLoggedIn.CookieName))) return;
// Clear cookie by setting expiry date in the past.
SetResponseCookie(KeepLoggedIn.CookieName, "", DateTime.Today.AddDays(-7), true);
SaLogger.Info($"{SysUtil.Fn} 'Keep Logged In' cookie cleared. Name: {KeepLoggedIn.CookieName}.");
SaLogger.Debug($"{SysUtil.Fn} 'Keep Logged In' cookie cleared. Name: {KeepLoggedIn.CookieName}.");
}
//-------------------------------------------------------------------
@@ -30,7 +30,7 @@ using static Sarand.Net.Standard.Base.Bus.SaErrorStateItem;
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
using Sarand.BusinessMgr.Web.Portal.Helpers;
namespace Sarand.BusinessMgr.Web.Portal.Controllers
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
{
//=======================================================================
// Portal Security Controller - Ajax actions.
@@ -17,7 +17,7 @@ using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace Sarand.BusinessMgr.Web.Portal.Controllers
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
{
//=======================================================================
// Online Security Controller.
@@ -1,9 +1,11 @@
using Sarand.BusinessMgr.Net.Core.Web.App;
using Microsoft.AspNetCore.Http;
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Controllers;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.BusinessMgr.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Utils;
@@ -14,100 +16,198 @@ using System.Threading.Tasks;
namespace Sarand.BusinessMgr.Web.Portal.Models.Commodities
{
//=======================================================================
public class Model_Commodity : SbmModel_Portal
{
//-------------------------------------------------------------------
// Construction.
public Model_Commodity(SbmLocaliser localiser) :
base(localiser)
{
AdditionalFiles_JS.Add("js/sbm-commodity.js");
}
//=======================================================================
public class Model_Commodity : SbmModel_Portal
{
//-------------------------------------------------------------------
// Construction.
public Model_Commodity(SbmLocaliser localiser) :
base(localiser)
{
}
//-------------------------------------------------------------------
// Filter properties.
public class FilterData
{
public string CommoditySearch { get; set; }
public string CommodityType { get; set; }
}
public FilterData Filter { get; } = new FilterData();
public Sbm.CommodityType GetFilterCommodityType()
{
return (Sbm.CommodityType)Internals.CommodityTypeCodes.GetTypeForCode(Filter.CommodityType);
}
//-------------------------------------------------------------------
// Filter properties.
public class FilterData
{
public string Search { get; set; }
public string CommodityType { get; set; }
}
public FilterData Filter { get; } = new FilterData();
public Sbm.CommodityType GetFilterCommodityType()
{
return (Sbm.CommodityType)Internals.CommodityTypeCodes.GetTypeForCode(Filter.CommodityType);
}
//-------------------------------------------------------------------
// Commodity properties.
public string CommodityId { get; set; }
public string CommodityExists { get; set; }
public string CommodityType { get; set; }
public Sbm.CommodityType GetCommodityType()
{
return (Sbm.CommodityType)Internals.CommodityTypeCodes.GetTypeForCode(CommodityType);
}
public string CommodityCode { get; set; }
public string CommodityDesc { get; set; }
// Common properties.
public string CommodityNotes { get; set; }
public string CommodityStatusCode { get; set; }
public SaStatus CommodityStatus { get { return SacsSystem.GetStatusForCode(CommodityStatusCode); } }
//-------------------------------------------------------------------
// Commodity properties.
public class CommodityData
{
public String Exists { get; set; }
public String Id { get; set; }
public String IdSupersede { get; set; }
public String Type { get; set; }
public String Code { get; set; }
public String DrawingIssue { get; set; }
public String DescBrief { get; set; }
public String AssocIdCustomer { get; set; }
public String AssocIdSupplier { get; set; }
// Common properties.
public String Notes { get; set; }
public String StatusCode { get; set; }
public String SupersededStatusConfirmed { get; set; }
}
public CommodityData Commodity { get; } = new CommodityData();
public Sbm.CommodityType GetCommodityType()
{
return (Sbm.CommodityType)Internals.CommodityTypeCodes.GetTypeForCode(Commodity.Type);
}
public SaStatus GetCommodityStatus()
{
return SacsSystem.GetStatusForCode(Commodity.StatusCode);
}
//-------------------------------------------------------------------
// Validation.
//-------------------------------------------------------------------
// Commodity validation.
public bool ValidateCommodityData(Sacs.Web.Components.SaController.AjaxResponse_Data responseData)
{
// Commodity Type.
if (CommodityType != null)
{
if (CommodityType.IsEmpty())
responseData.SetControlError(nameof(CommodityType), Localiser["msg.validation.mandatory.value"]);
}
//-------------------------------------------------------------------
// Validation.
//-------------------------------------------------------------------
// Commodity validation.
public bool ValidateCommodityData(Sacs.Web.Components.SaController.AjaxResponse_Data responseData)
{
// Commodity Type.
if (Commodity.Type != null)
{
String controlName = "CommodityType";
if (Commodity.Type.IsEmpty() || GetCommodityType() <= 0)
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
}
// Commodity Code.
if (CommodityCode != null)
{
responseData.SetControlValue(nameof(CommodityCode), CommodityCode);
if (CommodityCode.IsEmpty())
responseData.SetControlError(nameof(CommodityCode), Localiser["msg.validation.mandatory.value"]);
if (StringUtil.GetLength(CommodityCode) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Code))
responseData.SetControlError(nameof(CommodityCode), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Code)]);
}
// Commodity Code.
if (Commodity.Code != null)
{
String controlName = "CommodityCode";
responseData.SetControlValue(controlName, Commodity.Code);
if (Commodity.Code.IsEmpty())
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
if (StringUtil.GetLength(Commodity.Code) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Code))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Code)]);
}
// Commodity Desc.
if (CommodityDesc != null)
{
responseData.SetControlValue(nameof(CommodityDesc), CommodityDesc);
if (CommodityDesc.IsEmpty())
responseData.SetControlError(nameof(CommodityDesc), Localiser["msg.validation.mandatory.value"]);
if (StringUtil.GetLength(CommodityDesc) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_DescBrief))
responseData.SetControlError(nameof(CommodityDesc), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_DescBrief)]);
}
// Commodity Description.
if (Commodity.DescBrief != null)
{
String controlName = "CommodityDesc";
responseData.SetControlValue(controlName, Commodity.DescBrief);
if (Commodity.DescBrief.IsEmpty())
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
if (StringUtil.GetLength(Commodity.DescBrief) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_DescBrief))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_DescBrief)]);
}
// Commodity Notes.
if (CommodityNotes != null)
{
responseData.SetControlValue(nameof(CommodityNotes), CommodityNotes);
if (!CommodityNotes.IsEmpty() && StringUtil.GetLength(CommodityNotes) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Notes))
responseData.SetControlError(nameof(CommodityNotes), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Notes)]);
}
// Commodity Notes.
if (Commodity.Notes != null)
{
String controlName = "CommodityNotes";
responseData.SetControlValue(controlName, Commodity.Notes);
if (!Commodity.Notes.IsEmpty() && StringUtil.GetLength(Commodity.Notes) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Notes))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Notes)]);
}
// Commodity status.
if (CommodityStatusCode != null)
{
if (CommodityStatusCode.IsEmpty())
responseData.SetControlError(nameof(CommodityStatusCode), Localiser["msg.validation.mandatory.value"]);
else if (!SbmCommodity.ValidStatuses.Contains(CommodityStatus))
responseData.SetControlError(nameof(CommodityStatusCode), Localiser["msg.validation.invalid.value"]);
}
// Commodity status.
if (Commodity.StatusCode != null)
{
String controlName = "CommodityStatusCode";
if (Commodity.StatusCode.IsEmpty())
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
else if (!SbmCommodity.ValidStatuses.Contains(GetCommodityStatus()))
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
}
return !responseData.HasControlErrors();
}
if (!responseData.HasControlErrors())
{
using (DisposableCollection<SacsDisposable> disposables = new DisposableCollection<SacsDisposable>())
{
// Retrieve existing commodity.
SbmCommodity commodity = null;
if (StringUtil.ToBool(Commodity.Exists) && SysId.IsValid(Commodity.Id.ToSysId()))
{
commodity = CommodityMgr.GetCommodityById(Commodity.Id.ToSysId());
disposables.Add(commodity);
if (commodity == null)
responseData.SetMessage(Localiser["caption.commodity"], Localiser["msg.something.gone.wrong"]);
}
//-------------------------------------------------------------------
}
//=======================================================================
if (!responseData.HasControlErrors())
{
// Validate status.
String controlName = "CommodityStatusCode";
if (GetCommodityStatus() == SaStatus.Current)
{
// Check that no other current commodity exists with this code.
SbmCommodity.Params prmCommodity = new SbmCommodity.Params();
// Ignore this commodity if it already exists.
if (StringUtil.ToBool(Commodity.Exists) && SysId.IsValid(Commodity.Id.ToSysId()))
prmCommodity.PriceSetIdsExcluded.Add(Commodity.Id.ToSysId());
// Ignore the commodity being superseded, if any.
if (SysId.IsValid(Commodity.IdSupersede.ToSysId()))
prmCommodity.PriceSetIdsExcluded.Add(Commodity.IdSupersede.ToSysId());
// Same code and issue.
prmCommodity.CodeFull = Commodity.Code;
prmCommodity.DrawingIssueFull = Commodity.DrawingIssue;
// Restrict to same customer.
prmCommodity.AssociationIdCustomer = Commodity.AssocIdCustomer != null ? Commodity.AssocIdCustomer.ToSysId() : commodity.AssociationIdCustomer;
prmCommodity.StatusCat = SbmCommodity.StatusCat.Current;
List<SbmCommodity> commodities = CommodityMgr.GetCommodityList(prmCommodity);
disposables.AddRange(commodities);
foreach (SbmCommodity commodityByCode in commodities)
{
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
String msg = $"Another current Commodity already exists with this code: {Commodity.Code}.";
if (SysId.IsValid(commodityByCode.AssociationIdCustomer))
msg += $" Customer: {AccountMgr.GetAssociationTargetName(commodityByCode.AssociationIdCustomer)}.";
else
msg += $" Customer: None.";
if (SessionConsole.DisplayAttribute(SbmDbDfn.ColumnIdx.Commodity_DrawingIssue))
msg += $" Issue: {Commodity.DrawingIssue}.";
else
msg += $" Issue: None.";
SaLogger.Warn($"{SysUtil.Fn} {msg}");
break;
}
}
else if (GetCommodityStatus() == SaStatus.Superseded)
{
// Has the status already been confirmed.
if (!StringUtil.ToBool(Commodity.SupersededStatusConfirmed))
{
// Check that a current commodity exists with this code.
SbmCommodity.Params prmCommodity = new SbmCommodity.Params();
// Ignore this commodity if it already exists.
if (StringUtil.ToBool(Commodity.Exists) && SysId.IsValid(Commodity.Id.ToSysId()))
prmCommodity.PriceSetIdsExcluded.Add(Commodity.Id.ToSysId());
// Same code.
prmCommodity.CodeFull = Commodity.Code;
prmCommodity.StatusCat = SbmCommodity.StatusCat.Current;
if (CommodityMgr.GetCommodityCount(prmCommodity) > 0)
{
String msg = "There are no other Commodities for this code\nwith a status of 'Current'.\n\nAre you sure that this commodity should be set to 'Superseded'?";
responseData.SetConfirmMessage(Localiser["caption.commodity"], msg);
}
}
}
else if (GetCommodityStatus() == SaStatus.Discontinued)
{
}
else if (GetCommodityStatus() == SaStatus.Deleted)
{
}
}
}
}
return !responseData.HasControlErrors();
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,285 @@
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Drawing;
namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
{
//=======================================================================
/// <summary>
/// Association model - Configuration.
/// </summary>
partial class Model_Association
{
//-------------------------------------------------------------------
// List configuration.
public class ListConfigData
{
// List columns.
public class ColumnData
{
// Show column.
public class ShowData
{
public bool? Owner_Name { get; set; }
// Customer.
public bool? Trans_SalesValue_Open { get; set; }
public bool? Trans_LastSaleRaised { get; set; }
public bool? AnnualSalesTarget { get; set; }
public bool? Trans_SalesValue_Cytd { get; set; }
public bool? Trans_SalesValue_Lcy { get; set; }
public bool? CommodityCount { get; set; }
public bool? DiscountRate { get; set; }
public bool? PriceSet { get; set; }
public bool? Group { get; set; }
// Customer codes.
public bool? AccountManager { get; set; }
public bool? AccountHandler { get; set; }
public bool? ContactArea { get; set; }
public bool? ContactHandler { get; set; }
// Members.
public bool? Technician { get; set; }
public bool? Terminated { get; set; }
}
public ShowData Show { get; } = new ShowData();
// Column labels.
public class LabelData
{
// Members.
public String Technician { get; set; }
public String Terminated { get; set; }
}
public LabelData Label { get; } = new LabelData();
}
public ColumnData Column { get; } = new ColumnData();
}
public ListConfigData ListConfig { get; private set; }
//-------------------------------------------------------------------
/// <summary>
/// Populate Association list configuration data - only required on initial page construction.
/// </summary>
public void PopulateListConfig()
{
ListConfig = new ListConfigData();
PopulateListConfig(ListConfig);
}
public void PopulateListConfig(ListConfigData listConfig)
{
bool isCustomer = GetAssociationType() == Sbm.AssociationType.Customer;
bool isSupplier = GetAssociationType() == Sbm.AssociationType.Supplier;
bool userCanViewFinancials = SessionData_Portal.SecurityProfile_Core.UserCanViewFinancials();
// List columns.
if (Mode == AssociationPageMode.Relationships)
listConfig.Column.Show.Owner_Name = true;
if (Mode == AssociationPageMode.Maintain)
{
if (GetAssociationType() == Sbm.AssociationType.Customer)
{
// Customers.
if (userCanViewFinancials && SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Association_Trans_SalesValue_Open))
listConfig.Column.Show.Trans_SalesValue_Open = true;
if (SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Association_Trans_LastSaleRaised))
listConfig.Column.Show.Trans_LastSaleRaised = true;
if (userCanViewFinancials && SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Association_AnnualSalesTarget))
listConfig.Column.Show.AnnualSalesTarget = true;
if (userCanViewFinancials && SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Association_Trans_SalesValue_Cytd))
listConfig.Column.Show.Trans_SalesValue_Cytd = true;
if (userCanViewFinancials && SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Association_Trans_SalesValue_Lcy))
listConfig.Column.Show.Trans_SalesValue_Lcy = true;
// Commodities.
if (CommodityMgr.CanManageCommodityCustomers())
listConfig.Column.Show.CommodityCount = true;
// Customer pricing.
if (userCanViewFinancials && SessionConsole.AllowOption(Sbm.ConfigOption.CustomerDiscount))
listConfig.Column.Show.DiscountRate = true;
if (userCanViewFinancials && SessionConsole.AllowOption(Sbm.ConfigOption.CustomerPriceSet) && PriceMgr.PriceDatabaseIsValid)
listConfig.Column.Show.PriceSet = true;
// Association group.
if (SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Association_Group))
listConfig.Column.Show.Group = true;
// Codes.
if (CodeTypeConsole.CodeTypeHasCodes(Internals.GetCodeTypeCode(Sbm.ApplCodeType.AccountManager)))
listConfig.Column.Show.AccountManager = true;
if (CodeTypeConsole.CodeTypeHasCodes(Internals.GetCodeTypeCode(Sbm.ApplCodeType.AccountHandler)))
listConfig.Column.Show.AccountHandler = true;
if (CodeTypeConsole.CodeTypeHasCodes(Internals.GetCodeTypeCode(Sbm.ApplCodeType.ContactArea)))
listConfig.Column.Show.ContactArea = true;
if (CodeTypeConsole.CodeTypeHasCodes(Internals.GetCodeTypeCode(Sbm.ApplCodeType.ContactHandler)))
listConfig.Column.Show.ContactHandler = true;
}
else if (GetAssociationType() == Sbm.AssociationType.Supplier)
{
// Suppliers.
// Commodities.
if (CommodityMgr.CanManageCommoditySuppliers())
listConfig.Column.Show.CommodityCount = true;
}
else if (GetAssociationType() == Sbm.AssociationType.Member)
{
// Members.
if (StringUtil.ToSysId(Filter.OwnerId).Equals(SessionData_Portal.Organisation.AffiliateId))
listConfig.Column.Show.Technician = true;
listConfig.Column.Show.Terminated = true;
listConfig.Column.Label.Terminated = "Terminated";
}
}
}
//-------------------------------------------------------------------
// Item configuration.
// Legacy Association dialog tabs and panels.
// Tab 1:
// Organisation - Organisation
// Individual - Individual, Contact
// Address, Notes
// Tab 2:
// Customer - System Account, Account
// Tab 3:
// Internal - Config
// Contractor - Postcodes, Trades.
// Tab 4:
// Customer - Commodities
// Tab 5:
// Customer - Seasonal Categories
// Documents
// Interface Items
// Tab 7:
// Update log
//-------------------------------------------------------------------
public class ItemConfigData
{
public bool? ManagedByAccounts { get; set; }
public bool? LocalPricing { get; set; }
// Allowed actions.
public class AllowData
{
public bool? UpdateCode { get; set; }
}
public AllowData Allow { get; } = new AllowData();
// Item fields.
public class FieldData
{
// Show field.
public class ShowData
{
public bool? Owner { get; set; }
public bool? Code { get; set; }
public bool? ExtRef { get; set; }
public bool? Primary { get; set; }
public bool? Technician { get; set; }
public bool? Status { get; set; }
// Financials.
public bool? AnnualSalesTarget { get; set; }
public bool? CreditLimit { get; set; }
public bool? AccountBalance { get; set; }
public bool? DiscountType { get; set; }
public bool? DiscountRate { get; set; }
public bool? PriceSet { get; set; }
// Accounts.
public bool? DefaultNominalCode { get; set; }
// Customer.
public bool? Group { get; set; }
public bool? CommoditySalesDefault { get; set; }
// Customer codes.
public bool? AccountManager { get; set; }
public bool? AccountHandler { get; set; }
public bool? ContactArea { get; set; }
public bool? ContactHandler { get; set; }
}
public ShowData Show { get; } = new ShowData();
// Read-only field.
public class ReadOnlyData
{
}
public ReadOnlyData ReadOnly { get; } = new ReadOnlyData();
// Field label.
public class LabelData
{
// Members.
public String Technician { get; set; }
public String Terminated { get; set; }
}
public LabelData Label { get; } = new LabelData();
}
public FieldData Field { get; } = new FieldData();
}
/// <summary>
/// Populate item configuration for existing association.
/// </summary>
public void PopulateItemConfig(ItemConfigData config, SbmAssociation association, SbmAffiliate affiliateTarget)
{
PopulateItemConfig(config, association.GetItemId(), association.AffiliateIdOwner, association.AssociationType);
}
/// <summary>
/// Populate item configuration for new or existing association.
/// </summary>
public void PopulateItemConfig(ItemConfigData config, ItemId associationItemId, SysId ownerId, Sbm.AssociationType associationType)
{
bool canViewFinancials = SessionData_Portal.SecurityProfile_Core.UserCanViewFinancials();
bool canUpdateFinancials = SessionData_Portal.SecurityProfile_Core.UserCanUpdateFinancials();
bool ownerIsInternal = SessionData_Portal.Organisation.AffiliateId.Equals(ownerId);
bool isCustomer = SbmAssociation.IsCustomer(associationType);
bool isSupplier = SbmAssociation.IsSupplier(associationType);
bool isMember = (associationType == Sbm.AssociationType.Member);
bool isInternal = (associationType == Sbm.AssociationType.Internal);
// Accounts interface.
if (Internals.AccountsDfn.ItemIsImportedFromAccounts(associationItemId))
config.ManagedByAccounts = true;
// Determine pricing options.
if (isCustomer && Internals.AccountsDfn.UseLocalCustomerPricing())
config.LocalPricing = true;
if (isSupplier && Internals.AccountsDfn.UseLocalSupplierPricing())
config.LocalPricing = true;
// Allow actions.
if (SessionData_Portal.GetOwnerOption_AllowOption(Sbm.OrgOption_AllowOption.UpdateAssociationCode))
config.Allow.UpdateCode = true;
// Show fields.
if (ItemId.IsValid(associationItemId) && !ownerIsInternal)
config.Field.Show.Owner = true;
if (!isInternal)
config.Field.Show.Code = true;
if (!isInternal && !isMember)
config.Field.Show.Status = true;
if ((config.Field.Show.Code ?? false) && (isCustomer || isSupplier))
config.Field.Show.ExtRef = true;
if ((config.Field.Show.Code ?? false) && !(config.Field.Show.ExtRef ?? false) && !ownerIsInternal && isMember)
config.Field.Show.Primary = true;
if ((config.Field.Show.Code ?? false) && !(config.Field.Show.ExtRef ?? false) && !(config.Field.Show.Primary ?? false) && ownerIsInternal && isMember)
config.Field.Show.Technician = true;
if (canViewFinancials)
{
config.Field.Show.AnnualSalesTarget = true;
if (config.ManagedByAccounts ?? false)
{
config.Field.Show.CreditLimit = true;
config.Field.Show.AccountBalance = true;
}
if (SessionConsole.AllowOption(isSupplier ? Sbm.ConfigOption.SupplierDiscount : Sbm.ConfigOption.CustomerDiscount))
{
config.Field.Show.DiscountType = true;
config.Field.Show.DiscountRate = true;
}
if (SessionConsole.AllowOption(isSupplier ? Sbm.ConfigOption.SupplierPriceSet : Sbm.ConfigOption.CustomerPriceSet) && PriceMgr.PriceDatabaseIsValid)
config.Field.Show.PriceSet = true;
}
if (config.ManagedByAccounts ?? false)
{
config.Field.Show.DefaultNominalCode = true;
}
if (isCustomer && CommodityMgr.ColumnExists(SbmDbDfn.ColumnIdx.Association_CommodityIdSalesDefault))
config.Field.Show.CommoditySalesDefault = true;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,300 @@
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Controllers;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.BusinessMgr.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
{
//=======================================================================
/// <summary>
/// Association model - Filter and Form.
/// </summary>
public partial class Model_Association : SbmModel_Portal
{
//-------------------------------------------------------------------
// Definitions.
public enum AssociationPageMode
{
Search, Maintain, Relationships, PriceSet,
}
//-------------------------------------------------------------------
// Construction.
public Model_Association(SbmLocaliser localiser) :
base(localiser)
{
}
//-------------------------------------------------------------------
// Properties.
public AssociationPageMode Mode { get; set; } = AssociationPageMode.Maintain;
//-------------------------------------------------------------------
// Filter properties.
public class FilterData
{
public string OwnerId { get; set; }
public string AssociationType { get; set; }
public string Search { get; set; }
}
public FilterData Filter { get; } = new FilterData();
public Sbm.AssociationType GetFilterAssociationType()
{
return (Sbm.AssociationType)Internals.AssociationTypeCodes.GetTypeForCode(Filter.AssociationType);
}
//-------------------------------------------------------------------
// Association properties.
public class AssociationData
{
public string Exists { get; set; }
public string Id { get; set; }
public string AffiliateIdOwner { get; set; }
public string AffiliateIdTarget { get; set; }
public string Type { get; set; }
public string Code { get; set; }
public string ReferenceExt { get; set; }
public string Location { get; set; }
public string Role { get; set; }
public string PhoneMain { get; set; }
public string Email { get; set; }
public string Group { get; set; }
public string DescDetail { get; set; }
public string NominalCodeDefault { get; set; }
// Account.
public string AccountManagerCode { get; set; }
public string AccountHandlerCode { get; set; }
public string AccountTypeCode { get; set; }
public string AccountRatingCode { get; set; }
// Contact.
public string ContactAreaCode { get; set; }
public string ContactHandlerCode { get; set; }
public string ContactMethodCode { get; set; }
public string ContactCallCycleCode { get; set; }
public string CallsPerYear { get; set; }
public string LastCallDate { get; set; }
// Customer.
public string CommodityIdSalesDefault { get; set; }
public string OrderLeadTimeCode { get; set; }
public string DeliveryTypeCode { get; set; }
public string DeliveryMethodCode { get; set; }
public string DeliveryCourierCode { get; set; }
public string DeliveryBookInCode { get; set; }
// Transactions.
public string AmountTransMax { get; set; }
public string AnnualSalesTarget { get; set; }
public string CreditLimit { get; set; }
public string AccountBalance { get; set; }
public string DiscountType { get; set; }
public string DiscountRate { get; set; }
public string PriceSetId { get; set; }
public string TaxCodeId { get; set; }
public string PaymentTerms { get; set; }
public string InvoiceDesc { get; set; }
public string TerminatedDate { get; set; }
// Common properties.
public string Notes { get; set; }
public string StatusCode { get; set; }
}
public AssociationData Association { get; } = new AssociationData();
public Sbm.AssociationType GetAssociationType()
{
return (Sbm.AssociationType)Internals.AssociationTypeCodes.GetTypeForCode(Association.Type);
}
public Sbm.DiscountType GetAssociationDiscountType()
{
return Sbm.DiscountType.NoDiscount;
}
public SaStatus GetAssociationStatus() { return SacsSystem.GetStatusForCode(Association.StatusCode); }
//-------------------------------------------------------------------
// Validation.
//-------------------------------------------------------------------
// Association validation.
public bool ValidateAssociationData(Sacs.Web.Components.SaController.AjaxResponse_Data responseData)
{
//---------------------------------------------------------------
// Association Type.
if (Association.Type != null)
{
String controlName = "AssociationType";
if (StringUtil.IsBlank(Association.Type))
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
}
// Code.
if (Association.Code != null)
{
String controlName = "AssociationCode";
responseData.SetControlValue(controlName, Association.Code);
if (StringUtil.GetLength(Association.Code) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Code))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Code)]);
}
// External Reference.
if (Association.ReferenceExt != null)
{
String controlName = "AssociationReferenceExt";
responseData.SetControlValue(controlName, Association.ReferenceExt);
if (StringUtil.GetLength(Association.ReferenceExt) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_ExtRef))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_ExtRef)]);
}
// Location.
if (Association.Location != null)
{
String controlName = "AssociationLocation";
responseData.SetControlValue(controlName, Association.Location);
if (StringUtil.GetLength(Association.Location) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Location))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Location)]);
}
// Role.
if (Association.Role != null)
{
String controlName = "AssociationRole";
responseData.SetControlValue(controlName, Association.Role);
if (StringUtil.GetLength(Association.Role) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Role))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Role)]);
}
// Phone Main.
if (Association.PhoneMain != null)
{
String controlName = "AssociationPhoneMain";
responseData.SetControlValue(controlName, Association.PhoneMain);
if (StringUtil.GetLength(Association.PhoneMain) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_PhoneMain))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_PhoneMain)]);
}
// Email.
if (Association.Email != null)
{
String controlName = "AssociationEmail";
responseData.SetControlValue(controlName, Association.Email);
if (StringUtil.GetLength(Association.Email) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Email))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Email)]);
}
// Group.
if (Association.Group != null)
{
String controlName = "AssociationGroup";
responseData.SetControlValue(controlName, Association.Group);
if (StringUtil.GetLength(Association.Group) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Group))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Group)]);
}
// Description.
if (Association.DescDetail != null)
{
String controlName = "AssociationDescDetail";
responseData.SetControlValue(controlName, Association.DescDetail);
if (StringUtil.GetLength(Association.DescDetail) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_DescDetail))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_DescDetail)]);
}
// Default Nominal Code.
if (Association.NominalCodeDefault != null)
{
String controlName = "AssociationNominalCodeDefault";
responseData.SetControlValue(controlName, Association.NominalCodeDefault);
if (StringUtil.GetLength(Association.NominalCodeDefault) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_DefaultNominalCode))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_DefaultNominalCode)]);
}
//---------------------------------------------------------------
// Account.
// Account Manager code - AssociationAccountManagerCode
// Account Handler code - AssociationAccountHandlerCode
// Account Type code - AssociationAccountTypeCode
// Account Rating code - AssociationAccountRatingCode
//---------------------------------------------------------------
// Contact.
// Contact Area code - AssociationContactAreaCode
// Contact Handler code - AssociationContactHandlerCode
// Contact Method code - AssociationContactMethodCode
// Contact Call Cycle code - AssociationContactCallCycleCode
// Calls per year - AssociationCallsPerYear
// Last Call date - AssociationLastCallDate
//---------------------------------------------------------------
// Customer.
// AssociationCommodityIdSalesDefault
// AssociationOrderLeadTimeCode
// AssociationDeliveryTypeCode
// AssociationDeliveryMethodCode
// AssociationDeliveryCourierCode
// AssociationDeliveryBookInCode
//---------------------------------------------------------------
// Transactions.
// AssociationAmountTransMax
// AssociationAnnualSalesTarget
// AssociationCreditLimit
// AssociationAccountBalance
// AssociationDiscountType
// AssociationDiscountRate
// AssociationPriceSetId
// AssociationTaxCodeId
// AssociationPaymentTerms
// AssociationInvoiceDesc
// AssociationTerminatedDate
// AssociationAssociation
//---------------------------------------------------------------
// Common properties.
// Notes.
if (Association.Notes != null)
{
String controlName = "AssociationNotes";
responseData.SetControlValue(controlName, Association.Notes);
if (StringUtil.GetLength(Association.Notes) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Notes))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Notes)]);
}
// status.
if (Association.StatusCode != null)
{
String controlName = "AssociationStatusCode";
if (StringUtil.IsBlank(Association.StatusCode))
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
else if (!SbmAssociation.ValidStatuses.Contains(GetAssociationStatus()))
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
}
//---------------------------------------------------------------
return !responseData.HasControlErrors();
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,396 @@
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
{
//=======================================================================
/// <summary>
/// Contact model - Configuration.
/// </summary>
partial class Model_Contact
{
//-------------------------------------------------------------------
/// <summary>Prefix for column names.</summary>
public const String ColumnNamePrefix = "Contact";
/// <summary>Item columns.</summary>
public enum ItemColumn
{
Id,
Type,
Name,
Nature,
Contact,
Email,
Phone,
Address,
Members,
Prospect,
Notes,
}
/// <summary>
/// Identifier used by list columns to show/hide column etc.
/// <para>- Both page and model should use this method to consistently generate the column name.</para>
/// </summary>
public String GetColumnName(ItemField field)
{
return ColumnNamePrefix + field.ToString();
}
// List configuration.
public class ListConfigData
{
// List columns.
public class ColumnData
{
// Column name prefix.
public String Prefix { get; } = Model_Contact.ColumnNamePrefix;
// Hide column.
public HashSet<string> Hide { get; } = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
// Column labels.
public Dictionary<String, String> Label { get; } = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
}
public ColumnData Column { get; } = new ColumnData();
}
public ListConfigData ListConfig { get; private set; }
//-------------------------------------------------------------------
/// <summary>
/// Populate Contact list configuration data in this model - only required on initial page construction.
/// </summary>
public void PopulateListConfig()
{
ListConfig = new ListConfigData();
PopulateListConfig(ListConfig);
}
/// <summary>
/// Populate Contact list configuration data.
/// </summary>
public void PopulateListConfig(ListConfigData config)
{
Sbm.AffiliateType affiliateType = GetContactType();
bool contactGroupsOnly = affiliateType == Sbm.AffiliateType.ContactGroup;
// Contact type.
if (affiliateType <= 0)
config.Column.Label.Add(ItemColumn.Type.ToString(), Localiser["label.type"]);
else
config.Column.Hide.Add(ItemColumn.Type.ToString());
// Contact name.
config.Column.Label.Add(ItemColumn.Name.ToString(), Localiser["label.name"]);
// Nature.
bool showNature = false;
if (!contactGroupsOnly && showNature)
config.Column.Label.Add(ItemColumn.Nature.ToString(), Localiser["label.nature"]);
else
config.Column.Hide.Add(ItemColumn.Nature.ToString());
// Email.
if (!contactGroupsOnly && (affiliateType == Sbm.AffiliateType.Individual || !StringUtil.IsBlank(Filter.Email)))
config.Column.Label.Add(ItemColumn.Email.ToString(), Localiser["label.email"]);
else
config.Column.Hide.Add(ItemColumn.Email.ToString());
// Contact.
if (!contactGroupsOnly && (affiliateType != Sbm.AffiliateType.Individual))
config.Column.Label.Add(ItemColumn.Contact.ToString(), Localiser["label.contact"]);
else
config.Column.Hide.Add(ItemColumn.Contact.ToString());
// Phone.
if (!contactGroupsOnly)
config.Column.Label.Add(ItemColumn.Phone.ToString(), Localiser["label.phone"]);
else
config.Column.Hide.Add(ItemColumn.Phone.ToString());
// Address.
if (!contactGroupsOnly)
config.Column.Label.Add(ItemColumn.Address.ToString(), Localiser["label.address"]);
else
config.Column.Hide.Add(ItemColumn.Address.ToString());
// Group members.
if (contactGroupsOnly)
config.Column.Label.Add(ItemColumn.Members.ToString(), Localiser["label.members"]);
else
config.Column.Hide.Add(ItemColumn.Members.ToString());
// Prospect group.
if (contactGroupsOnly)
config.Column.Label.Add(ItemColumn.Prospect.ToString(), Localiser["label.prospect"]);
else
config.Column.Hide.Add(ItemColumn.Prospect.ToString());
// Contact notes.
config.Column.Label.Add(ItemColumn.Notes.ToString(), Localiser["label.notes"]);
// Contact Id.
if (SbmSystem.DebugMode)
config.Column.Label.Add(ItemColumn.Id.ToString(), Localiser["label.id"]);
else
config.Column.Hide.Add(ItemColumn.Id.ToString());
}
//-------------------------------------------------------------------
// Item configuration.
//-------------------------------------------------------------------
/// <summary>Prefix for field names.</summary>
public const String FieldNamePrefix = "Contact";
/// <summary>Item fields.</summary>
public enum ItemField
{
Id,
Type,
Parent,
Name,
FirstName,
LastName,
Initials,
Title,
Salutation,
Abbreviation,
Nature,
Contact,
Email,
PhoneMain,
PhoneAlt,
PhoneDirect,
PhoneFax,
PhoneMobile,
Website,
CompanyNo,
VatReg,
DateOfBirth,
BirthDay,
BirthMonth,
BirthYear,
MaritalStatus,
Spouse,
Children,
Hometown,
UserId,
Options,
Prospect,
Notes,
Status,
}
/// <summary>
/// Identifier used by form fields to show control specific messages generated by model validation etc.
/// <para>- Both page and model should use this method to consistently generate the field name.</para>
/// </summary>
public String GetFieldName(ItemField field)
{
return FieldNamePrefix + field.ToString();
}
// Legacy Contact dialog tabs and panels.
// - Individual
// - Organisation
// Contact item configuration.
public class ItemConfigData
{
// Item type.
public bool? IsOrganisation { get; set; }
public bool? IsIndividual { get; set; }
public bool? IsGroup { get; set; }
// Item fields.
public class FieldData
{
// Field name prefix.
public String Prefix { get; } = Model_Contact.FieldNamePrefix;
// Hide field.
public HashSet<string> Hide { get; } = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
// Read-only field.
public HashSet<string> ReadOnly { get; } = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
// Field labels.
public Dictionary<String, String> Label { get; } = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
}
public FieldData Field { get; } = new FieldData();
}
/// <summary>
/// Populate item configuration for existing association.
/// </summary>
public void PopulateItemConfig(ItemConfigData config, SbmAffiliate affiliate)
{
PopulateItemConfig(config, affiliate.GetItemId(), affiliate.AffiliateType);
}
/// <summary>
/// Populate item configuration for new or existing association.
/// </summary>
public void PopulateItemConfig(ItemConfigData config, ItemId affiliateItemId, Sbm.AffiliateType affiliateType)
{
// Item type.
bool isIndividual = SbmAffiliate.IsIndividual(affiliateType);
if (isIndividual) config.IsIndividual = true;
bool isOrganisation = SbmAffiliate.IsOrganisation(affiliateType);
if (isOrganisation) config.IsOrganisation = true;
bool isGroup = SbmAffiliate.IsContactGroup(affiliateType);
if (isGroup) config.IsGroup = true;
bool importedFromAccounts = Internals.AccountsDfn.ItemIsImportedFromAccounts(affiliateItemId);
bool showNotes = true;
// Id.
if (SbmSystem.DebugMode)
config.Field.ReadOnly.Add(ItemField.Id.ToString());
else
config.Field.Hide.Add(ItemField.Id.ToString());
// Contact type.
if (!isOrganisation)
config.Field.Hide.Add(ItemField.Type.ToString());
// Organisation name.
if (!isOrganisation && !isGroup)
{
config.Field.Hide.Add(ItemField.Name.ToString());
}
else
{
if (isIndividual)
config.Field.Label.Add(ItemField.Name.ToString(), Localiser["label.phone.home"]);
else
config.Field.Label.Add(ItemField.Name.ToString(), Localiser["label.phone"]);
if (importedFromAccounts)
{
config.Field.ReadOnly.Add(ItemField.Name.ToString());
}
}
// Individual name.
if (!isIndividual)
{
config.Field.Hide.Add(ItemField.FirstName.ToString());
config.Field.Hide.Add(ItemField.LastName.ToString());
config.Field.Hide.Add(ItemField.Initials.ToString());
config.Field.Hide.Add(ItemField.Title.ToString());
config.Field.Hide.Add(ItemField.Salutation.ToString());
}
if (importedFromAccounts)
{
config.Field.ReadOnly.Add(ItemField.FirstName.ToString());
config.Field.ReadOnly.Add(ItemField.LastName.ToString());
config.Field.ReadOnly.Add(ItemField.Initials.ToString());
config.Field.ReadOnly.Add(ItemField.Title.ToString());
config.Field.ReadOnly.Add(ItemField.Salutation.ToString());
}
// Organisation - Abbreviation.
if (!isOrganisation)
config.Field.Hide.Add(ItemField.Abbreviation.ToString());
else if (importedFromAccounts)
config.Field.ReadOnly.Add(ItemField.Abbreviation.ToString());
// Organisation - Nature.
if (!isOrganisation)
config.Field.Hide.Add(ItemField.Nature.ToString());
// Organisation - Contact.
if (!isOrganisation)
config.Field.Hide.Add(ItemField.Contact.ToString());
else if (importedFromAccounts)
config.Field.ReadOnly.Add(ItemField.Contact.ToString());
// Phone numbers.
// NB Main Phone is shared between Organisations and Individuals (home phone).
if (!isOrganisation && !isIndividual)
config.Field.Hide.Add(ItemField.PhoneMain.ToString());
else if (importedFromAccounts)
config.Field.ReadOnly.Add(ItemField.PhoneMain.ToString());
// Organisation - Phone numbers.
if (!isOrganisation)
{
config.Field.Hide.Add(ItemField.PhoneAlt.ToString());
config.Field.Hide.Add(ItemField.PhoneDirect.ToString());
config.Field.Hide.Add(ItemField.PhoneFax.ToString());
}
else if (importedFromAccounts)
{
config.Field.ReadOnly.Add(ItemField.PhoneAlt.ToString());
config.Field.ReadOnly.Add(ItemField.PhoneFax.ToString());
}
// Individual - Phone numbers.
if (!isIndividual)
{
config.Field.Hide.Add(ItemField.PhoneMobile.ToString());
}
else if (importedFromAccounts)
{
config.Field.ReadOnly.Add(ItemField.PhoneMobile.ToString());
}
// Email.
if (!isOrganisation && !isIndividual)
config.Field.Hide.Add(ItemField.Email.ToString());
else
{
if (isOrganisation)
config.Field.Label.Add(ItemField.Email.ToString(), Localiser["label.email.domain"]);
else
config.Field.Label.Add(ItemField.Email.ToString(), Localiser["label.email"]);
if (importedFromAccounts)
config.Field.ReadOnly.Add(ItemField.Email.ToString());
}
// Individual.
if (!isIndividual)
{
config.Field.Hide.Add(ItemField.DateOfBirth.ToString());
config.Field.Hide.Add(ItemField.MaritalStatus.ToString());
config.Field.Hide.Add(ItemField.Spouse.ToString());
config.Field.Hide.Add(ItemField.Children.ToString());
config.Field.Hide.Add(ItemField.Hometown.ToString());
}
// Organisation - Website.
if (!isOrganisation)
config.Field.Hide.Add(ItemField.Website.ToString());
else if (importedFromAccounts)
config.Field.ReadOnly.Add(ItemField.Website.ToString());
// Organisation - Company Number.
if (!isOrganisation)
config.Field.Hide.Add(ItemField.CompanyNo.ToString());
// Organisation - VatReg.
if (!isOrganisation)
config.Field.Hide.Add(ItemField.VatReg.ToString());
else if (importedFromAccounts)
config.Field.ReadOnly.Add(ItemField.VatReg.ToString());
// Prospect.
if (!isGroup)
config.Field.Hide.Add(ItemField.Prospect.ToString());
// Options - hidden if no options shown.
if (config.Field.Hide.ContainsCI(ItemField.Prospect.ToString()))
config.Field.Hide.Add(ItemField.Options.ToString());
// Notes.
if (!showNotes)
config.Field.Hide.Add(ItemField.Notes.ToString());
// Status.
if (importedFromAccounts)
config.Field.ReadOnly.Add(ItemField.Status.ToString());
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,330 @@
using DocumentFormat.OpenXml.EMMA;
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Controllers;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.BusinessMgr.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
{
//=======================================================================
/// <summary>
/// Contact (Affiliate) model - Configuration.
/// </summary>
public partial class Model_Contact : SbmModel_Portal
{
//-------------------------------------------------------------------
// Construction.
public Model_Contact(SbmLocaliser localiser) :
base(localiser)
{
}
//-------------------------------------------------------------------
// Filter properties.
public class FilterData
{
public string ContactType { get; set; }
public string Search { get; set; }
public string Email { get; set; }
}
public FilterData Filter { get; } = new FilterData();
public Sbm.AffiliateType GetFilterContactType()
{
return (Sbm.AffiliateType)Internals.AffiliateTypeCodes.GetTypeForCode(Filter.ContactType);
}
//-------------------------------------------------------------------
// Contact properties.
public class ContactData
{
public string Id { get; set; }
public string Exists { get; set; }
public string Type { get; set; }
public string IsIndividual { get; set; }
public string IsGroup { get; set; }
// Organisation.
public string Name { get; set; }
public string Abbreviation { get; set; }
public string Nature { get; set; }
public string Contact { get; set; }
public string PhoneMain { get; set; }
public string PhoneAlt { get; set; }
public string PhoneDirect { get; set; }
public string PhoneFax { get; set; }
public string Email { get; set; }
public string Website { get; set; }
public string CompanyNo { get; set; }
public string VatReg { get; set; }
// Individual.
public string Title { get; set; }
public string Salutation { get; set; }
public string FirstName { get; set; }
public string Initials { get; set; }
public string LastName { get; set; }
public string PhoneMobile { get; set; }
// Flags.
// NB Have to use bool with checkbox and then cannot tell whether
// false is unchecked or not submitted (ie. excluded from form, disabled etc).
public bool IsProspectSumbitted() { return prospectValue != null; }
private bool? prospectValue { get; set; }
public bool Prospect { get { return prospectValue ?? false; } set { prospectValue = value; } }
// Common properties.
public string Notes { get; set; }
public string StatusCode { get; set; }
}
public SysId GetAffiliateId() { return StringUtil.ToSysId(Contact.Id); }
public SaStatus GetAffiliateStatus() { return SacsSystem.GetStatusForCode(Contact.StatusCode); }
public ContactData Contact { get; } = new ContactData();
public Sbm.AffiliateType GetContactType()
{
if (StringUtil.ToBool(Contact.IsIndividual))
return Sbm.AffiliateType.Individual;
if (StringUtil.ToBool(Contact.IsGroup))
return Sbm.AffiliateType.ContactGroup;
if (Contact.Type != null)
return (Sbm.AffiliateType)Internals.AffiliateTypeCodes.GetTypeForCode(Contact.Type);
return Sbm.AffiliateType.Unknown;
}
//-------------------------------------------------------------------
// Validation.
//-------------------------------------------------------------------
// Affiliate validation.
public bool ValidateAffiliateData(Sacs.Web.Components.SaController.AjaxResponse_Data responseData)
{
// Affiliate Type.
if (Contact.Type != null)
{
String controlName = GetFieldName(ItemField.Type);
if (StringUtil.IsBlank(Contact.Type))
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
}
bool isIndividual = SbmAffiliate.IsIndividual(GetContactType());
bool isContactGroup = SbmAffiliate.IsContactGroup(GetContactType());
bool isOrganisation = !isIndividual && !isContactGroup;
// Organisation Name.
if (Contact.Name != null)
{
String controlName = GetFieldName(ItemField.Name);
responseData.SetControlValue(controlName, Contact.Name);
if (StringUtil.IsBlank(Contact.Name) && isOrganisation)
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
else if (StringUtil.GetLength(Contact.Name) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name)]);
else
{
// Check that the organisation name is unique.
SbmAffiliate.Params prmAffiliate = new SbmAffiliate.Params();
if (SysId.IsValid(GetAffiliateId()) && StringUtil.ToBool(Contact.Exists))
prmAffiliate.IdsExcluded.Add(GetAffiliateId());
prmAffiliate.AffiliateType = Sbm.AffiliateType.AnyOrganisation;
prmAffiliate.Name = Contact.Name;
prmAffiliate.StatusCat = SbmAffiliate.StatusCat.NotDeleted;
if (AccountMgr.GetAffiliateCount(prmAffiliate) > 0)
responseData.SetControlError(controlName, Localiser["msg.validation.duplicate.value"]);
}
}
// Organisation Abbreviation.
if (Contact.Abbreviation != null)
{
String controlName = GetFieldName(ItemField.Abbreviation);
Contact.Abbreviation = Contact.Abbreviation.ToUpper();
responseData.SetControlValue(controlName, Contact.Abbreviation);
if (StringUtil.GetLength(Contact.Abbreviation) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Abbrev))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Abbrev)]);
}
// Organisation Nature.
if (Contact.Nature != null)
{
String controlName = GetFieldName(ItemField.Nature);
responseData.SetControlValue(controlName, Contact.Nature);
if (StringUtil.GetLength(Contact.Nature) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Nature))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Nature)]);
}
// Organisation Contact.
if (Contact.Contact != null)
{
String controlName = GetFieldName(ItemField.Contact);
responseData.SetControlValue(controlName, Contact.Contact);
if (StringUtil.GetLength(Contact.Contact) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Contact))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Contact)]);
}
// Organisation Phone Main.
if (Contact.PhoneMain != null)
{
String controlName = GetFieldName(ItemField.PhoneMain);
responseData.SetControlValue(controlName, Contact.PhoneMain);
if (StringUtil.GetLength(Contact.PhoneMain) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneMain))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneMain)]);
else if (!StringUtil.IsBlank(Contact.PhoneMain) && !SacsDataValidationHelper.IsValidPhone(Contact.PhoneMain))
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneMain)]);
}
// Organisation Phone Alt.
if (Contact.PhoneAlt != null)
{
String controlName = GetFieldName(ItemField.PhoneAlt);
responseData.SetControlValue(controlName, Contact.PhoneAlt);
if (StringUtil.GetLength(Contact.PhoneAlt) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneAlt))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneAlt)]);
else if (!StringUtil.IsBlank(Contact.PhoneAlt) && !SacsDataValidationHelper.IsValidPhone(Contact.PhoneAlt))
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneAlt)]);
}
// Organisation Phone Direct.
if (Contact.PhoneDirect != null)
{
String controlName = GetFieldName(ItemField.PhoneDirect);
responseData.SetControlValue(controlName, Contact.PhoneDirect);
if (StringUtil.GetLength(Contact.PhoneDirect) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneDirect))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneDirect)]);
else if (!StringUtil.IsBlank(Contact.PhoneDirect) && !SacsDataValidationHelper.IsValidPhone(Contact.PhoneDirect))
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneDirect)]);
}
// Organisation Phone Fax.
if (Contact.PhoneFax != null)
{
String controlName = GetFieldName(ItemField.PhoneFax);
responseData.SetControlValue(controlName, Contact.PhoneFax);
if (StringUtil.GetLength(Contact.PhoneFax) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneFax))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneFax)]);
else if (!StringUtil.IsBlank(Contact.PhoneFax) && !SacsDataValidationHelper.IsValidPhone(Contact.PhoneFax))
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneFax)]);
}
// Organisation Email Domain.
if (Contact.Email != null)
{
String controlName = GetFieldName(ItemField.Email);
responseData.SetControlValue(controlName, Contact.Email);
if (StringUtil.GetLength(Contact.Email) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Email))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Email)]);
}
// Organisation Website.
if (Contact.Website != null)
{
String controlName = GetFieldName(ItemField.Website);
responseData.SetControlValue(controlName, Contact.Website);
if (StringUtil.GetLength(Contact.Website) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Website))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Website)]);
}
// Organisation Company No.
if (Contact.CompanyNo != null)
{
String controlName = GetFieldName(ItemField.CompanyNo);
responseData.SetControlValue(controlName, Contact.CompanyNo);
if (StringUtil.GetLength(Contact.CompanyNo) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_CompanyNo))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_CompanyNo)]);
}
// Organisation Vat Reg.
if (Contact.VatReg != null)
{
String controlName = GetFieldName(ItemField.VatReg);
responseData.SetControlValue(controlName, Contact.VatReg);
if (StringUtil.GetLength(Contact.VatReg) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_VatReg))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_VatReg)]);
}
// Individual Title.
if (Contact.Title != null)
{
String controlName = GetFieldName(ItemField.Title);
responseData.SetControlValue(controlName, Contact.Title);
if (StringUtil.GetLength(Contact.Title) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Title))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Title)]);
}
// Individual Salutation.
if (Contact.Salutation != null)
{
String controlName = GetFieldName(ItemField.Salutation);
responseData.SetControlValue(controlName, Contact.Salutation);
if (StringUtil.GetLength(Contact.Salutation) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Salutation))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Salutation)]);
}
// Individual First Name.
if (Contact.FirstName != null)
{
String controlName = GetFieldName(ItemField.FirstName);
responseData.SetControlValue(controlName, Contact.FirstName);
if (StringUtil.GetLength(Contact.FirstName) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_FirstName))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_FirstName)]);
}
// Individual Initials.
if (Contact.Initials != null)
{
String controlName = GetFieldName(ItemField.Initials);
responseData.SetControlValue(controlName, Contact.Initials);
if (StringUtil.GetLength(Contact.Initials) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Initials))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Initials)]);
}
// Individual Last Name.
if (Contact.LastName != null)
{
String controlName = GetFieldName(ItemField.LastName);
responseData.SetControlValue(controlName, Contact.LastName);
if (StringUtil.IsBlank(Contact.LastName) && isIndividual)
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
else if (StringUtil.GetLength(Contact.LastName) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_LastName))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_LastName)]);
}
// Individual Phone Mobile.
if (Contact.PhoneMobile != null)
{
String controlName = GetFieldName(ItemField.PhoneMobile);
responseData.SetControlValue(controlName, Contact.PhoneMobile);
if (StringUtil.GetLength(Contact.PhoneMobile) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneMobile))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneMobile)]);
else if (!StringUtil.IsBlank(Contact.PhoneMobile) && !SacsDataValidationHelper.IsValidPhone(Contact.PhoneMobile))
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneMobile)]);
}
// Contact Notes.
if (Contact.Notes != null)
{
String controlName = GetFieldName(ItemField.Notes);
responseData.SetControlValue(controlName, Contact.Notes);
if (StringUtil.GetLength(Contact.Notes) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Notes))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Notes)]);
}
// Contact status.
if (Contact.StatusCode != null)
{
String controlName = GetFieldName(ItemField.Status);
if (StringUtil.IsBlank(Contact.StatusCode))
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
else if (!SbmAffiliate.ValidStatuses.Contains(GetAffiliateStatus()))
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
}
return !responseData.HasControlErrors();
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -1,272 +0,0 @@
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Controllers;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.BusinessMgr.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Sarand.BusinessMgr.Web.Portal.Models
{
//=======================================================================
public class Model_Association : SbmModel_Portal
{
//-------------------------------------------------------------------
// Construction.
public Model_Association(SbmLocaliser localiser) :
base(localiser)
{
AdditionalFiles_JS.Add("js/sbm-association.js");
}
//-------------------------------------------------------------------
// Filter properties.
public class FilterData
{
public String AssociationSearch { get; set; }
public String AssociationType { get; set; }
}
public FilterData Filter { get; } = new FilterData();
public Sbm.AssociationType GetFilterAssociationType()
{
return (Sbm.AssociationType)Internals.AssociationTypeCodes.GetTypeForCode(Filter.AssociationType);
}
//-------------------------------------------------------------------
// Association properties.
public String AssociationId { get; set; }
public String AssociationExists { get; set; }
public String AffiliateIdOwner { get; set; }
public String AffiliateIdTarget { get; set; }
public String AssociationType { get; set; }
public Sbm.AssociationType GetAssociationType()
{
return (Sbm.AssociationType)Internals.AssociationTypeCodes.GetTypeForCode(AssociationType);
}
public String AssociationCode { get; set; }
public String AssociationReferenceExt { get; set; }
public String AssociationLocation { get; set; }
public String AssociationRole { get; set; }
public String AssociationPhoneMain { get; set; }
public String AssociationEmail { get; set; }
public String AssociationGroup { get; set; }
public String AssociationDescDetail { get; set; }
public String AssociationNominalCodeDefault { get; set; }
// Account.
public String AssociationAccountManagerCode { get; set; }
public String AssociationAccountHandlerCode { get; set; }
public String AssociationAccountTypeCode { get; set; }
public String AssociationAccountRatingCode { get; set; }
// Contact.
public String AssociationContactAreaCode { get; set; }
public String AssociationContactHandlerCode { get; set; }
public String AssociationContactMethodCode { get; set; }
public String AssociationContactCallCycleCode { get; set; }
public String AssociationCallsPerYear { get; set; }
public String AssociationLastCallDate { get; set; }
// Customer.
public String AssociationCommodityIdSalesDefault { get; set; }
public String AssociationOrderLeadTimeCode { get; set; }
public String AssociationDeliveryTypeCode { get; set; }
public String AssociationDeliveryMethodCode { get; set; }
public String AssociationDeliveryCourierCode { get; set; }
public String AssociationDeliveryBookInCode { get; set; }
// Transactions.
public String AssociationAmountTransMax { get; set; }
public String AssociationAnnualSalesTarget { get; set; }
public String AssociationCreditLimit { get; set; }
public String AssociationAccountBalance { get; set; }
public String AssociationDiscountType { get; set; }
public Sbm.DiscountType GetAssociationDiscountType()
{
return Sbm.DiscountType.NoDiscount;
}
public String AssociationDiscountRate { get; set; }
public String AssociationPriceSetId { get; set; }
public String AssociationTaxCodeId { get; set; }
public String AssociationPaymentTerms { get; set; }
public String AssociationInvoiceDesc { get; set; }
public String AssociationTerminatedDate { get; set; }
// Common properties.
public String AssociationNotes { get; set; }
public String AssociationStatusCode { get; set; }
public SaStatus AssociationStatus { get { return SacsSystem.GetStatusForCode(AssociationStatusCode); } }
//-------------------------------------------------------------------
// Validation.
//-------------------------------------------------------------------
// Association validation.
public bool ValidateAssociationData(SbmController_Web.AjaxResponse_Data responseData)
{
//---------------------------------------------------------------
// Association Type.
if (AssociationType != null)
{
if (StringUtil.IsEmpty(AssociationType))
responseData.SetControlError(nameof(AssociationType), Localiser["msg.validation.mandatory.value"]);
}
// Association Code.
if (AssociationCode != null)
{
responseData.SetControlValue(nameof(AssociationCode), AssociationCode);
if (StringUtil.IsEmpty(AssociationCode))
responseData.SetControlError(nameof(AssociationCode), Localiser["msg.validation.mandatory.value"]);
if (StringUtil.GetLength(AssociationCode) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Code))
responseData.SetControlError(nameof(AssociationCode), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Code)]);
}
// Association External Reference.
if (AssociationReferenceExt != null)
{
responseData.SetControlValue(nameof(AssociationReferenceExt), AssociationReferenceExt);
if (StringUtil.GetLength(AssociationReferenceExt) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_ExtRef))
responseData.SetControlError(nameof(AssociationReferenceExt), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_ExtRef)]);
}
// Association Location.
if (AssociationLocation != null)
{
responseData.SetControlValue(nameof(AssociationLocation), AssociationLocation);
if (StringUtil.GetLength(AssociationLocation) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Location))
responseData.SetControlError(nameof(AssociationLocation), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Location)]);
}
// Association Role.
if (AssociationRole != null)
{
responseData.SetControlValue(nameof(AssociationRole), AssociationRole);
if (StringUtil.GetLength(AssociationRole) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Role))
responseData.SetControlError(nameof(AssociationRole), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Role)]);
}
// Association Phone Main.
if (AssociationPhoneMain != null)
{
responseData.SetControlValue(nameof(AssociationPhoneMain), AssociationPhoneMain);
if (StringUtil.GetLength(AssociationPhoneMain) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_PhoneMain))
responseData.SetControlError(nameof(AssociationPhoneMain), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_PhoneMain)]);
}
// Association Email.
if (AssociationEmail != null)
{
responseData.SetControlValue(nameof(AssociationEmail), AssociationEmail);
if (StringUtil.GetLength(AssociationEmail) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Email))
responseData.SetControlError(nameof(AssociationEmail), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Email)]);
}
// Association Group.
if (AssociationGroup != null)
{
responseData.SetControlValue(nameof(AssociationGroup), AssociationGroup);
if (StringUtil.GetLength(AssociationGroup) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Group))
responseData.SetControlError(nameof(AssociationGroup), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Group)]);
}
// Association Description.
if (AssociationDescDetail != null)
{
responseData.SetControlValue(nameof(AssociationDescDetail), AssociationDescDetail);
if (StringUtil.IsEmpty(AssociationDescDetail))
responseData.SetControlError(nameof(AssociationDescDetail), Localiser["msg.validation.mandatory.value"]);
if (StringUtil.GetLength(AssociationDescDetail) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_DescDetail))
responseData.SetControlError(nameof(AssociationDescDetail), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_DescDetail)]);
}
// Association Default Nominal Code.
if (AssociationNominalCodeDefault != null)
{
responseData.SetControlValue(nameof(AssociationNominalCodeDefault), AssociationNominalCodeDefault);
if (StringUtil.GetLength(AssociationNominalCodeDefault) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_DefaultNominalCode))
responseData.SetControlError(nameof(AssociationNominalCodeDefault), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_DefaultNominalCode)]);
}
//---------------------------------------------------------------
// Account.
// Account Manager code - AssociationAccountManagerCode
// Account Handler code - AssociationAccountHandlerCode
// Account Type code - AssociationAccountTypeCode
// Account Rating code - AssociationAccountRatingCode
//---------------------------------------------------------------
// Contact.
// Contact Area code - AssociationContactAreaCode
// Contact Handler code - AssociationContactHandlerCode
// Contact Method code - AssociationContactMethodCode
// Contact Call Cycle code - AssociationContactCallCycleCode
// Calls per year - AssociationCallsPerYear
// Last Call date - AssociationLastCallDate
//---------------------------------------------------------------
// Customer.
// AssociationCommodityIdSalesDefault
// AssociationOrderLeadTimeCode
// AssociationDeliveryTypeCode
// AssociationDeliveryMethodCode
// AssociationDeliveryCourierCode
// AssociationDeliveryBookInCode
//---------------------------------------------------------------
// Transactions.
// AssociationAmountTransMax
// AssociationAnnualSalesTarget
// AssociationCreditLimit
// AssociationAccountBalance
// AssociationDiscountType
// AssociationDiscountRate
// AssociationPriceSetId
// AssociationTaxCodeId
// AssociationPaymentTerms
// AssociationInvoiceDesc
// AssociationTerminatedDate
// AssociationAssociation
//---------------------------------------------------------------
// Common properties.
// Association Notes.
if (AssociationNotes != null)
{
responseData.SetControlValue(nameof(AssociationNotes), AssociationNotes);
if (!StringUtil.IsEmpty(AssociationNotes) && StringUtil.GetLength(AssociationNotes) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Notes))
responseData.SetControlError(nameof(AssociationNotes), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Notes)]);
}
// Association status.
if (AssociationStatusCode != null)
{
if (StringUtil.IsEmpty(AssociationStatusCode))
responseData.SetControlError(nameof(AssociationStatusCode), Localiser["msg.validation.mandatory.value"]);
else if (!SbmAssociation.ValidStatuses.Contains(AssociationStatus))
responseData.SetControlError(nameof(AssociationStatusCode), Localiser["msg.validation.invalid.value"]);
}
//---------------------------------------------------------------
return !responseData.HasControlErrors();
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -1,132 +0,0 @@
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Controllers;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.BusinessMgr.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Sarand.BusinessMgr.Web.Portal.Models
{
//=======================================================================
public class Model_Contact : SbmModel_Portal
{
//-------------------------------------------------------------------
// Construction.
public Model_Contact(SbmLocaliser localiser) :
base(localiser)
{
AdditionalFiles_JS.Add("js/sbm-contact.js");
}
//-------------------------------------------------------------------
// Filter properties.
public class FilterData
{
public String ContactSearch { get; set; }
public String ContactType { get; set; }
}
public FilterData Filter { get; } = new FilterData();
public Sbm.AffiliateType GetFilterContactType()
{
return (Sbm.AffiliateType)Internals.AffiliateTypeCodes.GetTypeForCode(Filter.ContactType);
}
//-------------------------------------------------------------------
// Contact properties.
public String AffiliateId { get; set; }
public String ContactExists { get; set; }
public String ContactType { get; set; }
public String ContactIndividual { get; set; }
public Sbm.AffiliateType GetContactType()
{
if (ContactType != null)
return (Sbm.AffiliateType)Internals.AffiliateTypeCodes.GetTypeForCode(ContactType);
if (StringUtil.ToBool(ContactIndividual))
return Sbm.AffiliateType.Individual;
return Sbm.AffiliateType.Unknown;
}
// Organisation.
public String ContactName { get; set; }
// Individual.
public String ContactFirstName { get; set; }
public String ContactLastName { get; set; }
// Common properties.
public String ContactNotes { get; set; }
public String ContactStatusCode { get; set; }
public SaStatus ContactStatus { get { return SacsSystem.GetStatusForCode(ContactStatusCode); } }
//-------------------------------------------------------------------
// Validation.
//-------------------------------------------------------------------
// Affiliate validation.
public bool ValidateAffiliateData(SbmController_Web.AjaxResponse_Data responseData)
{
// Affiliate Type.
if (ContactType != null)
{
if (StringUtil.IsEmpty(ContactType))
responseData.SetControlError(nameof(ContactType), Localiser["msg.validation.mandatory.value"]);
}
bool individual = GetContactType() == Sbm.AffiliateType.Individual;
// Organisation Name.
if (ContactName != null)
{
responseData.SetControlValue(nameof(ContactName), ContactName);
if (StringUtil.IsEmpty(ContactName) && !individual)
responseData.SetControlError(nameof(ContactName), Localiser["msg.validation.mandatory.value"]);
if (StringUtil.GetLength(ContactName) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name))
responseData.SetControlError(nameof(ContactName), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name)]);
}
// Individual First Name.
if (ContactFirstName != null)
{
responseData.SetControlValue(nameof(ContactFirstName), ContactFirstName);
if (StringUtil.IsEmpty(ContactFirstName) && individual)
responseData.SetControlError(nameof(ContactFirstName), Localiser["msg.validation.mandatory.value"]);
if (StringUtil.GetLength(ContactFirstName) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_FirstName))
responseData.SetControlError(nameof(ContactFirstName), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_FirstName)]);
}
// Individual Last Name.
if (ContactLastName != null)
{
responseData.SetControlValue(nameof(ContactLastName), ContactLastName);
if (StringUtil.IsEmpty(ContactLastName) && individual)
responseData.SetControlError(nameof(ContactLastName), Localiser["msg.validation.mandatory.value"]);
if (StringUtil.GetLength(ContactLastName) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_LastName))
responseData.SetControlError(nameof(ContactLastName), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_LastName)]);
}
// Affiliate Notes.
if (ContactNotes != null)
{
responseData.SetControlValue(nameof(ContactNotes), ContactNotes);
if (!StringUtil.IsEmpty(ContactNotes) && StringUtil.GetLength(ContactNotes) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Notes))
responseData.SetControlError(nameof(ContactNotes), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Notes)]);
}
// Affiliate status.
if (ContactStatusCode != null)
{
if (StringUtil.IsEmpty(ContactStatusCode))
responseData.SetControlError(nameof(ContactStatusCode), Localiser["msg.validation.mandatory.value"]);
else if (!SbmAffiliate.ValidStatuses.Contains(ContactStatus))
responseData.SetControlError(nameof(ContactStatusCode), Localiser["msg.validation.invalid.value"]);
}
return !responseData.HasControlErrors();
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -13,8 +13,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="jQuery.UI.Combined" Version="1.13.2" />
<PackageReference Include="jQuery" Version="3.5.1" />
<PackageReference Include="jQuery.UI.Combined" Version="1.13.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.31" />
<PackageReference Include="System.Data.Odbc" Version="6.0.2" />
</ItemGroup>
<ItemGroup>
@@ -41,11 +43,9 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Portal\Controllers\Vehicles\" />
<Folder Include="Views\Assets\Asset\" />
<Folder Include="Views\Assets\Vehicle\" />
<Folder Include="Views\Vehicles\" />
<Folder Include="Views\Transactions\" />
<Folder Include="Views\Transaction\" />
</ItemGroup>
<ItemGroup>
@@ -6,7 +6,7 @@
Model.AdditionalFiles_JS.Add("js/sbm-asset.js");
}
<div class="sbm-panel Assets">
<div class="sbm-panel Assets fullheight">
<script type="text/javascript">
sbm.dlg.title.createItem = '@(Localiser.GetJavascriptText("caption.asset.create"))';
@@ -14,7 +14,7 @@
sbm.lbl.selectCategory = '@(Localiser.GetJavascriptText("caption.category.select"))';
</script>
<div class="sbm-panel-data">
<div class="sbm-panel-data sbm-flex">
@* Filter form - wrap header to include paging controls. *@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAssetFilter", @class = "sbm-form", @onSubmit = "return false;" }))
@@ -50,7 +50,7 @@
}
<div class="sbm-panel-item-table">
<div class="sbm-panel-item-table sbm-flex">
<table class="sbm-item-list">
<thead>
<tr>
@@ -6,19 +6,20 @@
Model.AdditionalFiles_JS.Add("js/sbm-asset-cat.js");
}
<div class="sbm-panel AssetCategories">
<div class="sbm-panel AssetCategories fullheight">
<script type="text/javascript">
sbm.dlg.title.createItem = '@(Localiser.GetJavascriptText("caption.asset.category.create"))';
sbm.dlg.title.updateItem = '@(Localiser.GetJavascriptText("caption.asset.category.update"))';
</script>
<div class="sbm-panel-data">
<div class="sbm-panel-data sbm-flex">
@* Filter form - wrap header to include paging controls. *@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAssetCategoryFilter", @class = "sbm-form", @onSubmit = "return false;" }))
{
@* Header - Page caption, paging controls, actions. *@
<div class="sbm-panel-header">
<div class="row">
<div class="fixed">
@@ -49,7 +50,8 @@
}
<div class="sbm-panel-item-table">
@* Item list *@
<div class="sbm-panel-item-table sbm-flex">
<table class="sbm-item-list">
<thead>
<tr>
@@ -67,10 +69,12 @@
@* Element templates *@
<div class="sbm-panel-item-template">
@* Filter Burger option template - ul is ignored *@
<ul class="sbm-dropdown-menu AssetCategoryFilter">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
@* AssetCategory row template - table is ignored. *@
<table class="">
<tr class="sbm-row-item AssetCategory">
@@ -91,10 +95,12 @@
</td>
</tr>
</table>
@* Item Burger option template - ul is ignored *@
<ul class="sbm-dropdown-menu AssetCategory">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
</div>
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAssetCategoryId", @onSubmit = "return false;" }))
@@ -6,14 +6,14 @@
Model.AdditionalFiles_JS.Add("js/sbm-veh-cls.js");
}
<div class="sbm-panel VehicleClasses">
<div class="sbm-panel VehicleClasses fullheight">
<script type="text/javascript">
sbm.dlg.title.createItem = '@(Localiser.GetJavascriptText("caption.vehicle.class.create"))';
sbm.dlg.title.updateItem = '@(Localiser.GetJavascriptText("caption.vehicle.class.update"))';
</script>
<div class="sbm-panel-data">
<div class="sbm-panel-data sbm-flex">
@* Filter form - wrap header to include paging controls. *@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmVehicleClassFilter", @class = "sbm-form", @onSubmit = "return false;" }))
@@ -49,7 +49,7 @@
}
<div class="sbm-panel-item-table">
<div class="sbm-panel-item-table sbm-flex">
<table class="sbm-item-list">
<thead>
<tr>
@@ -3,130 +3,118 @@
@{
/* Associations - Index */
ViewData["Title"] = "Associations";
Model.AdditionalFiles_JS.Add("js/sbm-assoc.js");
}
<div class="sbm-panel Associations">
<div class="sbm-panel Associations fullheight">
<script type="text/javascript">
</script>
<div class="row">
<div class="col-md-5 row">
<div class="col">
@* Filter Panel *@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAssociationFilter", @class = "sbm-form", @onSubmit = "return false;" }))
{
<div class="sbm-panel-filter">
@* Header - Page caption, paging controls, actions. *@
<div class="sbm-header">
<div class="row">
<div class="col"><div class="sbm-caption">@Localiser["association.caption.associations"]</div></div>
<div class="fixed row">
<div class="col">
<partial name="~/Views/Common/ResultsPaging.cshtml" />
</div>
<div class="fixed row">
@* Burger menu *@
<ul class="nav navbar-nav navbar-dark navbar-right sbm-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sbm-content">
@* Association filter - name etc. *@
<div class="row pb4">
<div class="col-sm-5 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
<div class="col-sm-7">
@Html.TextBoxFor(model => model.Filter.AssociationSearch, new { @id = "", @class = "FilterAssociation", @maxlength = "32" })
</div>
</div>
@* Association Category *@
<div class="row pb4">
<div class="col-sm-5 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
<div class="col-sm-7">
@Html.DropDownListFor(model => model.Filter.AssociationType, Model.GetAssociationTypeCodesForSelect(), Localiser["label.any"], new { @id = "", @class = "FilterAssociationType sbm-select" })
</div>
</div>
</div>
@* Filter element templates *@
<div class="sbm-panel-item-template">
@* Burger dropdown item template - ul is ignored *@
<ul class="sbm-dropdown-menu AssociationFilter">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
</div>
<div class="sbm-panel-data sbm-flex">
@* Filter form - wrap header to include paging controls. *@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAssociationFilter", @class = "sbm-form", @onSubmit = "return false;" }))
{
@* Header - Page caption, paging controls, actions. *@
<div class="sbm-panel-header">
<div class="row">
<div class="col">
<partial name="~/Views/Common/ResultsPaging.cshtml" />
</div>
}
</div>
@* Separate filter from results when alondside each other. *@
<div class="fixed"><div class="d-none d-md-block" style="width:8px;"></div></div>
</div>
<div class="col-md-7">
@* Results Panel *@
<div class="sbm-panel-results">
<div class="sbm-panel-messages"></div>
<div class="sbm-panel-item-list"></div>
@* Element templates *@
<div class="sbm-panel-item-template">
@* Association item template *@
<div class="sbm-panel-item Association">
<div class="sbm-header row">
<div class="col">
@* Association caption *@
<div class="sbm-caption"><div class="sbm-action sbm-item-update"><span class="AssociationCode"></span> - <span class="AssociationTargetName"></span></div></div>
</div>
<div class="fixed sbm-actions">
@* Burger menu *@
<ul class="nav navbar-nav navbar-light navbar-right sbm-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div>
</div>
<div class="sbm-content">
<div class="row">
<div class="col-sm-4"><div class="AssociationType"></div></div>
<div class="col-sm-4"><div class="AssociationAssociationCount sbm-action-text">@Localiser["label.associations"]:&nbsp;<span class="AssociationCount"></span></div></div>
<div class="col-sm-4 text-left text-sm-right"><div class="StatusDesc"></div></div>
</div>
<div class="row">
<div class=""><div class="AssociationAddress"></div></div>
</div>
<div class="row">
<div class=""><div class="AssociationNotes sbm-note"></div></div>
</div>
</div>
<div class="fixed center"><div class="sbm-panel-caption">@Localiser["label.associations"]</div></div>
<div class="col right">
@* Burger menu *@
<ul class="nav navbar-nav navbar-dark navbar-right sbm-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div>
@* Burger dropdown item template - ul is ignored *@
<ul class="sbm-dropdown-menu Association">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
</div>
</div>
@* Filter Panel *@
<div class="sbm-panel-filter">
<div class="row pb4">
<div class="col-sm-4 row pb4">
@* Association filter - name etc. *@
<div class="col-4 col-sm-5 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
<div class="col-7 col-sm-7">
@Html.TextBoxFor(model => model.Filter.Search, new { @id = "", @class = "FilterSearch sbm-input", @maxlength = "32" })
</div>
</div>
<div class="col-sm-4 row pb4">
@* Association Category *@
<div class="col-4 col-sm-5 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
<div class="col-7 col-sm-7">
@Html.DropDownListFor(model => model.Filter.AssociationType, Model.GetAssociationTypeCodesForSelect(), Localiser["label.any"], new { @id = "", @class = "FilterAssociationType sbm-select" })
</div>
</div>
</div>
<div class="col-sm-4 row pb4">
</div>
</div>
}
@* Item list *@
<div class="sbm-panel-item-table sbm-flex">
<table class="sbm-item-list">
<thead>
<tr>
<th class="pl-2">@Localiser["label.type"]</th>
<th class="">@Localiser["label.code"]</th>
<th class="">@Localiser["label.name"]</th>
<th class="d-none d-md-table-cell">@Localiser["label.address"]</th>
<th class="d-none d-md-table-cell">@Localiser["label.notes"]</th>
<th class="center">@Localiser["label.status"]</th>
<th class="right" style="width:2%;"></th>
</tr>
<tr><td colspan="6"><div class="sbm-panel-messages"></div></td></tr>
</thead>
<tbody></tbody>
</table>
</div>
@* Element templates *@
<div class="sbm-panel-item-template">
@* Burger dropdown item template - ul is ignored *@
<ul class="sbm-dropdown-menu AssociationList">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
@* Association row template - table is ignored. *@
<table>
<tr class="sbm-row-item Association">
<td><div class="AssociationType pl-1"></div></td>
<td><div class="AssociationCode"></div></td>
<td><div class="AssociationTargetName"></div></td>
<td class="d-none d-md-table-cell"><div class="AssociationAddress"></div></td>
<td class="d-none d-md-table-cell"><div class="AssociationNotes"></div></td>
<td><div class="AssociationStatusDesc center"></div></td>
<td>
<div class="right">
@* Burger menu *@
<ul class="nav navbar-nav navbar-light navbar-right sbm-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span></a>
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div>
</td>
</tr>
</table>
@* Burger dropdown item template - ul is ignored *@
<ul class="sbm-dropdown-menu Association">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
</div>
</div>
</div>
<partial name="Panel-AssociationDialog.cshtml" />
@@ -5,75 +5,111 @@
}
<script type="text/javascript">
sbm.dlg.title.createAssociation = '@Localiser.GetJavascriptText("association.caption.association.create")';
sbm.dlg.title.updateAssociation = '@Localiser.GetJavascriptText("association.caption.association.update")';
sbm.dlg.title.createAssociation = '@Localiser.GetJavascriptText("caption.association.create")';
sbm.dlg.title.updateAssociation = '@Localiser.GetJavascriptText("caption.association.update")';
</script>
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAssociationId", @class = "sbm-form" }))
{
@Html.HiddenFor(model => model.AssociationId, new { @class = "AssociationId" })
@Html.HiddenFor(model => model.Association.Id, new { @class = "AssociationId" })
}
<div id="dlgAssociation" class="sbm-dialog" title="">
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAssociation", @class = "sbm-form", @onSubmit = "return false;" }))
{
@Html.HiddenFor(model => model.AssociationId, new { @id = "", @class = "AssociationId" })
@Html.HiddenFor(model => model.AssociationExists, new { @id = "", @class = "AssociationExists" });
@Html.HiddenFor(model => model.Association.Id, new { @id = "", @class = "AssociationId sbm-input" })
@Html.HiddenFor(model => model.Association.Exists, new { @id = "", @class = "AssociationExists sbm-input" })
@* Association Type *@
<div class="sbm-form-control AssociationType">
<div class="sbm-label">
<label for="cbAssociationType"><span>@Localiser["label.type"]</span><span class="required">&nbsp;*</span></label>
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="cbAssociationType"><span>@Localiser["label.type"]</span><span class="required">&nbsp;*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.DropDownListFor(model => model.Association.Type, Model.GetAssociationTypeCodesForSelect(), Localiser["label.select"], new { @id = "cbAssociationType", @class = "AssociationType sbm-select" })
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="sbm-control">
@Html.DropDownListFor(model => model.AssociationType, Model.GetAssociationTypeCodesForSelect(), Localiser["label.select"], new { @id = "cbAssociationType", @class = "AssociationType sbm-select" })
</div>
@* Target contact *@
<div class="sbm-form-control AssociationTarget">
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="ifAssociationTarget"><span>@Localiser["label.target"]</span><span class="required">&nbsp;*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbc-control row">
<div class="col">
@Html.HiddenFor(model => model.Association.AffiliateIdTarget, new { @id = "", @class = "AssociationId sbm-input" })
<input type="text" id="ifAssociationTarget" class="AssociationTarget sbm-input" readonly="readonly" />
</div>
<div class="fixed">
<div class="sbc-action AssetTargetSearch"><img src="~/img/action/search24.png" alt="" title="" /></div>
</div>
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="sbm-message"></div>
</div>
@* Association Code *@
<div class="sbm-form-control AssociationCode">
<div class="sbm-label">
<label for="ifAssociationCode"><span>@Localiser["label.code"]</span><span class="required">&nbsp;*</span></label>
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="ifAssociationCode"><span>@Localiser["label.code"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Association.Code, new { @id = "ifAssociationCode", @class = "AssociationCode sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Code) })
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="sbm-control">
@Html.TextBoxFor(model => model.AssociationCode, new { @id = "ifAssociationCode", @class = "AssociationCode sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Code) })
</div>
<div class="sbm-message"></div>
</div>
@* Association Description *@
<div class="sbm-form-control AssociationDesc">
<div class="sbm-label">
<label for="ifAssociationDescDetail"><span>@Localiser["label.description"]</span><span class="required">&nbsp;*</span></label>
</div>
<div class="sbm-control">
@Html.TextBoxFor(model => model.AssociationDescDetail, new { @id = "ifAssociationDescDetail", @class = "AssociationDescDetail sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_DescDetail) })
</div>
<div class="sbm-message"></div>
</div>
@* Association status *@
<div class="sbm-form-control AssociationStatus">
<div class="sbm-label">
<label for="cbAssociationStatus"><span>@Localiser["label.status"]</span><span class="required">&nbsp;*</span></label>
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="cbAssociationStatus"><span>@Localiser["label.status"]</span><span class="required">&nbsp;*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
<select id="cbAssociationStatus" class="sbm-select AssociationStatus" name="Association.StatusCode"></select>
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="sbm-control">
<select id="cbAssociationStatus" class="sbm-select AssociationStatus" name="AssociationStatusCode"></select>
</div>
<div class="sbm-message"></div>
</div>
@* Association Notes *@
<div class="sbm-form-control AssociationNotes">
<div class="sbm-label">
<label for="ifAssociationNotes"><span>@Localiser["label.notes"]</span></label>
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="ifAssociationNotes"><span>@Localiser["label.notes"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextAreaFor(model => model.Association.Notes, new { @id = "ifAssociationNotes", @class = "AssociationNotes sbm-textarea", @rows = "3", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Notes) })
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="sbm-control">
@Html.TextAreaFor(model => model.AssociationNotes, new { @id = "ifAssociationNotes", @class = "AssociationNotes sbm-textarea", @rows = "3", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Notes) })
</div>
<div class="sbm-message"></div>
</div>
}
@@ -3,130 +3,119 @@
@{
/* Commodities - Index */
ViewData["Title"] = "Commodities";
Model.AdditionalFiles_JS.Add("js/sbm-commodity.js");
}
<div class="sbm-panel Commodities">
<div class="sbm-panel Commodities fullheight">
<script type="text/javascript">
</script>
<div class="row">
<div class="col-md-5 row">
<div class="col">
@* Filter Panel *@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCommodityFilter", @class = "sbm-form", @onSubmit = "return false;" }))
{
<div class="sbm-panel-filter">
@* Header - Page caption, paging controls, actions. *@
<div class="sbm-header">
<div class="row">
<div class="col"><div class="sbm-caption">@Localiser["commodity.caption.commodities"]</div></div>
<div class="fixed row">
<div class="col">
<partial name="~/Views/Common/ResultsPaging.cshtml" />
</div>
<div class="fixed row">
@* Burger menu *@
<ul class="nav navbar-nav navbar-dark navbar-right sbm-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sbm-content">
@* Commodity filter - name etc. *@
<div class="row pb4">
<div class="col-sm-5 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
<div class="col-sm-7">
@Html.TextBoxFor(model => model.Filter.CommoditySearch, new { @id = "", @class = "FilterCommodity", @maxlength = "32" })
</div>
</div>
@* Commodity Category *@
<div class="row pb4">
<div class="col-sm-5 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
<div class="col-sm-7">
@Html.DropDownListFor(model => model.Filter.CommodityType, Model.GetCommodityTypeCodesForSelect(), Localiser["label.any"], new { @id = "", @class = "FilterCommodityType sbm-select" })
</div>
</div>
</div>
@* Filter element templates *@
<div class="sbm-panel-item-template">
@* Burger dropdown item template - ul is ignored *@
<ul class="sbm-dropdown-menu CommodityFilter">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
</div>
<div class="sbm-panel-data sbm-flex">
@* Filter form - wrap header to include paging controls. *@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCommodityFilter", @class = "sbm-form", @onSubmit = "return false;" }))
{
@* Header - Page caption, paging controls, actions. *@
<div class="sbm-panel-header">
<div class="row">
<div class="col"><partial name="~/Views/Common/ResultsPaging.cshtml" /></div>
<div class="fixed center"><div class="sbm-panel-caption">@Localiser["caption.commodities"]</div></div>
<div class="col right">
@* Burger menu *@
<ul class="nav navbar-nav navbar-dark navbar-right sbm-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div>
}
</div>
@* Separate filter from results when alondside each other. *@
<div class="fixed"><div class="d-none d-md-block" style="width:8px;"></div></div>
</div>
<div class="col-md-7">
@* Results Panel *@
<div class="sbm-panel-results">
<div class="sbm-panel-messages"></div>
<div class="sbm-panel-item-list"></div>
@* Element templates *@
<div class="sbm-panel-item-template">
@* Commodity item template *@
<div class="sbm-panel-item Commodity">
<div class="sbm-header row">
<div class="col">
@* Commodity caption *@
<div class="sbm-caption"><div class="sbm-action sbm-item-update"><span class="CommodityCode"></span> - <span class="CommodityDesc"></span></div></div>
</div>
<div class="fixed sbm-actions">
@* Burger menu *@
<ul class="nav navbar-nav navbar-light navbar-right sbm-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div>
</div>
<div class="sbm-content">
<div class="row">
<div class="col-sm-4"><div class="CommodityType"></div></div>
<div class="col-sm-4"><div class="CommodityAssociationCount sbm-action-text">@Localiser["label.associations"]:&nbsp;<span class="AssociationCount"></span></div></div>
<div class="col-sm-4 text-left text-sm-right"><div class="StatusDesc"></div></div>
</div>
<div class="row">
<div class=""><div class="CommodityAddress"></div></div>
</div>
<div class="row">
<div class=""><div class="CommodityNotes sbm-note"></div></div>
</div>
</div>
</div>
@* Burger dropdown item template - ul is ignored *@
<ul class="sbm-dropdown-menu Commodity">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
</div>
</div>
@* Filter Panel *@
<div class="sbm-panel-filter">
<div class="row">
<div class="col-sm-4 row pb4">
@* Commodity filter - code, description etc *@
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
<div class="col-7 col-sm-8">
@Html.TextBoxFor(model => model.Filter.Search, new { @id = "", @class = "FilterCommodity sbm-input", @maxlength = "32" })
</div>
</div>
<div class="col-sm-4 row pb4">
@* Commodity Category *@
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
<div class="col-7 col-sm-8">
@Html.DropDownListFor(model => model.Filter.CommodityType, Model.GetCommodityTypeCodesForSelect(), Localiser["label.any"], new { @id = "", @class = "FilterCommodityType sbm-select" })
</div>
</div>
<div class="col-sm-4 row pb4">
</div>
</div>
</div>
}
@* Item list *@
<div class="sbm-panel-item-table sbm-flex">
<table class="sbm-item-list">
<thead>
<tr>
<th class="pl-2">@Localiser["label.code"]</th>
<th class="">@Localiser["label.description"]</th>
<th class="">@Localiser["label.type"]</th>
<th class="right">@Localiser["label.sales.price"]</th>
<th class="center">@Localiser["label.unit.of.sale"]</th>
<th class="d-none d-md-table-cell">@Localiser["label.notes"]</th>
<th class="center">@Localiser["label.status"]</th>
<th class="right" style="width:2%;"></th>
</tr>
<tr><td colspan="6"><div class="sbm-panel-messages"></div></td></tr>
</thead>
<tbody></tbody>
</table>
</div>
@* Element templates *@
<div class="sbm-panel-item-template">
@* List burger dropdown template - ul is ignored *@
<ul class="sbm-dropdown-menu CommodityList">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
@* Item row template - table is ignored. *@
<table>
<tr class="sbm-row-item Commodity">
<td><div class="CommodityCode pl-1"></div></td>
<td><div class="CommodityDesc"></div></td>
<td><div class="CommodityType"></div></td>
<td class="right"><div class="CommoditySalesPrice"></div></td>
<td class="center"><div class="CommoditySalesUnits"></div></td>
<td class="d-none d-md-table-cell"><div class="CommodityNotes"></div></td>
<td><div class="CommodityStatusDesc center"></div></td>
<td>
<div class="right">
@* Burger menu *@
<ul class="nav navbar-nav navbar-light navbar-right sbm-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span></a>
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div>
</td>
</tr>
</table>
@* Item burger dropdown template - ul is ignored *@
<ul class="sbm-dropdown-menu Commodity">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
</div>
</div>
</div>
<partial name="Panel-CommodityDialog.cshtml" />
@@ -5,75 +5,106 @@
}
<script type="text/javascript">
sbm.dlg.title.createCommodity = '@Localiser.GetJavascriptText("commodity.caption.commodity.create")';
sbm.dlg.title.updateCommodity = '@Localiser.GetJavascriptText("commodity.caption.commodity.update")';
sbm.dlg.title.createCommodity = '@Localiser.GetJavascriptText("caption.commodity.create")';
sbm.dlg.title.updateCommodity = '@Localiser.GetJavascriptText("caption.commodity.update")';
</script>
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCommodityId", @class = "sbm-form" }))
{
@Html.HiddenFor(model => model.CommodityId, new { @class = "CommodityId" })
@Html.HiddenFor(model => model.Commodity.Id, new { @class = "CommodityId" })
}
<div id="dlgCommodity" class="sbm-dialog" title="">
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCommodity", @class = "sbm-form", @onSubmit = "return false;" }))
{
@Html.HiddenFor(model => model.CommodityId, new { @id = "", @class = "CommodityId" })
@Html.HiddenFor(model => model.CommodityExists, new { @id = "", @class = "CommodityExists" });
@Html.HiddenFor(model => model.Commodity.Id, new { @id = "", @class = "CommodityId sbm-input" })
@Html.HiddenFor(model => model.Commodity.Exists, new { @id = "", @class = "CommodityExists sbm-input" })
@Html.HiddenFor(model => model.Commodity.SupersededStatusConfirmed, new { @id = "", @class = "SupersededStatusConfirmed sbm-input" })
@* Commodity Type *@
<div class="sbm-form-control CommodityType">
<div class="sbm-label">
<label for="cbCommodityType"><span>@Localiser["label.type"]</span><span class="required">&nbsp;*</span></label>
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="cbCommodityType"><span>@Localiser["label.type"]</span><span class="required">&nbsp;*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.DropDownListFor(model => model.Commodity.Type, Model.GetCommodityTypeCodesForSelect(), Localiser["label.select"], new { @id = "cbCommodityType", @class = "CommodityType sbm-select" })
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="sbm-control">
@Html.DropDownListFor(model => model.CommodityType, Model.GetCommodityTypeCodesForSelect(), Localiser["label.select"], new { @id = "cbCommodityType", @class = "CommodityType sbm-select" })
</div>
<div class="sbm-message"></div>
</div>
@* Commodity Code *@
<div class="sbm-form-control CommodityCode">
<div class="sbm-label">
<label for="ifCommodityCode"><span>@Localiser["label.code"]</span><span class="required">&nbsp;*</span></label>
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="ifCommodityCode"><span>@Localiser["label.code"]</span><span class="required">&nbsp;*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Commodity.Code, new { @id = "ifCommodityCode", @class = "CommodityCode sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Code) })
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="sbm-control">
@Html.TextBoxFor(model => model.CommodityCode, new { @id = "ifCommodityCode", @class = "CommodityCode sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Code) })
</div>
<div class="sbm-message"></div>
</div>
@* Commodity Description *@
<div class="sbm-form-control CommodityDesc">
<div class="sbm-label">
<label for="ifCommodityDesc"><span>@Localiser["label.description"]</span><span class="required">&nbsp;*</span></label>
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="ifCommodityDesc"><span>@Localiser["label.description"]</span><span class="required">&nbsp;*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Commodity.DescBrief, new { @id = "ifCommodityDesc", @class = "CommodityDesc sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_DescBrief) })
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="sbm-control">
@Html.TextBoxFor(model => model.CommodityDesc, new { @id = "ifCommodityDesc", @class = "CommodityDesc sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_DescBrief) })
</div>
<div class="sbm-message"></div>
</div>
@* Commodity status *@
<div class="sbm-form-control CommodityStatus">
<div class="sbm-label">
<label for="cbCommodityStatus"><span>@Localiser["label.status"]</span><span class="required">&nbsp;*</span></label>
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="cbCommodityStatus"><span>@Localiser["label.status"]</span><span class="required">&nbsp;*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
<select id="cbCommodityStatus" class="sbm-select CommodityStatus" name="Commodity.StatusCode"></select>
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="sbm-control">
<select id="cbCommodityStatus" class="sbm-select CommodityStatus" name="CommodityStatusCode"></select>
</div>
<div class="sbm-message"></div>
</div>
@* Commodity Notes *@
<div class="sbm-form-control CommodityNotes">
<div class="sbm-label">
<label for="ifCommodityNotes"><span>@Localiser["label.notes"]</span></label>
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="ifCommodityNotes"><span>@Localiser["label.notes"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextAreaFor(model => model.Commodity.Notes, new { @id = "ifCommodityNotes", @class = "CommodityNotes sbm-textarea", @rows = "3", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Notes) })
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="sbm-control">
@Html.TextAreaFor(model => model.CommodityNotes, new { @id = "ifCommodityNotes", @class = "CommodityNotes sbm-textarea", @rows = "3", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Notes) })
</div>
<div class="sbm-message"></div>
</div>
}
@@ -3,128 +3,116 @@
@{
/* Contacts - Index */
ViewData["Title"] = "Contacts";
Model.AdditionalFiles_JS.Add("js/sbm-contact.js");
}
<div class="sbm-panel Contacts">
<div class="sbm-panel Contacts fullheight">
<script type="text/javascript">
sbm.lbl.createOrg = '@(Localiser.GetJavascriptText("label.create.organisation"))';
sbm.lbl.createInd = '@(Localiser.GetJavascriptText("label.create.individual"))';
sbm.lbl.createOrg = '@(Localiser.GetJavascriptText("caption.organisation.create"))';
sbm.lbl.createInd = '@(Localiser.GetJavascriptText("caption.individual.create"))';
sbm.lbl.createGrp = '@(Localiser.GetJavascriptText("caption.contact.group.create"))';
</script>
<div class="row">
<div class="col-md-5 row">
<div class="col">
@* Filter Panel *@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmContactFilter", @class = "sbm-form", @onSubmit = "return false;" }))
{
<div class="sbm-panel-filter">
@* Header - Page caption, paging controls, actions. *@
<div class="sbm-header">
<div class="row">
<div class="col"><div class="sbm-caption">@Localiser["contact.caption.contacts"]</div></div>
<div class="fixed row">
<div class="col">
<partial name="~/Views/Common/ResultsPaging.cshtml" />
</div>
<div class="fixed row">
@* Burger menu *@
<ul class="nav navbar-nav navbar-dark navbar-right sbm-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sbm-content">
@* Contact filter - name etc. *@
<div class="row pb4">
<div class="col-sm-5 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
<div class="col-sm-7">
@Html.TextBoxFor(model => model.Filter.ContactSearch, new { @id = "", @class = "FilterContact", @maxlength = "32" })
</div>
</div>
@* Contact type *@
<div class="row pb4">
<div class="col-sm-5 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
<div class="col-sm-7">
@Html.DropDownListFor(model => model.Filter.ContactType, Model.GetAffiliateTypeCodesForSelect(), Localiser["label.any"], new { @id = "", @class = "FilterContactType sbm-select" })
</div>
</div>
</div>
@* Filter element templates *@
<div class="sbm-panel-item-template">
@* Burger dropdown item template - ul is ignored *@
<ul class="sbm-dropdown-menu ContactFilter">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
</div>
<div class="sbm-panel-data sbm-flex">
@* Filter form - wrap header to include paging controls. *@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmContactFilter", @class = "sbm-form", @onSubmit = "return false;" }))
{
@* Header - Page caption, paging controls, actions. *@
<div class="sbm-panel-header">
<div class="row">
<div class="col"><partial name="~/Views/Common/ResultsPaging.cshtml" /></div>
<div class="fixed center"><div class="sbm-panel-caption">@Localiser["label.contacts"]</div></div>
<div class="col right">
@* Burger menu *@
<ul class="nav navbar-nav navbar-dark navbar-right sbm-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div>
}
</div>
</div>
@* Separate filter from results when alondside each other. *@
<div class="fixed"><div class="d-none d-md-block" style="width:8px;"></div></div>
@* Filter Panel *@
<div class="sbm-panel-filter">
<div class="row pb4">
@* Contact filter - name etc. *@
<div class="col-4 col-sm-2 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
<div class="col-8 col-sm-4">
@Html.TextBoxFor(model => model.Filter.Search, new { @id = "", @class = "FilterSearch sbm-input", @maxlength = "32" })
</div>
@* Contact type *@
<div class="col-4 col-sm-2 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
<div class="col-8 col-sm-4">
@Html.DropDownListFor(model => model.Filter.ContactType, Model.GetAffiliateTypeCodesForSelect(), Localiser["label.any"], new { @id = "", @class = "FilterContactType sbm-select" })
</div>
</div>
</div>
}
@* Item list *@
<div class="sbm-panel-item-table sbm-flex">
<table class="sbm-item-list">
<thead>
<tr>
<th class="pl-2">@Localiser["label.type"]</th>
<th class="">@Localiser["label.name"]</th>
<th class="d-none d-md-table-cell">@Localiser["label.address"]</th>
<th class="d-none d-md-table-cell">@Localiser["label.contact"]</th>
<th class="d-none d-sm-table-cell">@Localiser["label.phone"]</th>
<th class="d-none d-md-table-cell">@Localiser["label.notes"]</th>
<th class="center">@Localiser["label.associations"]</th>
<th class="center">@Localiser["label.status"]</th>
<th class="right" style="width:2%;"></th>
</tr>
<tr><td colspan="6"><div class="sbm-panel-messages"></div></td></tr>
</thead>
<tbody></tbody>
</table>
</div>
<div class="col-md-7">
@* Element templates *@
<div class="sbm-panel-item-template">
@* Results Panel *@
<div class="sbm-panel-results">
<div class="sbm-panel-messages"></div>
<div class="sbm-panel-item-list"></div>
@* Burger dropdown item template - ul is ignored *@
<ul class="sbm-dropdown-menu ContactList">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
@* element templates *@
<div class="sbm-panel-item-template">
@* Contact item template *@
<div class="sbm-panel-item Contact">
<div class="sbm-header row">
<div class="col">
@* Contact caption *@
<div class="sbm-caption"><div class="sbm-action sbm-item-update ContactName"></div></div>
</div>
<div class="fixed sbm-actions">
@* Item row template - table is ignored. *@
<table>
<tr class="sbm-row-item Contact">
<td><div class="ContactType pl-1"></div></td>
<td><div class="ContactName"></div></td>
<td class="d-none d-md-table-cell"><div class="ContactAddress"></div></td>
<td class="d-none d-md-table-cell"><div class="ContactContact"></div></td>
<td class="d-none d-sm-table-cell"><div class="ContactPhone"></div></td>
<td class="d-none d-md-table-cell"><div class="ContactNotes"></div></td>
<td class=""><div class="ContactAssociationCount center"></div></td>
<td><div class="ContactStatusDesc center"></div></td>
<td>
<div class="right">
@* Burger menu *@
<ul class="nav navbar-nav navbar-light navbar-right sbm-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span></a>
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div>
</div>
<div class="sbm-content">
<div class="row">
<div class="col-sm-4"><div class="ContactType"></div></div>
<div class="col-sm-4"><div class="ContactAssociationCount sbm-action-text">@Localiser["label.associations"]:&nbsp;<span class="AssociationCount"></span></div></div>
<div class="col-sm-4 text-left text-sm-right"><div class="StatusDesc"></div></div>
</div>
<div class="row">
<div class=""><div class="ContactAddress sbm-note"></div></div>
</div>
<div class="row">
<div class=""><div class="ContactNotes sbm-note"></div></div>
</div>
</div>
</div>
@* Burger dropdown item template - ul is ignored *@
<ul class="sbm-dropdown-menu Contact">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
</div>
</td>
</tr>
</table>
</div>
@* Burger dropdown item template - ul is ignored *@
<ul class="sbm-dropdown-menu Contact">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
</div>
</div>
</div>
@@ -5,72 +5,449 @@
}
<script type="text/javascript">
sbm.dlg.title.createContact = '@Localiser.GetJavascriptText("contact.caption.contact.create")';
sbm.dlg.title.updateContact = '@Localiser.GetJavascriptText("contact.caption.contact.update")';
sbm.dlg.title.createContact = '@Localiser.GetJavascriptText("caption.contact.create")';
sbm.dlg.title.updateContact = '@Localiser.GetJavascriptText("caption.contact.update")';
</script>
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmContactId", @class = "sbm-form" }))
{
@Html.HiddenFor(model => model.AffiliateId, new { @class = "AffiliateId" })
@Html.HiddenFor(model => model.Contact.Id, new { @class = "ContactId" })
}
<div id="dlgContact" class="sbm-dialog" title="">
<div class="spacer2"></div>
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmContact", @class = "sbm-form", @onSubmit = "return false;" }))
{
@Html.HiddenFor(model => model.AffiliateId, new { @id = "", @class = "AffiliateId" });
@Html.HiddenFor(model => model.ContactExists, new { @id = "", @class = "ContactExists" });
@Html.HiddenFor(model => model.ContactIndividual, new { @id = "", @class = "ContactIndividual" });
@Html.HiddenFor(model => model.Contact.Id, new { @id = "", @class = "ContactId sbm-input" })
@Html.HiddenFor(model => model.Contact.Exists, new { @id = "", @class = "ContactExists sbm-input" })
@Html.HiddenFor(model => model.Contact.IsIndividual, new { @id = "", @class = "ContactIsIndividual sbm-input" })
@Html.HiddenFor(model => model.Contact.IsGroup, new { @id = "", @class = "ContactIsGroup sbm-input" })
<div class="row">
<div class="col-sm-6">
@* Contact Type *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Type)">
<div class="row">
<div class="col-sm-6">
<div class="sbm-label">
<label for="cbContactType"><span class="sbm-control-label">@Localiser["label.type"]</span><span class="required"> *</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
<select name="Contact.Type" id="cbContactType" class="ContactType sbm-select"></select>
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
@* Contact Type *@
<div class="sbm-form-control ContactType">
<div class="sbm-label">
<label for="cbContactType"><span>@Localiser["label.type"]</span><span class="required"> *</span></label>
</div>
<div class="sbm-control">
@Html.DropDownListFor(model => model.ContactType, Model.GetAffiliateTypeCodesForSelect(), Localiser["label.select"], new { @id = "cbContactType", @class = "ContactType sbm-select" })
<div class="col-sm-1"></div>
<div class="col-sm">
@* Organisation Abbreviation *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Abbreviation)">
<div class="row">
<div class="col-sm-5">
<div class="sbm-label">
<label for="ifContactAbbreviation"><span class="sbm-control-label">@Localiser["label.abbreviation"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.Abbreviation, new { @id = "ifContactAbbreviation", @class = "ContactAbbreviation sbm-input upper", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Abbrev) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
</div>
</div>
@* Organisation Name *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Name)">
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="ifContactName"><span class="sbm-control-label">@Localiser["label.name"]</span><span class="required"> *</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.Name, new { @id = "ifContactName", @class = "ContactName sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
@* Contact Organisation Name *@
<div class="sbm-form-control ContactName">
<div class="sbm-label">
<label for="ifContactName"><span>@Localiser["label.name"]</span><span class="required"> *</span></label>
<div class="row">
<div class="col-sm-6">
@* Nature Organisation Nature *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Nature)">
<div class="row">
<div class="col-sm-6">
<div class="sbm-label">
<label for="ifContactNature"><span class="sbm-control-label">@Localiser["label.nature"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.Nature, new { @id = "ifContactNature", @class = "ContactNature sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Nature) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="sbm-control">
@Html.TextBoxFor(model => model.ContactName, new { @id = "ifContactName", @class = "ContactName sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name) })
<div class="col-sm-1"></div>
<div class="col-sm">
@* Organisation Contact *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Contact)">
<div class="row">
<div class="col-sm-5">
<div class="sbm-label">
<label for="ifContactContact"><span class="sbm-control-label">@Localiser["label.contact"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.Contact, new { @id = "ifContactContact", @class = "ContactContact sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Contact) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
@* Individual Title *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Title)">
<div class="row">
<div class="col-sm-6">
<div class="sbm-label">
<label for="cbContactTitle"><span class="sbm-control-label">@Localiser["label.title"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.DropDownListFor(model => model.Contact.Title, Model.GetCodeTypeCodesForSelect(Sbm.ApplCodeType.ContactTitle), new { @id = "cbContactTitle", @class = "ContactTitle sbm-select", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Title) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="col-sm-1"></div>
<div class="col-sm">
@* Individual Salutation *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Salutation)">
<div class="row">
<div class="col-sm-5">
<div class="sbm-label">
<label for="ifContactSalutation"><span class="sbm-control-label">@Localiser["label.salutation"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.Salutation, new { @id = "ifContactSalutation", @class = "ContactSalutation sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Salutation) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
@* Individual First Name *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.FirstName)">
<div class="row">
<div class="col-sm-6">
<div class="sbm-label">
<label for="ifContactFirstName"><span class="sbm-control-label">@Localiser["label.name.first"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.FirstName, new { @id = "ifContactFirstName", @class = "ContactFirstName sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_FirstName) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="col-sm-1"></div>
<div class="col-sm">
@* Individual Initials *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Initials)">
<div class="row">
<div class="col-sm-5">
<div class="sbm-label">
<label for="ifContactInitials"><span class="sbm-control-label">@Localiser["label.initials"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.Initials, new { @id = "ifContactInitials", @class = "ContactInitials sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Initials) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
</div>
</div>
@* Individual Last Name *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.LastName)">
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="ifContactLastName"><span class="sbm-control-label">@Localiser["label.name.last"]</span><span class="required"> *</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.LastName, new { @id = "ifContactLastName", @class = "ContactLastName sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_LastName) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
@* Contact Individual First Name *@
<div class="sbm-form-control ContactFirstName">
<div class="sbm-label">
<label for="ifContactFirstName"><span>@Localiser["label.name.first"]</span></label>
<div class="row">
<div class="col-sm-6">
@* Organisation Main Phone & Individual Home Phone *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.PhoneMain)">
<div class="row">
<div class="col-sm-6">
<div class="sbm-label">
<label for="ifContactPhoneMain"><span class="sbm-control-label">@Localiser["label.phone"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.PhoneMain, new { @id = "ifContactPhoneMain", @class = "ContactPhoneMain sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneMain) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="sbm-control">
@Html.TextBoxFor(model => model.ContactFirstName, new { @id = "ifContactFirstName", @class = "ContactFirstName sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_FirstName) })
<div class="col-sm-1"></div>
<div class="col-sm">
@* Organisation Alt Phone *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.PhoneAlt)">
<div class="row">
<div class="col-sm-5">
<div class="sbm-label">
<label for="ifContactPhoneAlt"><span class="sbm-control-label">@Localiser["label.phone.alt"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.PhoneAlt, new { @id = "ifContactPhoneAlt", @class = "ContactPhoneAlt sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneAlt) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
@* Individual Mobile Phone *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.PhoneMobile)">
<div class="row">
<div class="col-sm-5">
<div class="sbm-label">
<label for="ifContactPhoneMobile"><span class="sbm-control-label">@Localiser["label.phone.mobile"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.PhoneMobile, new { @id = "ifContactPhoneMobile", @class = "ContactPhoneMobile sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneMobile) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
@* Organisation Direct Phone *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.PhoneDirect)">
<div class="row">
<div class="col-sm-6">
<div class="sbm-label">
<label for="ifContactPhoneDirect"><span class="sbm-control-label">@Localiser["label.phone.direct"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.PhoneDirect, new { @id = "ifContactPhoneDirect", @class = "ContactPhoneDirect sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneDirect) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="col-sm-1"></div>
<div class="col-sm">
@* Organisation Fax *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.PhoneFax)">
<div class="row">
<div class="col-sm-5">
<div class="sbm-label">
<label for="ifContactPhoneFax"><span class="sbm-control-label">@Localiser["label.phone.fax"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.PhoneFax, new { @id = "ifContactPhoneFax", @class = "ContactPhoneFax sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneFax) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
</div>
</div>
@* Contact Email *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Email)">
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="ifContactEmail"><span class="sbm-control-label">@Localiser["label.email"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.Email, new { @id = "ifContactEmail", @class = "ContactEmail sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Email) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
@* Contact Individual Last Name *@
<div class="sbm-form-control ContactLastName">
<div class="sbm-label">
<label for="ifContactLastName"><span>@Localiser["label.name.last"]</span><span class="required"> *</span></label>
</div>
<div class="sbm-control">
@Html.TextBoxFor(model => model.ContactLastName, new { @id = "ifContactLastName", @class = "ContactLastName sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_LastName) })
@* Contact Website *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Website)">
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="ifContactWebsite"><span class="sbm-control-label">@Localiser["label.website"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.Website, new { @id = "ifContactWebsite", @class = "ContactWebsite sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Website) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
<div class="row">
<div class="col-sm-6">
@* Organisation Company Number *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.CompanyNo)">
<div class="row">
<div class="col-sm-6">
<div class="sbm-label">
<label for="ifContactCompanyNo"><span class="sbm-control-label">@Localiser["label.company.no"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.CompanyNo, new { @id = "ifContactCompanyNo", @class = "ContactCompanyNo sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_CompanyNo) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="col-sm-1"></div>
<div class="col-sm">
@* Organisation VAT registration number *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.VatReg)">
<div class="row">
<div class="col-sm-5">
<div class="sbm-label">
<label for="ifContactVatReg"><span class="sbm-control-label">@Localiser["label.vat.reg"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Contact.VatReg, new { @id = "ifContactVatReg", @class = "ContactVatReg sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_VatReg) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
</div>
</div>
@* Contact Options *@
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Options)">
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="ifContactNotes"><span class="sbm-control-label">@Localiser["label.options"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Prospect)">
<div class="sbm-control">
@Html.CheckBoxFor(Model => Model.Contact.Prospect, new { @id = "chkContactProspect", @class = "ContactProspect sbm-checkbox" })
&nbsp;<span class="sbc-label pointer" onclick="$('#chkContactProspect').click();">@Localiser["label.prospect"]</span>
</div>
<div class="sbm-message"></div>
</div>
</div>
</div>
</div>
@* Contact Notes *@
<div class="sbm-form-control ContactNotes">
<div class="sbm-label">
<label for="ifContactNotes"><span>@Localiser["label.notes"]</span></label>
</div>
<div class="sbm-control">
@Html.TextAreaFor(model => model.ContactNotes, new { @id = "ifContactNotes", @class = "ContactNotes sbm-textarea", @rows = "3", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Notes) })
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Notes)">
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="ifContactNotes"><span class="sbm-control-label">@Localiser["label.notes"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextAreaFor(model => model.Contact.Notes, new { @id = "ifContactNotes", @class = "ContactNotes sbm-textarea", @rows = "3", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Notes) })
</div>
</div>
</div>
<div class="sbm-message"></div>
</div>
@@ -99,7 +99,7 @@
<header id="sbm-page-header">
@* Navigation bar *@
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom">
<div class="container">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Sarand BusinessMgr</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
@@ -174,7 +174,7 @@
</div>
@* Footer *@
<footer id="sbm-page-footer" class="">
<footer id="sbm-page-footer" class="border-top footer text-muted">
<div class="container">
<div class="row">
<div class="col-md-6 text-center text-md-left">@(Model.OrganisationName)</div>
@@ -1,8 +1,9 @@
@using Sarand.BusinessMgr.Net.Core.Web.App
@using Sarand.BusinessMgr.Net.Standard.Base.App
@using Sarand.BusinessMgr.Web.Portal.Models
@using Sarand.BusinessMgr.Web.Portal.Models.Contacts
@using Sarand.BusinessMgr.Web.Portal.Models.Commodities
@using Sarand.BusinessMgr.Web.Portal.Models.Codes
@using Sarand.BusinessMgr.Web.Portal.Models.Assets
@using Sarand.BusinessMgr.Web.Portal.Models.Codes
@using Sarand.Net.Standard.Base.CodeTypes
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@@ -128,13 +128,15 @@
.sbm-panel-data .sbm-panel-header .sbm-results-paging .sbm-action
{
margin: 2px 1px 0 1px;
background-color: #b0b0b0;
background-color: #e0e0e0;
opacity: 50%;
box-shadow: 0 0 0 1px #40404080 inset;
border-radius: 6px;
}
.sbm-panel-data .sbm-panel-header .sbm-results-paging .sbm-action:hover
{
background-color: #c0c0c0;
opacity: 80%;
}
/* Panel header - Burger */
@@ -467,22 +469,27 @@ table.sbm-item-list tbody td
/* Item statuses */
.sbm-status-awa
.sbm-status-awa, .sbm-status-req, .sbm-status-rai, .sbm-status-clo
{
color: darkorange;
}
.sbm-status-atv, .sbm-status-cur
.sbm-status-atv, .sbm-status-ena, .sbm-status-cur, .sbm-status-rei, .sbm-status-ope, .sbm-status-con, .sbm-status-com, .sbm-status-acc, .sbm-status-gra
{
color: green;
}
.sbm-status-ina
.sbm-status-ina, .sbm-status-dis, .sbm-status-dsc, .sbm-status-red, .sbm-status-can, .sbm-status-fai, .sbm-status-rej, .sbm-status-den
{
color: darkred;
}
.sbm-status-hld
.sbm-status-inp, .sbm-status-exp, .sbm-status-inv, .sbm-status-suc, .sbm-status-act, .sbm-status-que, .sbm-status-log
{
color: darkcyan;
}
.sbm-status-pre, .sbm-status-pro, .sbm-status-inp, .sbm-status-hld, .sbm-status-upd, .sbm-status-sup, .sbm-status-aut, .sbm-status-sub
{
color: dodgerblue;
}
@@ -62,7 +62,7 @@ body
body.sbm-layout-flex #sbm-page-body
{
flex: 1;
min-height:0;
min-height: 0;
}
}
@@ -142,7 +142,7 @@ button.accept-policy
#sbm-page-footer
{
margin: 4px 0;
padding: 4px 0;
}
#sbm-page-footer, #sbm-page-footer div
@@ -249,10 +249,9 @@ a:focus
{
display: none;
position: fixed;
top: 0;
right: 0;
min-width: 180px;
margin-right: 12px;
margin-top: 6px;
margin-right: 48px;
z-index: 1000;
border: 1px solid #808080;
border-bottom-left-radius: 4px;
@@ -390,10 +389,14 @@ a:focus
.ui-dialog .ui-dialog-buttonpane
{
border-color: #d4af37;
margin-top: .25em;
padding: .2em 1em .2em .5em;
}
.ui-dialog .ui-dialog-buttonpane button
{
min-width: 80px;
margin: .5em .25em .5em .5em;
color: #fff;
background-color: #d4af37;
border-color: #d4af37;
@@ -14,7 +14,7 @@
{
if (!ac.awaitingRefreshResponse)
{
$('.sbm-burger', $pnl.header).invisible();
$pnl.bgr.invisible();
$pnl.table.find('tbody tr').remove();
$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
}
@@ -31,23 +31,24 @@
sbm.refreshPaging(response, '#frmAssetCategoryFilter', ac.refreshResults);
if (!response.success) return;
// Reference data - Statuses.
// Reference data.
if (response.statuses) sbm.data.statuses = response.statuses;
if (response.statusesCreate) sbm.data.statusesCreate = response.statusesCreate;
if (response.statusCodeDefault) sbm.data.statusCodeDefault = response.statusCodeDefault;
// Menu.
var $bgr = $('.sbm-burger', $pnl.header).invisible();
var $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
$mnu.append(ac.getFilterMenuOption(sbm.lbl.refresh, function () { ac.refreshResults(); }, 'sbm-refresh'));
$mnu.append(ac.getFilterMenuOption(sbm.lbl.create, function () { ac.createItem(); }, 'sbm-add'));
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
$pnl.bgr.invisible();
$pnl.mnu.empty();
$pnl.mnu.append(ac.getFilterMenuOption(sbm.lbl.refresh, function () { ac.refreshResults(); }, 'sbm-refresh'));
$pnl.mnu.append(ac.getFilterMenuOption(sbm.lbl.create, function () { ac.createItem(); }, 'sbm-add'));
$pnl.bgr.toggleVisibility(!!$('.sbm-dropdown-item', $pnl.mnu).length);
// Items.
var items = response.assetCategories || [];
if (!items.length)
return $pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
$table.append(ac.populateItem(ac.getItemRowTemplate(), items[itemIdx]));
$table.append(ac.populateItem(ac.getItemTemplate(), items[itemIdx]));
}
ac.populateItem = function ($item, item)
{
@@ -57,7 +58,7 @@
$('.AssetCategoryType', $item).text(item.typeDesc);
$('.AssetCategoryCode', $item).text(item.code);
$('.AssetCategoryDescription', $item).text(item.descBrief);
$('.AssetCategoryStatusDesc', $item).text(item.statusDesc).removeClass(function (idx, name) { return (name.match(/(^|\s)sbm-status-\S+/g) || []).join(' '); }).addClass('sbm-status-' + item.statusCode.toLowerCase());
$('.AssetCategoryStatusDesc', $item).text(item.statusDesc).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
// Actions.
let fnUpd = function () { ac.updateItem($item, item) };
var $bgr = $('.sbm-burger', $item).invisible();
@@ -81,7 +82,7 @@
{
return $('.sbm-dropdown-menu.AssetCategoryFilter li.sbm-dropdown-item', $pnl.tmpls).clone();
}
ac.getItemRowTemplate = function ()
ac.getItemTemplate = function ()
{
return $('table tr.sbm-row-item.AssetCategory', $pnl.tmpls).clone();
}
@@ -89,6 +90,8 @@
{
return $('.sbm-dropdown-menu.AssetCategory li.sbm-dropdown-item', $pnl.tmpls).clone();
}
//--------------------------------------------------------------
ac.getFilterMenuOption = function (lbl, fn, cls)
{
return ac.getMenuOption(ac.getFilterDropdownTemplate(), lbl, fn, cls);
@@ -165,15 +168,13 @@
$dlg.item.dialog('close');
var item = response.assetCategory;
var $item = $('#' + ac.getItemId(item));
var $item = $('#' + ac.getItemId(item), $pnl.table);
if (!$item.length)
{
$item = ac.getItemRowTemplate();
$item = ac.getItemTemplate();
$('table tbody', $pnl.table).prepend($item).show();
}
ac.populateItem($item, item);
// Force repopulation of sprts.
delete ac.data.assetCategories;
}
//--------------------------------------------------------------
@@ -181,9 +182,11 @@
{
$pnl.items = $('.sbm-panel.AssetCategories');
$pnl.header = $('.sbm-panel-header', $pnl.items);
$pnl.bgr = $('.sbm-burger', $pnl.header);
$pnl.mnu = $('ul.sbm-dropdown-menu', $pnl.bgr);
$pnl.filter = $('.sbm-panel-filter', $pnl.items);
$pnl.msgs = $('.sbm-panel-messages', $pnl.items);
$pnl.table = $('.sbm-panel-item-table', $pnl.items);
$pnl.msgs = $('.sbm-panel-messages', $pnl.items);
$pnl.tmpls = $('.sbm-panel-item-template', $pnl.items);
$frm.filter = $('#frmAssetCategoryFilter');
@@ -57,7 +57,7 @@
$('.AssetCategory', $item).text(item.categoryDesc);
$('.AssetSerial', $item).text(item.serialNumber);
$('.AssetDescription', $item).text(item.descBrief);
$('.AssetStatusDesc', $item).text(item.statusDesc).removeClass(function (idx, name) { return (name.match(/(^|\s)sbm-status-\S+/g) || []).join(' '); }).addClass('sbm-status-' + item.statusCode.toLowerCase());
$('.AssetStatusDesc', $item).text(item.statusDesc).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
// Actions.
let fnUpd = function () { ac.updateItem($item, item) };
var $bgr = $('.sbm-burger', $item).invisible();
@@ -187,7 +187,7 @@
$dlg.item.dialog('close');
var item = response.asset;
var $item = $('#' + ac.getItemId(item));
var $item = $('#' + ac.getItemId(item), $pnl.table);
if (!$item.length)
{
$item = ac.getItemRowTemplate();
@@ -0,0 +1,211 @@
/*
* Association page scripts.
*/
(function (win, doc, undef)
{
"use strict";
let as = sbm.Associations = { data: {}, ajax: {} };
let $pnl = as.$pnl = {}, $frm = as.$frm = {}, $dlg = as.$dlg = {};
//--------------------------------------------------------------
as.refreshResults = function (delay)
{
if (!sbm.awaitingRefreshResponse)
{
$pnl.bgr.invisible();
$pnl.table.find('tbody tr').remove();
$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
}
as.ajax.refreshResults = as.ajax.refreshResults || { url: sbm.url.base + 'Association/Ajax/List', formId: $frm.filter.prop('id'), callbackFn: as.doRefreshResults };
sbm.doAjaxRequest(as.ajax.refreshResults, delay || 50);
sbm.awaitingRefreshResponse = true;
}
as.doRefreshResults = function (response)
{
sbm.debug('doRefreshResults', response);
delete sbm.awaitingRefreshResponse;
$pnl.msgs.hide().empty();
let $table = $('table', $pnl.table).find('tbody tr').remove().end();
sbm.refreshPaging(response, '#frmAssociationFilter', as.refreshResults);
if (!response.success) return;
// Reference data.
as.data.associationTypes = response.associationTypes;
as.data.statuses = response.statuses;
as.data.defaultStatusCode = response.defaultStatusCode;
// Menu.
$pnl.bgr.invisible();
$pnl.mnu.empty();
$pnl.mnu.append(as.getFilterMenuOption(sbm.lbl.refresh, function () { as.refreshResults(); }, 'sbm-refresh'));
$pnl.mnu.append(as.getFilterMenuOption(sbm.lbl.create, function () { as.createItem(); }, 'sbm-add'));
$pnl.bgr.toggleVisibility(!!$('.sbm-dropdown-item', $pnl.mnu).length);
// Items.
var items = response.associations || [];
if (!items.length)
return $pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
$table.append(as.populateItem(as.getItemTemplate(), items[itemIdx]));
}
as.populateItem = function ($item, item)
{
if (!item) return;
$pnl.msgs.hide().empty();
$item.prop('id', as.getItemId(item));
$('.AssociationCode', $item).text(item.code);
$('.AssociationTargetName', $item).text(item.targetName);
$('.AssociationType', $item).text(item.typeDesc);
$('.AssociationAddress', $item).text(item.addressSummary);
$('.AssociationNotes', $item).text(item.notes);
$('.AssociationStatusDesc', $item).text(item.statusDesc).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
// Actions.
var $bgr = $('.sbm-burger', $item).hide();
let $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
if (!item.deleted)
{
let fnUpd = function () { as.updateItem(item) };
$mnu.append(as.getItemMenuOption(sbm.lbl.edit, fnUpd, 'sbm-edit'));
$('.AssociationTargetName', $item).off('click').on('click', fnUpd).addClass('sbm-action-text');
$item.off('dblclick').on('dblclick', fnUpd);
}
$bgr.toggle(!!$('.sbm-dropdown-item', $mnu).length);
return $item;
}
as.getItemId = function (item)
{
return 'Ass_' + (item || {}).id;
}
//--------------------------------------------------------------
as.getFilterDropdownTemplate = function ()
{
return $('.sbm-dropdown-menu.AssociationList li.sbm-dropdown-item', $pnl.tmpls).clone();
}
as.getItemTemplate = function ()
{
return $('table tr.sbm-row-item.Association', $pnl.tmpls).clone();
}
as.getItemDropdownTemplate = function ()
{
return $('.sbm-dropdown-menu.Association li.sbm-dropdown-item', $pnl.tmpls).clone();
}
//--------------------------------------------------------------
as.getFilterMenuOption = function (lbl, fn, cls)
{
return as.getMenuOption(as.getFilterDropdownTemplate(), lbl, fn, cls);
}
as.getItemMenuOption = function (lbl, fn, cls)
{
return as.getMenuOption(as.getItemDropdownTemplate(), lbl, fn, cls);
}
as.getMenuOption = function ($opt, lbl, fn, cls)
{
return $opt.find('div.sbm-label').text(lbl).end().on('click', fn).addClass(cls);
}
//--------------------------------------------------------------
as.createItem = function ()
{
as.clearItem();
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', $frm.item);
$ctrls.filter('.AssociationType').val('').prop('disabled', false);
$ctrls.filter('.AssociationStatus').val(as.data.defaultStatusCode);
$dlg.item.dialog('option', 'title', sbm.dlg.title.createAssociation);
as.openItemDlg();
}
as.clearItem = function ()
{
sbm.clearControlErrors($frm.item);
$('.sbm-input,.sbm-textarea,.sbm-select', $frm.item).val('');
sbm.populateSelectCodeDesc('#cbAssociationType', as.data.associationTypes);
sbm.populateSelectCodeDesc('#cbAssociationStatus', as.data.statuses);
}
as.openItemDlg = function ()
{
sbm.openDialog($dlg.item, 600, 640);
}
//--------------------------------------------------------------
as.updateItem = function (item)
{
$('.AssociationId', $frm.itemId).val(item.id);
as.ajax.updateItem = as.ajax.updateItem || { url: sbm.url.base + 'Association/Ajax/GetItem', formId: 'frmAssociationId', callbackFn: as.onUpdateItem };
sbm.doAjaxRequest(as.ajax.updateItem, 50);
}
as.onUpdateItem = function (response)
{
//sbm.debug('onUpdateItem', response);
as.clearItem();
if (!response.success) return;
let item = response.association;
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', $frm.item);
$ctrls.filter('.AssociationId').val(item.id);
$ctrls.filter('.AssociationExists').val(1);
let $ctrlType = $ctrls.filter('.AssociationType');
sbm.selectOrAdd($ctrlType, item.typeCode, item.typeDesc)
if ($ctrlType.val()) $ctrlType.prop('disabled', true);
$ctrls.filter('.AssociationTargetId').val(item.targetId);
$ctrls.filter('.AssociationTarget').val(item.targetName);
$ctrls.filter('.AssociationCode').val(item.code);
$ctrls.filter('.AssociationDesc').val(item.desc);
$ctrls.filter('.AssociationNotes').val(item.notes);
sbm.selectOrAdd($ctrls.filter('.AssociationStatus'), item.statusCode, item.statusDesc)
$dlg.item.dialog('option', 'title', sbm.dlg.title.updateAssociation);
as.openItemDlg();
}
//--------------------------------------------------------------
as.storeItem = function ()
{
as.ajax.storeItem = as.ajax.storeItem || { url: sbm.url.base + 'Association/Ajax/StoreItem', formId: 'frmAssociation', callbackFn: as.onStoreItem };
sbm.doAjaxRequest(as.ajax.storeItem, 50);
}
as.onStoreItem = function (response)
{
//sbm.debug('onStoreItem', response);
sbm.refreshControlValues(response.controlValues);
if (!response.success) return;
$dlg.item.dialog('close');
var item = response.association;
var $item = $('#' + as.getItemId(item), $pnl.table);
if (!$item.length)
{
$item = as.getItemTemplate();
$('table tbody', $pnl.table).prepend($item).show();
}
as.populateItem($item, item);
}
//--------------------------------------------------------------
$(function ()
{
$pnl.items = $('.sbm-panel.Associations');
$pnl.header = $('.sbm-panel-header', $pnl.items);
$pnl.bgr = $('.sbm-burger', $pnl.header);
$pnl.mnu = $('ul.sbm-dropdown-menu', $pnl.bgr);
$pnl.table = $('.sbm-panel-item-table', $pnl.items);
$pnl.msgs = $('.sbm-panel-messages', $pnl.table);
$pnl.tmpls = $('.sbm-panel-item-template', $pnl.items);
$frm.filter = $('#frmAssociationFilter');
$frm.filter.on('input', '.FilterSearch', function () { as.refreshResults(250); }).on('change', '.FilterAssociationType', function () { as.refreshResults(50); });
$frm.itemId = $('#frmAssociationId');
$frm.item = $('#frmAssociation');
$frm.item.on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
var opt = sbm.dlgOpts();
opt.buttons[sbm.lbl.ok] = function () { as.storeItem(); };
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
$dlg.item = $('#dlgAssociation').dialog(opt);
setTimeout(as.refreshResults, 250);
});
}(window, window.document));
/* The End */
@@ -1,189 +0,0 @@
/*
* Association page scripts.
*/
(function (win, doc, undef)
{
"use strict";
sbm.itemIdPrefix = 'Itm_';
let $pnl = sbm.$pnl;
let $frm = sbm.$frm;
let $dlg = sbm.$dlg;
//--------------------------------------------------------------
sbm.refreshResults = function (delay)
{
if (!sbm.awaitingRefreshResponse)
{
$('.sbm-burger', $pnl.filter).hide();
$('.sbm-panel-item-list', $pnl.results).fadeOut(200).empty();
$('.sbm-panel-messages', $pnl.results).hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
}
sbm.ajax.refreshResults = sbm.ajax.refreshResults || { url: sbm.url.base + 'Association/Ajax/List', formId: 'frmAssociationFilter', callbackFn: sbm.doRefreshResults };
sbm.doAjaxRequest(sbm.ajax.refreshResults, delay || 50);
sbm.awaitingRefreshResponse = true;
}
sbm.doRefreshResults = function (response)
{
//sbm.debug('doRefreshResults', response);
delete sbm.awaitingRefreshResponse;
sbm.refreshControlValues(response.controlValues);
var $msgs = $('.sbm-panel-messages', $pnl.results).hide().empty();
var $items = $('.sbm-panel-item-list', $pnl.results).hide().empty();
sbm.refreshPaging(response, '#frmAssociationFilter', sbm.refreshResults);
if (!response.success) return;
// Reference data - Statuses.
if (response.defaultStatusCode) sbm.data.defaultStatusCode = response.defaultStatusCode;
if (response.statuses)
sbm.populateSelectCodeDesc('#cbAssociationStatus', response.statuses);
// Menu.
var $bgr = $('.sbm-burger', $pnl.filter).hide();
var $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
$mnu.append(sbm.getFilterMenuOption(sbm.lbl.refresh, function () { sbm.refreshResults(); }));
$mnu.append(sbm.getFilterMenuOption(sbm.lbl.create, function () { sbm.createItem(); }));
$bgr.toggle(!!$('.sbm-dropdown-item', $mnu).length);
// Items.
var items = response.associations;
if (!items.length)
return $msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
$items.append(sbm.populateItem(sbm.getItemTemplate(), items[itemIdx]));
$items.fadeIn(50);
}
sbm.populateItem = function ($item, item)
{
if (!item) return;
$item.prop('id', sbm.itemIdPrefix + item.id);
$('.AssociationCode', $item).text(item.code);
$('.AssociationTargetName', $item).text(item.targetName);
$('.AssociationType', $item).text(item.typeDesc);
//$('.AssociationTransactionCount', $item).on('click', function () { sbm.onClickTransactionCount(item.id); }).toggle(item.associationCount).find('.TransactionCount').text(item.associationCount);
$('.AssociationAddress', $item).text(item.addressSummary);
$('.AssociationNotes', $item).text(item.notes);
$('.StatusDesc', $item).text(item.statusDesc).addClass('sbm-status-' + item.statusCode.toLowerCase());
$('.sbm-caption .sbm-action').toggleClass('sbm-action', !item.deleted);
let $mnu = $('ul.sbm-dropdown-menu', $item);
if (!item.deleted)
{
$mnu.append(sbm.getItemMenuOption(sbm.lbl.edit, function () { sbm.updateItem(item.id) }));
$('.sbm-header .sbm-action.sbm-item-update', $item).off('click').on('click', function () { sbm.updateItem(item.id) });
$item.off('dblclick').on('dblclick', function () { sbm.updateItem(item.id) });
}
$('.sbm-burger', $item).toggle(!!$('.sbm-dropdown-item', $mnu).length);
$('.sbm-panel-messages', $pnl.results).hide().empty();
return $item;
}
//--------------------------------------------------------------
sbm.getFilterDropdownTemplate = function ()
{
return $('.sbm-panel-item-template .sbm-dropdown-menu.AssociationFilter li.sbm-dropdown-item', $pnl.filter).clone();
}
sbm.getItemTemplate = function ()
{
return $('.sbm-panel-item-template .sbm-panel-item.Association', $pnl.results).clone();
}
sbm.getItemDropdownTemplate = function ()
{
return $('.sbm-panel-item-template .sbm-dropdown-menu.Association li.sbm-dropdown-item', $pnl.results).clone();
}
sbm.getFilterMenuOption = function (lbl, fn)
{
return sbm.getMenuOption(sbm.getFilterDropdownTemplate(), lbl, fn);
}
sbm.getItemMenuOption = function (lbl, fn)
{
return sbm.getMenuOption(sbm.getItemDropdownTemplate(), lbl, fn);
}
sbm.getMenuOption = function ($opt, lbl, fn)
{
return $opt.find('div.sbm-label').text(lbl).end().on('click', fn);
}
//--------------------------------------------------------------
sbm.createItem = function ()
{
let frm = $frm.association;
$('.AssociationId,.AssociationExists,input[type="text"],textarea,select', frm).val('');
$('.AssociationStatus', frm).val(sbm.data.defaultStatusCode);
sbm.clearControlErrors();
sbm.$dlg.association.dialog('option', 'title', sbm.dlg.title.createAssociation);
sbm.openDialog(sbm.$dlg.association, 600, 600);
}
//--------------------------------------------------------------
sbm.updateItem = function (id)
{
$('.AssociationId', $frm.associationId).val(id);
sbm.ajax.updateItem = sbm.ajax.updateItem || { url: sbm.url.base + 'Association/Ajax/GetItem', formId: 'frmAssociationId', callbackFn: sbm.onUpdateItem };
sbm.doAjaxRequest(sbm.ajax.updateItem, 50);
}
sbm.onUpdateItem = function (response)
{
sbm.debug('onUpdateItem', response);
let frm = $frm.association;
$('.AssociationId,input[type="text"],textarea,select', frm).val('');
if (!response.success) return;
let item = response.association;
$('.AssociationId', frm).val(item.id);
$('.AssociationExists', frm).val(1);
$('.AssociationType', frm).val(item.typeCode);
$('.AssociationCode', frm).val(item.code);
$('.AssociationDesc', frm).val(item.desc);
$('.AssociationNotes', frm).val(item.notes);
$('.AssociationStatus', frm).val(item.statusCode);
sbm.clearControlErrors();
sbm.$dlg.association.dialog('option', 'title', sbm.dlg.title.updateAssociation);
sbm.openDialog(sbm.$dlg.association, 600, 600);
}
//--------------------------------------------------------------
sbm.storeItem = function ()
{
sbm.ajax.storeItem = sbm.ajax.storeItem || { url: sbm.url.base + 'Association/Ajax/StoreItem', formId: 'frmAssociation', callbackFn: sbm.onStoreItem };
sbm.doAjaxRequest(sbm.ajax.storeItem, 50);
}
sbm.onStoreItem = function (response)
{
//sbm.debug('onStoreItem', response);
sbm.refreshControlValues(response.controlValues);
if (!response.success) return;
sbm.$dlg.association.dialog('close');
var item = response.association;
var $item = $('#' + sbm.itemIdPrefix + item.id);
if (!$item.length)
{
$item = sbm.getItemTemplate();
$('.sbm-panel-item-list', $pnl.results).prepend($item).show();
}
$item.replaceWith(sbm.populateItem(sbm.getItemTemplate(), item));
}
//--------------------------------------------------------------
$(function ()
{
$pnl.associations = $('.sbm-panel.Associations');
$pnl.filter = $('.sbm-panel-filter', $pnl.associations);
$pnl.results = $('.sbm-panel-results', $pnl.associations);
$('.sbm-input, .sbm-textarea').on('input', function () { sbm.clearControlError(this); });
$('.sbm-select').on('change', function () { sbm.clearControlError(this); });
$frm.filter = $('#frmAssociationFilter');
$('.FilterAssociation', $frm.filter).on('input', function () { sbm.refreshResults(250); });
$('.FilterAssociationType,.FilterAssociationStatusCategory', $frm.filter).on('change', function () { sbm.refreshResults(50); });
$frm.associationId = $('#frmAssociationId');
$frm.association = $('#frmAssociation');
var opt = sbm.dlgOpts();
opt.buttons[sbm.lbl.ok] = function () { sbm.storeItem(); };
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
sbm.$dlg.association = $('#dlgAssociation').dialog(opt);
setTimeout(sbm.refreshResults, 250);
});
}(window, window.document));
/* The End */
@@ -57,7 +57,7 @@
$('.CodeTypeCode', $item).text(item.code);
$('.CodeTypeName', $item).text(item.name);
$('.CodeTypeCodes', $item).text(item.codeCount);
$('.CodeTypeStatusDesc', $item).text(item.statusDesc).removeClass(function (idx, name) { return (name.match(/(^|\s)sbm-status-\S+/g) || []).join(' '); }).addClass('sbm-status-' + item.statusCode.toLowerCase());
$('.CodeTypeStatusDesc', $item).text(item.statusDesc).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
// Actions.
let fnUpd = function () { ac.updateItem($item, item) };
var $bgr = $('.sbm-burger', $item).invisible();
@@ -65,9 +65,9 @@
if (!item.deleted)
{
$mnu.append(ac.getItemMenuOption(sbm.lbl.edit, fnUpd, 'sbm-edit'));
$('.CodeTypeName', $item).on('click', fnUpd).addClass('sbm-action-text');
$('.CodeTypeCodes', $item).on('click', function () { sbm.navigateTo('Codes/Code?Filter.CodeTypeCode='+item.code);return false; }).on('dblclick', function () { return false; }).addClass('sbm-action-text');
$item.on('dblclick', fnUpd);
$('.CodeTypeName', $item).off('click').on('click', fnUpd).addClass('sbm-action-text');
$('.CodeTypeCodes', $item).off('click').on('click', function () { sbm.navigateTo('Codes/Code?Filter.CodeTypeCode='+item.code);return false; }).on('dblclick', function () { return false; }).addClass('sbm-action-text');
$item.off('dblclick').on('dblclick', fnUpd);
}
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
return $item;
@@ -165,7 +165,7 @@
$dlg.item.dialog('close');
var item = response.codeType;
var $item = $('#' + ac.getItemId(item));
var $item = $('#' + ac.getItemId(item), $pnl.table);
if (!$item.length)
{
$item = ac.getItemRowTemplate();
@@ -58,7 +58,7 @@
$('.CodeType', $item).text(item.typeName);
$('.CodeCode', $item).text(item.code);
$('.CodeDesc', $item).text(item.description);
$('.CodeStatusDesc', $item).text(item.statusDesc).removeClass(function (idx, name) { return (name.match(/(^|\s)sbm-status-\S+/g) || []).join(' '); }).addClass('sbm-status-' + item.statusCode.toLowerCase());
$('.CodeStatusDesc', $item).text(item.statusDesc).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
// Actions.
let fnUpd = function () { ac.updateItem($item, item) };
var $bgr = $('.sbm-burger', $item).invisible();
@@ -66,8 +66,8 @@
if (!item.deleted)
{
$mnu.append(ac.getItemMenuOption(sbm.lbl.edit, fnUpd, 'sbm-edit'));
$('.CodeDesc', $item).on('click', fnUpd).addClass('sbm-action-text');
$item.on('dblclick', fnUpd);
$('.CodeDesc', $item).off('click').on('click', fnUpd).addClass('sbm-action-text');
$item.off('dblclick').on('dblclick', fnUpd);
}
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
return $item;
@@ -188,7 +188,7 @@
$dlg.item.dialog('close');
var item = response.code;
var $item = $('#' + ac.getItemId(item));
var $item = $('#' + ac.getItemId(item), $pnl.table);
if (!$item.length)
{
$item = ac.getItemRowTemplate();
@@ -5,183 +5,200 @@
(function (win, doc, undef)
{
"use strict";
sbm.itemIdPrefix = 'Itm_';
let $pnl = sbm.$pnl;
let $frm = sbm.$frm;
let $dlg = sbm.$dlg;
let co = sbm.Commodities = { data: {}, ajax: {} };
let $pnl = co.$pnl = {}, $frm = co.$frm = {}, $dlg = co.$dlg = {};
//--------------------------------------------------------------
sbm.refreshResults = function (delay)
co.refreshResults = function (delay)
{
if (!sbm.awaitingRefreshResponse)
{
$('.sbm-burger', $pnl.filter).hide();
$('.sbm-panel-item-list', $pnl.results).fadeOut(200).empty();
$('.sbm-panel-messages', $pnl.results).hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
$pnl.bgr.invisible();
$pnl.table.find('tbody tr').remove();
$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
}
sbm.ajax.refreshResults = sbm.ajax.refreshResults || { url: sbm.url.base + 'Commodity/Ajax/List', formId: 'frmCommodityFilter', callbackFn: sbm.doRefreshResults };
sbm.doAjaxRequest(sbm.ajax.refreshResults, delay || 50);
co.ajax.refreshResults = co.ajax.refreshResults || { url: sbm.url.base + 'Commodity/Ajax/List', formId: $frm.filter.prop('id'), callbackFn: co.doRefreshResults };
sbm.doAjaxRequest(co.ajax.refreshResults, delay || 50);
sbm.awaitingRefreshResponse = true;
}
sbm.doRefreshResults = function (response)
co.doRefreshResults = function (response)
{
//sbm.debug('doRefreshResults', response);
delete sbm.awaitingRefreshResponse;
sbm.refreshControlValues(response.controlValues);
var $msgs = $('.sbm-panel-messages', $pnl.results).hide().empty();
var $items = $('.sbm-panel-item-list', $pnl.results).hide().empty();
sbm.refreshPaging(response, '#frmCommodityFilter', sbm.refreshResults);
$pnl.msgs.hide().empty();
let $table = $('table', $pnl.table).find('tbody tr').remove().end();
sbm.refreshPaging(response, '#frmCommodityFilter', co.refreshResults);
if (!response.success) return;
// Reference data - Statuses.
// Reference data.
if (response.defaultStatusCode) sbm.data.defaultStatusCode = response.defaultStatusCode;
if (response.statuses)
sbm.populateSelectCodeDesc('#cbCommodityStatus', response.statuses);
if (response.statuses) sbm.data.statuses = response.statuses;
// Menu.
var $bgr = $('.sbm-burger', $pnl.filter).hide();
var $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
$mnu.append(sbm.getFilterMenuOption(sbm.lbl.refresh, function () { sbm.refreshResults(); }));
$mnu.append(sbm.getFilterMenuOption(sbm.lbl.create, function () { sbm.createItem(); }));
$bgr.toggle(!!$('.sbm-dropdown-item', $mnu).length);
$pnl.bgr.invisible();
$pnl.mnu.empty();
$pnl.mnu.append(co.getFilterMenuOption(sbm.lbl.refresh, function () { co.refreshResults(); }, 'sbm-refresh'));
$pnl.mnu.append(co.getFilterMenuOption(sbm.lbl.create, function () { co.createItem(); }, 'sbm-add'));
$pnl.bgr.toggleVisibility(!!$('.sbm-dropdown-item', $pnl.mnu).length);
// Items.
var items = response.commodities;
var items = response.commodities || [];
if (!items.length)
return $msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
return $pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
$items.append(sbm.populateItem(sbm.getItemTemplate(), items[itemIdx]));
$items.fadeIn(50);
$table.append(co.populateItem(co.getItemTemplate(), items[itemIdx]));
}
sbm.populateItem = function ($item, item)
co.populateItem = function ($item, item)
{
if (!item) return;
$item.prop('id', sbm.itemIdPrefix + item.id);
$pnl.msgs.hide().empty();
$item.prop('id', co.getItemId(item));
$('.CommodityType', $item).text(item.typeDesc);
$('.CommodityCode', $item).text(item.code);
$('.CommodityDesc', $item).text(item.desc);
$('.CommodityType', $item).text(item.typeDesc);
$('.CommodityAssociationCount', $item).on('click', function () { sbm.onClickAssociationCount(item.id); }).toggle(item.associationCount).find('.AssociationCount').text(item.associationCount);
$('.CommodityAddress', $item).text(item.addressSummary);
$('.CommoditySalesPrice', $item).text(item.salesPriceFmt);
$('.CommoditySalesUnits', $item).text(item.salesUnit);
$('.CommodityNotes', $item).text(item.notes);
$('.StatusDesc', $item).text(item.statusDesc).addClass('sbm-status-' + item.statusCode.toLowerCase());
$('.sbm-caption .sbm-action').toggleClass('sbm-action', !item.deleted);
let $mnu = $('ul.sbm-dropdown-menu', $item);
$('.CommodityStatusDesc', $item).text(item.statusDesc).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
// Actions.
var $bgr = $('.sbm-burger', $item).hide();
let $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
if (!item.deleted)
{
$mnu.append(sbm.getItemMenuOption(sbm.lbl.edit, function () { sbm.updateItem(item.id) }));
$('.sbm-header .sbm-action.sbm-item-update', $item).off('click').on('click', function () { sbm.updateItem(item.id) });
$item.off('dblclick').on('dblclick', function () { sbm.updateItem(item.id) });
let fnUpd = function () { co.updateItem(item) };
$mnu.append(co.getItemMenuOption(sbm.lbl.edit, fnUpd, 'sbm-edit'));
$('.CommodityCode,.CommodityDesc', $item).off('click').on('click', fnUpd).addClass('sbm-action-text');
$item.off('dblclick').on('dblclick', fnUpd);
}
$('.sbm-burger', $item).toggle(!!$('.sbm-dropdown-item', $mnu).length);
$('.sbm-panel-messages', $pnl.results).hide().empty();
$bgr.toggle(!!$('.sbm-dropdown-item', $mnu).length);
return $item;
}
//--------------------------------------------------------------
sbm.getFilterDropdownTemplate = function ()
co.getItemId = function (item)
{
return $('.sbm-panel-item-template .sbm-dropdown-menu.CommodityFilter li.sbm-dropdown-item', $pnl.filter).clone();
}
sbm.getItemTemplate = function ()
{
return $('.sbm-panel-item-template .sbm-panel-item.Commodity', $pnl.results).clone();
}
sbm.getItemDropdownTemplate = function ()
{
return $('.sbm-panel-item-template .sbm-dropdown-menu.Commodity li.sbm-dropdown-item', $pnl.results).clone();
}
sbm.getFilterMenuOption = function (lbl, fn)
{
return sbm.getMenuOption(sbm.getFilterDropdownTemplate(), lbl, fn);
}
sbm.getItemMenuOption = function (lbl, fn)
{
return sbm.getMenuOption(sbm.getItemDropdownTemplate(), lbl, fn);
}
sbm.getMenuOption = function ($opt, lbl, fn)
{
return $opt.find('div.sbm-label').text(lbl).end().on('click', fn);
return 'Cmd_' + (item || {}).id;
}
//--------------------------------------------------------------
sbm.createItem = function ()
co.getFilterDropdownTemplate = function ()
{
let frm = $frm.commodity;
$('.CommodityId,.CommodityExists,input[type="text"],textarea,select', frm).val('');
return $('.sbm-dropdown-menu.CommodityList li.sbm-dropdown-item', $pnl.tmpls).clone();
}
co.getItemTemplate = function ()
{
return $('table tr.sbm-row-item.Commodity', $pnl.tmpls).clone();
}
co.getItemDropdownTemplate = function ()
{
return $('.sbm-dropdown-menu.Commodity li.sbm-dropdown-item', $pnl.tmpls).clone();
}
//--------------------------------------------------------------
co.getFilterMenuOption = function (lbl, fn, cls)
{
return co.getMenuOption(co.getFilterDropdownTemplate(), lbl, fn, cls);
}
co.getItemMenuOption = function (lbl, fn, cls)
{
return co.getMenuOption(co.getItemDropdownTemplate(), lbl, fn, cls);
}
co.getMenuOption = function ($opt, lbl, fn, cls)
{
return $opt.find('div.sbm-label').text(lbl).end().on('click', fn).addClass(cls);
}
//--------------------------------------------------------------
co.createItem = function ()
{
co.clearItem();
let frm = $frm.item;
$('.CommodityStatus', frm).val(sbm.data.defaultStatusCode);
sbm.clearControlErrors();
sbm.$dlg.commodity.dialog('option', 'title', sbm.dlg.title.createCommodity);
sbm.openDialog(sbm.$dlg.commodity, 600, 600);
$dlg.item.dialog('option', 'title', sbm.dlg.title.createCommodity).prop('readonly', false);
co.openItemDlg();
}
co.clearItem = function ()
{
sbm.clearControlErrors($frm.item);
$('.sbm-input,.sbm-textarea,.sbm-select', $frm.item).val('');
sbm.populateSelectCodeDesc('#cbCommodityStatus', sbm.data.statuses);
}
co.openItemDlg = function ()
{
sbm.openDialog($dlg.item, 600, 640);
}
//--------------------------------------------------------------
sbm.updateItem = function (id)
co.updateItem = function (item)
{
$('.CommodityId', $frm.commodityId).val(id);
sbm.ajax.updateItem = sbm.ajax.updateItem || { url: sbm.url.base + 'Commodity/Ajax/GetItem', formId: 'frmCommodityId', callbackFn: sbm.onUpdateItem };
sbm.doAjaxRequest(sbm.ajax.updateItem, 50);
$('.CommodityId', $frm.itemId).val(item.id);
co.ajax.updateItem = co.ajax.updateItem || { url: sbm.url.base + 'Commodity/Ajax/GetItem', formId: 'frmCommodityId', callbackFn: co.onUpdateItem };
sbm.doAjaxRequest(co.ajax.updateItem, 50);
}
sbm.onUpdateItem = function (response)
co.onUpdateItem = function (response)
{
sbm.debug('onUpdateItem', response);
let frm = $frm.commodity;
$('.CommodityId,input[type="text"],textarea,select', frm).val('');
//sbm.debug('onUpdateItem', response);
co.clearItem();
if (!response.success) return;
let item = response.commodity;
$('.CommodityId', frm).val(item.id);
$('.CommodityExists', frm).val(1);
$('.CommodityType', frm).val(item.typeCode);
$('.CommodityCode', frm).val(item.code);
$('.CommodityDesc', frm).val(item.desc);
$('.CommodityNotes', frm).val(item.notes);
$('.CommodityStatus', frm).val(item.statusCode);
sbm.clearControlErrors();
sbm.$dlg.commodity.dialog('option', 'title', sbm.dlg.title.updateCommodity);
sbm.openDialog(sbm.$dlg.commodity, 600, 600);
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', $frm.item);
$ctrls.filter('.CommodityId').val(item.id);
$ctrls.filter('.CommodityExists').val(1);
$ctrls.filter('.CommodityType').val(item.typeCode);
$ctrls.filter('.CommodityCode').val(item.code);
$ctrls.filter('.CommodityDesc').val(item.desc);
$ctrls.filter('.CommodityNotes').val(item.notes);
sbm.selectOrAdd($ctrls.filter('.CommodityStatus'), item.statusCode, item.statusDesc);
$dlg.item.dialog('option', 'title', sbm.dlg.title.updateCommodity);
co.openItemDlg();
}
//--------------------------------------------------------------
sbm.storeItem = function ()
co.storeItem = function ()
{
sbm.ajax.storeItem = sbm.ajax.storeItem || { url: sbm.url.base + 'Commodity/Ajax/StoreItem', formId: 'frmCommodity', callbackFn: sbm.onStoreItem };
sbm.doAjaxRequest(sbm.ajax.storeItem, 50);
co.ajax.storeItem = co.ajax.storeItem || { url: sbm.url.base + 'Commodity/Ajax/StoreItem', formId: 'frmCommodity', callbackFn: co.onStoreItem };
sbm.doAjaxRequest(co.ajax.storeItem, 50);
}
sbm.onStoreItem = function (response)
co.onStoreItem = function (response)
{
//sbm.debug('onStoreItem', response);
sbm.refreshControlValues(response.controlValues);
if (!response.success) return;
sbm.$dlg.commodity.dialog('close');
$dlg.item.dialog('close');
var item = response.commodity;
var $item = $('#' + sbm.itemIdPrefix + item.id);
var $item = $('#' + co.getItemId(item), $pnl.table);
if (!$item.length)
{
$item = sbm.getItemTemplate();
$('.sbm-panel-item-list', $pnl.results).prepend($item).show();
$item = co.getItemTemplate();
$('table tbody', $pnl.table).prepend($item).show();
}
$item.replaceWith(sbm.populateItem(sbm.getItemTemplate(), item));
co.populateItem($item, item);
}
//--------------------------------------------------------------
$(function ()
{
$pnl.commodities = $('.sbm-panel.Commodities');
$pnl.filter = $('.sbm-panel-filter', $pnl.commodities);
$pnl.results = $('.sbm-panel-results', $pnl.commodities);
$('.sbm-input, .sbm-textarea').on('input', function () { sbm.clearControlError(this); });
$('.sbm-select').on('change', function () { sbm.clearControlError(this); });
$pnl.items = $('.sbm-panel.Commodities');
$pnl.header = $('.sbm-panel-header', $pnl.items);
$pnl.bgr = $('.sbm-burger', $pnl.header);
$pnl.mnu = $('ul.sbm-dropdown-menu', $pnl.bgr);
$pnl.table = $('.sbm-panel-item-table', $pnl.items);
$pnl.msgs = $('.sbm-panel-messages', $pnl.table);
$pnl.tmpls = $('.sbm-panel-item-template', $pnl.items);
$frm.filter = $('#frmCommodityFilter');
$('.FilterCommodity', $frm.filter).on('input', function () { sbm.refreshResults(250); });
$('.FilterCommodityType,.FilterCommodityStatusCategory', $frm.filter).on('change', function () { sbm.refreshResults(50); });
$frm.commodityId = $('#frmCommodityId');
$frm.commodity = $('#frmCommodity');
$frm.filter.on('input', '.FilterSearch', function () { co.refreshResults(250); }).on('change', '.FilterCommodityType,.FilterStatusCat', function () { co.refreshResults(50); });
$frm.itemId = $('#frmCommodityId');
$frm.item = $('#frmCommodity');
$frm.item.on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
var opt = sbm.dlgOpts();
opt.buttons[sbm.lbl.ok] = function () { sbm.storeItem(); };
opt.buttons[sbm.lbl.ok] = function () { co.storeItem(); };
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
sbm.$dlg.commodity = $('#dlgCommodity').dialog(opt);
$dlg.item = $('#dlgCommodity').dialog(opt);
setTimeout(sbm.refreshResults, 250);
setTimeout(co.refreshResults, 250);
});
}(window, window.document));
@@ -5,206 +5,254 @@
(function (win, doc, undef)
{
"use strict";
sbm.itemIdPrefix = 'Itm_';
let $pnl = sbm.$pnl;
let $frm = sbm.$frm;
let $dlg = sbm.$dlg;
let co = sbm.Contacts = { data: {}, ajax: {} };
let $pnl = co.$pnl = {}, $frm = co.$frm = {}, $dlg = co.$dlg = {};
//--------------------------------------------------------------
sbm.refreshResults = function (delay)
co.refreshResults = function (delay)
{
if (!sbm.awaitingRefreshResponse)
{
$('.sbm-burger', $pnl.filter).hide();
$('.sbm-panel-item-list', $pnl.results).fadeOut(200).empty();
$('.sbm-panel-messages', $pnl.results).hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
$pnl.bgr.invisible();
$pnl.table.find('tbody tr').remove();
$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
}
sbm.ajax.refreshResults = sbm.ajax.refreshResults || { url: sbm.url.base + 'Contact/Ajax/List', formId: 'frmContactFilter', callbackFn: sbm.doRefreshResults };
sbm.doAjaxRequest(sbm.ajax.refreshResults, delay || 50);
co.ajax.refreshResults = co.ajax.refreshResults || { url: sbm.url.base + 'Contact/Ajax/List', formId: $frm.filter.prop('id'), callbackFn: co.doRefreshResults };
sbm.doAjaxRequest(co.ajax.refreshResults, delay || 50);
sbm.awaitingRefreshResponse = true;
}
sbm.getFilterDropdownTemplate = function ()
{
return $('.sbm-panel-item-template .sbm-dropdown-menu.ContactFilter li.sbm-dropdown-item', $pnl.filter).clone();
}
sbm.getItemTemplate = function ()
{
return $('.sbm-panel-item-template .sbm-panel-item.Contact', $pnl.results).clone();
}
sbm.getItemDropdownTemplate = function ()
{
return $('.sbm-panel-item-template .sbm-dropdown-menu.Contact li.sbm-dropdown-item', $pnl.results).clone();
}
sbm.doRefreshResults = function (response)
co.doRefreshResults = function (response)
{
//sbm.debug('doRefreshResults', response);
delete sbm.awaitingRefreshResponse;
sbm.refreshControlValues(response.controlValues);
var $msgs = $('.sbm-panel-messages', $pnl.results).hide().empty();
var $items = $('.sbm-panel-item-list', $pnl.results).hide().empty();
sbm.refreshPaging(response, '#frmContactFilter', sbm.refreshResults);
$pnl.msgs.hide().empty();
let $table = $('table', $pnl.table).find('tbody tr').remove().end();
sbm.refreshPaging(response, '#frmContactFilter', co.refreshResults);
if (!response.success) return;
// Reference data - Statuses.
if (response.defaultStatusCode) sbm.data.defaultStatusCode = response.defaultStatusCode;
if (response.statuses)
sbm.populateSelectCodeDesc('#cbContactStatus', response.statuses);
// Reference data.
co.config = response.config;
co.configInd = response.configInd;
co.configOrg = response.configOrg;
co.configGrp = response.configGrp;
co.data.organisationTypes = response.organisationTypes;
co.data.titles = response.titles;
co.data.salutations = response.salutations;
co.data.statuses = response.statuses;
co.data.defaultStatusCode = response.defaultStatusCode;
// Menu.
var $bgr = $('.sbm-burger', $pnl.filter).hide();
var $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
$mnu.append(sbm.getFilterMenuOption(sbm.lbl.refresh, function () { sbm.refreshResults(); }));
$mnu.append(sbm.getFilterMenuOption(sbm.lbl.createOrg, function () { sbm.createItem(); }));
$mnu.append(sbm.getFilterMenuOption(sbm.lbl.createInd, function () { sbm.createItem(1); }));
$bgr.toggle(!!$('.sbm-dropdown-item', $mnu).length);
$pnl.bgr.invisible();
$pnl.mnu.empty();
$pnl.mnu.append(co.getFilterMenuOption(sbm.lbl.refresh, function () { co.refreshResults(); }, 'sbm-refresh'));
$pnl.mnu.append(co.getFilterMenuOption(sbm.lbl.createOrg, function () { co.createItem(co.configOrg, sbm.dlg.title.createContact); }, 'sbm-add'));
$pnl.mnu.append(co.getFilterMenuOption(sbm.lbl.createInd, function () { co.createItem(co.configInd, sbm.dlg.title.createContact); }, 'sbm-add'));
$pnl.mnu.append(co.getFilterMenuOption(sbm.lbl.createGrp, function () { co.createItem(co.configGrp, sbm.dlg.title.createContact); }, 'sbm-add'));
$pnl.bgr.toggleVisibility(!!$('.sbm-dropdown-item', $pnl.mnu).length);
// Items.
var items = response.affiliates;
var items = response.contacts || [];
if (!items.length)
return $msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
return $pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
$items.append(sbm.populateItem(sbm.getItemTemplate(), items[itemIdx]));
$items.fadeIn(50);
$table.append(co.populateItem(co.getItemTemplate(), items[itemIdx]));
}
sbm.populateItem = function ($item, item)
co.populateItem = function ($item, item)
{
if (!item) return;
$item.prop('id', sbm.itemIdPrefix + item.id);
$pnl.msgs.hide().empty();
$item.prop('id', co.getItemId(item));
$('.ContactName', $item).text(item.displayName);
$('.ContactType', $item).text(item.typeDesc);
$('.ContactAssociationCount', $item).on('click', function () { sbm.onClickAssociationCount(item.id); }).toggle(item.associationCount).find('.AssociationCount').text(item.associationCount);
if (item.associationCount)
$('.ContactAssociationCount', $item).text(item.associationCount).on('click', function () { co.onClickAssociationCount(item); }).addClass('sbm-action-text');
$('.ContactAddress', $item).text(item.addressSummary);
$('.ContactContact', $item).text(item.contact);
$('.ContactPhone', $item).text(item.phone);
$('.ContactNotes', $item).text(item.notes);
$('.StatusDesc', $item).text(item.statusDesc).addClass('sbm-status-' + item.statusCode.toLowerCase());
$('.sbm-caption .sbm-action').toggleClass('sbm-action', !item.deleted);
let $mnu = $('ul.sbm-dropdown-menu', $item).empty();
$('.ContactStatusDesc', $item).text(item.statusDesc).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
// Actions.
var $bgr = $('.sbm-burger', $item).hide();
let $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
if (!item.deleted)
{
$mnu.append(sbm.getItemMenuOption(sbm.lbl.edit, function () { sbm.updateItem(item.id) }));
$('.sbm-header .sbm-action.sbm-item-update', $item).off('click').on('click', function () { sbm.updateItem(item.id) });
$item.off('dblclick').on('dblclick', function () { sbm.updateItem(item.id) });
let fnUpd = function () { co.updateItem(item) };
$mnu.append(co.getItemMenuOption(sbm.lbl.edit, fnUpd, 'sbm-edit'));
$('.ContactName', $item).off('click').on('click', fnUpd).addClass('sbm-action-text');
$item.off('dblclick').on('dblclick', fnUpd);
}
$('.sbm-burger', $item).toggle(!!$('.sbm-dropdown-item', $mnu).length);
$('.sbm-panel-messages', $pnl.results).hide().empty();
$bgr.toggle(!!$('.sbm-dropdown-item', $mnu).length);
return $item;
}
//--------------------------------------------------------------
sbm.getFilterMenuOption = function (lbl, fn)
co.getItemId = function (item)
{
return sbm.getMenuOption(sbm.getFilterDropdownTemplate(), lbl, fn);
}
sbm.getItemMenuOption = function (lbl, fn)
{
return sbm.getMenuOption(sbm.getItemDropdownTemplate(), lbl, fn);
}
sbm.getMenuOption = function ($opt, lbl, fn)
{
return $opt.find('div.sbm-label').text(lbl).end().on('click', fn);
return 'Con_' + (item || {}).id;
}
//--------------------------------------------------------------
sbm.createItem = function (ind)
co.getFilterDropdownTemplate = function ()
{
let frm = $frm.contact;
sbm.clearControlErrors(frm);
$('.AffiliateId,.ContactExists,input[type="text"],textarea,select', frm).val('');
$('.ContactIndividual', frm).val(!!ind ? 1 : null);
$('.ContactStatus', frm).val(sbm.data.defaultStatusCode);
sbm.toggleContactControls(ind);
$dlg.contact.dialog('option', 'title', sbm.dlg.title.createContact);
sbm.openDialog($dlg.contact, 600, 600);
return $('.sbm-dropdown-menu.ContactList li.sbm-dropdown-item', $pnl.tmpls).clone();
}
sbm.toggleContactControls = function (ind)
co.getItemTemplate = function ()
{
let frm = $frm.contact;
$('.sbm-form-control.ContactType,.sbm-form-control.ContactName', frm).toggle(!ind).find('input,select').prop('disabled', !!ind);
$('.sbm-form-control.ContactFirstName,.sbm-form-control.ContactLastName', frm).toggle(!!ind).find('input,select').prop('disabled', !ind);
return $('table tr.sbm-row-item.Contact', $pnl.tmpls).clone();
}
co.getItemDropdownTemplate = function ()
{
return $('.sbm-dropdown-menu.Contact li.sbm-dropdown-item', $pnl.tmpls).clone();
}
//--------------------------------------------------------------
sbm.updateItem = function (id)
co.getFilterMenuOption = function (lbl, fn, cls)
{
$('.AffiliateId', $frm.contactId).val(id);
sbm.ajax.updateItem = sbm.ajax.updateItem || { url: sbm.url.base + 'Contact/Ajax/GetItem', formId: 'frmContactId', callbackFn: sbm.onUpdateItem };
sbm.doAjaxRequest(sbm.ajax.updateItem, 50);
return co.getMenuOption(co.getFilterDropdownTemplate(), lbl, fn, cls);
}
sbm.onUpdateItem = function (response)
co.getItemMenuOption = function (lbl, fn, cls)
{
return co.getMenuOption(co.getItemDropdownTemplate(), lbl, fn, cls);
}
co.getMenuOption = function ($opt, lbl, fn, cls)
{
return $opt.find('div.sbm-label').text(lbl).end().on('click', fn).addClass(cls);
}
//--------------------------------------------------------------
co.createItem = function (cfg, title)
{
co.clearItem(cfg);
let frm = $frm.item;
$('.ContactStatus', frm).val(co.data.defaultStatusCode).prop('readonly', false);
co.configureItemControls(cfg);
co.openItemDlg(title);
}
co.clearItem = function (cfg)
{
//sbm.debug('clearItem', cfg);
let frm = $frm.item;
sbm.clearItemForm(frm);
if (cfg.isIndividual) $('.ContactIsIndividual', frm).val(1);
if (cfg.isGroup) $('.ContactIsGroup', frm).val(1);
sbm.populateSelectCodeDesc('#cbContactType', co.data.organisationTypes);
sbm.populateSelectCodeDesc('#cbContactTitle', co.data.titles);
sbm.selectOrAdd('#cbContactTitle', "", "")
sbm.populateSelectCodeDesc('#cbContactSalutation', co.data.salutations);
sbm.populateSelectCodeDesc('#cbContactStatus', co.data.statuses);
}
sbm.clearItemForm = function ($frm)
{
sbm.clearControlErrors($frm);
$('.sbm-input,.sbm-textarea,.sbm-select,.sbm-checkbox', $frm).val('').prop('readonly', false).prop('disabled', false).removeAttr('checked');
}
co.configureItemControls = function (cfg)
{
sbm.configureItemControls($frm.item, cfg);
}
sbm.configureItemControls = function ($frm, cfg)
{
//sbm.debug('configureItemControls', cfg);
let fld = cfg.field || {};
let $ctrl = $('.sbm-form-control', $frm.item).show();
(fld.hide || []).forEach(function (v, i, a) { $ctrl.filter('.' + cfg.field.prefix + v).hide().find('.sbm-input,.sbm-textarea,.sbm-select,.sbm-checkbox').prop('disabled', true); });
(fld.readonly || []).forEach(function (v, i, a) { $ctrl.filter('.' + cfg.field.prefix + v).find('.sbm-input,.sbm.textarea,.sbm-select,.sbm-checkbox').prop('readonly', true).prop('disabled', true); });
}
co.openItemDlg = function (title)
{
if (title)$dlg.item.dialog('option', 'title', title);
sbm.openDialog($dlg.item, 640, 600);
}
//--------------------------------------------------------------
co.updateItem = function (item)
{
$('.ContactId', $frm.itemId).val(item.id);
co.ajax.updateItem = co.ajax.updateItem || { url: sbm.url.base + 'Contact/Ajax/GetItem', formId: 'frmContactId', callbackFn: co.onUpdateItem };
sbm.doAjaxRequest(co.ajax.updateItem, 50);
}
co.onUpdateItem = function (response)
{
//sbm.debug('onUpdateItem', response);
let frm = $frm.contact;
$('.AffiliateId,input[type="text"],textarea,select', frm).val('');
co.clearItem(response.config);
if (!response.success) return;
let item = response.affiliate;
sbm.toggleContactControls(item.individual);
$('.AffiliateId', frm).val(item.id);
$('.ContactExists', frm).val(1);
$('.ContactIndividual', frm).val(!!item.individual ? 1 : null);
$('.ContactType', frm).val(item.typeCode);
$('.ContactName', frm).val(item.name);
$('.ContactFirstName', frm).val(item.firstName);
$('.ContactLastName', frm).val(item.lastName);
$('.ContactNotes', frm).val(item.notes);
$('.ContactStatus', frm).val(item.statusCode);
sbm.clearControlErrors();
$dlg.contact.dialog('option', 'title', sbm.dlg.title.updateContact);
sbm.openDialog($dlg.contact, 600, 600);
let item = response.contact;
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select,.sbm-checkbox', $frm.item);
$ctrls.filter('.ContactId').val(item.id);
$ctrls.filter('.ContactExists').val(1);
$ctrls.filter('.ContactType').val(item.typeCode);
$ctrls.filter('.ContactProspect').prop('checked', !!item.prospect);
$ctrls.filter('.ContactNotes').val(item.notes);
$ctrls.filter('.ContactStatus').val(item.statusCode);
sbm.populateFieldValues(response.config, $frm.item, item.field);
co.configureItemControls(response.config);
co.openItemDlg(sbm.dlg.title.updateContact);
}
sbm.populateFieldValues = function (cfg, $frm, fld)
{
let val = (fld || {}).value || [];
let $ctrl = $('.sbm-form-control', $frm.item).show();
for (var name in val) { $ctrl.filter('.' + cfg.field.prefix + name).find('.sbm-input,.sbm-textarea,.sbm-select').val(val[name]).end().find('.sbm-checkbox').prop('checked',!!val[name]); };
}
//--------------------------------------------------------------
sbm.storeItem = function ()
co.storeItem = function ()
{
sbm.ajax.storeItem = sbm.ajax.storeItem || { url: sbm.url.base + 'Contact/Ajax/StoreItem', formId: 'frmContact', callbackFn: sbm.onStoreItem };
sbm.doAjaxRequest(sbm.ajax.storeItem, 50);
co.ajax.storeItem = co.ajax.storeItem || { url: sbm.url.base + 'Contact/Ajax/StoreItem', formId: 'frmContact', callbackFn: co.onStoreItem };
sbm.doAjaxRequest(co.ajax.storeItem, 50);
}
sbm.onStoreItem = function (response)
co.onStoreItem = function (response)
{
//sbm.debug('onStoreItem', response);
sbm.refreshControlValues(response.controlValues);
if (!response.success) return;
$dlg.contact.dialog('close');
$dlg.item.dialog('close');
var item = response.affiliate;
var $item = $('#' + sbm.itemIdPrefix + item.id);
var item = response.contact;
var $item = $('#' + co.getItemId(item), $pnl.table);
if (!$item.length)
{
$item = sbm.getItemTemplate();
$('.sbm-panel-item-list', $pnl.results).prepend($item).show();
$item = co.getItemTemplate();
$('table tbody', $pnl.table).prepend($item).show();
}
$item.replaceWith(sbm.populateItem(sbm.getItemTemplate(), item));
co.populateItem($item, item);
}
//--------------------------------------------------------------
sbm.onClickAssociationCount = function (id)
co.onClickAssociationCount = function (item)
{
if (!(id * 1)) return;
if (!item.id) return;
sbm.doPleaseWait();
let frm = $frm.contactId;
$('.AffiliateId', frm).val(id);
let frm = $frm.itemId;
$('.ContactId', frm).val(item.id);
frm.prop('action', sbm.url.base + 'Association').submit();
}
//--------------------------------------------------------------
$(function ()
{
$pnl.contacts = $('.sbm-panel.Contacts');
$pnl.filter = $('.sbm-panel-filter', $pnl.contacts);
$pnl.results = $('.sbm-panel-results', $pnl.contacts);
$pnl.items = $('.sbm-panel.Contacts');
$pnl.header = $('.sbm-panel-header', $pnl.items);
$pnl.bgr = $('.sbm-burger', $pnl.header);
$pnl.mnu = $('ul.sbm-dropdown-menu', $pnl.bgr);
$pnl.table = $('.sbm-panel-item-table', $pnl.items);
$pnl.msgs = $('.sbm-panel-messages', $pnl.table);
$pnl.tmpls = $('.sbm-panel-item-template', $pnl.items);
$('.sbm-input, .sbm-textarea').on('input', function () { sbm.clearControlError(this); });
$('.sbm-select').on('change', function () { sbm.clearControlError(this); });
$frm.filter = $('#frmContactFilter', $pnl.items);
$frm.filter.on('input', '.FilterSearch', function () { co.refreshResults(250); }).on('change', '.FilterContactType', function () { co.refreshResults(50); });
$frm.filter = $('#frmContactFilter');
$('.FilterContact', $frm.filter).on('input', function () { sbm.refreshResults(250); });
$('.FilterContactType', $frm.filter).on('change', function () { sbm.refreshResults(50); });
$frm.contactId = $('#frmContactId');
$frm.contact = $('#frmContact');
$frm.itemId = $('#frmContactId');
$frm.item = $('#frmContact');
$frm.item.on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
var opt = sbm.dlgOpts();
opt.buttons[sbm.lbl.ok] = function () { sbm.storeItem(); };
opt.buttons[sbm.lbl.ok] = function () { co.storeItem(); };
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
$dlg.contact = $('#dlgContact').dialog(opt);
$dlg.item = $('#dlgContact').dialog(opt);
setTimeout(sbm.refreshResults, 250);
setTimeout(co.refreshResults, 250);
});
//--------------------------------------------------------------
}(window, window.document));
/* The End */
@@ -97,6 +97,13 @@
return index % 2 == 1 ? (cName || "other") : "";
});
}
sbm.selectOrAdd = function ($sel, code, desc)
{
$sel = $($sel);
if ($sel.val(code).val() == code) return;
$sel.append($('<option>').prop('value', code).text(desc));
$sel.val(code);
}
sbm.populateSelect = function ($sel, values, code, desc)
{
code = code || 'code';
@@ -107,7 +114,7 @@
}
sbm.populateSelectCodeDesc = function ($sel, values)
{
sbm.populateSelect($sel, values);
sbm.populateSelect($($sel), values);
}
sbm.checkTextAreaMaxLength = function (ctrl, len)
{
@@ -521,6 +528,11 @@
return this.css('visibility', function (i, visibility) { return (visibility == 'visible') ? 'hidden' : 'visible'; });
};
$.fn.removeStatusClasses = function ()
{
return this.removeClass(function (idx, name) { return (name.match(/(^|\s)sbm-status-\S+/g) || []).join(' '); });
};
if (sbm.keepLoggedIn)
sbm.configureKeepLoggedIn();
else if (!sbm.awaitingLogin)
@@ -58,7 +58,7 @@
$('.VehicleClassModel', $item).text(item.model);
$('.VehicleClassDerivative', $item).text(item.derivative);
$('.VehicleClassDescription', $item).text(item.descBrief);
$('.VehicleClassStatusDesc', $item).text(item.statusDesc).removeClass(function (idx, name) { return (name.match(/(^|\s)sbm-status-\S+/g) || []).join(' '); }).addClass('sbm-status-' + item.statusCode.toLowerCase());
$('.VehicleClassStatusDesc', $item).text(item.statusDesc).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
// Actions.
let fnUpd = function () { vc.updateItem($item, item) };
var $bgr = $('.sbm-burger', $item).invisible();
@@ -166,7 +166,7 @@
$dlg.item.dialog('close');
var item = response.vehicleClass;
var $item = $('#' + vc.getItemId(item));
var $item = $('#' + vc.getItemId(item), $pnl.table);
if (!$item.length)
{
$item = vc.getItemRowTemplate();