Web app logon.
This commit is contained in:
@@ -117,6 +117,18 @@
|
||||
<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">
|
||||
<value>Association</value>
|
||||
</data>
|
||||
<data name="association.caption.association.create" xml:space="preserve">
|
||||
<value>Create Association</value>
|
||||
</data>
|
||||
<data name="association.caption.association.update" xml:space="preserve">
|
||||
<value>Update Association</value>
|
||||
</data>
|
||||
<data name="association.caption.associations" xml:space="preserve">
|
||||
<value>Associations</value>
|
||||
</data>
|
||||
<data name="commodity.caption.commodities" xml:space="preserve">
|
||||
<value>Commodities</value>
|
||||
</data>
|
||||
@@ -156,6 +168,9 @@
|
||||
<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>
|
||||
@@ -189,6 +204,9 @@
|
||||
<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>
|
||||
@@ -198,6 +216,9 @@
|
||||
<data name="label.create.organisation" xml:space="preserve">
|
||||
<value>Create Organisation</value>
|
||||
</data>
|
||||
<data name="label.customers" xml:space="preserve">
|
||||
<value>Customers</value>
|
||||
</data>
|
||||
<data name="label.description" xml:space="preserve">
|
||||
<value>Description</value>
|
||||
</data>
|
||||
@@ -279,6 +300,9 @@
|
||||
<data name="label.signout" xml:space="preserve">
|
||||
<value>Sign-out</value>
|
||||
</data>
|
||||
<data name="label.Suppliers" xml:space="preserve">
|
||||
<value>Suppliers</value>
|
||||
</data>
|
||||
<data name="label.type" xml:space="preserve">
|
||||
<value>Type</value>
|
||||
</data>
|
||||
|
||||
@@ -18,142 +18,164 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App
|
||||
{
|
||||
//=======================================================================
|
||||
public class SbmApplication_Portal : SbmApplication_Web
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private PropertySet properties;
|
||||
private Dictionary<String, SbmAppConfig> appConfigs = new Dictionary<string, SbmAppConfig>();
|
||||
private Dictionary<String, SbmEmailConfig> emailConfigs = new Dictionary<string, SbmEmailConfig>();
|
||||
// Session contexts.
|
||||
private static ushort sessionContextIdx_Next = 100;
|
||||
private ushort sessionContextIdx_Control = 0;
|
||||
private class SessionContextData
|
||||
{
|
||||
public SessionContextData(SbmSessionContext_Web sessionContext)
|
||||
{
|
||||
SessionContext = sessionContext;
|
||||
}
|
||||
public SbmSessionContext_Web SessionContext { get; }
|
||||
public ISacsDatabase ControlDatabase { get; set; }
|
||||
public ISacsDatabase BusMgrDatabase { get; set; }
|
||||
}
|
||||
private readonly Dictionary<int, SessionContextData> sessionContexts = new Dictionary<int, SessionContextData>();
|
||||
//=======================================================================
|
||||
public class SbmApplication_Portal : SbmApplication_Web
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private PropertySet properties;
|
||||
private Dictionary<String, SbmAppConfig> appConfigs = new Dictionary<string, SbmAppConfig>();
|
||||
private Dictionary<String, SbmEmailConfig> emailConfigs = new Dictionary<string, SbmEmailConfig>();
|
||||
private ISacsDatabase controlDatabase = null;
|
||||
// Session contexts.
|
||||
private static ushort sessionContextIdx_Next = 100;
|
||||
private class SessionContextData
|
||||
{
|
||||
public SessionContextData(SbmSessionContext_Web sessionContext)
|
||||
{
|
||||
SessionContext = sessionContext;
|
||||
}
|
||||
public SbmSessionContext_Web SessionContext { get; }
|
||||
public List<string> DbIdentifiers { get; } = new List<string>();
|
||||
public ISacsDatabase BusMgrDatabase { get; set; }
|
||||
}
|
||||
private readonly Dictionary<int, SessionContextData> sessionContexts = new Dictionary<int, SessionContextData>();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SbmApplication_Portal(IConfiguration configuration) : base ()
|
||||
{
|
||||
InitialiseTemporaryLoggingFolder();
|
||||
try
|
||||
{
|
||||
properties = new PropertySet();
|
||||
SbmGlobals.System = (SbmGlobals_Web.System = (System_Web = new SbmSystem_Web(properties)));
|
||||
Configuration = configuration;
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Error(GetType().Name + ".CTR " + ExceptionUtil.GetErrorStateMessage(exc));
|
||||
throw exc;
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SbmApplication_Portal(IConfiguration configuration) : base()
|
||||
{
|
||||
InitialiseTemporaryLoggingFolder();
|
||||
try
|
||||
{
|
||||
properties = new PropertySet();
|
||||
SbmGlobals.System = (SbmGlobals_Web.System = (System_Web = new SbmSystem_Web(properties)));
|
||||
Configuration = configuration;
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Error(GetType().Name + ".CTR " + ExceptionUtil.GetErrorStateMessage(exc));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
// Application Configuration.
|
||||
public override SbmAppConfig AppConfig { get { return appConfigs.Values.ToList().getConfigForApplication(); } }
|
||||
// Session Configuration.
|
||||
public override String SessionCookieName { get { return Sbm.Config.Portal.Session.Cookie.Name; } }
|
||||
public override List<ushort> GetSessionContextIdxs()
|
||||
{
|
||||
return sessionContexts.Values.Select(item => item.SessionContext.Index).ToList();
|
||||
}
|
||||
public override SbmSessionContext GetSessionContext(ushort index)
|
||||
{
|
||||
return sessionContexts.GetValue(index, null)?.SessionContext ?? null;
|
||||
}
|
||||
public override ISacsDatabase GetControlDatabase(SbmSessionContext sessionContext)
|
||||
{
|
||||
return sessionContexts.GetValue(sessionContext.Index, null)?.ControlDatabase;
|
||||
}
|
||||
public override ISacsDatabase GetBusMgrDatabase(SbmSessionContext sessionContext)
|
||||
{
|
||||
return sessionContexts.GetValue(sessionContext.Index, null)?.BusMgrDatabase;
|
||||
}
|
||||
public override SbmEmailConfig EmailConfig { get { return emailConfigs.Values.ToList().getConfigForSession(AppConfig); } }
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
// Application Configuration.
|
||||
public override SbmAppConfig AppConfig { get { return appConfigs.Values.ToList().getConfigForApplication(); } }
|
||||
// Session Configuration.
|
||||
public override String SessionCookieName { get { return Sbm.Config.Portal.Session.Cookie.Name; } }
|
||||
public override List<ushort> GetSessionContextIdxs()
|
||||
{
|
||||
return sessionContexts.Values.Select(item => item.SessionContext.Index).ToList();
|
||||
}
|
||||
public override SbmSessionContext GetSessionContext(ushort index)
|
||||
{
|
||||
return sessionContexts.GetValue(index, null)?.SessionContext ?? null;
|
||||
}
|
||||
public override ISacsDatabase GetControlDatabase()
|
||||
{
|
||||
return controlDatabase;
|
||||
}
|
||||
public override ISacsDatabase GetTemplateDatabase()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
public override List<string> GetDbIdentifiers(SbmSessionContext sessionContext)
|
||||
{
|
||||
return sessionContexts.GetValue(sessionContext.Index, null)?.DbIdentifiers ?? new List<string>();
|
||||
}
|
||||
public override ISacsDatabase GetBusMgrDatabase(SbmSessionContext sessionContext)
|
||||
{
|
||||
return sessionContexts.GetValue(sessionContext.Index, null)?.BusMgrDatabase;
|
||||
}
|
||||
public override SbmEmailConfig EmailConfig { get { return emailConfigs.Values.ToList().getConfigForSession(AppConfig); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Initialisation.
|
||||
/// <summary>Initialise environment - from Startup.</summary>
|
||||
internal void InitWebHostEnvironment(IWebHostEnvironment env)
|
||||
{
|
||||
InitEnvironment(env);
|
||||
}
|
||||
/// <summary>Initialise environment - from internal (above) or unit tests.</summary>
|
||||
protected void InitEnvironment(IWebHostEnvironment env)
|
||||
{
|
||||
String fn = GetType().Name + ".InitEnvironment";
|
||||
Development = env.IsDevelopment();
|
||||
environmentName = env.EnvironmentName;
|
||||
SaLogger.LogFilenamePrefix = "Sbm-Web-Onl";
|
||||
SaLogger.IncludeHostInFileMessage = false;
|
||||
SaLogger.IncludeUserInFileMessage = false;
|
||||
//-------------------------------------------------------------------
|
||||
// Initialisation.
|
||||
/// <summary>Initialise environment - from Startup.</summary>
|
||||
internal void InitWebHostEnvironment(IWebHostEnvironment env)
|
||||
{
|
||||
InitEnvironment(env);
|
||||
}
|
||||
/// <summary>Initialise environment - from internal (above) or unit tests.</summary>
|
||||
protected void InitEnvironment(IWebHostEnvironment env)
|
||||
{
|
||||
String fn = GetType().Name + ".InitEnvironment";
|
||||
Development = env.IsDevelopment();
|
||||
environmentName = env.EnvironmentName;
|
||||
SaLogger.LogFilenamePrefix = "Sbm-Web-Onl";
|
||||
SaLogger.IncludeHostInFileMessage = false;
|
||||
SaLogger.IncludeUserInFileMessage = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Load server configuration.
|
||||
var builder = new ConfigurationBuilder()
|
||||
.SetBasePath(env.ContentRootPath)
|
||||
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
|
||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: false)
|
||||
.AddJsonFile($"appsettings.machine.{SbmSystem.ComputerName}.json", optional: false, reloadOnChange: false)
|
||||
.AddEnvironmentVariables();
|
||||
SbmConfiguration = builder.Build();
|
||||
try
|
||||
{
|
||||
// Load server configuration.
|
||||
var builder = new ConfigurationBuilder()
|
||||
.SetBasePath(env.ContentRootPath)
|
||||
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
|
||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: false)
|
||||
.AddJsonFile($"appsettings.machine.{SbmSystem.ComputerName}.json", optional: false, reloadOnChange: false)
|
||||
.AddEnvironmentVariables();
|
||||
SbmConfiguration = builder.Build();
|
||||
|
||||
// Application configuration.
|
||||
appConfigs = SbmAppConfigHelper.ExtractAppConfigs(SbmConfiguration.GetSection("AppConfigs"));
|
||||
emailConfigs = SbmEmailConfigHelper.ExtractEmailConfigs(SbmConfiguration.GetSection("EmailConfigs"));
|
||||
LoggingRootFolder = AppConfig.Logging.RootFolder;
|
||||
// Application configuration.
|
||||
appConfigs = SbmAppConfigHelper.ExtractAppConfigs(SbmConfiguration.GetSection("AppConfigs"));
|
||||
emailConfigs = SbmEmailConfigHelper.ExtractEmailConfigs(SbmConfiguration.GetSection("EmailConfigs"));
|
||||
LoggingRootFolder = AppConfig.Logging.RootFolder;
|
||||
|
||||
// Application instance.
|
||||
if (AppConfig.Instance.EqualsCI("Dev")) instanceType = Sbm.InstanceType.Dev;
|
||||
else if (AppConfig.Instance.ContainsCI("Q")) instanceType = Sbm.InstanceType.QC;
|
||||
else if (AppConfig.Instance.ContainsCI("UAT")) instanceType = Sbm.InstanceType.UAT;
|
||||
else if (AppConfig.Instance.EqualsCI("PreProd")) instanceType = Sbm.InstanceType.UAT;
|
||||
// Application instance.
|
||||
if (AppConfig.Instance.EqualsCI("Dev")) instanceType = Sbm.InstanceType.Dev;
|
||||
else if (AppConfig.Instance.ContainsCI("Q")) instanceType = Sbm.InstanceType.QC;
|
||||
else if (AppConfig.Instance.ContainsCI("UAT")) instanceType = Sbm.InstanceType.UAT;
|
||||
else if (AppConfig.Instance.EqualsCI("PreProd")) instanceType = Sbm.InstanceType.UAT;
|
||||
|
||||
// Initialise hard-coded logging path.
|
||||
if (StringUtil.IsEmpty(LoggingRootFolder))
|
||||
{
|
||||
if (SbmSystem.ComputerName.EqualsCI("WIN-BPCLM1QUOMT"))
|
||||
LoggingRootFolder = @"D:\Sbmonite\Logs\" + (Development ? "Dev" : "Test");
|
||||
}
|
||||
if (DirectoryUtil.DirectoryExists(LoggingRootFolder))
|
||||
SaLogger.LogFolder = LoggingRootFolder;
|
||||
LogApplicationStart(fn);
|
||||
// Initialise hard-coded logging path.
|
||||
if (StringUtil.IsEmpty(LoggingRootFolder))
|
||||
{
|
||||
if (SbmSystem.ComputerName.EqualsCI("WIN-BPCLM1QUOMT"))
|
||||
LoggingRootFolder = @"D:\Sbmonite\Logs\" + (Development ? "Dev" : "Test");
|
||||
}
|
||||
if (DirectoryUtil.DirectoryExists(LoggingRootFolder))
|
||||
SaLogger.LogFolder = LoggingRootFolder;
|
||||
LogApplicationStart(fn);
|
||||
|
||||
// Configure database connection.
|
||||
SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig();
|
||||
config.location = AppConfig.BusMgrDatabase.Location;
|
||||
config.user = AppConfig.BusMgrDatabase.User;
|
||||
config.pword = AppConfig.BusMgrDatabase.Password;
|
||||
SacsDatabase coreDatabase = SacsDatabaseConsole.OpenOdbcDatabase(config);
|
||||
if (coreDatabase.HasErrorState())
|
||||
SaLogger.Warn(fn + " Database initialisation error: " + coreDatabase.ErrorStateMessage);
|
||||
// Control database connection.
|
||||
SacsDatabaseConsole.OdbcConfig odbcConfig = new SacsDatabaseConsole.OdbcConfig();
|
||||
odbcConfig.location = AppConfig.ControlDatabase.Location;
|
||||
odbcConfig.user = AppConfig.ControlDatabase.User;
|
||||
odbcConfig.pword = AppConfig.ControlDatabase.Password;
|
||||
controlDatabase = SacsDatabaseConsole.OpenOdbcDatabase(odbcConfig);
|
||||
if (controlDatabase.HasErrorState())
|
||||
SaLogger.Warn(fn + " Control Database initialisation error: " + controlDatabase.ErrorStateMessage);
|
||||
|
||||
// Session context - only one context available/necessary (for now).
|
||||
sessionContextIdx_Control = sessionContextIdx_Next++;
|
||||
SessionContextData sessionContextData = new SessionContextData(new SbmSessionContext_Web(sessionContextIdx_Control, Sbm.Application.WebPortal));
|
||||
sessionContextData.BusMgrDatabase = coreDatabase;
|
||||
sessionContexts.Add(sessionContextData.SessionContext.Index, sessionContextData);
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Error(fn + " " + ExceptionUtil.GetLogMessage(exc));
|
||||
}
|
||||
}
|
||||
// Configure BusMgr database connections.
|
||||
foreach (SbmAppConfig.DatabaseConfig dbConfig in AppConfig.BusMgrDatabases)
|
||||
{
|
||||
SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig();
|
||||
config.location = dbConfig.Location;
|
||||
config.user = dbConfig.User;
|
||||
config.pword = dbConfig.Password;
|
||||
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.BusMgrDatabase = coreDatabase;
|
||||
sessionContextData.DbIdentifiers.AddRange(dbConfig.Identifiers);
|
||||
sessionContexts.Add(sessionContextData.SessionContext.Index, sessionContextData);
|
||||
}
|
||||
else SaLogger.Warn(fn + " Database: " + coreDatabase.DatabaseName + ". Initialisation error: " + coreDatabase.ErrorStateMessage);
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Error(fn + " " + ExceptionUtil.GetLogMessage(exc));
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using static Sarand.BusinessMgr.Net.Standard.Base.App.Sbm.Config.Database;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App
|
||||
{
|
||||
@@ -22,15 +23,16 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App
|
||||
[JsonConstructor]
|
||||
private SbmSessionData_Portal(long sessionIdx, int itemIdx, SbmSessionContext sessionContext) :
|
||||
base(sessionIdx, itemIdx, sessionContext)
|
||||
{ }
|
||||
{}
|
||||
/// <summary>
|
||||
/// SessionData construction.
|
||||
/// <para>SessionContext and UserAccount must be supplied.</para>
|
||||
/// <para>Organisation is optional.</para>
|
||||
/// </summary>
|
||||
public SbmSessionData_Portal(SbmSessionContext sessionContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation) :
|
||||
public SbmSessionData_Portal(SbmSessionContext sessionContext, String dbIdentifier, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation) :
|
||||
base(sessionContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation)
|
||||
{
|
||||
DbIdentifier = dbIdentifier;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
@@ -68,6 +70,12 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App
|
||||
return false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Database context.
|
||||
|
||||
/// <summary>Database context specified on sign-in.</summary>
|
||||
public String DbIdentifier { get; set; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// User Profile.
|
||||
@@ -98,11 +106,22 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
}
|
||||
/// <summary>
|
||||
/// Contacts filter properties.
|
||||
/// </summary>
|
||||
/// <summary>Contacts filter properties.</summary>
|
||||
public ContactsData Contacts { get; } = new ContactsData();
|
||||
|
||||
// Associations filter.
|
||||
public class AssociationsData
|
||||
{
|
||||
public class FilterData
|
||||
{
|
||||
public uint PageNo { get; set; } = 1;
|
||||
public ushort PageLength { get; set; } = 16;
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
}
|
||||
/// <summary>Associations filter properties.</summary>
|
||||
public AssociationsData Associations { get; } = new AssociationsData();
|
||||
|
||||
// Commodities filter.
|
||||
public class CommoditiesData
|
||||
{
|
||||
@@ -113,9 +132,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
}
|
||||
/// <summary>
|
||||
/// Commodities filter properties.
|
||||
/// </summary>
|
||||
/// <summary>Commodities filter properties.</summary>
|
||||
public CommoditiesData Commodities { get; } = new CommoditiesData();
|
||||
}
|
||||
public UserProfileData Profile { get; protected set; } = new UserProfileData();
|
||||
|
||||
@@ -0,0 +1,400 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
|
||||
using Sarand.BusinessMgr.Net.Core.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.Net.Core.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)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_AssociationList";
|
||||
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.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 fn = GetType().Name + ".Ajax_GetItem";
|
||||
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(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 fn = GetType().Name + ".Ajax_StoreItem";
|
||||
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(fn + " Id not specified for existing Association.");
|
||||
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
if (!associationExists && SysId.IsValid(associationId))
|
||||
{
|
||||
SaLogger.Warn(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(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.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(fn + " Failed to insert association: " + AccountMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
}
|
||||
responseData.SetNotification(messageTitle, Localiser["msg.item.created"]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!AccountMgr.UpdateAssociation(association, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to update association [Id:" + SysId.ToString(association.Id) + "]: " + AccountMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
}
|
||||
responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]);
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateAssociationResponseData(association, responseData.association);
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Security;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public partial class AssociationController : SbmController_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public AssociationController(SbmLocaliser localiser, ILogger<AssociationController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[HttpGet]
|
||||
public IActionResult Index()
|
||||
{
|
||||
String fn = GetType().Name + ".Index";
|
||||
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
// Association page.
|
||||
Model_Association model = new Model_Association(Localiser);
|
||||
model.Paging.PageNo = SessionData_Portal.Profile.Associations.Filter.PageNo;
|
||||
model.Paging.PageLength = SessionData_Portal.Profile.Associations.Filter.PageLength;
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -31,7 +31,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Commodity data.
|
||||
private class CommodityData_List : AjaxResponse_Data.ItemData
|
||||
private class CommodityData_List : AjaxResponse_Data.ItemData_Base
|
||||
{
|
||||
public String TypeCode { get; set; }
|
||||
public String TypeDesc { get; set; }
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Affiliate data.
|
||||
private class AffiliateData_List : AjaxResponse_Data.ItemData
|
||||
private class AffiliateData_List : AjaxResponse_Data.ItemData_Base
|
||||
{
|
||||
public String DisplayName { get; set; }
|
||||
public String TypeCode { get; set; }
|
||||
|
||||
@@ -18,103 +18,102 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public class HomeController : SbmController_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
//=======================================================================
|
||||
public class HomeController : SbmController_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public HomeController(SbmLocaliser localiser, ILogger<HomeController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public HomeController(SbmLocaliser localiser, ILogger<HomeController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[HttpGet]
|
||||
public IActionResult Index()
|
||||
{
|
||||
String fn = GetType().Name + ".Index";
|
||||
//-------------------------------------------------------------------
|
||||
[HttpGet]
|
||||
public IActionResult Index()
|
||||
{
|
||||
|
||||
// Check for 'Keep Logged In' cookie.
|
||||
// NB Only allowed if there isn't a current user session.
|
||||
if (!ValidUserSession && AppConfig.Security.SignIn.KeepLoggedIn.Allowed)
|
||||
{
|
||||
// Extract parameters and validate that they are populated.
|
||||
String encryptedParams = GetRequestCookie(CookieName_KeepLoggedIn);
|
||||
KeepLoggedInParams keepLoggedInParams = ExtractKeepLoggedInParams(encryptedParams);
|
||||
String logPrefix = fn + " 'Keep Logged In' cookie found but ";
|
||||
String logSuffix = keepLoggedInParams.GetValidParams().Concat("", " ", ".");
|
||||
if (keepLoggedInParams.IsValid())
|
||||
{
|
||||
// User may be defined on any one of the BusinessMgr databases - need to find out which.
|
||||
// Identify session contexts with a BusMgr database that hosts the specified email address.
|
||||
List<ushort> sessionContextIdxs = SbmSessionContextHelper_Web.GetSessionContextIdxsForUsersBusMgrDatabase(keepLoggedInParams.EmailAddress);
|
||||
foreach (ushort sessionContextIdx in sessionContextIdxs)
|
||||
{
|
||||
// Consoles and Managers must be associated with the specific context.
|
||||
SbmSessionContext sessionContext = SbmSessionContextHelper_Web.GetSessionContext(sessionContextIdx);
|
||||
SbmUserContext_Web userContext = new SbmUserContext_Web(sessionContext);
|
||||
using (SaSecurityConsole securityConsoleForUser = App.CreateSecurityConsole(userContext))
|
||||
using (SbmAccountMgr accountMgrForUser = App.System.CreateAccountMgr(userContext))
|
||||
{
|
||||
using (SaSecurityItem securityItemUser = securityConsoleForUser.GetUserByEmail(keepLoggedInParams.EmailAddress))
|
||||
using (SbmAffiliate affiliateUser = accountMgrForUser.GetAffiliateById(keepLoggedInParams.AffiliateIdUser))
|
||||
using (SbmAssociation associationOrganisation = accountMgrForUser.GetAssociationById(keepLoggedInParams.AssociationIdOrganisation))
|
||||
using (SbmAffiliate affiliateOrganisation = accountMgrForUser.GetAffiliateById(associationOrganisation?.AffiliateIdOwner ?? null))
|
||||
{
|
||||
if (securityItemUser != null && affiliateUser != null && associationOrganisation != null && affiliateOrganisation != null)
|
||||
{
|
||||
if (securityItemUser.Id.Equals(keepLoggedInParams.SecurityItemId) && affiliateUser.UserId.Equals(securityItemUser.Id))
|
||||
{
|
||||
if (affiliateUser.IsStatusCurrent)
|
||||
{
|
||||
List<SysIdString> supervisedOrganisations = accountMgrForUser.GetAffiliatesSupervisedBy(affiliateUser.Id);
|
||||
String errorMessage = "";
|
||||
if (SignUserIn(userContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation, true, ref errorMessage))
|
||||
{
|
||||
SaLogger.Info(logPrefix + " 'Keep Logged In' cookie found." + logSuffix);
|
||||
break;
|
||||
}
|
||||
else SaLogger.Warn(logPrefix + "failed to sign user in: " + errorMessage + "." + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(logPrefix + "Affiliate is not active." + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(logPrefix + "Security Item and Affiliate are inconsistent. " + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(logPrefix + "Security Item or Affiliate not found. " + logSuffix);
|
||||
}
|
||||
}
|
||||
if (ValidUserSession)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!StringUtil.IsEmpty(encryptedParams))
|
||||
SaLogger.Warn(fn + " Keep Logged In cookie found but with incomplete details." + logSuffix);
|
||||
}
|
||||
// Check for 'Keep Logged In' cookie.
|
||||
// NB Only allowed if there isn't a current user session.
|
||||
if (!ValidUserSession && AppConfig.Security.SignIn.KeepLoggedIn.Allowed)
|
||||
{
|
||||
// Extract parameters and validate that they are populated.
|
||||
String encryptedParams = GetRequestCookie(CookieName_KeepLoggedIn);
|
||||
KeepLoggedInParams keepLoggedInParams = ExtractKeepLoggedInParams(encryptedParams);
|
||||
String logPrefix = $"{SysUtil.Fn} 'Keep Logged In' cookie found but ";
|
||||
String logSuffix = keepLoggedInParams.GetValidParams().Concat("", " ", ".");
|
||||
if (keepLoggedInParams.IsValid())
|
||||
{
|
||||
// User may be defined on any one of the BusinessMgr databases - need to find out which.
|
||||
// Identify session contexts with a BusMgr database that hosts the specified email address.
|
||||
List<ushort> sessionContextIdxs = SbmSessionContextHelper_Web.GetSessionContextIdxsForContextUserEmail(keepLoggedInParams.DbIdentifier, keepLoggedInParams.EmailAddress);
|
||||
foreach (ushort sessionContextIdx in sessionContextIdxs)
|
||||
{
|
||||
// Consoles and Managers must be associated with the specific context.
|
||||
SbmSessionContext sessionContext = SbmSessionContextHelper_Web.GetSessionContext(sessionContextIdx);
|
||||
SbmUserContext_Web userContext = new SbmUserContext_Web(sessionContext);
|
||||
using (SaSecurityConsole securityConsoleForUser = App.CreateSecurityConsole(userContext))
|
||||
using (SbmAccountMgr accountMgrForUser = App.System.CreateAccountMgr(userContext))
|
||||
{
|
||||
using (SaSecurityItem securityItemUser = securityConsoleForUser.GetUserByEmail(keepLoggedInParams.EmailAddress))
|
||||
using (SbmAffiliate affiliateUser = accountMgrForUser.GetAffiliateById(keepLoggedInParams.AffiliateIdUser))
|
||||
using (SbmAssociation associationOrganisation = accountMgrForUser.GetAssociationById(keepLoggedInParams.AssociationIdOrganisation))
|
||||
using (SbmAffiliate affiliateOrganisation = accountMgrForUser.GetAffiliateById(associationOrganisation?.AffiliateIdOwner ?? null))
|
||||
{
|
||||
if (securityItemUser != null && affiliateUser != null && associationOrganisation != null && affiliateOrganisation != null)
|
||||
{
|
||||
if (securityItemUser.Id.Equals(keepLoggedInParams.SecurityItemId) && affiliateUser.UserId.Equals(securityItemUser.Id))
|
||||
{
|
||||
if (affiliateUser.IsStatusCurrent)
|
||||
{
|
||||
List<SysIdString> supervisedOrganisations = accountMgrForUser.GetAffiliatesSupervisedBy(affiliateUser.Id);
|
||||
String errorMessage = "";
|
||||
if (SignUserIn(userContext, keepLoggedInParams.DbIdentifier, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation, true, ref errorMessage))
|
||||
{
|
||||
SaLogger.Info(logPrefix + " 'Keep Logged In' cookie found." + logSuffix);
|
||||
break;
|
||||
}
|
||||
else SaLogger.Warn(logPrefix + "failed to sign user in: " + errorMessage + "." + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(logPrefix + "Affiliate is not active." + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(logPrefix + "Security Item and Affiliate are inconsistent. " + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(logPrefix + "Security Item or Affiliate not found. " + logSuffix);
|
||||
}
|
||||
}
|
||||
if (ValidUserSession)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!StringUtil.IsEmpty(encryptedParams))
|
||||
SaLogger.Warn($"{SysUtil.Fn} Keep Logged In cookie found but with incomplete details." + logSuffix);
|
||||
}
|
||||
|
||||
// Redirect to sign-in if not signed-in.
|
||||
if (!ValidUserSession)
|
||||
{
|
||||
ClearKeepLoggedInCookie();
|
||||
return RedirectToAction("", "Security");
|
||||
}
|
||||
// Redirect to sign-in if not signed-in.
|
||||
if (!ValidUserSession)
|
||||
{
|
||||
ClearKeepLoggedInCookie();
|
||||
return RedirectToAction("", "Security");
|
||||
}
|
||||
|
||||
// Home page.
|
||||
Model_Home model = new Model_Home(Localiser);
|
||||
model.ProhibitCache = false;
|
||||
return View(model);
|
||||
}
|
||||
// Home page.
|
||||
Model_Home model = new Model_Home(Localiser);
|
||||
model.ProhibitCache = false;
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public IActionResult Error()
|
||||
{
|
||||
return View(new ErrorViewModel(Localiser) { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public IActionResult Error()
|
||||
{
|
||||
return View(new ErrorViewModel(Localiser) { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using static Sarand.BusinessMgr.Net.Standard.Base.App.Sbm.Config.Database;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
{
|
||||
@@ -52,7 +53,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
/// <para>- Open user session - store details against Sesion Data.</para>
|
||||
/// <para>- Set 'Keep logged in' cookie if required.</para>
|
||||
/// </summary>
|
||||
protected bool SignUserIn(ISbmUserContext userContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation, bool keepLoggedIn, ref String errorMessage)
|
||||
protected bool SignUserIn(ISbmUserContext userContext, String dbIdentifier, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation, bool keepLoggedIn, ref String errorMessage)
|
||||
{
|
||||
String fn = GetType().Name + ".SignUserIn";
|
||||
|
||||
@@ -125,7 +126,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
}
|
||||
|
||||
// Create session.
|
||||
OpenUserSession(userContext.SessionContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation);
|
||||
OpenUserSession(userContext.SessionContext, dbIdentifier, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation);
|
||||
|
||||
// Send the 'Keep Logged In' cookie if requested.
|
||||
if (affiliateUser.KeepLoggedIn_Portal)
|
||||
@@ -153,7 +154,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Start a new user session on sign-in.</summary>
|
||||
protected bool OpenUserSession(SbmSessionContext sessionContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation)
|
||||
protected bool OpenUserSession(SbmSessionContext sessionContext, String dbIdentifier, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation)
|
||||
{
|
||||
// Validate user properties.
|
||||
if (!SysId.IsValid(affiliateUser.Id)) return false;
|
||||
@@ -163,7 +164,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
CloseUserSession();
|
||||
|
||||
// Open session.
|
||||
return SetSessionData(new SbmSessionData_Portal(sessionContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation));
|
||||
return SetSessionData(new SbmSessionData_Portal(sessionContext, dbIdentifier, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation));
|
||||
}
|
||||
protected void CloseUserSession()
|
||||
{
|
||||
@@ -205,6 +206,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Keep-logged-in cookie value.
|
||||
private static readonly String ParamName_KeepLoggedIn_DbIdentifier = "dbi";
|
||||
private static readonly String ParamName_KeepLoggedIn_EmailAddress = "ema";
|
||||
private static readonly String ParamName_KeepLoggedIn_SecurityItemId = "sii";
|
||||
private static readonly String ParamName_KeepLoggedIn_AffiliateIdUser = "afiu";
|
||||
@@ -212,6 +214,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
private String GenerateKeepLoggedInCookieValue()
|
||||
{
|
||||
NameValueCollection keepLoggedInParams = new NameValueCollection();
|
||||
keepLoggedInParams.Add(ParamName_KeepLoggedIn_DbIdentifier, SessionData_Portal.DbIdentifier);
|
||||
keepLoggedInParams.Add(ParamName_KeepLoggedIn_EmailAddress, SessionData_Portal.User.EmailAddress);
|
||||
keepLoggedInParams.Add(ParamName_KeepLoggedIn_SecurityItemId, SysId.ToString(SessionData_Portal.User.SecurityItemId));
|
||||
keepLoggedInParams.Add(ParamName_KeepLoggedIn_AffiliateIdUser, SysId.ToString(SessionData_Portal.User.AffiliateId));
|
||||
@@ -222,6 +225,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
//-------------------------------------------------------------------
|
||||
public class KeepLoggedInParams
|
||||
{
|
||||
public String DbIdentifier { get; set; }
|
||||
public String EmailAddress { get; set; }
|
||||
public SysId SecurityItemId { get; set; }
|
||||
public SysId AffiliateIdUser { get; set; }
|
||||
@@ -230,7 +234,9 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
public List<String> GetValidParams()
|
||||
{
|
||||
List<String> values = new List<String>();
|
||||
if (!StringUtil.IsEmpty(EmailAddress))
|
||||
if (!StringUtil.IsBlank(DbIdentifier))
|
||||
values.Add("DbIdentifier: " + DbIdentifier);
|
||||
if (!StringUtil.IsBlank(EmailAddress))
|
||||
values.Add("EmailAddress: " + EmailAddress);
|
||||
if (SysId.IsValid(SecurityItemId))
|
||||
values.Add("SecurityItemId: " + SysId.ToString(SecurityItemId));
|
||||
@@ -244,7 +250,8 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
public bool IsValid()
|
||||
{
|
||||
return
|
||||
!StringUtil.IsEmpty(EmailAddress) &&
|
||||
!StringUtil.IsBlank(DbIdentifier) &&
|
||||
StringUtil.IsBlank(EmailAddress) &&
|
||||
SysId.IsValid(SecurityItemId) &&
|
||||
SysId.IsValid(AffiliateIdUser) &&
|
||||
SysId.IsValid(AssociationIdOrganisation);
|
||||
@@ -256,6 +263,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
if (!StringUtil.IsEmpty(encryptedParams))
|
||||
{
|
||||
NameValueCollection linkParams = DecryptParameters(encryptedParams, Base64IV_KeepLoggedIn, Base64Key_KeepLoggedIn);
|
||||
keepLoggedInParams.DbIdentifier = linkParams.Get(ParamName_KeepLoggedIn_DbIdentifier);
|
||||
keepLoggedInParams.EmailAddress = linkParams.Get(ParamName_KeepLoggedIn_EmailAddress);
|
||||
keepLoggedInParams.SecurityItemId = linkParams.Get(ParamName_KeepLoggedIn_SecurityItemId).ToSysId();
|
||||
keepLoggedInParams.AffiliateIdUser = linkParams.Get(ParamName_KeepLoggedIn_AffiliateIdUser).ToSysId();
|
||||
|
||||
@@ -54,16 +54,20 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
model.ValidateSignInData(responseData);
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
|
||||
// Identify session contexts with a BusMgr database that hosts the specified email address.
|
||||
List<ushort> sessionContextIdxs = SbmSessionContextHelper_Web.GetSessionContextIdxsForUsersBusMgrDatabase(model.EmailAddress);
|
||||
foreach (ushort sessionContextIdx in sessionContextIdxs)
|
||||
using (DisposableCollection<IDisposable> disposableItems = new DisposableCollection<IDisposable>())
|
||||
{
|
||||
SbmSessionContext sessionContext = SbmSessionContextHelper_Web.GetSessionContext(sessionContextIdx);
|
||||
SbmUserContext_Web userContext = new SbmUserContext_Web(sessionContext);
|
||||
|
||||
using (DisposableCollection<IDisposable> disposableItems = new DisposableCollection<IDisposable>())
|
||||
// Identify session contexts with a BusMgr database that hosts the specified email address.
|
||||
List<ushort> sessionContextIdxs = SbmSessionContextHelper_Web.GetSessionContextIdxsForContextUserEmail(model.DbIdentifier, model.EmailAddress);
|
||||
if (sessionContextIdxs.IsEmpty())
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), model.Localiser["security.msg.signin.invalid"]));
|
||||
foreach (ushort sessionContextIdx in sessionContextIdxs)
|
||||
{
|
||||
SbmSessionContext sessionContext = SbmSessionContextHelper_Web.GetSessionContext(sessionContextIdx);
|
||||
SbmUserContext_Web userContext = new SbmUserContext_Web(sessionContext);
|
||||
ISacsDatabase busMgrDatabase = App.GetBusMgrDatabase(sessionContext);
|
||||
if (busMgrDatabase == null) continue;
|
||||
|
||||
// Account manager.
|
||||
SaSecurityConsole securityConsoleForUser = App.CreateSecurityConsole(userContext);
|
||||
disposableItems.Add(securityConsoleForUser);
|
||||
@@ -73,27 +77,36 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
// User's security item.
|
||||
SaSecurityItem securityItemUser = GetSecurityItemForSignin(securityConsoleForUser, model);
|
||||
if (securityItemUser == null)
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), model.Localiser["security.msg.signin.invalid"]));
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve Security Item. Database: " + busMgrDatabase.DatabaseName + ". Email: " + model.EmailAddress);
|
||||
continue;
|
||||
}
|
||||
disposableItems.Add(securityItemUser);
|
||||
|
||||
// User's affiliate.
|
||||
SbmAffiliate affiliateUser = GetAffiliateForSignin(accountMgrForUser, model, securityItemUser);
|
||||
if (affiliateUser == null)
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), model.Localiser["security.msg.signin.invalid"]));
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve Affiliate for signin. Database: " + busMgrDatabase.DatabaseName + ". UserId: " + SysId.ToString(securityItemUser.Id));
|
||||
continue;
|
||||
}
|
||||
disposableItems.Add(affiliateUser);
|
||||
|
||||
// User's supervised organisations.
|
||||
List<SysIdString> supervisedOrganisations = accountMgrForUser.GetAffiliatesSupervisedBy(affiliateUser.Id);
|
||||
if (supervisedOrganisations.IsEmpty())
|
||||
{
|
||||
SaLogger.Warn(fn + " User has no supervised organisations. Email: " + model.EmailAddress);
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), model.Localiser["security.msg.signin.invalid"]));
|
||||
SaLogger.Warn(fn + " User has no supervised organisations. Database: " + busMgrDatabase.DatabaseName + ". Email: " + model.EmailAddress);
|
||||
continue;
|
||||
}
|
||||
|
||||
// User's organisation association.
|
||||
SbmAssociation associationOrganisation = GetOrganisationAssociationForSignIn(accountMgrForUser, model, affiliateUser, supervisedOrganisations);
|
||||
if (associationOrganisation == null)
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), model.Localiser["security.msg.signin.invalid"]));
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to identify Organisation Association. Database: " + busMgrDatabase.DatabaseName + ". Email: " + model.EmailAddress);
|
||||
continue;
|
||||
}
|
||||
disposableItems.Add(associationOrganisation);
|
||||
|
||||
// User's organisation affiliate.
|
||||
@@ -101,15 +114,22 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
disposableItems.Add(affiliateOrganisation);
|
||||
if (affiliateOrganisation == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve Affiliate for organisation. Id: " + SysId.ToString(associationOrganisation?.Id ?? null));
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), model.Localiser["security.msg.signin.invalid"]));
|
||||
SaLogger.Warn(fn + " Failed to retrieve Affiliate for organisation. Database: " + busMgrDatabase.DatabaseName + ". Id: " + SysId.ToString(associationOrganisation?.Id ?? null));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Initialise user session.
|
||||
String errorMessage = "";
|
||||
if (!SignUserIn(userContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation, model.KeepMeSignedIn, ref errorMessage))
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), errorMessage));
|
||||
if (SignUserIn(userContext, model.DbIdentifier, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation, model.KeepMeSignedIn, ref errorMessage))
|
||||
break;
|
||||
else return Json(responseData.SetControlError(nameof(model.EmailAddress), errorMessage));
|
||||
}
|
||||
}
|
||||
if (!(SessionData_Portal?.ValidUserSession ?? false))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to identify Suitable database. Email: " + model.EmailAddress);
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), model.Localiser["security.msg.signin.invalid"]));
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
responseData.Success = SessionData_Portal?.ValidUserSession ?? false;
|
||||
@@ -131,7 +151,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
}
|
||||
|
||||
// Validate password.
|
||||
if (!SbmPasswordHelper.VerifyHashedPassword(securityItemUser, model.Password) && !(DebugMode && model.EmailAddress.EqualsCI("ahoward@sarand.com")))
|
||||
if (!SbmPasswordHelper.VerifyHashedPassword(securityItemUser, model.Password) && !(DebugMode && model.EmailAddress.EqualsCI("andy@sarand.com")))
|
||||
{
|
||||
// Record invalid login attempt.
|
||||
securityItemUser.InvalidLoginCount++;
|
||||
@@ -331,8 +351,8 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
if (requestPasswordParams.IsValid())
|
||||
{
|
||||
// User may be defined on any one of the BusinessMgr databases - need to find out which.
|
||||
// Identify session contexts with a BusMgr database that hosts the specified email address.
|
||||
List<ushort> sessionContextIdxs = SbmSessionContextHelper_Web.GetSessionContextIdxsForUsersBusMgrDatabase(requestPasswordParams.EmailAddress);
|
||||
// Identify session contexts for databases with specified Id that hosts the specified email address.
|
||||
List<ushort> sessionContextIdxs = SbmSessionContextHelper_Web.GetSessionContextIdxsForContextUserEmail(requestPasswordParams.DbIdentifier, requestPasswordParams.EmailAddress);
|
||||
foreach (ushort sessionContextIdx in sessionContextIdxs)
|
||||
{
|
||||
// Consoles and Managers must be associated with the specific context.
|
||||
@@ -460,7 +480,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
if (responseData.HasControlErrors()) return Json(responseData);
|
||||
|
||||
// Identify session contexts with a BusMgr database that hosts the specified email address.
|
||||
List<ushort> sessionContextIdxs = SbmSessionContextHelper_Web.GetSessionContextIdxsForUsersBusMgrDatabase(model.EmailAddress);
|
||||
List<ushort> sessionContextIdxs = SbmSessionContextHelper_Web.GetSessionContextIdxsForContextUserEmail(model.DbIdentifier, model.EmailAddress);
|
||||
foreach (ushort sessionContextIdx in sessionContextIdxs)
|
||||
{
|
||||
SbmSessionContext sessionContext = SbmSessionContextHelper_Web.GetSessionContext(sessionContextIdx);
|
||||
@@ -519,13 +539,14 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
emailConsole.ReplaceDynamicEmailBodyTags(emailData, null);
|
||||
|
||||
// Replace dynamic tag for link back to change password page.
|
||||
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.RequestPassword]", GenerateRequestPasswordLink(securityItemUser.Id, affiliateUser.Id, securityItemUser.EmailAddress, ""));
|
||||
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.RequestPassword]", GenerateRequestPasswordLink(SessionData_Portal.DbIdentifier, securityItemUser.Id, affiliateUser.Id, securityItemUser.EmailAddress, ""));
|
||||
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.ExpiresMinutes]", GetRequestPasswordEmailLinkExpiresMinutes().ToString());
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Password request link.
|
||||
private static String ParamName_RequestPasswordEncrypted { get; } = "rpe";
|
||||
private static String ParamName_DbIdentifier { get; } = "dbi";
|
||||
private static String ParamName_EmailAddress { get; } = "ema";
|
||||
private static String ParamName_SecurityItemId { get; } = "sei";
|
||||
private static String ParamName_AffiliateId { get; } = "afi";
|
||||
@@ -536,9 +557,10 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
private static String Base64Key_RequestPassword { get; } = SacsEncryptionHelper.EncodePlainKey("[-SaBusMgr+<Request=Password>!^]", SacsEncryptionHelper.KeyLength);
|
||||
//private static String Base64IV_RequestPassword_Generated { get; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(Base64Key_RequestPassword);
|
||||
private static String Base64IV_RequestPassword { get; } = "iALRIxzrZIfrB4boNFRXfA==";
|
||||
private String GenerateRequestPasswordLink(SysId securityItemId, SysId affiliateId, String emailAddress, String requestPasswordToken)
|
||||
private String GenerateRequestPasswordLink(String dbIdentifier, SysId securityItemId, SysId affiliateId, String emailAddress, String requestPasswordToken)
|
||||
{
|
||||
NameValueCollection parameters = new NameValueCollection();
|
||||
parameters.Add(ParamName_DbIdentifier, dbIdentifier);
|
||||
parameters.Add(ParamName_EmailAddress, emailAddress);
|
||||
parameters.Add(ParamName_SecurityItemId, SysId.ToString(securityItemId));
|
||||
parameters.Add(ParamName_AffiliateId, SysId.ToString(affiliateId));
|
||||
@@ -558,6 +580,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
}
|
||||
private class RequestPasswordParams
|
||||
{
|
||||
public String DbIdentifier { get; set; }
|
||||
public String EmailAddress { get; set; }
|
||||
public SysId SecurityItemId { get; set; }
|
||||
public SysId AffiliateId { get; set; }
|
||||
@@ -567,7 +590,9 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
public List<String> GetValidParams()
|
||||
{
|
||||
List<String> values = new List<String>();
|
||||
if (!StringUtil.IsEmpty(EmailAddress))
|
||||
if (!StringUtil.IsBlank(DbIdentifier))
|
||||
values.Add("DbIdentifier: " + DbIdentifier);
|
||||
if (!StringUtil.IsBlank(EmailAddress))
|
||||
values.Add("Email: " + EmailAddress);
|
||||
if (SysId.IsValid(SecurityItemId))
|
||||
values.Add("SecurityItemId: " + SysId.ToString(SecurityItemId));
|
||||
@@ -575,7 +600,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
values.Add("AffiliateId: " + SysId.ToString(AffiliateId));
|
||||
if (DateUtil.IsValid(ExpiresAt))
|
||||
values.Add("Expires: " + DateUtil.FormatXmlDateTime(ExpiresAt));
|
||||
if (!StringUtil.IsEmpty(Token))
|
||||
if (!StringUtil.IsBlank(Token))
|
||||
values.Add("Token: " + Token);
|
||||
return values;
|
||||
}
|
||||
@@ -583,7 +608,8 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
public bool IsValid()
|
||||
{
|
||||
return
|
||||
!StringUtil.IsEmpty(EmailAddress) &&
|
||||
!StringUtil.IsBlank(DbIdentifier) &&
|
||||
StringUtil.IsBlank(EmailAddress) &&
|
||||
SysId.IsValid(SecurityItemId) &&
|
||||
SysId.IsValid(AffiliateId) &&
|
||||
DateUtil.IsValid(ExpiresAt) && ExpiresAt >= DateTime.Now;
|
||||
@@ -606,6 +632,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
if (!StringUtil.IsEmpty(encryptedParams))
|
||||
{
|
||||
NameValueCollection linkParams = DecryptParameters(encryptedParams, Base64IV_RequestPassword, Base64Key_RequestPassword);
|
||||
requestPasswordParams.DbIdentifier = linkParams.Get(ParamName_DbIdentifier);
|
||||
requestPasswordParams.EmailAddress = linkParams.Get(ParamName_EmailAddress);
|
||||
requestPasswordParams.SecurityItemId = new SysId(StringUtil.ToInt(linkParams.Get(ParamName_SecurityItemId)));
|
||||
requestPasswordParams.AffiliateId = new SysId(StringUtil.ToInt(linkParams.Get(ParamName_AffiliateId)));
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
String logSuffix = requestPasswordParams.GetValidParams().Concat("", " ", ".");
|
||||
// User may be defined on any one of the BusinessMgr databases - need to find out which.
|
||||
// Identify session contexts with a BusMgr database that hosts the specified email address.
|
||||
List<ushort> sessionContextIdxs = SbmSessionContextHelper_Web.GetSessionContextIdxsForUsersBusMgrDatabase(requestPasswordParams.EmailAddress);
|
||||
List<ushort> sessionContextIdxs = SbmSessionContextHelper_Web.GetSessionContextIdxsForContextUserEmail(requestPasswordParams.DbIdentifier, requestPasswordParams.EmailAddress);
|
||||
foreach (ushort sessionContextIdx in sessionContextIdxs)
|
||||
{
|
||||
// Consoles and Managers must be associated with the specific context.
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
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.Net.Core.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_Base.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();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -30,6 +30,8 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Models
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Form properties.
|
||||
/// <summary>Database config identifier.</summary>
|
||||
public String DbIdentifier { get; set; }
|
||||
public String EmailAddress { get; set; }
|
||||
public String PasswordCurrent { get; set; }
|
||||
public String Password { get; set; }
|
||||
@@ -44,17 +46,31 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Models
|
||||
// Sign-in.
|
||||
public bool ValidateSignInData(SbmController_Base.AjaxResponse_Data responseData)
|
||||
{
|
||||
// Email address.
|
||||
responseData.SetControlValue(nameof(EmailAddress), EmailAddress);
|
||||
if (StringUtil.IsEmpty(EmailAddress))
|
||||
responseData.SetControlError(nameof(EmailAddress), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SacsDataValidationHelper.IsValidEmailAddress(EmailAddress))
|
||||
responseData.SetControlError(nameof(EmailAddress), Localiser["msg.validation.invalid.value"]);
|
||||
{
|
||||
// Database context.
|
||||
String controlName = nameof(DbIdentifier);
|
||||
responseData.SetControlValue(controlName, DbIdentifier);
|
||||
if (StringUtil.IsEmpty(DbIdentifier))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
}
|
||||
|
||||
// Password.
|
||||
// NB Do not return the password value in the response.
|
||||
if (StringUtil.IsEmpty(Password))
|
||||
responseData.SetControlError(nameof(Password), Localiser["msg.validation.mandatory.value"]);
|
||||
{
|
||||
// Email address.
|
||||
String controlName = nameof(EmailAddress);
|
||||
responseData.SetControlValue(controlName, EmailAddress);
|
||||
if (StringUtil.IsEmpty(EmailAddress))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SacsDataValidationHelper.IsValidEmailAddress(EmailAddress))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
|
||||
{
|
||||
// Password.
|
||||
// NB Do not return the password value in the response.
|
||||
String controlName = nameof(Password);
|
||||
if (StringUtil.IsEmpty(Password))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
}
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
@@ -96,12 +112,23 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Models
|
||||
// Request Password.
|
||||
public bool ValidateRequestPasswordData(SbmController_Base.AjaxResponse_Data responseData)
|
||||
{
|
||||
// Email address.
|
||||
responseData.SetControlValue(nameof(EmailAddress), EmailAddress);
|
||||
if (StringUtil.IsEmpty(EmailAddress))
|
||||
responseData.SetControlError(nameof(EmailAddress), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SacsDataValidationHelper.IsValidEmailAddress(EmailAddress))
|
||||
responseData.SetControlError(nameof(EmailAddress), Localiser["msg.validation.invalid.value"]);
|
||||
{
|
||||
// Database context.
|
||||
String controlName = nameof(DbIdentifier);
|
||||
responseData.SetControlValue(controlName, DbIdentifier);
|
||||
if (StringUtil.IsEmpty(DbIdentifier))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
}
|
||||
|
||||
{
|
||||
// Email address.
|
||||
String controlName = nameof(EmailAddress);
|
||||
responseData.SetControlValue(controlName, EmailAddress);
|
||||
if (StringUtil.IsEmpty(EmailAddress))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SacsDataValidationHelper.IsValidEmailAddress(EmailAddress))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
@@ -1,44 +1,43 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<CopyRefAssembliesToPublishDirectory>false</CopyRefAssembliesToPublishDirectory>
|
||||
<RootNamespace>Sarand.BusinessMgr.Net.Core.Web</RootNamespace>
|
||||
<AssemblyName>Sarand.BusinessMgr.Net.Core.Web</AssemblyName>
|
||||
<Description>SaBusinessMgrCoreWebPortal</Description>
|
||||
<PackageId>SaBusinessMgrCoreWebPortal</PackageId>
|
||||
<Authors>Sarand</Authors>
|
||||
<Product>BusinessMgr</Product>
|
||||
<Version>3.0.0</Version>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<CopyRefAssembliesToPublishDirectory>false</CopyRefAssembliesToPublishDirectory>
|
||||
<RootNamespace>Sarand.BusinessMgr.Net.Core.Web</RootNamespace>
|
||||
<AssemblyName>Sarand.BusinessMgr.Net.Core.Web</AssemblyName>
|
||||
<Description>SaBusinessMgrCoreWebPortal</Description>
|
||||
<PackageId>SaBusinessMgrCoreWebPortal</PackageId>
|
||||
<Authors>Sarand</Authors>
|
||||
<Product>BusinessMgr</Product>
|
||||
<Version>3.0.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="jQuery.UI.Combined" Version="1.12.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.16" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="jQuery.UI.Combined" Version="1.13.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.31" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsCoreWeb\SacsCoreWeb.csproj" />
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardBase\SacsStandardBase.csproj" />
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardDbas\SacsStandardDbas.csproj" />
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardProc\SacsStandardProc.csproj" />
|
||||
<ProjectReference Include="..\SaBusMgrCoreProcs\SaBusMgrCoreProcs.csproj" />
|
||||
<ProjectReference Include="..\SaBusMgrCoreWeb\SaBusMgrCoreWeb.csproj" />
|
||||
<ProjectReference Include="..\SaBusMgrStandardBase\SaBusMgrStandardBase.csproj" />
|
||||
<ProjectReference Include="..\SaBusMgrStandardDbas\SaBusMgrStandardDbas.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsCoreWeb\SacsCoreWeb.csproj" />
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardBase\SacsStandardBase.csproj" />
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardDbas\SacsStandardDbas.csproj" />
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardProc\SacsStandardProc.csproj" />
|
||||
<ProjectReference Include="..\SaBusMgrCoreProcs\SaBusMgrCoreProcs.csproj" />
|
||||
<ProjectReference Include="..\SaBusMgrCoreWeb\SaBusMgrCoreWeb.csproj" />
|
||||
<ProjectReference Include="..\SaBusMgrStandardBase\SaBusMgrStandardBase.csproj" />
|
||||
<ProjectReference Include="..\SaBusMgrStandardDbas\SaBusMgrStandardDbas.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.Machine.Sarand107.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.Machine.Sarand110.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Views\Association\" />
|
||||
<Folder Include="Views\Transactions\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Views\Transactions\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
@model Model_Association
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
/* Associations - Index */
|
||||
ViewData["Title"] = "Associations";
|
||||
}
|
||||
|
||||
<div class="sbm-panel Associations">
|
||||
|
||||
<script type="text/javascript">
|
||||
sbm.lbl.refresh = '@(Localiser.GetJavascriptText("label.refresh"))';
|
||||
sbm.lbl.create = '@(Localiser.GetJavascriptText("label.create"))';
|
||||
sbm.lbl.edit = '@(Localiser.GetJavascriptText("label.edit"))';
|
||||
</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>
|
||||
}
|
||||
|
||||
</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"]: <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>
|
||||
|
||||
@* 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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<partial name="Panel-AssociationDialog.cshtml" />
|
||||
@@ -0,0 +1,81 @@
|
||||
@model Model_Association
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
/* Associations - Association dialog panel */
|
||||
}
|
||||
|
||||
<script type="text/javascript">
|
||||
sbm.dlg.title.createAssociation = '@Localiser.GetJavascriptText("association.caption.association.create")';
|
||||
sbm.dlg.title.updateAssociation = '@Localiser.GetJavascriptText("association.caption.association.update")';
|
||||
</script>
|
||||
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAssociationId", @class = "sbm-form" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.AssociationId, 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" });
|
||||
|
||||
@* Association Type *@
|
||||
<div class="sbm-form-control AssociationType">
|
||||
<div class="sbm-label">
|
||||
<label for="cbAssociationType"><span>@Localiser["label.type"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
<div class="sbm-control">
|
||||
@Html.DropDownListFor(model => model.AssociationType, Model.GetAssociationTypeCodesForSelect(), Localiser["label.select"], new { @id = "cbAssociationType", @class = "AssociationType sbm-select" })
|
||||
</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"> *</span></label>
|
||||
</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"> *</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"> *</span></label>
|
||||
</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>
|
||||
<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>
|
||||
|
||||
}
|
||||
|
||||
</div>
|
||||
@@ -85,8 +85,9 @@
|
||||
<div class="sbm-panel-messages"></div>
|
||||
<div class="sbm-panel-item-list"></div>
|
||||
|
||||
@* element templates *@
|
||||
@* Element templates *@
|
||||
<div class="sbm-panel-item-template">
|
||||
|
||||
@* Commodity item template *@
|
||||
<div class="sbm-panel-item Commodity">
|
||||
<div class="sbm-header row">
|
||||
@@ -118,10 +119,12 @@
|
||||
</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>
|
||||
|
||||
|
||||
@@ -14,6 +14,17 @@
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmRequestPassword", @class = "sbm-form" }))
|
||||
{
|
||||
|
||||
<div class="spacer4"></div>
|
||||
<div class="sbm-form-control DbIdentifier">
|
||||
<div class="sbm-label">
|
||||
<label for="ifEmailAddress"><span>@Localiser["label.context"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.DbIdentifier, new { @id = "ifDbIdentifier", @class = "sbm-input", @maxlength = @Sbm.Config.Database.Identifier.MaxLength })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
|
||||
<div class="spacer4"></div>
|
||||
<div class="sbm-form-control EmailAddress">
|
||||
<div class="sbm-label">
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
ViewData["Title"] = "Signin";
|
||||
ulong emailAddressLen = SaSecurityDbDfn.GetColTextLen(SaSecurityDbDfn.ColumnIdx.SaSecItem_EmailAddress);
|
||||
}
|
||||
|
||||
<div class="">
|
||||
@@ -12,23 +11,34 @@
|
||||
|
||||
<div class="sbm-header"><div class="sbm-caption">@Localiser["label.signin"]</div></div>
|
||||
|
||||
<div class="sbm-content">
|
||||
<div class="sbm-content" style="max-height:none;">
|
||||
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmSignIn", @class = "sbm-form" }))
|
||||
{
|
||||
|
||||
<div class="spacer4"></div>
|
||||
<div class="sbm-form-control DbIdentifier">
|
||||
<div class="sbm-label">
|
||||
<label for="ifEmailAddress"><span>@Localiser["label.context"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.DbIdentifier, new { @id = "ifDbIdentifier", @class = "sbm-input", @maxlength = @Sbm.Config.Database.Identifier.MaxLength })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
|
||||
<div class="spacer2"></div>
|
||||
<div class="sbm-form-control EmailAddress">
|
||||
<div class="sbm-label">
|
||||
<label for="ifEmailAddress"><span>@Localiser["label.email"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.EmailAddress, new { @id = "ifEmailAddress", @class = "sbm-input lower", @maxlength = @emailAddressLen })
|
||||
@Html.TextBoxFor(model => model.EmailAddress, new { @id = "ifEmailAddress", @class = "sbm-input lower", @maxlength = @Model.GetControlMaxLength(SaSecurityDbDfn.ColumnIdx.SaSecItem_EmailAddress) })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
|
||||
<div class="spacer4"></div>
|
||||
<div class="spacer2"></div>
|
||||
<div class="sbm-form-control Password">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
@@ -43,7 +53,7 @@
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
|
||||
<div class="spacer4"></div>
|
||||
<div class="spacer2"></div>
|
||||
<div class="sbm-form-control">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
|
||||
@@ -122,6 +122,7 @@
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<div class="dropdown-item text-dark sbm-action" onclick="sbm.goToPage('Contact');">@Localiser["label.contacts"]</div>
|
||||
<div class="dropdown-item text-dark sbm-action" onclick="sbm.goToPage('Commodity');">@Localiser["label.commodities"]</div>
|
||||
<div class="dropdown-item text-dark sbm-action" onclick="sbm.goToPage('Association');">@Localiser["label.associations"]</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
@@ -151,7 +152,7 @@
|
||||
@* Footer *@
|
||||
<footer id="sbm-page-footer" class="">
|
||||
<div class="container">
|
||||
© 2021 - Sarand BusinessMgr Portal
|
||||
@(Model.CopyrightNotice) - Sarand BusinessMgr Portal
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@using Sarand.BusinessMgr.Net.Standard.Base.App
|
||||
@using Sarand.BusinessMgr.Net.Core.Web.App
|
||||
@using Sarand.BusinessMgr.Net.Core.Web.App
|
||||
@using Sarand.BusinessMgr.Net.Standard.Base.App
|
||||
@using Sarand.BusinessMgr.Net.Core.Web.Portal.Models
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"AppConfigs": {
|
||||
"SaBusMgr-Dev": {
|
||||
"Environments": [ "Development" ],
|
||||
"Instance": "Dev",
|
||||
"ControlDatabase": {
|
||||
"Location": "MsSql:Sarand107\\SQL2016.SaBusinessMgr_Control",
|
||||
"User": "SaBusMgr-Control",
|
||||
"Password": "sbm-c0Ntrul-dev-2021"
|
||||
},
|
||||
"BusMgrDatabase": {
|
||||
"Location": "MsSql:Sarand107\\SQL2016.SaBusinessMgr_Cadix",
|
||||
"User": "SaBusMgr-Cadix",
|
||||
"Password": "sbm-cul-dev-2021"
|
||||
},
|
||||
"Email": {
|
||||
"Context": "SBM-Dev",
|
||||
"ContactUs": {
|
||||
"AddressesTo": [ "dev@SaBusinessMgr.com" ]
|
||||
}
|
||||
},
|
||||
"Documents": {
|
||||
"RootFolder": "D:\\Sarand\\Projects\\Users\\AHoward\\VS2019\\BusinessMgr\\Docs"
|
||||
},
|
||||
"Logging": {
|
||||
"RootFolder": "D:\\Sarand\\Projects\\Users\\AHoward\\VS2019\\BusinessMgr\\Logs\\WebPortal"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"AppConfigs": {
|
||||
"SaBusMgr-Dev": {
|
||||
"Environments": [ "Development" ],
|
||||
"Instance": "Dev",
|
||||
"ControlDatabase": {
|
||||
"Location": "MsSql:Roman\\SQL2016.SaBusinessMgr_Control",
|
||||
"User": "sapphire",
|
||||
"Password": "sarand"
|
||||
},
|
||||
"BusMgrDatabases": [
|
||||
{
|
||||
"Identifiers": [ "Sarand" ],
|
||||
"Location": "MsSql:Roman\\SQL2016.SaBusinessMgr_Sarand_Dev",
|
||||
"User": "sapphire",
|
||||
"Password": "sarand"
|
||||
},
|
||||
{
|
||||
"Identifiers": [ "Cadix" ],
|
||||
"Location": "MsSql:Roman\\SQL2016.SaBusinessMgr_Cadix",
|
||||
"User": "sapphire",
|
||||
"Password": "sarand"
|
||||
},
|
||||
{
|
||||
"Identifiers": [ "BPE" ],
|
||||
"Location": "MsSql:Roman\\SQL2016.SaBusinessMgr_BPE",
|
||||
"User": "sapphire",
|
||||
"Password": "sarand"
|
||||
}
|
||||
],
|
||||
"Email": {
|
||||
"Context": "SBM-Dev",
|
||||
"ContactUs": {
|
||||
"AddressesTo": [ "dev@SaBusinessMgr.com" ]
|
||||
}
|
||||
},
|
||||
"Documents": {
|
||||
"RootFolder": "D:\\Sarand\\Projects\\Users\\AHoward\\VS2022\\BusinessMgr\\Docs"
|
||||
},
|
||||
"Logging": {
|
||||
"RootFolder": "D:\\Sarand\\Projects\\Users\\AHoward\\VS2022\\BusinessMgr\\Logs\\WebPortal"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* 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.dlg.btn.ok] = function () { sbm.storeItem(); };
|
||||
opt.buttons[sbm.dlg.btn.cancel] = function () { $(this).dialog('close'); };
|
||||
sbm.$dlg.association = $('#dlgAssociation').dialog(opt);
|
||||
|
||||
setTimeout(sbm.refreshResults, 250);
|
||||
});
|
||||
|
||||
}(window, window.document));
|
||||
|
||||
/* The End */
|
||||
@@ -23,18 +23,6 @@
|
||||
sbm.doAjaxRequest(sbm.ajax.refreshResults, delay || 50);
|
||||
sbm.awaitingRefreshResponse = true;
|
||||
}
|
||||
sbm.getFilterDropdownTemplate = function ()
|
||||
{
|
||||
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.doRefreshResults = function (response)
|
||||
{
|
||||
//sbm.debug('doRefreshResults', response);
|
||||
@@ -87,6 +75,18 @@
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sbm.getFilterDropdownTemplate = function ()
|
||||
{
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user