3.0.0.5 Portal Security, Commodity, Code Types, Codes.

This commit is contained in:
Andy Howard
2025-02-12 18:06:18 +00:00
parent ef4da874b0
commit 6cc179ae0a
65 changed files with 1031 additions and 836 deletions
+6 -6
View File
@@ -144,12 +144,12 @@ namespace Sarand.BusinessMgr.Net.Core.Web.App
}
//-------------------------------------------------------------------
// Code descriptions.
// System Codes.
//-------------------------------------------------------------------
private class CodeCache
{
public Dictionary<Sbm.SystemCode, List<TypeCodeDesc>> codes { get; } = new Dictionary<Sbm.SystemCode, List<TypeCodeDesc>>();
public List<TypeCodeDesc> GetCodesOfType(Sbm.SystemCode codeType)
public List<TypeCodeDesc> GetSystemCodes(Sbm.SystemCode codeType)
{
if (!codes.ContainsKey(codeType))
codes.Add(codeType, SbmSystem.GetSystemCodes(codeType));
@@ -170,7 +170,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.App
{
if ((int)affiliateType < 1) return "";
// ToDo Affiliate Type localisation.
List<TypeCodeDesc> affiliateTypeCodes = systemCodes.GetCodesOfType(Sbm.SystemCode.AffiliateType);
List<TypeCodeDesc> affiliateTypeCodes = systemCodes.GetSystemCodes(Sbm.SystemCode.AffiliateType);
return affiliateTypeCodes.GetDescForType(affiliateType, affiliateTypeCodes.GetCodeForType(affiliateType));
}
@@ -179,7 +179,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.App
{
if ((int)associationType < 1) return "";
// ToDo Association Type localisation.
List<TypeCodeDesc> associationTypeCodes = systemCodes.GetCodesOfType(Sbm.SystemCode.AssociationType);
List<TypeCodeDesc> associationTypeCodes = systemCodes.GetSystemCodes(Sbm.SystemCode.AssociationType);
return associationTypeCodes.GetDescForType(associationType, associationTypeCodes.GetCodeForType(associationType));
}
@@ -188,7 +188,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.App
{
if ((int)assetType < 1) return "";
// ToDo Asset Type localisation.
List<TypeCodeDesc> assetTypeCodes = systemCodes.GetCodesOfType(Sbm.SystemCode.AssetType);
List<TypeCodeDesc> assetTypeCodes = systemCodes.GetSystemCodes(Sbm.SystemCode.AssetType);
return assetTypeCodes.GetDescForType(assetType, assetTypeCodes.GetCodeForType(assetType));
}
@@ -197,7 +197,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.App
{
if ((int)transactionType < 1) return "";
// ToDo Transaction Type localisation.
List<TypeCodeDesc> transactionTypeCodes = systemCodes.GetCodesOfType(Sbm.SystemCode.TransactionType);
List<TypeCodeDesc> transactionTypeCodes = systemCodes.GetSystemCodes(Sbm.SystemCode.TransactionType);
return transactionTypeCodes.GetDescForType(transactionType, transactionTypeCodes.GetCodeForType(transactionType));
}
+2 -1
View File
@@ -15,7 +15,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.App
//-------------------------------------------------------------------
public static class Version
{
private static String version { get; } = "3.0.0.4";
private static String version { get; } = "3.0.0.5";
// Retrieve version.
public static String GetFullVersion() { return version; }
public static String GetAppVersion()
@@ -43,6 +43,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.App
// 3.0.0.2 08-Feb-25 Production SMTP config.
// 3.0.0.3 10-Feb-25 Osie feedback #1. Control Repository Schema, Logs.
// 3.0.0.4 11-Feb-25 Portal Commodity Sales properties. Control Index population.
// 3.0.0.5 12-Feb-25 Portal Security forms tidy. Default Commodity type. Code Types and Codes.
//-------------------------------------------------------------------
}
//=======================================================================
@@ -40,7 +40,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles
{
if (BusMgrColumnLengths[column] == 0)
BusMgrColumnLengths[column] = GetDbColTextLen(column);
return BusMgrColumnLengths[column];
if (BusMgrColumnLengths[column] > 0)
return BusMgrColumnLengths[column];
}
return SbmDbDfn.GetColTextLen(column);
}
@@ -64,7 +65,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles
// Get the column's length from the currently open database:
if (SbmDbDfn.GetColDataType(column) != DbColumnDataType.VarChar) return 0;
DbDfnTable dfnTable = db.GetTableDfn(SbmDbDfn.GetTableName(SbmDbDfn.GetTableForColumn(column), false));
ulong columnLength = (ulong)(dfnTable.Columns.Find(col => col.Name.EqualsCI(SbmDbDfn.GetColumnName(column, false)))?.Size ?? 0);
String columnName = SbmDbDfn.GetColumnName(column, false);
ulong columnLength = (ulong)(dfnTable.Columns.Find(col => col.Name.EqualsCI(columnName))?.Size ?? 0);
return (SbmDbDfn.MaxTextLen > 1 ? Math.Min(SbmDbDfn.MaxTextLen, columnLength) : columnLength);
}
@@ -77,7 +79,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles
{
if (SecurityColumnLengths[column] == 0)
SecurityColumnLengths[column] = GetDbColTextLen(column);
return SecurityColumnLengths[column];
if (SecurityColumnLengths[column] > 0)
return SecurityColumnLengths[column];
}
return SaSecurityDbDfn.GetColTextLen(column);
}
@@ -93,7 +96,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles
// Get the column's length from the currently open database:
if (SaSecurityDbDfn.GetColDataType(column) != DbColumnDataType.VarChar) return 0;
DbDfnTable dfnTable = db.GetTableDfn(SaSecurityDbDfn.GetTableName(SaSecurityDbDfn.GetTableForColumn(column), false));
ulong columnLength = (ulong)(dfnTable.Columns.Find(col => col.Name.EqualsCI(SaSecurityDbDfn.GetColumnName(column, false)))?.Size ?? 0);
String columnName = SaSecurityDbDfn.GetColumnName(column, false);
ulong columnLength = (ulong)(dfnTable.Columns.Find(col => col.Name.EqualsCI(columnName))?.Size ?? 0);
return (SaSecurityDbDfn.MaxTextLen > 1 ? Math.Min(SaSecurityDbDfn.MaxTextLen, columnLength) : columnLength);
}
@@ -106,7 +110,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles
{
if (CodeTypeColumnLengths[column] == 0)
CodeTypeColumnLengths[column] = GetDbColTextLen(column);
return CodeTypeColumnLengths[column];
if (CodeTypeColumnLengths[column] > 0)
return CodeTypeColumnLengths[column];
}
return SaCodeTypeDbDfn.GetColTextLen(column);
}
@@ -123,8 +128,9 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles
// Get the column's length from the currently open database:
if (SaCodeTypeDbDfn.GetColDataType(column) != DbColumnDataType.VarChar) return 0;
DbDfnTable dfnTable = db.GetTableDfn(SaCodeTypeDbDfn.GetTableName(SaCodeTypeDbDfn.GetTableForColumn(column), false));
ulong columnLength = (ulong)(dfnTable.Columns.Find(col => col.Name.EqualsCI(SaCodeTypeDbDfn.GetColumnName(column, false)))?.Size ?? 0);
return 0;// (SaCodeTypeDbDfn.MaxTextLen > 1 ? Math.Min(SaCodeTypeDbDfn.MaxTextLen, columnLength) : columnLength);
String columnName = SaCodeTypeDbDfn.GetColumnName(column, false);
ulong columnLength = (ulong)(dfnTable.Columns.Find(col => col.Name.EqualsCI(columnName))?.Size ?? 0);
return (SaCodeTypeDbDfn.MaxTextLen > 1 ? Math.Min(SaCodeTypeDbDfn.MaxTextLen, columnLength) : columnLength);
}
//-------------------------------------------------------------------
@@ -136,7 +142,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles
{
if (ItemOptionColumnLengths[column] == 0)
ItemOptionColumnLengths[column] = GetDbColTextLen(column);
return ItemOptionColumnLengths[column];
if (ItemOptionColumnLengths[column] > 0)
return ItemOptionColumnLengths[column];
}
return SaItemOptionDbDfn.GetColTextLen(column);
}
@@ -153,8 +160,9 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles
// Get the column's length from the currently open database:
if (SaItemOptionDbDfn.GetColDataType(column) != DbColumnDataType.VarChar) return 0;
DbDfnTable dfnTable = db.GetTableDfn(SaItemOptionDbDfn.GetTableName(SaItemOptionDbDfn.GetTableForColumn(column), false));
ulong columnLength = (ulong)(dfnTable.Columns.Find(col => col.Name.EqualsCI(SaItemOptionDbDfn.GetColumnName(column, false)))?.Size ?? 0);
return 0;// (SaItemOptionDbDfn.MaxTextLen > 1 ? Math.Min(SaItemOptionDbDfn.MaxTextLen, columnLength) : columnLength);
String columnName = SaItemOptionDbDfn.GetColumnName(column, false);
ulong columnLength = (ulong)(dfnTable.Columns.Find(col => col.Name.EqualsCI(columnName))?.Size ?? 0);
return (SaItemOptionDbDfn.MaxTextLen > 1 ? Math.Min(SaItemOptionDbDfn.MaxTextLen, columnLength) : columnLength);
}
//-------------------------------------------------------------------
@@ -55,13 +55,13 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr
// Properties.
public abstract bool SystemAccountDatabaseIsValid { get; }
// System codes.
protected List<TypeCodeDesc> AffiliateTypes { get { return GetCodesOfType(Sbm.SystemCode.AffiliateType); } }
protected List<TypeCodeDesc> AssociationTypes { get { return GetCodesOfType(Sbm.SystemCode.AssociationType); } }
protected List<TypeCodeDesc> AddressTypes { get { return GetCodesOfType(Sbm.SystemCode.AddressType); } }
protected List<TypeCodeDesc> SysParamCategories { get { return GetCodesOfType(Sbm.SystemCode.SysParamCategory); } }
protected List<TypeCodeDesc> TransactionStatusCats { get { return GetCodesOfType(Sbm.SystemCode.TransactionStatusCat); } }
protected List<TypeCodeDesc> DiscountTypes { get { return GetCodesOfType(Sbm.SystemCode.DiscountType); } }
protected List<TypeCodeDesc> SystemAccountTypes { get { return GetCodesOfType(Sbm.SystemCode.SystemAccountType); } }
protected List<TypeCodeDesc> AffiliateTypes { get { return GetSystemCodes(Sbm.SystemCode.AffiliateType); } }
protected List<TypeCodeDesc> AssociationTypes { get { return GetSystemCodes(Sbm.SystemCode.AssociationType); } }
protected List<TypeCodeDesc> AddressTypes { get { return GetSystemCodes(Sbm.SystemCode.AddressType); } }
protected List<TypeCodeDesc> SysParamCategories { get { return GetSystemCodes(Sbm.SystemCode.SysParamCategory); } }
protected List<TypeCodeDesc> TransactionStatusCats { get { return GetSystemCodes(Sbm.SystemCode.TransactionStatusCat); } }
protected List<TypeCodeDesc> DiscountTypes { get { return GetSystemCodes(Sbm.SystemCode.DiscountType); } }
protected List<TypeCodeDesc> SystemAccountTypes { get { return GetSystemCodes(Sbm.SystemCode.SystemAccountType); } }
// Code types.
public override List<Sbm.ApplCodeType> SupportedCodeTypes { get { return new List<Sbm.ApplCodeType>(supportedCodeTypes); } }
+1 -1
View File
@@ -31,7 +31,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr
//-------------------------------------------------------------------
// Properties.
public List<TypeCodeDesc> AssetTypes { get { return GetCodesOfType(Sbm.SystemCode.AssetType); } }
public List<TypeCodeDesc> AssetTypes { get { return GetSystemCodes(Sbm.SystemCode.AssetType); } }
//-------------------------------------------------------------------
// Utilities.
@@ -53,14 +53,14 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr
public abstract bool ContainerDatabaseIsValid { get; }
public abstract bool PortfolioDatabaseIsValid { get; }
// Code lists.
public List<TypeCodeDesc> CommodityTypes { get { return GetCodesOfType(Sbm.SystemCode.CommodityType); } }
public List<TypeCodeDesc> ContainerCategories { get { return GetCodesOfType(Sbm.SystemCode.ContainerCategory); } }
public List<TypeCodeDesc> ContainerTypes { get { return GetCodesOfType(Sbm.SystemCode.ContainerType); } }
public List<TypeCodeDesc> PortfolioItemTypes { get { return GetCodesOfType(Sbm.SystemCode.PortfolioItemType); } }
public List<TypeCodeDesc> CommodityStatusCats { get { return GetCodesOfType(Sbm.SystemCode.CommodityStatusCat); } }
public List<TypeCodeDesc> TransactionTypes { get { return GetCodesOfType(Sbm.SystemCode.TransactionType); } }
public List<TypeCodeDesc> TransactionStatusCats { get { return GetCodesOfType(Sbm.SystemCode.TransactionStatusCat); } }
public List<TypeCodeDesc> RequirementStatusCats { get { return GetCodesOfType(Sbm.SystemCode.RequirementStatusCat); } }
public List<TypeCodeDesc> CommodityTypes { get { return GetSystemCodes(Sbm.SystemCode.CommodityType); } }
public List<TypeCodeDesc> ContainerCategories { get { return GetSystemCodes(Sbm.SystemCode.ContainerCategory); } }
public List<TypeCodeDesc> ContainerTypes { get { return GetSystemCodes(Sbm.SystemCode.ContainerType); } }
public List<TypeCodeDesc> PortfolioItemTypes { get { return GetSystemCodes(Sbm.SystemCode.PortfolioItemType); } }
public List<TypeCodeDesc> CommodityStatusCats { get { return GetSystemCodes(Sbm.SystemCode.CommodityStatusCat); } }
public List<TypeCodeDesc> TransactionTypes { get { return GetSystemCodes(Sbm.SystemCode.TransactionType); } }
public List<TypeCodeDesc> TransactionStatusCats { get { return GetSystemCodes(Sbm.SystemCode.TransactionStatusCat); } }
public List<TypeCodeDesc> RequirementStatusCats { get { return GetSystemCodes(Sbm.SystemCode.RequirementStatusCat); } }
// Code types.
public override List<Sbm.ApplCodeType> SupportedCodeTypes { get { return new List<Sbm.ApplCodeType>(supportedCodeTypes); } }
+3 -3
View File
@@ -166,8 +166,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr
//-------------------------------------------------------------------
// Properties.
// System codes.
protected List<TypeCodeDesc> ItemTypes { get { return GetCodesOfType(Sbm.SystemCode.ItemType); } }
protected List<TypeCodeDesc> InterfaceOptionCodes { get { return GetCodesOfType(Sbm.SystemCode.InterfaceOption); } }
protected List<TypeCodeDesc> ItemTypes { get { return GetSystemCodes(Sbm.SystemCode.ItemType); } }
protected List<TypeCodeDesc> InterfaceOptionCodes { get { return GetSystemCodes(Sbm.SystemCode.InterfaceOption); } }
// Numeric control values.
protected int WeightDecimals { get { InitialiseNumericControlValues(); return mbr.weightDecimals; } }
protected int LengthDecimals { get { InitialiseNumericControlValues(); return mbr.lengthDecimals; } }
@@ -247,7 +247,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr
//-------------------------------------------------------------------
// Utilities.
public List<TypeCodeDesc> GetCodesOfType(Sbm.SystemCode systemCode)
public List<TypeCodeDesc> GetSystemCodes(Sbm.SystemCode systemCode)
{
return Internals.GetSystemCodes(systemCode);
}
+4 -4
View File
@@ -40,10 +40,10 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr
// Properties.
public abstract bool PriceDatabaseIsValid { get; }
// System codes.
public List<TypeCodeDesc> PriceTypes { get { return GetCodesOfType(Sbm.SystemCode.PriceType); } }
public List<TypeCodeDesc> PriceCalculationMethods { get { return GetCodesOfType(Sbm.SystemCode.PriceCalcMethod); } }
public List<TypeCodeDesc> PriceRounderMethods { get { return GetCodesOfType(Sbm.SystemCode.PriceRounderMethod); } }
public List<TypeCodeDesc> PriceRounderDirections { get { return GetCodesOfType(Sbm.SystemCode.PriceRounderDirection); } }
public List<TypeCodeDesc> PriceTypes { get { return GetSystemCodes(Sbm.SystemCode.PriceType); } }
public List<TypeCodeDesc> PriceCalculationMethods { get { return GetSystemCodes(Sbm.SystemCode.PriceCalcMethod); } }
public List<TypeCodeDesc> PriceRounderMethods { get { return GetSystemCodes(Sbm.SystemCode.PriceRounderMethod); } }
public List<TypeCodeDesc> PriceRounderDirections { get { return GetSystemCodes(Sbm.SystemCode.PriceRounderDirection); } }
// Code types.
public override List<Sbm.ApplCodeType> SupportedCodeTypes { get { return new List<Sbm.ApplCodeType>(supportedCodeTypes); } }
@@ -39,8 +39,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr
// Properties.
public abstract bool ProcessDatabaseIsValid { get; }
// System codes.
public List<TypeCodeDesc> ProcessTypes { get { return GetCodesOfType(Sbm.SystemCode.ProcessType); } }
public List<TypeCodeDesc> processCategories { get { return GetCodesOfType(Sbm.SystemCode.ProcessCategory); } }
public List<TypeCodeDesc> ProcessTypes { get { return GetSystemCodes(Sbm.SystemCode.ProcessType); } }
public List<TypeCodeDesc> processCategories { get { return GetSystemCodes(Sbm.SystemCode.ProcessCategory); } }
//-------------------------------------------------------------------
}
+1 -1
View File
@@ -41,7 +41,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr
//-------------------------------------------------------------------
// Properties.
// Code lists.
public List<TypeCodeDesc> LocationCategories { get { return GetCodesOfType(Sbm.SystemCode.LocationCategory); } }
public List<TypeCodeDesc> LocationCategories { get { return GetSystemCodes(Sbm.SystemCode.LocationCategory); } }
//-------------------------------------------------------------------
// Utilities.
@@ -50,12 +50,12 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr
//-------------------------------------------------------------------
// Properties.
public List<TypeCodeDesc> TransactionTypes { get { return GetCodesOfType(Sbm.SystemCode.TransactionType); } }
public List<TypeCodeDesc> TransactionStatusCats { get { return GetCodesOfType(Sbm.SystemCode.TransactionStatusCat); } }
public List<TypeCodeDesc> AssociationTypes { get { return GetCodesOfType(Sbm.SystemCode.AssociationType); } }
public List<TypeCodeDesc> RequirementStatusCats { get { return GetCodesOfType(Sbm.SystemCode.RequirementStatusCat); } }
public List<TypeCodeDesc> ConstituentTypes { get { return GetCodesOfType(Sbm.SystemCode.ConstituentType); } }
public List<TypeCodeDesc> ConstituentStatusCats { get { return GetCodesOfType(Sbm.SystemCode.ConstituentStatusCat); } }
public List<TypeCodeDesc> TransactionTypes { get { return GetSystemCodes(Sbm.SystemCode.TransactionType); } }
public List<TypeCodeDesc> TransactionStatusCats { get { return GetSystemCodes(Sbm.SystemCode.TransactionStatusCat); } }
public List<TypeCodeDesc> AssociationTypes { get { return GetSystemCodes(Sbm.SystemCode.AssociationType); } }
public List<TypeCodeDesc> RequirementStatusCats { get { return GetSystemCodes(Sbm.SystemCode.RequirementStatusCat); } }
public List<TypeCodeDesc> ConstituentTypes { get { return GetSystemCodes(Sbm.SystemCode.ConstituentType); } }
public List<TypeCodeDesc> ConstituentStatusCats { get { return GetSystemCodes(Sbm.SystemCode.ConstituentStatusCat); } }
// Code types.
public override List<Sbm.ApplCodeType> SupportedCodeTypes { get { return new List<Sbm.ApplCodeType>(supportedCodeTypes); } }
@@ -176,7 +176,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
{
SbmItemData.Params prmData = new SbmItemData.Params();
prmData.lItemId.Add(SaItemId.Id, Sbm.ItemType.Vehicle);
List<TypeCodeDesc> itemDataTypes = SbmSystem.GetCodesOfType(Sbm.SystemCode.ItemDataType);
List<TypeCodeDesc> itemDataTypes = SbmSystem.GetSystemCodes(Sbm.SystemCode.ItemDataType);
prmData.lDataType.Add(itemDataTypes.GetCodeForType(Sbm.ItemData.Vehicle_HpiResponse));
prmData.lDataType.RemoveEmpty();
if (!StringUtil.IsEmpty(prmData.lDataType))
@@ -72,8 +72,8 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Account
// User list.
public List<UserListData> Users { get; } = new List<UserListData>();
// Reference data.
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public List<CodeDesc> StatusesCreate { get; } = new List<CodeDesc>();
public List<ItemCodeDesc> Statuses { get; } = new List<ItemCodeDesc>();
public List<ItemCodeDesc> StatusesCreate { get; } = new List<ItemCodeDesc>();
public String StatusCodeDefault { get; set; }
}
//-------------------------------------------------------------------
@@ -94,9 +94,9 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Account
// Reference data - statuses.
foreach (SaStatus status in SbmcUserAccount.ValidStatuses)
{
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.Statuses.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
if (status != SaStatus.Deleted)
responseData.StatusesCreate.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.StatusesCreate.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
}
responseData.StatusCodeDefault = SacsSystem.GetStatusCode(SbmcUserAccount.DefaultStatus);
@@ -59,8 +59,8 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
// Owner list.
public List<OwnerListData> Owners { get; } = new List<OwnerListData>();
// Reference data.
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public List<CodeDesc> StatusesCreate { get; } = new List<CodeDesc>();
public List<ItemCodeDesc> Statuses { get; } = new List<ItemCodeDesc>();
public List<ItemCodeDesc> StatusesCreate { get; } = new List<ItemCodeDesc>();
public String StatusCodeDefault { get; set; }
}
//-------------------------------------------------------------------
@@ -81,9 +81,9 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
// Reference data - statuses.
foreach (SaStatus status in SbmcOwner.ValidStatuses)
{
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.Statuses.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
if (status != SaStatus.Deleted)
responseData.StatusesCreate.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.StatusesCreate.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
}
responseData.StatusCodeDefault = SacsSystem.GetStatusCode(SbmcOwner.DefaultStatus);
@@ -61,8 +61,8 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
// Repository list.
public List<RepositoryListData> Repositories { get; } = new List<RepositoryListData>();
// Reference data.
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public List<CodeDesc> StatusesCreate { get; } = new List<CodeDesc>();
public List<ItemCodeDesc> Statuses { get; } = new List<ItemCodeDesc>();
public List<ItemCodeDesc> StatusesCreate { get; } = new List<ItemCodeDesc>();
public String StatusCodeDefault { get; set; }
}
//-------------------------------------------------------------------
@@ -83,9 +83,9 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
// Reference data - statuses.
foreach (SaStatus status in SbmcRepository.ValidStatuses)
{
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.Statuses.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
if (status != SaStatus.Deleted)
responseData.StatusesCreate.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.StatusesCreate.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
}
responseData.StatusCodeDefault = SacsSystem.GetStatusCode(SbmcRepository.DefaultStatus);
@@ -167,8 +167,8 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Param
// Items.
public List<ParamListData> Params { get; } = new List<ParamListData>();
// Reference data.
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public List<CodeDesc> StatusesCreate { get; } = new List<CodeDesc>();
public List<ItemCodeDesc> Statuses { get; } = new List<ItemCodeDesc>();
public List<ItemCodeDesc> StatusesCreate { get; } = new List<ItemCodeDesc>();
public String StatusCodeDefault { get; set; }
}
//-------------------------------------------------------------------
@@ -189,9 +189,9 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Param
// Reference data - statuses.
foreach (SaStatus status in SbmcItemParam.ValidStatuses)
{
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.Statuses.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
if (status != SaStatus.Deleted)
responseData.StatusesCreate.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.StatusesCreate.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
}
responseData.StatusCodeDefault = SacsSystem.GetStatusCode(SbmcItemParam.DefaultStatus);
@@ -227,7 +227,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers
public ActionResult Ajax_StorePassword(Model_Security model)
{
AjaxResponse_ChangePassword responseData = new AjaxResponse_ChangePassword(model);
String messageTitle = Localiser["security.caption.change.password"];
String messageTitle = Localiser["caption.change.password"];
// Record disposable items as they are created so all can be disposed when needed.
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
@@ -7,7 +7,7 @@
<div class="">
<div class="sbc-panel-form security">
<div class="sbc-header"><div class="sbc-caption">@Localiser["security.caption.change.password"]</div></div>
<div class="sbc-header"><div class="sbc-caption">@Localiser["caption.change.password"]</div></div>
<div class="sbc-content">
<div class="spacer4"></div>
@@ -57,7 +57,7 @@
<div class="spacer4"></div>
<div class="">
<div id="pbChangePassword" class="sbc-button-action fullwidth pointer" style="margin:16px 0;">@Localiser["security.caption.change.password"]</div>
<div id="pbChangePassword" class="sbc-button-action fullwidth pointer" style="margin:16px 0;">@Localiser["caption.change.password"]</div>
</div>
}
@@ -33,13 +33,12 @@
}
ch.handleDbSchemaResponse = function (response)
{
sbc.debug('handleDbSchemaResponse', response);
//sbc.debug('handleDbSchemaResponse', response);
delete ch.awaitingSchemaResponse;
let $pnlSchema = $('.sbc-panel-results .sbc-panel-info.DbSchema.' + response.instance);
var $msgs = $('.sbc-panel-messages', $pnlSchema).hide().empty();
var $tablePanel = $('.sbc-panel-item-table', $pnlSchema).hide();
var $table = $('table.sbc-item-list', $tablePanel);
sbc.debug($table);
$('tbody tr', $table).remove();
if (!response.success) return;
if (response.instance == 'Control') ch.toSchema = setTimeout(function () { ch.refreshDbSchema('Template'); }, 250);
@@ -172,8 +172,6 @@
$('table tbody', $pnl.table).prepend($item).show();
}
io.populateItem($item, item);
// Force repopulation of sprts.
delete io.data.owners;
}
//--------------------------------------------------------------
@@ -37,8 +37,6 @@
env.$pnl.bgr.invisible();
env.$pnl.mnu.empty();
env.$pnl.mnu.append(cd.getFilterMenuOption(env, sbc.lbl.refresh, function () { cd.refreshItems(env); }, 'sbc-refresh'));
env.$pnl.mnu.append(cd.getFilterMenuOption(env, sbc.lbl.popIndices, function () { cd.populateIndices(env); }, 'sbc-config'));
sbc.debug(!!$('.sbc-dropdown-item', env.$pnl.mnu).length);
env.$pnl.bgr.toggleVisibility(!!$('.sbc-dropdown-item', env.$pnl.mnu).length);
}
@@ -26,7 +26,7 @@
}
ir.onInitQuery = function (env, response)
{
sbc.debug('onInitQuery', response);
//sbc.debug('onInitQuery', response);
if (!response.success) return;
let $ctrls = env.$frm.init.find('.sbc-input,.sbc-textarea,.sbc-select').val('');
@@ -71,7 +71,7 @@
}
ir.onInitRepo = function (env, response)
{
sbc.debug('onInitRepo', env, response);
//sbc.debug('onInitRepo', env, response);
sbc.refreshControlValues(response.controlValues);
if (!response.success) return;
env.$dlg.init.dialog('close');
@@ -36,7 +36,6 @@
env.$pnl.mnu.empty();
env.$pnl.mnu.append(rs.getFilterMenuOption(env, sbc.lbl.refresh, function () { rs.refreshDbSchema(env); }, 'sbc-refresh'));
env.$pnl.mnu.append(rs.getFilterMenuOption(env, sbc.lbl.popIndices, function () { rs.populateIndices(env); }, 'sbc-process'));
sbc.debug(env.$pnl.mnu);
env.$pnl.bgr.toggleVisibility(!!env.$pnl.mnu.find('.sbc-dropdown-item').length);
}
// Items.
@@ -108,7 +108,7 @@
}
ir.onInitRepo = function (id)
{
sbc.debug('onInitRepo', id);
//sbc.debug('onInitRepo', id);
ir.refreshResults(50);
}
@@ -194,8 +194,6 @@
$('table tbody', $pnl.table).prepend($item).show();
}
ip.populateItem($item, item);
// Force repopulation of sprts.
delete ip.data.params;
}
//--------------------------------------------------------------
@@ -22,7 +22,7 @@
}
sl.doRefreshFolders = function (response)
{
sbc.debug('doRefreshFolders', response);
//sbc.debug('doRefreshFolders', response);
delete sl.data.awaitingRefreshFoldersResponse;
sl.clearFilterFolders();
sbc.refreshControlValues(response.controlValues);
@@ -176,8 +176,6 @@
$('table tbody', $pnl.table).prepend($item).show();
}
ua.populateItem($item, item);
// Force repopulation of sprts.
delete ua.data.users;
}
//--------------------------------------------------------------
@@ -378,10 +378,10 @@
<data name="msg.validation.maximum.length" xml:space="preserve">
<value>Value must not exceed {0} characters</value>
</data>
<data name="security.caption.change.password" xml:space="preserve">
<data name="caption.change.password" xml:space="preserve">
<value>Change Password</value>
</data>
<data name="security.caption.request.password" xml:space="preserve">
<data name="caption.request.password" xml:space="preserve">
<value>Request Password</value>
</data>
<data name="security.change.password.current.invalid" xml:space="preserve">
@@ -0,0 +1,358 @@
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Components;
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.Core;
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
using Sarand.BusinessMgr.Web.Portal.App;
using Sarand.BusinessMgr.Web.Portal.Helpers;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.CodeTypes;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Diary;
using Sarand.Net.Standard.Base.Email;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Interfaces;
using Sarand.Net.Standard.Base.ItemData;
using Sarand.Net.Standard.Base.ItemDocs;
using Sarand.Net.Standard.Base.ItemOptions;
using Sarand.Net.Standard.Base.ReferenceData;
using Sarand.Net.Standard.Base.Security;
using Sarand.Net.Standard.Base.UpdateLog;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Web;
namespace Sarand.BusinessMgr.Web.Portal.Components
{
//=======================================================================
// Portal Controller - Security.
//=======================================================================
partial class SbmController_Portal
{
//-------------------------------------------------------------------
// User Sign-In.
/// <summary>
/// Sign the account in.
/// <para>- Record login time and clear invalid login data.</para>
/// <para>- Open user session - store details against Sesion Data.</para>
/// <para>- Set 'Keep logged in' cookie if required.</para>
/// </summary>
protected bool SignUserIn(SbmSessionData_Portal sessionDataForUser, SbmInternals internalsForUser, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation, bool keepLoggedIn, ref string errorMessage)
{
string errorPrefix = $"Unable to sign account in";
string errorSuffix = $"Context: {sessionDataForUser.RepositoryContext}. Email: {sessionDataForUser.UserEmailAddress}.";
// Validate Security Item and Affiliate, just in case - should have been done before arriving here!
if (securityItemUser == null)
{
SaLogger.Error($"{SysUtil.Fn} {errorPrefix} - null security item. {errorSuffix}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
if (affiliateUser == null)
{
SaLogger.Error($"{SysUtil.Fn} {errorPrefix} - null affiliate. {errorSuffix}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
if (!affiliateUser.IsStatusCurrent)
{
SaLogger.Error($"{SysUtil.Fn} {errorPrefix} - affiliate is not active. {errorSuffix}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
// Organisation.
if (associationOrganisation == null)
{
SaLogger.Error($"{SysUtil.Fn} {errorPrefix} - null organisation association. {errorSuffix}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
if (associationOrganisation.AssociationType != Sbm.AssociationType.Internal)
{
SaLogger.Error($"{SysUtil.Fn} {errorPrefix} - organisation association is not type 'Internal'. {errorSuffix}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
if (affiliateOrganisation == null)
{
SaLogger.Error($"{SysUtil.Fn} {errorPrefix} - null organisation affiliate. {errorSuffix}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
// Verify Organisation is supervised by User.
if (!internalsForUser.AccountMgr.IsAffiliateSupervisedBy(affiliateOrganisation.Id, affiliateUser.Id))
{
SaLogger.Warn($"{SysUtil.Fn} {errorPrefix} - Organisation is not supervised by user. {errorSuffix}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
// Configure security profile.
sessionDataForUser.SecurityProfile.RefreshProfile(internalsForUser.SessionConsole, internalsForUser.SecurityConsole, securityItemUser.Id, internalsForUser.SecurityConsole.GetRegisteredRights());
// 'Keep logged in' can be switched off by the application configuration.
keepLoggedIn = App.AppConfig.Security.SignIn.KeepLoggedIn.Allowed && keepLoggedIn;
// Log user in.
securityItemUser.LastLogin = DateTime.Now;
securityItemUser.InvalidLoginCount = 0;
securityItemUser.LastInvalidLoginAt = DateTime.MinValue;
if (!internalsForUser.SecurityConsole.UpdateSecurityItem(securityItemUser, DbUpdateInfo))
{
SaLogger.Warn($"{SysUtil.Fn} Failed to update security item for {securityItemUser.EmailAddress}: {internalsForUser.SecurityConsole.ErrorStateMessage}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
// Update affiliate.
affiliateUser.KeepLoggedIn_Portal = keepLoggedIn;
if (!internalsForUser.AccountMgr.UpdateAffiliate(affiliateUser, DbUpdateInfo))
{
SaLogger.Warn($"{SysUtil.Fn} Failed to update affiliate for {securityItemUser.EmailAddress}: {internalsForUser.AccountMgr.ErrorStateMessage}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
SaLogger.Info($"{SysUtil.Fn} User session opened for {securityItemUser.EmailAddress}", true);
// Create session.
if (!OpenUserSession(sessionDataForUser))
{
Debugger.Break();
SaLogger.Warn($"{SysUtil.Fn} Failed to open user session. Repository context: {sessionDataForUser.RepositoryContext}. Email: {securityItemUser.EmailAddress}.");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
// Send the 'Keep Logged In' cookie if requested.
if (affiliateUser.KeepLoggedIn_Portal)
SetKeepLoggedInCookie();
return true;
}
//-------------------------------------------------------------------
/// <summary>Populate the user's profile contact details to the session.</summary>
protected bool RefreshSessionData(SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation)
{
SbmSessionData_Portal sessionData = SessionData_Portal;
SysId affiliateIdUser = sessionData?.User?.AffiliateId ?? null;
if (!SysId.IsValid(affiliateIdUser)) return false;
if (!SysId.IsValid(affiliateUser?.Id ?? null)) return false;
if (!affiliateIdUser.Equals(affiliateUser.Id)) return false;
if (!SysId.IsValid(affiliateOrganisation?.Id ?? null)) return false;
sessionData.Refresh(securityItemUser, affiliateUser, associationOrganisation, affiliateOrganisation);
return true;
}
//-------------------------------------------------------------------
/// <summary>Start a new user session on sign-in.</summary>
protected bool OpenUserSession(SbmSessionData_Portal sessionDataForUser)
{
// Validate user properties.
if (!SysId.IsValid(sessionDataForUser.UserAffiliateId))
{
return false;
}
if (sessionDataForUser.UserEmailAddress.IsBlank())
{
return false;
}
// Close previous session.
CloseUserSession();
// Open session.
return SetSessionData(sessionDataForUser);
}
protected void CloseUserSession()
{
ClearSessionData();
}
//-------------------------------------------------------------------
// Keep Logged In.
//-------------------------------------------------------------------
/// <summary>
/// Check for 'Keep Logged In' cookie and auto-login user if details are valid.
/// </summary>
/// <returns></returns>
protected bool AutoLoginUser()
{
// NB Only allowed if there isn't a current user session.
if (ValidUserSession) return true;
if (!AppConfig.Security.SignIn.KeepLoggedIn.Allowed) return false;
// Extract parameters and validate that they are populated.
string encryptedParams = GetRequestCookie(KeepLoggedIn.CookieName);
KeepLoggedInParams keepLoggedInParams = ExtractKeepLoggedInParams(encryptedParams);
string logPrefix = $"{SysUtil.Fn} 'Keep Logged In' cookie found but ";
string logSuffix = keepLoggedInParams.GetValidParams().Concat("", " ", ".");
if (keepLoggedInParams.IsValid())
{
// Instance Repository configured on Control database identified by Context.
SbmSessionContext sessionContext = SbmCoreInstanceHelper_Portal.GetSessionContextByRepositoryContext(keepLoggedInParams.RepositoryContext);
if (sessionContext != null)
{
// Consoles and Managers must be associated with the specific context.
SbmSessionData_Portal sessionDataForUser = new SbmSessionData_Portal(sessionContext, keepLoggedInParams.RepositoryContext, null, null, null, null);
using (SbmInternals internalsForUser = new SbmInternals(sessionDataForUser))
{
using (SaSecurityItem securityItemUser = internalsForUser.SecurityConsole.GetUserByEmail(keepLoggedInParams.EmailAddress))
using (SbmAffiliate affiliateUser = internalsForUser.AccountMgr.GetAffiliateById(keepLoggedInParams.AffiliateIdUser))
using (SbmAssociation associationOrganisation = internalsForUser.AccountMgr.GetAssociationById(keepLoggedInParams.AssociationIdOrganisation))
using (SbmAffiliate affiliateOrganisation = internalsForUser.AccountMgr.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)
{
// Bring the Session Data up to date with the session properties.
sessionDataForUser.Refresh(securityItemUser, affiliateUser, associationOrganisation, affiliateOrganisation);
string errorMessage = "";
if (SignUserIn(sessionDataForUser, internalsForUser, securityItemUser, affiliateUser, associationOrganisation, affiliateOrganisation, true, ref errorMessage))
{
// User auto-login successful.
SaLogger.Info(logPrefix + " 'Keep Logged In' cookie found." + logSuffix);
return true;
}
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);
}
}
}
else SaLogger.Warn($"{SysUtil.Fn} Keep Logged In cookie found but no matching session contexts found." + logSuffix);
}
else if (!encryptedParams.IsEmpty())
SaLogger.Warn($"{SysUtil.Fn} Keep Logged In cookie found but with incomplete details." + logSuffix);
ClearKeepLoggedInCookie();
return false;
}
//-------------------------------------------------------------------
/// <summary>Keep-Logged-In cookie.</summary>
protected void SetKeepLoggedInCookie()
{
string keepLoggedInCookieValue = GenerateKeepLoggedInCookieValue();
int cookieExpiresDays = Math.Max(Sbm.Config.Security.SignIn.KeepLoggedIn.CookieExpiresDays_Min, Math.Min(Sbm.Config.Security.SignIn.KeepLoggedIn.CookieExpiresDays_Max, AppConfig.Security.SignIn.KeepLoggedIn.CookieExpiresDays));
SetResponseCookie(KeepLoggedIn.CookieName, keepLoggedInCookieValue, DateTime.Now.AddDays(cookieExpiresDays), true);
SaLogger.Debug($"{SysUtil.Fn} 'Keep Logged In' cookie set. Name: {KeepLoggedIn.CookieName}. Value: {keepLoggedInCookieValue}");
}
/// <summary>Set the 'Keep Logged In' response cookie to expired with no data.</summary>
public void ClearKeepLoggedInCookie()
{
if (GetRequestCookie(KeepLoggedIn.CookieName).IsEmpty()) return;
// Clear cookie by setting expiry date in the past.
SetResponseCookie(KeepLoggedIn.CookieName, "", DateTime.Today.AddDays(-7), true);
SaLogger.Debug($"{SysUtil.Fn} 'Keep Logged In' cookie cleared. Name: {KeepLoggedIn.CookieName}.");
}
//-------------------------------------------------------------------
// 'Keep Logged In' cookie and encryption config.
// NB - IV value is generated from the key and fixed so that it doesn't change when the application restarts
// to ensure that cookie value can be decrypted even if application restarts in the meantime.
// - Generating IV from same key results in different value each time.
// - IV Must be regenerated if key is changed: uncomment 'Generated' variable and copy resulting value to IV variable.
// NB - 'Keep Logged In' is termed 'Remember Me' in the Portal application.
public static class KeepLoggedIn
{
public static string CookieName = "BMKLI";
public static string Base64Key = SacsEncryptionHelper.EncodePlainKey("<=SaBusMgr^P0rt4L{KeepLoggedIn}~", SacsEncryptionHelper.KeyLength);
//private static String KeepLoggedIn.Base64IV_Generated = SacsEncryptionHelper.InitSymmetricEncryptionIV(KeepLoggedIn.Base64Key);
public static string Base64IV = "m47AMcMgACp3aoQVc0Y92A==";
}
//-------------------------------------------------------------------
// Keep-logged-in cookie value.
private static readonly string ParamName_KeepLoggedIn_RepositoryContext = "rct";
private static readonly string ParamName_KeepLoggedIn_EmailAddress = "ema";
private static readonly string ParamName_KeepLoggedIn_SecurityItemId = "sii";
private static readonly string ParamName_KeepLoggedIn_AffiliateIdUser = "afiu";
private static readonly string ParamName_KeepLoggedIn_AssociationIdOrganisation = "asio";
private string GenerateKeepLoggedInCookieValue()
{
NameValueCollection keepLoggedInParams = new NameValueCollection();
keepLoggedInParams.Add(ParamName_KeepLoggedIn_RepositoryContext, SessionData_Portal.RepositoryContext);
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));
keepLoggedInParams.Add(ParamName_KeepLoggedIn_AssociationIdOrganisation, SysId.ToString(SessionData_Portal.Organisation.AssociationId));
return EncryptParameters(keepLoggedInParams, KeepLoggedIn.Base64IV, KeepLoggedIn.Base64Key);
}
//-------------------------------------------------------------------
public class KeepLoggedInParams
{
public string RepositoryContext { get; set; }
public string EmailAddress { get; set; }
public SysId SecurityItemId { get; set; }
public SysId AffiliateIdUser { get; set; }
public SysId AssociationIdOrganisation { get; set; }
/// <summary>Retrieve the list of valid parameters in printable format [Name: Value].</summary>
public List<string> GetValidParams()
{
List<string> values = new List<string>();
if (!RepositoryContext.IsBlank())
values.Add("RepositoryContext: " + RepositoryContext);
if (!EmailAddress.IsBlank())
values.Add("EmailAddress: " + EmailAddress);
if (SysId.IsValid(SecurityItemId))
values.Add("SecurityItemId: " + SysId.ToString(SecurityItemId));
if (SysId.IsValid(AffiliateIdUser))
values.Add("AffiliateIdUser: " + SysId.ToString(AffiliateIdUser));
if (SysId.IsValid(AssociationIdOrganisation))
values.Add("AssociationIdOrganisation: " + SysId.ToString(AssociationIdOrganisation));
return values;
}
/// <summary>Verifiy that the email and account Ids are populated and the data hasn't expired.</summary>
public bool IsValid()
{
return
!RepositoryContext.IsBlank() &&
!EmailAddress.IsBlank() &&
SysId.IsValid(SecurityItemId) &&
SysId.IsValid(AffiliateIdUser) &&
SysId.IsValid(AssociationIdOrganisation);
}
}
public KeepLoggedInParams ExtractKeepLoggedInParams(string encryptedParams)
{
KeepLoggedInParams keepLoggedInParams = new KeepLoggedInParams();
if (!encryptedParams.IsEmpty())
{
NameValueCollection linkParams = DecryptParameters(encryptedParams, KeepLoggedIn.Base64IV, KeepLoggedIn.Base64Key);
keepLoggedInParams.RepositoryContext = linkParams.Get(ParamName_KeepLoggedIn_RepositoryContext);
keepLoggedInParams.EmailAddress = linkParams.Get(ParamName_KeepLoggedIn_EmailAddress);
keepLoggedInParams.SecurityItemId = SysId.ToSysId(linkParams.Get(ParamName_KeepLoggedIn_SecurityItemId));
keepLoggedInParams.AffiliateIdUser = SysId.ToSysId(linkParams.Get(ParamName_KeepLoggedIn_AffiliateIdUser));
keepLoggedInParams.AssociationIdOrganisation = SysId.ToSysId(linkParams.Get(ParamName_KeepLoggedIn_AssociationIdOrganisation));
}
if (DebugMode && SysId.IsValid(keepLoggedInParams.AffiliateIdUser)) SaLogger.Info($"{SysUtil.Fn} UserAccountId: {SysId.ToString(keepLoggedInParams.AffiliateIdUser)}");
return keepLoggedInParams;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -34,14 +34,22 @@ using System.Web;
namespace Sarand.BusinessMgr.Web.Portal.Components
{
//=======================================================================
// Portal Controller - Utils.
// Portal Controller.
//=======================================================================
public class SbmController_Portal : SbmController_Web
public partial class SbmController_Portal : SbmController_Web
{
//-------------------------------------------------------------------
// Data members.
private SbmInternals internals;
private SbmSysParamCache sysParamCache = null;
public class DataMembers
{
/// <summary>Internals supplied by another component, likely the Controller.</summary>
public SbmInternals internalsSupplied;
/// <summary>Internals created locally when not supplied by another component.</summary>
public SbmInternals internals;
/// <summary>System Params - to persist session properties.</summary>
public SbmSysParamCache sysParamCache = null;
}
private readonly DataMembers mbr = new DataMembers();
//-------------------------------------------------------------------
// Protected construction.
@@ -52,15 +60,17 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
{
if (disposing)
{
if (internals != null) internals.Dispose(); internals = null;
if (sysParamCache != null) sysParamCache.Dispose(); sysParamCache = null;
if (mbr.internals != null) mbr.internals.Dispose(); mbr.internals = null;
if (mbr.sysParamCache != null) mbr.sysParamCache.Dispose(); mbr.sysParamCache = null;
}
base.Dispose(disposing);
}
//-------------------------------------------------------------------
// Properties.
protected SbmInternals Internals { get { if (internals == null && UserContext_Core != null) { internals = new SbmInternals(UserContext_Core); } return internals; } }
protected SbmInternals Internals { get { if (mbr.internalsSupplied != null) return mbr.internalsSupplied; if (mbr.internals == null && UserContext_Core != null) { mbr.internals = new SbmInternals(UserContext_Core); } return mbr.internals; } }
// Business components.
protected SbmSysParamCache SysParamCache { get { if (mbr.sysParamCache == null) { mbr.sysParamCache = new SbmSysParamCache(Internals, SessionData_Portal.User.AffiliateId); } return mbr.sysParamCache; } }
// Managers.
protected SbmAccountMgr AccountMgr { get { return Internals.AccountMgr; } }
protected SbmCommodityMgr CommodityMgr { get { return Internals.CommodityMgr; } }
@@ -85,7 +95,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
protected SbmStockControlConfig StockControlConfig { get { return Internals.StockControlConfig; } }
protected SbmRequirementCostingConfig RequirementCostingConfig { get { return Internals.RequirementCostingConfig; } }
// System codes.
protected List<TypeCodeDesc> GetCodesOfType(Sbm.SystemCode systemCode) { return Internals.GetSystemCodes(systemCode); }
protected List<TypeCodeDesc> GetSystemCodes(Sbm.SystemCode systemCode) { return Internals.GetSystemCodes(systemCode); }
// Email.
protected SaEmailConfig EmailConfig { get { return Internals.EmailConfig; } }
protected SbmEmailConsole EmailConsole { get { return Internals.EmailConsole; } }
@@ -104,157 +114,6 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
return JsonConvert.DeserializeObject<SbmSessionData_Portal>(sessionDataJson, SessionDataJsonDeserializerSettings);
}
//-------------------------------------------------------------------
// Properties.
// Business components.
protected SbmSysParamCache SysParamCache { get { if (sysParamCache == null) sysParamCache = new SbmSysParamCache(Internals, SessionData_Portal.User.AffiliateId); return sysParamCache; } }
//-------------------------------------------------------------------
// User Session.
/// <summary>
/// Sign the account in.
/// <para>- Record login time and clear invalid login data.</para>
/// <para>- Open user session - store details against Sesion Data.</para>
/// <para>- Set 'Keep logged in' cookie if required.</para>
/// </summary>
protected bool SignUserIn(SbmSessionData_Portal sessionDataForUser, SbmInternals internalsForUser, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation, bool keepLoggedIn, ref string errorMessage)
{
string errorPrefix = $"Unable to sign account in";
string errorSuffix = $"Context: {sessionDataForUser.RepositoryContext}. Email: {sessionDataForUser.UserEmailAddress}.";
// Validate Security Item and Affiliate, just in case - should have been done before arriving here!
if (securityItemUser == null)
{
SaLogger.Error($"{SysUtil.Fn} {errorPrefix} - null security item. {errorSuffix}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
if (affiliateUser == null)
{
SaLogger.Error($"{SysUtil.Fn} {errorPrefix} - null affiliate. {errorSuffix}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
if (!affiliateUser.IsStatusCurrent)
{
SaLogger.Error($"{SysUtil.Fn} {errorPrefix} - affiliate is not active. {errorSuffix}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
// Organisation.
if (associationOrganisation == null)
{
SaLogger.Error($"{SysUtil.Fn} {errorPrefix} - null organisation association. {errorSuffix}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
if (associationOrganisation.AssociationType != Sbm.AssociationType.Internal)
{
SaLogger.Error($"{SysUtil.Fn} {errorPrefix} - organisation association is not type 'Internal'. {errorSuffix}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
if (affiliateOrganisation == null)
{
SaLogger.Error($"{SysUtil.Fn} {errorPrefix} - null organisation affiliate. {errorSuffix}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
// Verify Organisation is supervised by User.
if (!internalsForUser.AccountMgr.IsAffiliateSupervisedBy(affiliateOrganisation.Id, affiliateUser.Id))
{
SaLogger.Warn($"{SysUtil.Fn} {errorPrefix} - Organisation is not supervised by user. {errorSuffix}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
// Configure security profile.
sessionDataForUser.SecurityProfile.RefreshProfile(internalsForUser.SessionConsole, internalsForUser.SecurityConsole, securityItemUser.Id, internalsForUser.SecurityConsole.GetRegisteredRights());
// 'Keep logged in' can be switched off by the application configuration.
keepLoggedIn = App.AppConfig.Security.SignIn.KeepLoggedIn.Allowed && keepLoggedIn;
// Log user in.
securityItemUser.LastLogin = DateTime.Now;
securityItemUser.InvalidLoginCount = 0;
securityItemUser.LastInvalidLoginAt = DateTime.MinValue;
if (!internalsForUser.SecurityConsole.UpdateSecurityItem(securityItemUser, DbUpdateInfo))
{
SaLogger.Warn($"{SysUtil.Fn} Failed to update security item for {securityItemUser.EmailAddress}: {internalsForUser.SecurityConsole.ErrorStateMessage}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
// Update affiliate.
affiliateUser.KeepLoggedIn_Portal = keepLoggedIn;
if (!internalsForUser.AccountMgr.UpdateAffiliate(affiliateUser, DbUpdateInfo))
{
SaLogger.Warn($"{SysUtil.Fn} Failed to update affiliate for {securityItemUser.EmailAddress}: {internalsForUser.AccountMgr.ErrorStateMessage}");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
SaLogger.Info($"{SysUtil.Fn} User session opened for {securityItemUser.EmailAddress}", true);
// Create session.
if (!OpenUserSession(sessionDataForUser))
{
Debugger.Break();
SaLogger.Warn($"{SysUtil.Fn} Failed to open user session. Repository context: {sessionDataForUser.RepositoryContext}. Email: {securityItemUser.EmailAddress}.");
errorMessage = Localiser["security.msg.signin.invalid"];
return false;
}
// Send the 'Keep Logged In' cookie if requested.
if (affiliateUser.KeepLoggedIn_Portal)
SetKeepLoggedInCookie();
return true;
}
//-------------------------------------------------------------------
/// <summary>Populate the user's profile contact details to the session.</summary>
protected bool RefreshSessionData(SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation)
{
SbmSessionData_Portal sessionData = SessionData_Portal;
SysId affiliateIdUser = sessionData?.User?.AffiliateId ?? null;
if (!SysId.IsValid(affiliateIdUser)) return false;
if (!SysId.IsValid(affiliateUser?.Id ?? null)) return false;
if (!affiliateIdUser.Equals(affiliateUser.Id)) return false;
if (!SysId.IsValid(affiliateOrganisation?.Id ?? null)) return false;
sessionData.Refresh(securityItemUser, affiliateUser, associationOrganisation, affiliateOrganisation);
return true;
}
//-------------------------------------------------------------------
/// <summary>Start a new user session on sign-in.</summary>
protected bool OpenUserSession(SbmSessionData_Portal sessionDataForUser)
{
// Validate user properties.
if (!SysId.IsValid(sessionDataForUser.UserAffiliateId))
{
return false;
}
if (sessionDataForUser.UserEmailAddress.IsBlank())
{
return false;
}
// Close previous session.
CloseUserSession();
// Open session.
return SetSessionData(sessionDataForUser);
}
protected void CloseUserSession()
{
ClearSessionData();
}
//-------------------------------------------------------------------
// Action execution events.
//-------------------------------------------------------------------
@@ -264,12 +123,12 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
// ToDo Store system params.
if (sysParamCache != null)
// Store system params.
if (mbr.sysParamCache != null)
{
if (sysParamCache.Modified)
if (mbr.sysParamCache.Modified)
{
sysParamCache.Store();
mbr.sysParamCache.Store();
SaLogger.Info($"{SysUtil.Fn} User params stored.");
}
}
@@ -291,180 +150,16 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
SbmModel_Portal portalModel = model as SbmModel_Portal;
if (portalModel != null)
{
if (!portalModel.HasInternals() && (mbr.internalsSupplied != null || mbr.internals != null))
{
portalModel.SetInternals(Internals);
SaLogger.Debug($"{SysUtil.Fn} Internals populated to model.");
}
// Populate menu options.
portalModel.PopulateMenu();
}
}
//-------------------------------------------------------------------
// Keep Logged In.
//-------------------------------------------------------------------
/// <summary>
/// Check for 'Keep Logged In' cookie and auto-login user if details are valid.
/// </summary>
/// <returns></returns>
protected bool AutoLoginUser()
{
// NB Only allowed if there isn't a current user session.
if (ValidUserSession) return true;
if (!AppConfig.Security.SignIn.KeepLoggedIn.Allowed) return false;
// Extract parameters and validate that they are populated.
string encryptedParams = GetRequestCookie(KeepLoggedIn.CookieName);
KeepLoggedInParams keepLoggedInParams = ExtractKeepLoggedInParams(encryptedParams);
string logPrefix = $"{SysUtil.Fn} 'Keep Logged In' cookie found but ";
string logSuffix = keepLoggedInParams.GetValidParams().Concat("", " ", ".");
if (keepLoggedInParams.IsValid())
{
// Instance Repository configured on Control database identified by Context.
SbmSessionContext sessionContext = SbmCoreInstanceHelper_Portal.GetSessionContextByRepositoryContext(keepLoggedInParams.RepositoryContext);
if (sessionContext != null)
{
// Consoles and Managers must be associated with the specific context.
SbmSessionData_Portal sessionDataForUser = new SbmSessionData_Portal(sessionContext, keepLoggedInParams.RepositoryContext, null, null, null, null);
using (SbmInternals internalsForUser = new SbmInternals(sessionDataForUser))
{
using (SaSecurityItem securityItemUser = internalsForUser.SecurityConsole.GetUserByEmail(keepLoggedInParams.EmailAddress))
using (SbmAffiliate affiliateUser = internalsForUser.AccountMgr.GetAffiliateById(keepLoggedInParams.AffiliateIdUser))
using (SbmAssociation associationOrganisation = internalsForUser.AccountMgr.GetAssociationById(keepLoggedInParams.AssociationIdOrganisation))
using (SbmAffiliate affiliateOrganisation = internalsForUser.AccountMgr.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)
{
// Bring the Session Data up to date with the session properties.
sessionDataForUser.Refresh(securityItemUser, affiliateUser, associationOrganisation, affiliateOrganisation);
string errorMessage = "";
if (SignUserIn(sessionDataForUser, internalsForUser, securityItemUser, affiliateUser, associationOrganisation, affiliateOrganisation, true, ref errorMessage))
{
// User auto-login successful.
SaLogger.Info(logPrefix + " 'Keep Logged In' cookie found." + logSuffix);
return true;
}
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);
}
}
}
else SaLogger.Warn($"{SysUtil.Fn} Keep Logged In cookie found but no matching session contexts found." + logSuffix);
}
else if (!encryptedParams.IsEmpty())
SaLogger.Warn($"{SysUtil.Fn} Keep Logged In cookie found but with incomplete details." + logSuffix);
ClearKeepLoggedInCookie();
return false;
}
//-------------------------------------------------------------------
/// <summary>Keep-Logged-In cookie.</summary>
protected void SetKeepLoggedInCookie()
{
string keepLoggedInCookieValue = GenerateKeepLoggedInCookieValue();
int cookieExpiresDays = Math.Max(Sbm.Config.Security.SignIn.KeepLoggedIn.CookieExpiresDays_Min, Math.Min(Sbm.Config.Security.SignIn.KeepLoggedIn.CookieExpiresDays_Max, AppConfig.Security.SignIn.KeepLoggedIn.CookieExpiresDays));
SetResponseCookie(KeepLoggedIn.CookieName, keepLoggedInCookieValue, DateTime.Now.AddDays(cookieExpiresDays), true);
SaLogger.Debug($"{SysUtil.Fn} 'Keep Logged In' cookie set. Name: {KeepLoggedIn.CookieName}. Value: {keepLoggedInCookieValue}");
}
/// <summary>Set the 'Keep Logged In' response cookie to expired with no data.</summary>
public void ClearKeepLoggedInCookie()
{
if (GetRequestCookie(KeepLoggedIn.CookieName).IsEmpty()) return;
// Clear cookie by setting expiry date in the past.
SetResponseCookie(KeepLoggedIn.CookieName, "", DateTime.Today.AddDays(-7), true);
SaLogger.Debug($"{SysUtil.Fn} 'Keep Logged In' cookie cleared. Name: {KeepLoggedIn.CookieName}.");
}
//-------------------------------------------------------------------
// 'Keep Logged In' cookie and encryption config.
// NB - IV value is generated from the key and fixed so that it doesn't change when the application restarts
// to ensure that cookie value can be decrypted even if application restarts in the meantime.
// - Generating IV from same key results in different value each time.
// - IV Must be regenerated if key is changed: uncomment 'Generated' variable and copy resulting value to IV variable.
// NB - 'Keep Logged In' is termed 'Remember Me' in the Portal application.
public static class KeepLoggedIn
{
public static string CookieName = "BMKLI";
public static string Base64Key = SacsEncryptionHelper.EncodePlainKey("<=SaBusMgr^P0rt4L{KeepLoggedIn}~", SacsEncryptionHelper.KeyLength);
//private static String KeepLoggedIn.Base64IV_Generated = SacsEncryptionHelper.InitSymmetricEncryptionIV(KeepLoggedIn.Base64Key);
public static string Base64IV = "m47AMcMgACp3aoQVc0Y92A==";
}
//-------------------------------------------------------------------
// Keep-logged-in cookie value.
private static readonly string ParamName_KeepLoggedIn_RepositoryContext = "rct";
private static readonly string ParamName_KeepLoggedIn_EmailAddress = "ema";
private static readonly string ParamName_KeepLoggedIn_SecurityItemId = "sii";
private static readonly string ParamName_KeepLoggedIn_AffiliateIdUser = "afiu";
private static readonly string ParamName_KeepLoggedIn_AssociationIdOrganisation = "asio";
private string GenerateKeepLoggedInCookieValue()
{
NameValueCollection keepLoggedInParams = new NameValueCollection();
keepLoggedInParams.Add(ParamName_KeepLoggedIn_RepositoryContext, SessionData_Portal.RepositoryContext);
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));
keepLoggedInParams.Add(ParamName_KeepLoggedIn_AssociationIdOrganisation, SysId.ToString(SessionData_Portal.Organisation.AssociationId));
return EncryptParameters(keepLoggedInParams, KeepLoggedIn.Base64IV, KeepLoggedIn.Base64Key);
}
//-------------------------------------------------------------------
public class KeepLoggedInParams
{
public string RepositoryContext { get; set; }
public string EmailAddress { get; set; }
public SysId SecurityItemId { get; set; }
public SysId AffiliateIdUser { get; set; }
public SysId AssociationIdOrganisation { get; set; }
/// <summary>Retrieve the list of valid parameters in printable format [Name: Value].</summary>
public List<string> GetValidParams()
{
List<string> values = new List<string>();
if (!RepositoryContext.IsBlank())
values.Add("RepositoryContext: " + RepositoryContext);
if (!EmailAddress.IsBlank())
values.Add("EmailAddress: " + EmailAddress);
if (SysId.IsValid(SecurityItemId))
values.Add("SecurityItemId: " + SysId.ToString(SecurityItemId));
if (SysId.IsValid(AffiliateIdUser))
values.Add("AffiliateIdUser: " + SysId.ToString(AffiliateIdUser));
if (SysId.IsValid(AssociationIdOrganisation))
values.Add("AssociationIdOrganisation: " + SysId.ToString(AssociationIdOrganisation));
return values;
}
/// <summary>Verifiy that the email and account Ids are populated and the data hasn't expired.</summary>
public bool IsValid()
{
return
!RepositoryContext.IsBlank() &&
!EmailAddress.IsBlank() &&
SysId.IsValid(SecurityItemId) &&
SysId.IsValid(AffiliateIdUser) &&
SysId.IsValid(AssociationIdOrganisation);
}
}
public KeepLoggedInParams ExtractKeepLoggedInParams(string encryptedParams)
{
KeepLoggedInParams keepLoggedInParams = new KeepLoggedInParams();
if (!encryptedParams.IsEmpty())
{
NameValueCollection linkParams = DecryptParameters(encryptedParams, KeepLoggedIn.Base64IV, KeepLoggedIn.Base64Key);
keepLoggedInParams.RepositoryContext = linkParams.Get(ParamName_KeepLoggedIn_RepositoryContext);
keepLoggedInParams.EmailAddress = linkParams.Get(ParamName_KeepLoggedIn_EmailAddress);
keepLoggedInParams.SecurityItemId = SysId.ToSysId(linkParams.Get(ParamName_KeepLoggedIn_SecurityItemId));
keepLoggedInParams.AffiliateIdUser = SysId.ToSysId(linkParams.Get(ParamName_KeepLoggedIn_AffiliateIdUser));
keepLoggedInParams.AssociationIdOrganisation = SysId.ToSysId(linkParams.Get(ParamName_KeepLoggedIn_AssociationIdOrganisation));
}
if (DebugMode && SysId.IsValid(keepLoggedInParams.AffiliateIdUser)) SaLogger.Info($"{SysUtil.Fn} UserAccountId: {SysId.ToString(keepLoggedInParams.AffiliateIdUser)}");
return keepLoggedInParams;
}
//-------------------------------------------------------------------
// Parameter encryption, eg. for images.
//-------------------------------------------------------------------
@@ -485,7 +180,6 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
//-------------------------------------------------------------------
// Logging.
//-------------------------------------------------------------------
protected string getLogSuffix()
{
List<string> logSuffix = new List<string>();
@@ -493,7 +187,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
if (sessionData != null)
{
if (!sessionData.User.EmailAddress.IsEmpty())
logSuffix.Add("User: " + sessionData.User.EmailAddress);
logSuffix.Add($"User: {sessionData.User.EmailAddress}");
}
return logSuffix.Concat("", " ", ".");
}
@@ -5,7 +5,9 @@ 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.Mgr;
using Sarand.BusinessMgr.Net.Standard.Dbas.Data;
using Sarand.BusinessMgr.Web.Portal.App;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.CodeTypes;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Diary;
@@ -17,6 +19,7 @@ using Sarand.Net.Standard.Base.ReferenceData;
using Sarand.Net.Standard.Base.Security;
using Sarand.Net.Standard.Base.UpdateLog;
using Sarand.Net.Standard.Base.Utils;
using Sarand.Net.Standard.Dbas.Base;
using System.Collections.Generic;
using System.Linq;
@@ -27,7 +30,14 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
{
//-------------------------------------------------------------------
// Data members.
private SbmInternals internals;
public class DataMembers
{
/// <summary>Internals supplied by another component, likely the Controller.</summary>
public SbmInternals internalsSupplied;
/// <summary>Internals created locally when not supplied by another component.</summary>
public SbmInternals internals;
}
private readonly DataMembers mbr = new DataMembers();
//-------------------------------------------------------------------
// Protected construction.
@@ -40,7 +50,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
{
if (disposing)
{
if (internals != null) internals.Dispose(); internals = null;
if (mbr.internals != null) mbr.internals.Dispose(); mbr.internals = null;
}
base.Dispose(disposing);
}
@@ -64,8 +74,24 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
//-------------------------------------------------------------------
// Business components.
// NB Keep these accessors protected to avoid them being called by the model binding logic before the session data is ready.
protected SbmInternals Internals { get { if (internals == null) internals = new SbmInternals(SessionData_Portal); return internals; } }
/// <summary>Retrieve internals. Protected accessor to avoid called by ModelBinder.</summary>
protected SbmInternals Internals
{
get
{
// User supplied internals if available.
if (mbr.internalsSupplied != null) { return mbr.internalsSupplied; }
// Otherwise, create internals if not previously done.
if (mbr.internals == null) { mbr.internals = new SbmInternals(SessionData_Portal); /*SaLogger.Debug($"{SysUtil.Fn} Internals created by model.");*/ }
return mbr.internals;
}
}
public bool HasInternals() { return mbr.internalsSupplied != null || mbr.internals != null; }
/// <summary>Retrieve internals. Public method to avoid access by ModelBinder.</summary>
public SbmInternals GetInternals() { return Internals; }
/// <summary>Internals supplied from aother component, eg. the Controller.</summary>
/// <param name="internals"></param>
public void SetInternals(SbmInternals internals) { if (mbr.internalsSupplied != null) { mbr.internalsSupplied = internals; } }
// Managers.
protected SbmAccountMgr AccountMgr { get { return Internals.AccountMgr; } }
protected SbmCommodityMgr CommodityMgr { get { return Internals.CommodityMgr; } }
@@ -90,7 +116,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
protected SbmStockControlConfig StockControlConfig { get { return Internals.StockControlConfig; } }
protected SbmRequirementCostingConfig RequirementCostingConfig { get { return Internals.RequirementCostingConfig; } }
// System codes.
protected List<TypeCodeDesc> GetCodesOfType(Sbm.SystemCode systemCode) { return Internals.GetSystemCodes(systemCode); }
protected List<TypeCodeDesc> GetSystemCodes(Sbm.SystemCode systemCode) { return Internals.GetSystemCodes(systemCode); }
//-------------------------------------------------------------------
// Page menu options.
@@ -192,7 +218,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
/// </summary>
public IEnumerable<SelectListItem> GetAffiliateTypeCodesForFilterDropdown()
{
List<TypeCodeDesc> affiliateTypes = GetCodesOfType(Sbm.SystemCode.AffiliateType);
List<TypeCodeDesc> affiliateTypes = GetSystemCodes(Sbm.SystemCode.AffiliateType);
if (!affiliateTypes.Any(item => item.Type == (int)Sbm.AffiliateType.AnyOrganisation))
affiliateTypes.Insert(0, new TypeCodeDesc((int)Sbm.AffiliateType.AnyOrganisation, ((short)Sbm.AffiliateType.AnyOrganisation).ToString(), Localiser["label.organisation"]));
affiliateTypes.Insert(0, Sbm.AffiliateType.Any, "", Localiser["label.any"]);
@@ -205,7 +231,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
/// </summary>
public IEnumerable<SelectListItem> GetAssociationTypeCodesForFilterDropdown()
{
List<TypeCodeDesc> associationTypes = GetCodesOfType(Sbm.SystemCode.AssociationType);
List<TypeCodeDesc> associationTypes = GetSystemCodes(Sbm.SystemCode.AssociationType);
associationTypes.Insert(0, Sbm.AssociationType.Any, "", Localiser["label.any"]);
associationTypes.RemoveAll(item => item.Type == (short)Sbm.AssociationType.Internal);
foreach (Sbm.AssociationType associationType in EnumUtil.GetValues<Sbm.AssociationType>())
@@ -226,7 +252,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
{
List<TypeCodeDesc> commodityTypes = new List<TypeCodeDesc>();
commodityTypes.Add(Sbm.CommodityType.Any, "", Localiser["label.any"]);
foreach (TypeCodeDesc commodityType in GetCodesOfType(Sbm.SystemCode.CommodityType))
foreach (TypeCodeDesc commodityType in GetSystemCodes(Sbm.SystemCode.CommodityType))
{
if (commodityType.Type == (int)Sbm.CommodityType.Asset && !SessionConsole.AllowOption(Sbm.ConfigOption.Assets)) continue;
commodityTypes.Add(commodityType);
@@ -240,7 +266,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
public IEnumerable<SelectListItem> GetCommodityTypeCodesForDropdown()
{
List<TypeCodeDesc> commodityTypes = new List<TypeCodeDesc>();
foreach (TypeCodeDesc commodityType in GetCodesOfType(Sbm.SystemCode.CommodityType))
foreach (TypeCodeDesc commodityType in GetSystemCodes(Sbm.SystemCode.CommodityType))
{
if (commodityType.Type == (int)Sbm.CommodityType.Asset && !SessionConsole.AllowOption(Sbm.ConfigOption.Assets)) continue;
commodityTypes.Add(commodityType);
@@ -255,7 +281,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
{
List<TypeCodeDesc> assetTypes = new List<TypeCodeDesc>();
assetTypes.Add(Sbm.AssetType.Any, "", Localiser["label.any"]);
foreach (TypeCodeDesc assetType in GetCodesOfType(Sbm.SystemCode.AssetType))
foreach (TypeCodeDesc assetType in GetSystemCodes(Sbm.SystemCode.AssetType))
{
assetTypes.Add(assetType);
}
@@ -268,7 +294,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
public IEnumerable<SelectListItem> GetAssetTypeCodesForDropdown()
{
List<TypeCodeDesc> assetTypes = new List<TypeCodeDesc>();
foreach (TypeCodeDesc assetType in GetCodesOfType(Sbm.SystemCode.AssetType))
foreach (TypeCodeDesc assetType in GetSystemCodes(Sbm.SystemCode.AssetType))
{
assetTypes.Add(assetType);
}
@@ -285,7 +311,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
{
List<TypeCodeDesc> transactionTypes = new List<TypeCodeDesc>();
transactionTypes.Add(Sbm.TransactionType.Any, "", Localiser["label.any"]);
foreach (TypeCodeDesc transactionType in GetCodesOfType(Sbm.SystemCode.TransactionType))
foreach (TypeCodeDesc transactionType in GetSystemCodes(Sbm.SystemCode.TransactionType))
{
if (!SessionConsole.AllowTransactionType((Sbm.TransactionType)transactionType.Type)) continue;
string description = SessionConsole.GetOwnerOption_Caption(Sbm.TransTypeToOrgOption((Sbm.TransactionType)transactionType.Type), Localiser.GetTransactionTypeCaption((Sbm.TransactionType)transactionType.Type));
@@ -300,7 +326,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
public IEnumerable<SelectListItem> GetTransactionTypeCodesForDropdown()
{
List<TypeCodeDesc> transactionTypes = new List<TypeCodeDesc>();
foreach (TypeCodeDesc transactionType in GetCodesOfType(Sbm.SystemCode.TransactionType))
foreach (TypeCodeDesc transactionType in GetSystemCodes(Sbm.SystemCode.TransactionType))
{
if (!SessionConsole.AllowTransactionType((Sbm.TransactionType)transactionType.Type)) continue;
string description = SessionConsole.GetOwnerOption_Caption(Sbm.TransTypeToOrgOption((Sbm.TransactionType)transactionType.Type), Localiser.GetTransactionTypeCaption((Sbm.TransactionType)transactionType.Type));
@@ -74,10 +74,10 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets
public Model_AssetCategory.ListConfigData Config { get; } = new Model_AssetCategory.ListConfigData();
public Model_AssetCategory.ItemConfigData ConfigItemNew { get; } = new Model_AssetCategory.ItemConfigData();
// Reference data.
public List<CodeDesc> AssetTypes { get; } = new List<CodeDesc>();
public List<CodeDesc> IncomeTypes { get; } = new List<CodeDesc>();
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public List<CodeDesc> StatusesCreate { get; } = new List<CodeDesc>();
public List<ItemCodeDesc> AssetTypes { get; } = new List<ItemCodeDesc>();
public List<ItemCodeDesc> IncomeTypes { get; } = new List<ItemCodeDesc>();
public List<ItemCodeDesc> Statuses { get; } = new List<ItemCodeDesc>();
public List<ItemCodeDesc> StatusesCreate { get; } = new List<ItemCodeDesc>();
public String StatusCodeDefault { get; set; }
}
// Ajax request.
@@ -108,17 +108,17 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets
model.PopulateItemConfig(responseData.ConfigItemNew, null, Sbm.AssetType.Unknown);
// Reference data - select lists.
foreach (TypeCodeDesc assetType in GetCodesOfType(Sbm.SystemCode.AssetType))
responseData.AssetTypes.Add(assetType.Code, assetType.Desc);
foreach (TypeCodeDesc incomeType in GetCodesOfType(Sbm.SystemCode.AssetIncomeType))
responseData.IncomeTypes.Add(incomeType.Code, incomeType.Desc);
foreach (TypeCodeDesc assetType in GetSystemCodes(Sbm.SystemCode.AssetType))
responseData.AssetTypes.Add(new AjaxResponse_Data.ItemCodeDesc(assetType.Code, assetType.Desc));
foreach (TypeCodeDesc incomeType in GetSystemCodes(Sbm.SystemCode.AssetIncomeType))
responseData.IncomeTypes.Add(new AjaxResponse_Data.ItemCodeDesc(incomeType.Code, incomeType.Desc));
// Reference data - statuses.
foreach (SaStatus status in SbmAssetCategory.ValidStatuses)
{
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.Statuses.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
if (status != SaStatus.Deleted)
responseData.StatusesCreate.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.StatusesCreate.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
}
responseData.StatusCodeDefault = SacsSystem.GetStatusCode(SbmAssetCategory.DefaultStatus);
}
@@ -355,6 +355,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets
SaLogger.Warn($"{SysUtil.Fn} Failed to insert Asset Category: " + AssetMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.created"]);
}
else
{
@@ -363,6 +364,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets
SaLogger.Warn($"{SysUtil.Fn} Failed to update Asset Category [Id:" + SysId.ToString(assetCategory.Id) + "]: " + AssetMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]);
}
// Construct response.
@@ -80,8 +80,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets
public Model_Asset.ListConfigData Config { get; } = new Model_Asset.ListConfigData();
public Model_Asset.ItemConfigData ConfigItemNew { get; } = new Model_Asset.ItemConfigData();
// Reference data.
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public List<CodeDesc> StatusesCreate { get; } = new List<CodeDesc>();
public List<ItemCodeDesc> Statuses { get; } = new List<ItemCodeDesc>();
public List<ItemCodeDesc> StatusesCreate { get; } = new List<ItemCodeDesc>();
public String StatusCodeDefault { get; set; }
}
//-------------------------------------------------------------------
@@ -114,9 +114,9 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets
// Reference data - statuses.
foreach (SaStatus status in SbmAsset.ValidStatuses)
{
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.Statuses.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
if (status != SaStatus.Deleted)
responseData.StatusesCreate.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.StatusesCreate.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
}
responseData.StatusCodeDefault = SacsSystem.GetStatusCode(SbmAsset.DefaultStatus);
}
@@ -169,7 +169,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets
// Item filter.
SbmAsset.Params prmAsset = new SbmAsset.Params();
prmAsset.AssetCategoryId= model.GetFilterAssetCategoryId();
prmAsset.AssetCategoryId = model.GetFilterAssetCategoryId();
prmAsset.Search = model.Filter.Search;
prmAsset.StatusCat = model.GetFilterStatusCat();
model.Paging.ItemTotal = (ulong)AssetMgr.GetAssetCount(prmAsset);
@@ -180,7 +180,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets
ColumnDfn colCategoryDesc = AssetMgr.GetAssetColumnDfn(SbmAsset.Column.Category_DescBrief);
ColumnDfn colSerial = AssetMgr.GetAssetColumnDfn(SbmAsset.Column.SerialNumber);
ColumnDfn colDescBrief = AssetMgr.GetAssetColumnDfn(SbmAsset.Column.DescBrief);
ColumnDfn colNotes= AssetMgr.GetAssetColumnDfn(SbmAsset.Column.Notes);
ColumnDfn colNotes = AssetMgr.GetAssetColumnDfn(SbmAsset.Column.Notes);
ColumnDfn colStatus = AssetMgr.GetAssetColumnDfn(SbmAsset.Column.Status);
List<ColumnDfn> columns = new List<ColumnDfn>()
{
@@ -382,6 +382,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets
SaLogger.Warn($"{SysUtil.Fn} Failed to insert Asset: " + AssetMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.created"]);
}
else
{
@@ -390,6 +391,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets
SaLogger.Warn($"{SysUtil.Fn} Failed to update Asset [Id:" + SysId.ToString(asset.Id) + "]: " + AssetMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]);
}
// Construct response.
@@ -63,12 +63,13 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes
{
// Construction.
public AjaxResponse_CodeList(SbmModel_Portal model) : base(model) { }
// Reference data.
public List<ItemIdName> CodeTypes { get; } = new List<ItemIdName>();
public List<ItemCodeDesc> Statuses { get; } = new List<ItemCodeDesc>();
public List<ItemCodeDesc> StatusesCreate { get; } = new List<ItemCodeDesc>();
public String StatusCodeDefault { get; set; }
// Code list.
public List<CodeListData> Codes { get; } = new List<CodeListData>();
// Reference data.
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public List<CodeDesc> StatusesCreate { get; } = new List<CodeDesc>();
public String StatusCodeDefault { get; set; }
}
//-------------------------------------------------------------------
[HttpPost]
@@ -85,12 +86,18 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
RefreshModel(model);
// Reference data - Code Types.
SaCodeType.Params prmCodeType = new SaCodeType.Params();
prmCodeType.StatusCat = SaCodeType.StatusCat.NotDeleted;
foreach (SaCodeType codeType in CodeTypeConsole.GetCodeTypeList(prmCodeType))
responseData.CodeTypes.Add(new AjaxResponse_Data.ItemIdName(codeType.Id, codeType.Name));
// Reference data - statuses.
foreach (SaStatus status in SaCode.ValidStatuses)
{
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.Statuses.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
if (status != SaStatus.Deleted)
responseData.StatusesCreate.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.StatusesCreate.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
}
responseData.StatusCodeDefault = SacsSystem.GetStatusCode(SaCode.DefaultStatus);
@@ -302,6 +309,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes
SaLogger.Warn($"{SysUtil.Fn} Failed to insert Code: " + CodeTypeConsole.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.created"]);
}
else
{
@@ -310,6 +318,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes
SaLogger.Warn($"{SysUtil.Fn} Failed to update Code [Id:" + SysId.ToString(code.Id) + "]: " + CodeTypeConsole.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]);
}
// Construct response.
@@ -26,8 +26,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes
}
//-------------------------------------------------------------------
[Route("Codes/Code")]
public IActionResult Index(Model_Code model)
[Route("Codes/Code/{codeTypeCode=}")]
public IActionResult Index(String codeTypeCode)
{
if (!ValidUserSession)
AutoLoginUser();
@@ -40,6 +40,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes
}
// Prepare model.
Model_Code model = new Model_Code(Localiser);
model.Filter.CodeTypeCode = codeTypeCode;
RefreshModel(model);
model.PopulateCodeTypes();
@@ -60,8 +60,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes
// CodeTYpe list.
public List<CodeTypeListData> CodeTypes { get; } = new List<CodeTypeListData>();
// Reference data.
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public List<CodeDesc> StatusesCreate { get; } = new List<CodeDesc>();
public List<ItemCodeDesc> Statuses { get; } = new List<ItemCodeDesc>();
public List<ItemCodeDesc> StatusesCreate { get; } = new List<ItemCodeDesc>();
public String StatusCodeDefault { get; set; }
}
//-------------------------------------------------------------------
@@ -82,9 +82,9 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes
// Reference data - statuses.
foreach (SaStatus status in SaCodeType.ValidStatuses)
{
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.Statuses.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
if (status != SaStatus.Deleted)
responseData.StatusesCreate.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.StatusesCreate.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
}
responseData.StatusCodeDefault = SacsSystem.GetStatusCode(SaCodeType.DefaultStatus);
@@ -154,7 +154,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes
[Route("Codes/CodeType/Ajax/GetCodeType")]
public IActionResult Ajax_GetCodeType(Model_CodeType model)
{
String messageTitle = Localiser["caption.asset.category"];
String messageTitle = Localiser["caption.code.type"];
AjaxResponse_CodeType responseData = new AjaxResponse_CodeType(model);
// Validate session and referrer.
@@ -195,7 +195,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes
[Route("Codes/CodeType/Ajax/StoreCodeType")]
public IActionResult Ajax_StoreCodeType(Model_CodeType model)
{
String messageTitle = Localiser["caption.asset.category"];
String messageTitle = Localiser["caption.code.type"];
AjaxResponse_CodeType responseData = new AjaxResponse_CodeType(model);
// Validate session and referrer.
@@ -269,6 +269,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes
SaLogger.Warn($"{SysUtil.Fn} Failed to insert Asset Category: {CodeTypeConsole.ErrorStateMessage}");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.created"]);
}
else
{
@@ -277,6 +278,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes
SaLogger.Warn($"{SysUtil.Fn} Failed to update Asset Category [Id: {SysId.ToString(codeType.Id)}]: {CodeTypeConsole.ErrorStateMessage}");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]);
}
// Construct response.
@@ -13,6 +13,7 @@ using Sarand.Net.Standard.Base.Security;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
@@ -113,16 +114,21 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
// Configuration.
public Model_Commodity.ListConfigData Config { get; } = new Model_Commodity.ListConfigData();
public Model_Commodity.ItemConfigData ConfigItemNew { get; } = new Model_Commodity.ItemConfigData();
// Reference data.
public List<ItemCodeDesc> CommodityTypes { get; } = new List<ItemCodeDesc>();
public List<TaxCode> TaxCodes { get; } = new List<TaxCode>();
public String taxCodeDefault { get; set; }
public List<ItemCodeDesc> UomCats { get; } = new List<ItemCodeDesc>();
public List<ItemCodeDesc> UomTypes { get; } = new List<ItemCodeDesc>();
public String uomTypeDefault { get; set; }
public List<UomData> Uoms { get; set; } = new List<UomData>();
public List<ItemCodeDesc> Statuses { get; } = new List<ItemCodeDesc>();
public String DefaultStatusCode { get; set; }
// Reference data - object copied directly to env.datain script.
public class ReferenceData
{
public List<ItemCodeDesc> CommodityTypes { get; } = new List<ItemCodeDesc>();
public String CommodityTypeDefault { get; set; }
public List<TaxCode> TaxCodes { get; } = new List<TaxCode>();
public String taxCodeDefault { get; set; }
public List<ItemCodeDesc> UomCats { get; } = new List<ItemCodeDesc>();
public List<ItemCodeDesc> UomTypes { get; } = new List<ItemCodeDesc>();
public String uomTypeDefault { get; set; }
public List<UomData> Uoms { get; set; } = new List<UomData>();
public List<ItemCodeDesc> Statuses { get; } = new List<ItemCodeDesc>();
public String DefaultStatusCode { get; set; }
}
public ReferenceData Data { get; set; } = new ReferenceData();
}
// Ajax request.
[HttpPost]
@@ -151,23 +157,28 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
model.PopulateListConfig(responseData.Config);
model.PopulateItemConfig(responseData.ConfigItemNew, null, Sbm.CommodityType.Unknown);
// Reference data - commodity types.
foreach (TypeCodeDesc commodityType in GetCodesOfType(Sbm.SystemCode.CommodityType))
responseData.CommodityTypes.Add(new AjaxResponse_Data.ItemCodeDesc(commodityType.Code, commodityType.Desc));
// Commodity types.
List<TypeCodeDesc> commodityTypes = GetSystemCodes(Sbm.SystemCode.CommodityType);
foreach (TypeCodeDesc commodityType in commodityTypes)
responseData.Data.CommodityTypes.Add(new AjaxResponse_Data.ItemCodeDesc(commodityType.Code, commodityType.Desc));
Sbm.CommodityType commodityTypeDefault = SessionConsole.GetOwnerOption_CommodityType(Sbm.OrgOption_CommodityType.CommodityCreationDefault);
if (commodityTypeDefault <= 0) commodityTypeDefault = SessionConsole.GetCommodityTypeDefault(Sbm.OrgOption_CommodityType.CommodityCreationDefault);
if (commodityTypeDefault <= 0) commodityTypeDefault = Sbm.CommodityType.Stock;
if (commodityTypeDefault > 0) responseData.Data.CommodityTypeDefault = commodityTypes.GetCodeForType(commodityTypeDefault);
// Tax codes.
DateTime taxEffectiveOn = DateTime.Today;
responseData.TaxCodes.AddRange(Internals.GetTaxCodesEffectiveOn(taxEffectiveOn).Select(tax => new AjaxResponse_Data.TaxCode() { Id = $"{SysId.ToLong(tax.Id)}", Code = tax.Code, Caption = tax.GetCaption(), Rate = tax.TaxRate }));
responseData.taxCodeDefault = Internals.GetDefaultTaxCode();
responseData.Data.TaxCodes.AddRange(Internals.GetTaxCodesEffectiveOn(taxEffectiveOn).Select(tax => new AjaxResponse_Data.TaxCode() { Id = $"{SysId.ToLong(tax.Id)}", Code = tax.Code, Caption = tax.GetCaption(), Rate = tax.TaxRate }));
responseData.Data.taxCodeDefault = Internals.GetDefaultTaxCode();
// Units of measure.
List<TypeCodeDesc> uomCategories = SbmSystem.GetSystemCodes(Sbm.SystemCode.UnitMeasureCategory);
List<TypeCodeDesc> uomTypes = SbmSystem.GetSystemCodes(Sbm.SystemCode.UnitMeasureType);
responseData.UomCats.AddRange(uomCategories.Select(item => new AjaxResponse_Data.ItemCodeDesc(item.Code, item.Desc)));
responseData.UomTypes.AddRange(uomTypes.Select(item => new AjaxResponse_Data.ItemCodeDesc(item.Code, item.Desc)));
responseData.Data.UomCats.AddRange(uomCategories.Select(item => new AjaxResponse_Data.ItemCodeDesc(item.Code, item.Desc)));
responseData.Data.UomTypes.AddRange(uomTypes.Select(item => new AjaxResponse_Data.ItemCodeDesc(item.Code, item.Desc)));
foreach (SaUnitMeasure uom in Internals.GetUnitsOfMeasure())
{
responseData.Uoms.Add(new AjaxResponse_Data.UomData()
responseData.Data.Uoms.Add(new AjaxResponse_Data.UomData()
{
Id = $"{SysId.ToLong(uom.Id)}",
Category = uomCategories.GetCodeForType(uom.Category),
@@ -175,12 +186,12 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
Caption = uom.Multiple,
});
}
responseData.uomTypeDefault = uomTypes.GetCodeForType(Internals.GetDefaultUomType());
responseData.Data.uomTypeDefault = uomTypes.GetCodeForType(Internals.GetDefaultUomType());
// Reference data - statuses.
foreach (SaStatus status in SbmCommodity.ValidStatuses.FindAll(item => item != SaStatus.Deleted))
responseData.Statuses.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SbmCommodity.DefaultStatus);
responseData.Data.Statuses.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
responseData.Data.DefaultStatusCode = SacsSystem.GetStatusCode(SbmCommodity.DefaultStatus);
}
//-------------------------------------------------------------------
@@ -101,8 +101,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
public Model_Association.ItemConfigData ConfigCust { get; } = new Model_Association.ItemConfigData();
public Model_Association.ItemConfigData ConfigSupp { get; } = new Model_Association.ItemConfigData();
// Reference data.
public List<CodeDesc> AssociationTypes { get; } = new List<CodeDesc>();
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public List<ItemCodeDesc> AssociationTypes { get; } = new List<ItemCodeDesc>();
public List<ItemCodeDesc> Statuses { get; } = new List<ItemCodeDesc>();
public String DefaultStatusCode { get; set; }
}
// Ajax request.
@@ -147,12 +147,12 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
{
if (type <= 0 || type == Sbm.AssociationType.Internal) continue;
if (!SessionConsole.AllowAssociationType(type)) continue;
responseData.AssociationTypes.Add(associationTypes.GetCodeForType(type), Localiser.GetAssociationTypeCaption(type));
responseData.AssociationTypes.Add(new AjaxResponse_Data.ItemCodeDesc(associationTypes.GetCodeForType(type), Localiser.GetAssociationTypeCaption(type)));
}
// Reference data - statuses.
foreach (SaStatus status in SbmAssociation.ValidStatuses.FindAll(item => item != SaStatus.Deleted))
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.Statuses.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SbmAssociation.DefaultStatus);
}
@@ -147,7 +147,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
model.PopulateItemConfig(responseData.ConfigGrp, null, Sbm.AffiliateType.ContactGroup);
// Reference data - Organisation types.
foreach (TypeCodeDesc affiliateType in GetCodesOfType(Sbm.SystemCode.AffiliateType).Where(item => item.Type != (short)Sbm.AffiliateType.Individual && item.Type != (short)Sbm.AffiliateType.ContactGroup))
foreach (TypeCodeDesc affiliateType in GetSystemCodes(Sbm.SystemCode.AffiliateType).Where(item => item.Type != (short)Sbm.AffiliateType.Individual && item.Type != (short)Sbm.AffiliateType.ContactGroup))
responseData.OrganisationTypes.Add(new AjaxResponse_Data.ItemCodeDesc(affiliateType.Code, affiliateType.Desc));
// Reference data - titles.
@@ -358,7 +358,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
public ActionResult Ajax_StorePassword(Model_Security model)
{
AjaxResponse_ChangePassword responseData = new AjaxResponse_ChangePassword(model);
String messageTitle = Localiser["security.caption.change.password"];
String messageTitle = Localiser["caption.change.password"];
// Validate referrer.
if (!ValidReferer) return Forbid();
@@ -488,7 +488,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
public ActionResult Ajax_RequestPassword(Model_Security model)
{
AjaxResponse_RequestPassword responseData = new AjaxResponse_RequestPassword(model);
String messageTitle = Localiser["security.caption.request.password"];
String messageTitle = Localiser["caption.request.password"];
// Validate referrer.
if (!ValidReferer) return Forbid();
@@ -522,7 +522,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
SaEmailData emailData = new SaEmailData();
emailData.Config = App.EmailConfig;
emailData.AddressesTo.Add(model.EmailAddress);
emailData.Subject = Localiser["security.caption.request.password"];
emailData.Subject = $"BusinessMgr - {Localiser["caption.request.password"]}";
PopulateRequestPasswordEmailBody(emailConsole, sessionDataForUser, emailData, securityItemUser, affiliateUser);
if (emailConsole.SendEmail(emailData))
SaLogger.Info($"{SysUtil.Fn} Password request email sent to {model.EmailAddress}.", true);
@@ -542,7 +542,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
responseData.SuccessMsg = Localiser["security.msg.request.password.email.sent"];
return Json(responseData);
}
private void PopulateRequestPasswordEmailBody(SbmEmailConsole emailConsole, ISbmUserOrganisationContext userContext, SaEmailData emailData, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser)
private void PopulateRequestPasswordEmailBody(SbmEmailConsole emailConsole, SbmSessionData_Portal sessionData, SaEmailData emailData, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser)
{
// Will need to handle culture (language/country) as and when introduced.
emailData.MessageBody = SbmResourceHelper.GetResourceText(SbmResourceHelper.TextResource.Email_RequestPassword_Html);
@@ -552,7 +552,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
emailConsole.ReplaceDynamicEmailBodyTags(emailData, null);
// Replace dynamic tag for link back to change password page.
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.RequestPassword]", GenerateRequestPasswordLink(SessionData_Portal.RepositoryContext, securityItemUser.Id, affiliateUser.Id, securityItemUser.EmailAddress, ""));
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.RequestPassword]", GenerateRequestPasswordLink(sessionData.RepositoryContext, securityItemUser.Id, affiliateUser.Id, securityItemUser.EmailAddress, ""));
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.ExpiresMinutes]", GetRequestPasswordEmailLinkExpiresMinutes().ToString());
}
@@ -619,7 +619,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
{
return
!StringUtil.IsBlank(RepositoryContext) &&
StringUtil.IsBlank(EmailAddress) &&
!StringUtil.IsBlank(EmailAddress) &&
SysId.IsValid(SecurityItemId) &&
SysId.IsValid(AffiliateId) &&
DateUtil.IsValid(ExpiresAt) && ExpiresAt >= DateTime.Now;
@@ -134,7 +134,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
return RedirectToAction("", "");
// Configure page.
model.PageCaption = Localiser["security.caption.change.password"];
model.PageCaption = Localiser["caption.change.password"];
return View(model);
}
@@ -153,7 +153,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
Model_Security model = new Model_Security(Localiser);
// Configure page.
model.PageCaption = Localiser["security.caption.request.password"];
model.PageCaption = Localiser["caption.request.password"];
model.ProhibitCache = false;
return View(model);
@@ -92,8 +92,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Transactions
public Model_Transaction.ListConfigData Config { get; } = new Model_Transaction.ListConfigData();
public Model_Transaction.ItemConfigData ConfigItemNew { get; } = new Model_Transaction.ItemConfigData();
// Reference data.
public List<CodeDesc> TransactionTypes { get; } = new List<CodeDesc>();
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public List<ItemCodeDesc> TransactionTypes { get; } = new List<ItemCodeDesc>();
public List<ItemCodeDesc> Statuses { get; } = new List<ItemCodeDesc>();
public String DefaultStatusCode { get; set; }
}
// Ajax request.
@@ -124,12 +124,12 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Transactions
model.PopulateItemConfig(responseData.ConfigItemNew, null, Sbm.TransactionType.Unknown);
// Reference data - transaction types.
foreach (TypeCodeDesc transactionType in GetCodesOfType(Sbm.SystemCode.TransactionType))
responseData.TransactionTypes.Add(transactionType.Code, transactionType.Desc);
foreach (TypeCodeDesc transactionType in GetSystemCodes(Sbm.SystemCode.TransactionType))
responseData.TransactionTypes.Add(new AjaxResponse_Data.ItemCodeDesc(transactionType.Code, transactionType.Desc));
// Reference data - statuses.
foreach (SaStatus status in SbmTransaction.ValidStatuses().FindAll(item => item != SaStatus.Deleted))
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.Statuses.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SbmTransaction.DefaultStatus);
}
@@ -65,8 +65,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Vehicles
// VehicleClass list.
public List<VehicleClassListData> VehicleClasses { get; } = new List<VehicleClassListData>();
// Reference data.
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public List<CodeDesc> StatusesCreate { get; } = new List<CodeDesc>();
public List<ItemCodeDesc> Statuses { get; } = new List<ItemCodeDesc>();
public List<ItemCodeDesc> StatusesCreate { get; } = new List<ItemCodeDesc>();
public String StatusCodeDefault { get; set; }
}
//-------------------------------------------------------------------
@@ -87,9 +87,9 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Vehicles
// Reference data - statuses.
foreach (SaStatus status in SbmVehicleClass.ValidStatuses)
{
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.Statuses.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
if (status != SaStatus.Deleted)
responseData.StatusesCreate.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.StatusesCreate.Add(new AjaxResponse_Data.ItemCodeDesc(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)));
}
responseData.StatusCodeDefault = SacsSystem.GetStatusCode(SbmVehicleClass.DefaultStatus);
@@ -269,6 +269,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Vehicles
SaLogger.Warn($"{SysUtil.Fn} Failed to insert Vehicle Class: " + AssetMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.created"]);
}
else
{
@@ -277,6 +278,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Vehicles
SaLogger.Warn($"{SysUtil.Fn} Failed to update Vehicle Class [Id:" + SysId.ToString(vehicleClass.Id) + "]: " + AssetMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
}
responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]);
}
// Construct response.
@@ -112,6 +112,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Assets
bool userCanCreateAssets = SessionData_Portal.SecurityProfile.UserCanCreateItemType(Sbm.ItemType.Asset);
bool userCanUpdateAssets = SessionData_Portal.SecurityProfile.UserCanUpdateItemType(Sbm.ItemType.Asset);
//---------------------------------------------------------------
// Actions.
if (userCanCreateAssets)
@@ -1,4 +1,5 @@
using DocumentFormat.OpenXml.Spreadsheet;
using NPOI.SS.Formula.Functions;
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Components;
using Sarand.BusinessMgr.Net.Standard.Base.App;
@@ -59,7 +60,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Codes
public String Exists { get; set; }
public String Id { get; set; }
public String CodeTypeId { get; set; }
public String Code{ get; set; }
public String Code { get; set; }
public String Description { get; set; }
public String Sequence { get; set; }
public String Notes { get; set; }
@@ -92,6 +93,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Codes
if (Code.Code != null)
{
String controlName = "CodeCode";
Code.Code = Code.Code.ToUpperInvariant();
responseData.SetControlValue(controlName, Code.Code);
if (StringUtil.IsBlank(Code.Code))
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
@@ -111,7 +113,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Codes
}
// Notes.
if (Code.Notes!= null)
if (Code.Notes != null)
{
String controlName = "CodeNotes";
responseData.SetControlValue(controlName, Code.Notes);
@@ -68,6 +68,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Codes
if (CodeType.Code != null)
{
String controlName = "CodeTypeCode";
CodeType.Code = CodeType.Code.ToUpperInvariant();
responseData.SetControlValue(controlName, CodeType.Code);
if (StringUtil.IsBlank(CodeType.Code))
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
@@ -189,6 +189,17 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Commodities
// List configuration.
public class ListConfigData
{
// Actions.
public class ActionData
{
public class AllowData
{
public bool? Create { get; set; }
public bool? Update { get; set; }
}
public AllowData Allow { get; } = new AllowData();
}
public ActionData Action { get; } = new ActionData();
// List columns.
public class ColumnData
{
@@ -223,9 +234,18 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Commodities
bool modeIsSearch = viewMode == ViewMode.Search;
bool modeIsStockControl = viewMode == ViewMode.StockControl;
bool modeIsStockTake = viewMode == ViewMode.StockTake;
bool userCanCreateCommodities = SessionData_Portal.SecurityProfile.UserCanCreateItemType(Sbm.ItemType.Commodity);
bool userCanUpdateCommodities = SessionData_Portal.SecurityProfile.UserCanUpdateItemType(Sbm.ItemType.Commodity);
Sbm.CommodityType commodityType = GetFilterCommodityType();
//---------------------------------------------------------------
// Actions.
if (userCanCreateCommodities)
config.Action.Allow.Create = true;
if (userCanUpdateCommodities)
config.Action.Allow.Update = true;
//---------------------------------------------------------------
// Commodity list columns.
@@ -140,6 +140,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Commodities
if (Commodity.Code != null)
{
String controlName = GetFieldName(Model_Commodity.ItemField.Code);
Commodity.Code = Commodity.Code.ToUpperInvariant();
responseData.SetControlValue(controlName, Commodity.Code);
if (Commodity.Code.IsEmpty())
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
@@ -248,7 +249,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Commodities
prmCommodity.CodeFull = Commodity.Code;
prmCommodity.DrawingIssueFull = Commodity.DrawingIssue;
// Restrict to same customer.
prmCommodity.AssociationIdCustomer = Commodity.AssocIdCustomer != null ? SysId.ToSysId(Commodity.AssocIdCustomer) : commodity.AssociationIdCustomer;
prmCommodity.AssociationIdCustomer = Commodity.AssocIdCustomer != null ? SysId.ToSysId(Commodity.AssocIdCustomer) : commodity?.AssociationIdCustomer;
prmCommodity.StatusCat = SbmCommodity.StatusCat.Current;
List<SbmCommodity> commodities = CommodityMgr.GetCommodityList(prmCommodity);
disposables.AddRange(commodities);
@@ -135,6 +135,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
if (Association.Code != null)
{
String controlName = "AssociationCode";
Association.Code = Association.Code.ToUpperInvariant();
responseData.SetControlValue(controlName, Association.Code);
if (StringUtil.GetLength(Association.Code) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Code))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Code)]);
@@ -144,6 +145,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
if (Association.ReferenceExt != null)
{
String controlName = "AssociationReferenceExt";
Association.ReferenceExt = Association.ReferenceExt.ToUpperInvariant();
responseData.SetControlValue(controlName, Association.ReferenceExt);
if (StringUtil.GetLength(Association.ReferenceExt) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_ExtRef))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_ExtRef)]);
@@ -153,7 +153,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
if (Contact.Abbreviation != null)
{
String controlName = GetFieldName(ItemField.Abbreviation);
Contact.Abbreviation = Contact.Abbreviation.ToUpper();
Contact.Abbreviation = Contact.Abbreviation.ToUpperInvariant();
responseData.SetControlValue(controlName, Contact.Abbreviation);
if (StringUtil.GetLength(Contact.Abbreviation) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Abbrev))
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Abbrev)]);
@@ -131,7 +131,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Association.Code" id="ifAssociationCode" class="AssociationCode sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Code)" />
<input type="text" name="Association.Code" id="ifAssociationCode" class="AssociationCode sbm-input upper sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Code)" />
</div>
<div class="sbm-message"></div>
</div>
@@ -152,7 +152,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Association.ReferenceExt" id="ifAssociationExtRef" class="AssociationExtRef sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_ExtRef)" />
<input type="text" name="Association.ReferenceExt" id="ifAssociationExtRef" class="AssociationExtRef sbm-input upper sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_ExtRef)" />
</div>
<div class="sbm-message"></div>
</div>
@@ -118,8 +118,8 @@
<div class="spacer2"></div>
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCode", @class = "sbm-form", @onSubmit = "return false;" }))
{
@Html.HiddenFor(model => model.Code.Exists, new { @id = "", @class = "CodeExists" })
@Html.HiddenFor(model => model.Code.Id, new { @id = "", @class = "CodeId" })
@Html.HiddenFor(model => model.Code.Exists, new { @id = "", @class = "CodeExists sbm-input" })
@Html.HiddenFor(model => model.Code.Id, new { @id = "", @class = "CodeId sbm-input" })
@* Type *@
<div class="sbm-form-control CodeType">
@@ -131,44 +131,54 @@
</div>
<div class="col-sm-9">
<div class="sbm-control">
<select name="model.Code.CodeTypeId" class="CodeType sbm-select" readonly="readonly"></select>
<select id="cbCodeType" name="Code.CodeTypeId" class="CodeType sbm-select" readonly="readonly"></select>
</div>
<div class="sbm-message"></div>
</div>
</div>
</div>
@* Code *@
<div class="sbm-form-control CodeCode">
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="ifCodeCode"><span>@Localiser["label.code"]</span><span class="required">&nbsp;*</span></label>
</div>
</div>
<div class="col-sm-9">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Code.Code, new { @id = "ifCodeCode", @class = "CodeCode sbm-input", @maxlength = 3 })
</div>
<div class="sbm-message"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
@* Sequence *@
<div class="sbm-form-control CodeSequence">
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
<label for="ifCodeSequence"><span>@Localiser["label.sequence"]</span><span class="required">&nbsp;*</span></label>
@* Code *@
<div class="sbm-form-control CodeCode">
<div class="row">
<div class="col-sm-6">
<div class="sbm-label">
<label for="ifCodeCode"><span>@Localiser["label.code"]</span><span class="required">&nbsp;*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Code.Code, new { @id = "ifCodeCode", @class = "CodeCode sbm-input upper", @maxlength = 3 })
</div>
<div class="sbm-message"></div>
</div>
</div>
</div>
<div class="col-sm-9">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Code.Sequence, new { @id = "ifCodeSequence", @class = "CodeSequence sbm-input", @maxlength = 3 })
</div>
<div class="col-sm">
@* Sequence *@
<div class="sbm-form-control CodeSequence">
<div class="row">
<div class="col-sm-1"></div>
<div class="col-sm-4">
<div class="sbm-label">
<label for="ifCodeSequence"><span>@Localiser["label.sequence"]</span><span class="required">&nbsp;*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Code.Sequence, new { @id = "ifCodeSequence", @class = "CodeSequence sbm-input", @maxlength = 3 })
</div>
<div class="sbm-message"></div>
</div>
</div>
<div class="sbm-message"></div>
</div>
</div>
</div>
@@ -105,8 +105,8 @@
<div class="spacer2"></div>
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCodeType", @class = "sbm-form", @onSubmit = "return false;" }))
{
@Html.HiddenFor(model => model.CodeType.Exists, new { @id = "", @class = "CodeTypeExists" })
@Html.HiddenFor(model => model.CodeType.Id, new { @id = "", @class = "CodeTypeId" })
@Html.HiddenFor(model => model.CodeType.Exists, new { @id = "", @class = "CodeTypeExists sbm-input" })
@Html.HiddenFor(model => model.CodeType.Id, new { @id = "", @class = "CodeTypeId sbm-input" })
@* Code *@
<div class="sbm-form-control CodeTypeCode">
@@ -118,7 +118,7 @@
</div>
<div class="col-sm-9">
<div class="sbm-control">
@Html.TextBoxFor(model => model.CodeType.Code, new { @id = "ifCodeTypeCode", @class = "CodeTypeCode sbm-input", @maxlength = @Model.GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_Code) })
@Html.TextBoxFor(model => model.CodeType.Code, new { @id = "ifCodeTypeCode", @class = "CodeTypeCode sbm-input upper", @maxlength = @Model.GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_Code) })
</div>
<div class="sbm-message"></div>
</div>
@@ -40,7 +40,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBox("Commodity.Code", "", new { @id = "ifCommodityCode", @class = "CommodityCode sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Code) })
@Html.TextBox("Commodity.Code", "", new { @id = "ifCommodityCode", @class = "CommodityCode sbm-input upper sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Code) })
</div>
<div class="sbm-message"></div>
</div>
@@ -8,7 +8,7 @@
<div class="sbm-panel-form security">
<div class="sbm-header"><div class="sbm-caption">@Localiser["security.caption.change.password"]</div></div>
<div class="sbm-header"><div class="sbm-caption">@Localiser["caption.change.password"]</div></div>
<div class="sbm-content">
@@ -69,7 +69,7 @@
<div class="spacer4"></div>
<div class="">
<div id="pbChangePassword" class="sbm-button-action fullwidth pointer" style="margin:16px 0;">@Localiser["security.caption.change.password"]</div>
<div id="pbChangePassword" class="sbm-button-action fullwidth pointer" style="margin:16px 0;">@Localiser["caption.change.password"]</div>
</div>
}
@@ -7,7 +7,7 @@
<div class="">
<div class="sbm-panel-form security">
<div class="sbm-header"><div class="sbm-caption">@Localiser["security.caption.request.password"]</div></div>
<div class="sbm-header"><div class="sbm-caption">@Localiser["caption.request.password"]</div></div>
<div class="sbm-content">
@@ -38,7 +38,7 @@
<div class="spacer4"></div>
<div class="">
<div id="pbRequestPassword" class="sbm-button-action fullwidth pointer" style="margin:16px 0;">@Localiser["security.caption.request.password"]</div>
<div id="pbRequestPassword" class="sbm-button-action fullwidth pointer" style="margin:16px 0;">@Localiser["caption.request.password"]</div>
</div>
}
@@ -98,11 +98,11 @@
<body>
@* Header *@
<header id="sbm-page-header">
<header id="sbm-page-header" class="bg-white border-bottom">
<div class="container">
@* Navigation bar *@
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom">
<div class="container">
@* Navigation bar *@
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">BusinessMgr</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
@@ -150,13 +150,13 @@
}
</ul>
</div>
</div>
</nav>
</nav>
</div>
</header>
@* Page body *@
<div id="sbm-page-body">
<main role="main" class="container pt-2 pb-2 fullheight">
<main role="main" class="container fullheight">
@RenderBody()
</main>
</div>
@@ -19,7 +19,7 @@
"RootFolder": "C:\\Sarand\\BusinessMgr\\Docs"
},
"Logging": {
"RootFolder": "C:\\Sarand\\BusinessMgr\\Logs"
"RootFolder": "C:\\Sarand\\BusinessMgr\\Log"
}
}
}
@@ -59,6 +59,12 @@ body
background-color: #f8ffff;
}
#sbm-page-body main.container
{
position: relative;
padding: 4px 4px;
}
#sbm-page-body > .container, header > .container, footer > .container
{
padding: 0 4px;
@@ -94,6 +100,11 @@ body
{
}
.navbar
{
padding: 6px 2px;
}
.navbar a.navbar-brand
{
padding-top: 0.3rem;
@@ -141,7 +152,7 @@ button.accept-policy
#sbm-page-footer
{
padding: 4px 0;
padding: 3px 0;
}
#sbm-page-footer, #sbm-page-footer div
@@ -247,10 +258,11 @@ a:focus
#sbm-notification
{
display: none;
position: fixed;
position: absolute;
top: 2px;
right: 48px;
min-width: 180px;
margin-top: 6px;
margin-right: 48px;
z-index: 1000;
border: 1px solid #808080;
border-bottom-left-radius: 4px;
@@ -6,29 +6,28 @@
(function (win, doc, undef)
{
"use strict";
let ac = sbm.CodeCat = { data: {}, ajax: {} };
let $pnl = ac.$pnl = {}, $frm = ac.$frm = {}, $dlg = ac.$dlg = {};
let ct = sbm.CodeTypes = { env: {} };
//--------------------------------------------------------------
ac.refreshResults = function (delay)
ct.refreshResults = function (env, delay)
{
if (!ac.awaitingRefreshResponse)
if (!ct.awaitingRefreshResponse)
{
$('.sbm-burger', $pnl.header).invisible();
$pnl.table.find('tbody tr').remove();
$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
env.$pnl.bgr.invisible();
env.$pnl.table.find('tbody tr').remove();
env.$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
}
ac.ajax.codeTypes = ac.ajax.codeTypes || { url: sbm.url.base + 'Codes/CodeType/Ajax/GetCodeTypes', formId: $frm.filter.prop('id'), callbackFn: ac.handleCodeTypes };
sbm.doAjaxRequest(ac.ajax.codeTypes, delay || 50);
ac.awaitingRefreshResponse = true;
env.ajax.codeTypes = env.ajax.codeTypes || { url: sbm.url.base + 'Codes/CodeType/Ajax/GetCodeTypes', formSel: env.$frm.filter, callbackFn: function (response) { ct.handleCodeTypes(env, response); } };
sbm.doAjaxRequest(env.ajax.codeTypes, delay || 50);
ct.awaitingRefreshResponse = true;
}
ac.handleCodeTypes = function (response)
ct.handleCodeTypes = function (env, response)
{
//sbm.debug('handleCodeTypes', response);
delete ac.awaitingRefreshResponse;
let $table = $('table', $pnl.table).find('tbody tr').remove().end();
$pnl.msgs.hide().empty();
sbm.refreshPaging(response, '#frmCodeTypeFilter', ac.refreshResults);
delete ct.awaitingRefreshResponse;
let $table = $('table', env.$pnl.table).find('tbody tr').remove().end();
env.$pnl.msgs.hide().empty();
sbm.refreshPaging(response, '#frmCodeTypeFilter', function () { ct.refreshResults(env); });
if (!response.success) return;
// Reference data - Statuses.
@@ -37,167 +36,179 @@
if (response.statusCodeDefault) sbm.data.statusCodeDefault = response.statusCodeDefault;
// Menu.
var $bgr = $('.sbm-burger', $pnl.header).invisible();
var $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
$mnu.append(ac.getFilterMenuOption(sbm.lbl.refresh, function () { ac.refreshResults(); }, 'sbm-refresh'));
$mnu.append(ac.getFilterMenuOption(sbm.lbl.create, function () { ac.createItem(); }, 'sbm-add'));
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
if (env.$pnl.bgr.length)
{
env.$pnl.bgr.invisible();
env.$pnl.mnu.empty();
env.$pnl.mnu.append(ct.getFilterMenuOption(env, sbm.lbl.refresh, function () { ct.refreshResults(env); }, 'sbm-refresh'));
env.$pnl.mnu.append(ct.getFilterMenuOption(env, sbm.lbl.create, function () { ct.createItem(env); }, 'sbm-add'));
env.$pnl.bgr.toggleVisibility(!!$('.sbm-dropdown-item', env.$pnl.mnu).length);
}
// Items.
var items = response.codeTypes || [];
if (!items.length)
return $pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
$table.append(ac.populateItem(ac.getItemRowTemplate(), items[itemIdx]));
return env.$pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
for (const item of items)
$table.append(ct.populateItem(env, ct.getItemRowTemplate(env), item));
}
ac.populateItem = function ($item, item)
ct.populateItem = function (env, $item, item)
{
if (!item) return $item;
$pnl.msgs.hide().empty();
$item.prop('id', ac.getItemId(item));
$('.CodeTypeCode', $item).text(item.code);
$('.CodeTypeName', $item).text(item.name);
$('.CodeTypeCodes', $item).text(item.codeCount);
$('.CodeTypeStatusDesc', $item).text(item.statusDesc).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
env.$pnl.msgs.hide().empty();
$item.prop('id', ct.getItemId(item));
$item.find('.CodeTypeCode').text(item.code);
$item.find('.CodeTypeName').text(item.name);
$item.find('.CodeTypeCodes').text(item.codeCount);
$item.find('.CodeTypeStatusDesc').text(item.statusDesc).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
// Actions.
let fnUpd = function () { ac.updateItem($item, item) };
let fnUpd = function () { ct.updateItem(env, $item, item) };
var $bgr = $('.sbm-burger', $item).invisible();
let $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
if (!item.deleted)
{
$mnu.append(ac.getItemMenuOption(sbm.lbl.edit, fnUpd, 'sbm-edit'));
$mnu.append(ct.getItemMenuOption(env, sbm.lbl.edit, fnUpd, 'sbm-edit'));
$('.CodeTypeName', $item).off('click').on('click', fnUpd).addClass('sbm-action-text');
$('.CodeTypeCodes', $item).off('click').on('click', function () { sbm.navigateTo('Codes/Code?Filter.CodeTypeCode='+item.code);return false; }).on('dblclick', function () { return false; }).addClass('sbm-action-text');
$('.CodeTypeCodes', $item).off('click').on('click', function () { sbm.goToPage('Codes/Code/' + item.code); return false; }).on('dblclick', function () { return false; }).addClass('sbm-action-text');
$item.off('dblclick').on('dblclick', fnUpd);
}
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
return $item;
}
ac.getItemId = function (item)
ct.getItemId = function (item)
{
return 'Itm_' + (item || {}).id;
return 'Ctp_' + (item || {}).id;
}
//--------------------------------------------------------------
ac.getFilterDropdownTemplate = function ()
ct.getFilterDropdownTemplate = function (env)
{
return $('.sbm-dropdown-menu.CodeTypeFilter li.sbm-dropdown-item', $pnl.tmpls).clone();
return $('.sbm-dropdown-menu.CodeTypeFilter li.sbm-dropdown-item', env.$pnl.tmpl).clone();
}
ac.getItemRowTemplate = function ()
ct.getItemRowTemplate = function (env)
{
return $('table tr.sbm-row-item.CodeType', $pnl.tmpls).clone();
return $('table tr.sbm-row-item.CodeType', env.$pnl.tmpl).clone();
}
ac.getItemDropdownTemplate = function ()
ct.getItemDropdownTemplate = function (env)
{
return $('.sbm-dropdown-menu.CodeType li.sbm-dropdown-item', $pnl.tmpls).clone();
return $('.sbm-dropdown-menu.CodeType li.sbm-dropdown-item', env.$pnl.tmpl).clone();
}
ac.getFilterMenuOption = function (lbl, fn, cls)
ct.getFilterMenuOption = function (env, lbl, fn, cls)
{
return ac.getMenuOption(ac.getFilterDropdownTemplate(), lbl, fn, cls);
return ct.getMenuOption(ct.getFilterDropdownTemplate(env), lbl, fn, cls);
}
ac.getItemMenuOption = function (lbl, fn, cls)
ct.getItemMenuOption = function (env, lbl, fn, cls)
{
return ac.getMenuOption(ac.getItemDropdownTemplate(), lbl, fn, cls);
return ct.getMenuOption(ct.getItemDropdownTemplate(env), lbl, fn, cls);
}
ac.getMenuOption = function ($opt, lbl, fn, cls)
ct.getMenuOption = function ($opt, lbl, fn, cls)
{
return $opt.find('div.sbm-label').text(lbl).end().on('click', fn).addClass(cls);
}
//--------------------------------------------------------------
ac.createItem = function ()
ct.createItem = function (env)
{
ac.clearItem();
ct.clearItem();
sbm.populateSelectCodeDesc('#cbCodeTypeStatus', sbm.data.statusesCreate);
$('#cbCodeTypeStatus').val(sbm.data.statusCodeDefault).prop('readonly', false);
$dlg.item.dialog('option', 'title', sbm.dlg.title.createItem);
ac.openCodeTypeDlg();
ct.openCodeTypeDlg(env, sbm.dlg.title.createItem);
}
ac.openCodeTypeDlg = function ()
ct.clearItem = function (env)
{
sbm.openDialog($dlg.item, 600, 600);
}
ac.clearItem = function ()
{
let frm = $frm.item;
$('.CodeTypeExists,.CodeTypeId,input[type="text"],textarea,select', frm).val('');
let $frm = env.$frm.item;
$frm.find('.CodeTypeExists,.CodeTypeId,input[type="text"],textarea,select').val('');
sbm.populateSelectCodeDesc('#cbCodeTypeStatus', sbm.data.statuses);
$('.CodeTypeCode', frm).prop('readonly', false);
$frm.find('.CodeTypeCode').prop('readonly', false);
sbm.clearControlErrors();
}
ct.openCodeTypeDlg = function (env, title)
{
let $dlg = env.$dlg.item;
let $frm = env.$frm.item;
var btns = {};
btns[sbm.lbl.ok] = function () { ct.storeItem(env); };
btns[sbm.lbl.cancel] = function () { delete env.prmEdit; $(this).dialog('close'); };
$dlg.dialog('option', 'buttons', btns);
if (title) $dlg.dialog('option', 'title', title);
sbm.openDialog($dlg, 600, 480);
}
//--------------------------------------------------------------
ac.updateItem = function ($item, item)
ct.updateItem = function (env, $item, item)
{
ac.clearItem();
$('.CodeTypeId', $frm.itemId).val(item.id);
sbm.ajax.updateItem = sbm.ajax.updateItem || { url: sbm.url.base + 'Codes/CodeType/Ajax/GetItem', formId: $frm.itemId.prop('id'), callbackFn: ac.onUpdateItem };
sbm.doAjaxRequest(sbm.ajax.updateItem, 50);
ct.clearItem(env);
$('.CodeTypeId', env.$frm.itemId).val(item.id);
env.ajax.updateItem = env.ajax.updateItem || { url: sbm.url.base + 'Codes/CodeType/Ajax/GetItem', formSel: env.$frm.itemId, callbackFn: function (response) { ct.onUpdateItem(env, response); } };
sbm.doAjaxRequest(env.ajax.updateItem, 50);
}
ac.onUpdateItem = function (response)
ct.onUpdateItem = function (env, response)
{
//sbm.debug('onUpdateItem', response);
let frm = $frm.item;
ac.clearItem();
ct.clearItem(env);
if (!response.success) return;
let item = response.codeType;
$('.CodeTypeExists', frm).val(1);
$('.CodeTypeId', frm).val(item.id);
$('.CodeTypeCode', frm).val(item.code).prop('readonly', true);
$('.CodeTypeName', frm).val(item.name);
$('.CodeTypeNotes', frm).val(item.notes);
$('.CodeTypeStatus', frm).val(item.statusCode);
sbm.clearControlErrors();
$dlg.item.dialog('option', 'title', sbm.dlg.title.updateItem);
ac.openCodeTypeDlg();
let $frm = env.$frm.item;
let $ctrls = $frm.find('.sbm-input,.sbm-textarea,.sbm-select');
$ctrls.filter('.CodeTypeExists').val(1);
$ctrls.filter('.CodeTypeId').val(item.id);
$ctrls.filter('.CodeTypeCode').val(item.code).prop('readonly', true);
$ctrls.filter('.CodeTypeName').val(item.name);
$ctrls.filter('.CodeTypeNotes').val(item.notes);
$ctrls.filter('.CodeTypeStatus').val(item.statusCode);
ct.openCodeTypeDlg(env, sbm.dlg.title.updateItem);
}
//--------------------------------------------------------------
ac.storeItem = function ()
ct.storeItem = function (env)
{
sbm.ajax.storeItem = sbm.ajax.storeItem || { url: sbm.url.base + 'Codes/CodeType/Ajax/StoreItem', formId: 'frmCodeType', callbackFn: ac.onStoreItem };
sbm.doAjaxRequest(sbm.ajax.storeItem, 50);
env.ajax.storeItem = env.ajax.storeItem || { url: sbm.url.base + 'Codes/CodeType/Ajax/StoreItem', formSel: env.$frm.item, callbackFn: function (response) { ct.onStoreItem(env, response) } };
sbm.doAjaxRequest(env.ajax.storeItem, 50);
}
ac.onStoreItem = function (response)
ct.onStoreItem = function (env, response)
{
//sbm.debug('onStoreItem', response);
sbm.refreshControlValues(response.controlValues);
if (!response.success) return;
$dlg.item.dialog('close');
env.$dlg.item.dialog('close');
var item = response.codeType;
var $item = $('#' + ac.getItemId(item), $pnl.table);
if (!$item.length)
if (env.$pnl.table.length)
{
$item = ac.getItemRowTemplate();
$('table tbody', $pnl.table).prepend($item).show();
env.$pnl.msgs.hide().empty();
var $item = $('#' + ct.getItemId(item), env.$pnl.table);
if (!$item.length)
{
$item = ct.getItemRowTemplate(env);
$('table tbody', env.$pnl.table).prepend($item).show();
}
ct.populateItem($item, item);
}
ac.populateItem($item, item);
// Force repopulation of sprts.
delete ac.data.codeTypes;
}
//--------------------------------------------------------------
$(function ()
{
$pnl.items = $('.sbm-panel.CodeTypes');
$pnl.header = $('.sbm-panel-header', $pnl.items);
$pnl.filter = $('.sbm-panel-filter', $pnl.items);
$pnl.msgs = $('.sbm-panel-messages', $pnl.items);
$pnl.table = $('.sbm-panel-item-table', $pnl.items);
$pnl.tmpls = $('.sbm-panel-item-template', $pnl.items);
let env = { data: {}, ajax: {}, $pnl: {}, $frm: {}, $ctrl: {}, $dlg: {} };
let $items = env.$pnl.items = $('.sbm-panel.CodeTypes');
env.$pnl.header = $items.find('.sbm-panel-header');
env.$pnl.bgr = env.$pnl.header.find('.sbm-burger');
env.$pnl.mnu = env.$pnl.bgr.find('ul.sbm-dropdown-menu');
env.$pnl.table = $items.find('.sbm-panel-item-table');
env.$pnl.msgs = env.$pnl.table.find('.sbm-panel-messages');
env.$pnl.tmpl = $items.find('.sbm-panel-item-template');
$frm.filter = $('#frmCodeTypeFilter');
$('.FilterSearch', $frm.filter).on('input', function () { ac.refreshResults(250); });
env.$frm.filter = $items.find('#frmCodeTypeFilter');
env.$frm.filter.on('input', '.FilterSearch', function () { ct.refreshResults(env, 250); });
$frm.itemId = $('#frmCodeTypeId');
env.$frm.itemId = $items.find('#frmCodeTypeId');
var opt = sbm.dlgOpts();
opt.buttons[sbm.lbl.save] = function () { ac.storeItem(); };
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
$dlg.item = $('#dlgCodeType').dialog(opt);
$frm.item = $('#frmCodeType');
$($frm.item).on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
env.$dlg.item = $items.find('#dlgCodeType').dialog(opt);
env.$frm.item = env.$dlg.item.find('#frmCodeType');
env.$frm.item.on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
setTimeout(ac.refreshResults, 250);
ct.env.maint = env;
if (ct.env.maint.$pnl.items.length)
setTimeout(function () { ct.refreshResults(ct.env.maint); }, 250);
});
//--------------------------------------------------------------
+135 -122
View File
@@ -6,223 +6,236 @@
(function (win, doc, undef)
{
"use strict";
let ac = sbm.CodeCat = { data: {}, ajax: {} };
let $pnl = ac.$pnl = {}, $frm = ac.$frm = {}, $dlg = ac.$dlg = {};
let cd = sbm.Codes = { env: {} };
//--------------------------------------------------------------
ac.refreshResults = function (delay)
cd.refreshResults = function (env, delay)
{
if (!ac.awaitingRefreshResponse)
if (!cd.awaitingRefreshResponse)
{
$('.sbm-burger', $pnl.header).invisible();
$pnl.table.find('tbody tr').remove();
$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
env.$pnl.bgr.invisible();
env.$pnl.table.find('tbody tr').remove();
env.$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
}
ac.ajax.codes = ac.ajax.codes || { url: sbm.url.base + 'Codes/Code/Ajax/GetCodes', formId: $frm.filter.prop('id'), callbackFn: ac.handleCodes };
sbm.doAjaxRequest(ac.ajax.codes, delay || 50);
ac.awaitingRefreshResponse = true;
env.ajax.codes = env.ajax.codes || { url: sbm.url.base + 'Codes/Code/Ajax/GetCodes', formSel: env.$frm.filter, callbackFn: function (response) { cd.handleCodes(env, response); } };
sbm.doAjaxRequest(env.ajax.codes, delay || 50);
cd.awaitingRefreshResponse = true;
}
ac.handleCodes = function (response)
cd.handleCodes = function (env, response)
{
//sbm.debug('handleCodes', response);
delete ac.awaitingRefreshResponse;
let $table = $('table', $pnl.table).find('tbody tr').remove().end();
$pnl.msgs.hide().empty();
sbm.refreshPaging(response, '#frmCodeFilter', ac.refreshResults);
delete cd.awaitingRefreshResponse;
let $table = $('table', env.$pnl.table).find('tbody tr').remove().end();
env.$pnl.msgs.hide().empty();
sbm.refreshPaging(response, '#frmCodeFilter', function () { ct.refreshResults(env); });
if (!response.success) return;
// Reference data - Statuses.
if (response.statuses) sbm.data.statuses = response.statuses;
if (response.statusesCreate) sbm.data.statusesCreate = response.statusesCreate;
if (response.statusCodeDefault) sbm.data.statusCodeDefault = response.statusCodeDefault;
env.data.codeTypes = response.codeTypes;
env.data.statuses = response.statuses;
env.data.statusesCreate = response.statusesCreate;
env.data.statusCodeDefault = response.statusCodeDefault;
// Menu.
var $bgr = $('.sbm-burger', $pnl.header).invisible();
var $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
$mnu.append(ac.getFilterMenuOption(sbm.lbl.refresh, function () { ac.refreshResults(); }, 'sbm-refresh'));
$mnu.append(ac.getFilterMenuOption(sbm.lbl.create, function () { ac.createItem(); }, 'sbm-add'));
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
if (env.$pnl.bgr.length)
{
env.$pnl.bgr.invisible();
env.$pnl.mnu.empty();
env.$pnl.mnu.append(cd.getFilterMenuOption(env, sbm.lbl.refresh, function () { cd.refreshResults(env); }, 'sbm-refresh'));
env.$pnl.mnu.append(cd.getFilterMenuOption(env, sbm.lbl.create, function () { cd.createItem(env); }, 'sbm-add'));
env.$pnl.bgr.toggleVisibility(!!$('.sbm-dropdown-item', env.$pnl.mnu).length);
}
// Items.
var items = response.codes || [];
if (!items.length)
return $pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
$table.append(ac.populateItem(ac.getItemRowTemplate(), items[itemIdx]));
//for (let i = 1; i < 101; i++) $table.append($('<tr><td>'+i+'</td></tr>'));
return env.$pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
for (const item of items)
$table.append(cd.populateItem(env, cd.getItemRowTemplate(env), item));
}
ac.populateItem = function ($item, item)
cd.populateItem = function (env, $item, item)
{
if (!item) return $item;
$pnl.msgs.hide().empty();
$item.prop('id', ac.getItemId(item));
$('.CodeType', $item).text(item.typeName);
$('.CodeCode', $item).text(item.code);
$('.CodeDesc', $item).text(item.description);
$('.CodeStatusDesc', $item).text(item.statusDesc).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
env.$pnl.msgs.hide().empty();
$item.prop('id', cd.getItemId(item));
$item.find('.CodeType').text(item.typeName);
$item.find('.CodeCode').text(item.code);
$item.find('.CodeDesc').text(item.description);
$item.find('.CodeStatusDesc').text(item.statusDesc).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
// Actions.
let fnUpd = function () { ac.updateItem($item, item) };
let fnUpd = function () { cd.updateItem(env, $item, item) };
var $bgr = $('.sbm-burger', $item).invisible();
let $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
if (!item.deleted)
{
$mnu.append(ac.getItemMenuOption(sbm.lbl.edit, fnUpd, 'sbm-edit'));
$mnu.append(cd.getItemMenuOption(env, sbm.lbl.edit, fnUpd, 'sbm-edit'));
$('.CodeDesc', $item).off('click').on('click', fnUpd).addClass('sbm-action-text');
$item.off('dblclick').on('dblclick', fnUpd);
}
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
return $item;
}
ac.getItemId = function (item)
cd.getItemId = function (item)
{
return 'Itm_' + (item || {}).id;
return 'Cod_' + (item || {}).id;
}
//--------------------------------------------------------------
ac.getFilterDropdownTemplate = function ()
cd.getFilterDropdownTemplate = function (env)
{
return $('.sbm-dropdown-menu.CodeFilter li.sbm-dropdown-item', $pnl.tmpls).clone();
return $('.sbm-dropdown-menu.CodeFilter li.sbm-dropdown-item', env.$pnl.tmpl).clone();
}
ac.getItemRowTemplate = function ()
cd.getItemRowTemplate = function (env)
{
return $('table tr.sbm-row-item.Code', $pnl.tmpls).clone();
return $('table tr.sbm-row-item.Code', env.$pnl.tmpl).clone();
}
ac.getItemDropdownTemplate = function ()
cd.getItemDropdownTemplate = function (env)
{
return $('.sbm-dropdown-menu.Code li.sbm-dropdown-item', $pnl.tmpls).clone();
return $('.sbm-dropdown-menu.Code li.sbm-dropdown-item', env.$pnl.tmpl).clone();
}
ac.getFilterMenuOption = function (lbl, fn, cls)
cd.getFilterMenuOption = function (env, lbl, fn, cls)
{
return ac.getMenuOption(ac.getFilterDropdownTemplate(), lbl, fn, cls);
return cd.getMenuOption(cd.getFilterDropdownTemplate(env), lbl, fn, cls);
}
ac.getItemMenuOption = function (lbl, fn, cls)
cd.getItemMenuOption = function (env, lbl, fn, cls)
{
return ac.getMenuOption(ac.getItemDropdownTemplate(), lbl, fn, cls);
return cd.getMenuOption(cd.getItemDropdownTemplate(env), lbl, fn, cls);
}
ac.getMenuOption = function ($opt, lbl, fn, cls)
cd.getMenuOption = function ($opt, lbl, fn, cls)
{
return $opt.find('div.sbm-label').text(lbl).end().on('click', fn).addClass(cls);
}
//--------------------------------------------------------------
ac.createItem = function ()
cd.createItem = function (env)
{
ac.clearItem();
sbm.populateSelectCodeDesc('#cbCodeStatus', sbm.data.statusesCreate);
$('#cbCodeStatus').val(sbm.data.statusCodeDefault).prop('readonly', false);
$dlg.item.dialog('option', 'title', sbm.dlg.title.createItem);
ac.openCodeDlg();
cd.clearItem(env);
sbm.populateSelectCodeDesc('#cbCodeStatus', env.data.statusesCreate);
$('#cbCodeStatus').val(env.data.statusCodeDefault).prop('readonly', false);
cd.openCodeDlg(env, sbm.dlg.title.createItem);
}
ac.openCodeDlg = function ()
cd.clearItem = function (env)
{
sbm.openDialog($dlg.item, 600, 600);
}
ac.clearItem = function ()
{
let frm = $frm.item;
$('.CodeExists,.CodeId,input[type="text"],textarea,select', frm).val('');
sbm.populateSelectCodeDesc('#cbCodeStatus', sbm.data.statuses);
$('.CodeStatus', frm).prop('disabled', false);
let $frm = env.$frm.item;
$frm.find('.sbm-input,.sbm-textarea,sbm-select').val('');
sbm.populateSelect('#cbCodeType', env.data.codeTypes, 'id', 'name');
sbm.populateSelectCodeDesc('#cbCodeStatus', env.data.statuses);
$frm.find('.CodeStatus').prop('disabled', false);
sbm.clearControlErrors();
}
cd.openCodeDlg = function (env, title)
{
let $dlg = env.$dlg.item;
let $frm = env.$frm.item;
var btns = {};
btns[sbm.lbl.ok] = function () { cd.storeItem(env); };
btns[sbm.lbl.cancel] = function () { delete env.prmEdit; $(this).dialog('close'); };
$dlg.dialog('option', 'buttons', btns);
if (title) $dlg.dialog('option', 'title', title);
sbm.openDialog($dlg, 600, 480);
}
//--------------------------------------------------------------
ac.updateItem = function ($item, item)
cd.updateItem = function (env, $item, item)
{
ac.clearItem();
$('.CodeId', $frm.itemId).val(item.id);
sbm.ajax.updateItem = sbm.ajax.updateItem || { url: sbm.url.base + 'Codes/Code/Ajax/GetItem', formId: $frm.itemId.prop('id'), callbackFn: ac.onUpdateItem };
sbm.doAjaxRequest(sbm.ajax.updateItem, 50);
cd.clearItem(env);
$('.CodeId', env.$frm.itemId).val(item.id);
env.ajax.updateItem = env.ajax.updateItem || { url: sbm.url.base + 'Codes/Code/Ajax/GetItem', formSel: env.$frm.itemId, callbackFn: function (response) { cd.onUpdateItem(env, response); } };
sbm.doAjaxRequest(env.ajax.updateItem, 50);
}
ac.onUpdateItem = function (response)
cd.onUpdateItem = function (env, response)
{
//sbm.debug('onUpdateItem', response);
let frm = $frm.item;
ac.clearItem();
sbm.debug('onUpdateItem', response);
cd.clearItem(env);
if (!response.success) return;
let item = response.code;
$('.CodeExists', frm).val(1);
$('.CodeId', frm).val(item.id);
$('.CodeCategoryId', frm).val(item.categoryId);
$('.CodeCategory', frm).val(item.categoryDesc);
$('.CodeSerialNumber', frm).val(item.serialNumber);
$('.CodeDescription', frm).val(item.descBrief);
$('.CodeNotes', frm).val(item.notes);
$('.CodeStatus', frm).val(item.statusCode).prop('disabled', true);
sbm.clearControlErrors();
$dlg.item.dialog('option', 'title', sbm.dlg.title.updateItem);
ac.openCodeDlg();
let $frm = env.$frm.item;
let $ctrls = $frm.find('.sbm-input,.sbm-textarea,.sbm-select');
$ctrls.filter('.CodeExists').val(1);
$ctrls.filter('.CodeId').val(item.id);
$ctrls.filter('.CodeType').val(item.codeTypeId);
$ctrls.filter('.CodeCode').val(item.code);
$ctrls.filter('.CodeDescription').val(item.description);
$ctrls.filter('.CodeCategory').val(item.categoryDesc);
$ctrls.filter('.CodeSerialNumber').val(item.serialNumber);
$ctrls.filter('.CodeNotes').val(item.notes);
$ctrls.filter('.CodeStatus').val(item.statusCode).prop('disabled', true);
cd.openCodeDlg(env, sbm.dlg.title.updateItem);
}
//--------------------------------------------------------------
ac.selectCategory = function ()
cd.selectCategory = function (env)
{
let fnHandleCategories = function (response)
{
//sbm.debug('fnHandleCategories', response)
if (!response.success) return;
let cfg = { caption: sbm.lbl.selectCategory, items: [], itemId: $('.CodeCategoryId', $frm.item).val(), fnCallback: fnItemSelected };
(response.codeCategories || []).forEach((ac, i) => { cfg.items.push({ id: ac.id, name: ac.descBrief }) });
let cfg = { caption: sbm.lbl.selectCategory, items: [], itemId: $('.CodeCategoryId', env.$frm.item).val(), fnCallback: fnItemSelected };
(response.codeCategories || []).forEach((cd, i) => { cfg.items.push({ id: cd.id, name: cd.descBrief }) });
sbm.fn.selectItem(cfg);
}
let fnItemSelected = function (item)
{
//sbm.debug('fnCallback', item);
$('.CodeCategoryId', $frm.item).val(item.id);
$('.CodeCategory', $frm.item).val(item.name);
$('.CodeCategoryId', env.$frm.item).val(item.id);
$('.CodeCategory', env.$frm.item).val(item.name);
}
ac.ajax.categories = ac.ajax.categories || { url: sbm.url.base + 'Codes/CodeCategory/Ajax/GetCodeCategories', formId: $frm.categories.prop('id'), callbackFn: fnHandleCategories };
sbm.doAjaxRequest(ac.ajax.categories, 50);
env.ajax.categories = env.ajax.categories || { url: sbm.url.base + 'Codes/CodeCategory/Ajax/GetCodeCategories', formSel: env.$frm.categories, callbackFn: fnHandleCategories };
sbm.doAjaxRequest(env.ajax.categories, 50);
}
//--------------------------------------------------------------
ac.storeItem = function ()
cd.storeItem = function (env)
{
sbm.ajax.storeItem = sbm.ajax.storeItem || { url: sbm.url.base + 'Codes/Code/Ajax/StoreItem', formId: 'frmCode', callbackFn: ac.onStoreItem };
sbm.doAjaxRequest(sbm.ajax.storeItem, 50);
env.ajax.storeItem = env.ajax.storeItem || { url: sbm.url.base + 'Codes/Code/Ajax/StoreItem', formSel: env.$frm.item, callbackFn: function (response) { cd.onStoreItem(env, response); } };
sbm.doAjaxRequest(env.ajax.storeItem, 50);
}
ac.onStoreItem = function (response)
cd.onStoreItem = function (env, response)
{
//sbm.debug('onStoreItem', response);
sbm.debug('onStoreItem', response);
sbm.refreshControlValues(response.controlValues);
if (!response.success) return;
$dlg.item.dialog('close');
env.$dlg.item.dialog('close');
var item = response.code;
var $item = $('#' + ac.getItemId(item), $pnl.table);
if (!$item.length)
if (env.$pnl.table.length)
{
$item = ac.getItemRowTemplate();
$('table tbody', $pnl.table).prepend($item).show();
env.$pnl.msgs.hide().empty();
var $item = $('#' + cd.getItemId(item), env.$pnl.table);
if (!$item.length)
{
$item = cd.getItemRowTemplate(env);
$('table tbody', env.$pnl.table).prepend($item).show();
}
cd.populateItem($item, item);
}
ac.populateItem($item, item);
// Force repopulation of sprts.
delete ac.data.codes;
}
//--------------------------------------------------------------
$(function ()
{
$pnl.items = $('.sbm-panel.Codes');
$pnl.header = $('.sbm-panel-header', $pnl.items);
$pnl.filter = $('.sbm-panel-filter', $pnl.items);
$pnl.msgs = $('.sbm-panel-messages', $pnl.items);
$pnl.table = $('.sbm-panel-item-table', $pnl.items);
$pnl.tmpls = $('.sbm-panel-item-template', $pnl.items);
let env = { data: {}, ajax: {}, $pnl: {}, $frm: {}, $ctrl: {}, $dlg: {} };
let $items = env.$pnl.items = $('.sbm-panel.Codes');
env.$pnl.header = $items.find('.sbm-panel-header');
env.$pnl.bgr = env.$pnl.header.find('.sbm-burger');
env.$pnl.mnu = env.$pnl.bgr.find('ul.sbm-dropdown-menu');
env.$pnl.table = $items.find('.sbm-panel-item-table');
env.$pnl.msgs = env.$pnl.table.find('.sbm-panel-messages');
env.$pnl.tmpl = $items.find('.sbm-panel-item-template');
$frm.filter = $('#frmCodeFilter');
$frm.filter.on('input', '.FilterSearch', function () { ac.refreshResults(250); }).on('change', '.FilterCodeTypeCode', function () { ac.refreshResults(250); });
env.$frm.filter = $items.find('#frmCodeFilter');
env.$frm.filter.on('input', '.FilterSearch', function () { cd.refreshResults(env, 250); }).on('change', '.FilterCodeTypeCode', function () { cd.refreshResults(env, 250); });
$frm.itemId = $('#frmCodeId');
$frm.categories = $('#frmCategories');
env.$frm.itemId = $items.find('#frmCodeId');
env.$frm.categories = $('#frmCategories');
var opt = sbm.dlgOpts();
opt.buttons[sbm.lbl.save] = function () { ac.storeItem(); };
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
$dlg.item = $('#dlgCode').dialog(opt);
$frm.item = $('#frmCode');
$($frm.item).on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
$($frm.item).on('dblclick', '.sbm-input.CodeCategory', ac.selectCategory).on('click', '.sbm-action.CodeCategorySearch', ac.selectCategory);
env.$dlg.item = $items.find('#dlgCode').dialog(opt);
env.$frm.item = env.$dlg.item.find('#frmCode');
env.$frm.item.on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
env.$frm.item.on('dblclick', '.sbm-input.CodeCategory', function () { cd.selectCategory(env); }).on('click', '.sbm-action.CodeCategorySearch', function () { cd.selectCategory(env); });
setTimeout(ac.refreshResults, 250);
cd.env.maint = env;
if (cd.env.maint.$pnl.items.length)
setTimeout(function () { cd.refreshResults(cd.env.maint); }, 250);
});
//--------------------------------------------------------------
@@ -18,18 +18,9 @@
//sbm.debug('doRefreshConfig', env, response);
if (!response.success) return;
// Config.
env.mode = response.mode;
env.config = response.config;
env.configItemNew = response.configItemNew;
env.data.commodityTypes = response.commodityTypes;
env.data.taxCodes = response.taxCodes;
env.data.taxCodeDefault = response.taxCodeDefault;
env.data.uomCats = response.uomCats;
env.data.uomTypes = response.uomTypes;
env.data.uomTypeDefault = response.uomTypeDefault;
env.data.uoms = response.uoms;
env.data.statuses = response.statuses;
env.data.defaultStatusCode = response.defaultStatusCode;
Object.assign(env.data, response.data);
}
//--------------------------------------------------------------
@@ -54,6 +45,7 @@
sbm.refreshPaging(response, env.$frm.filter, function () { co.refreshResults(env); });
if (!response.success) return;
co.doRefreshConfig(env, response);
env.mode = response.mode;
// Menu.
if (env.$pnl.bgr.length)
@@ -61,7 +53,7 @@
env.$pnl.bgr.invisible();
env.$pnl.mnu.empty();
env.$pnl.mnu.append(co.getFilterMenuOption(env, sbm.lbl.refresh, function () { co.refreshResults(env); }, 'sbm-refresh'));
env.$pnl.mnu.append(co.getFilterMenuOption(env, sbm.lbl.create, function () { co.createItem(env, env.configItemNew); }, 'sbm-add'));
if (env.config.action.allow.create) env.$pnl.mnu.append(co.getFilterMenuOption(env, sbm.lbl.create, function () { co.createItem(env, env.configItemNew); }, 'sbm-add'));
env.$pnl.bgr.toggleVisibility(!!$('.sbm-dropdown-item', env.$pnl.mnu).length);
}
@@ -109,15 +101,15 @@
//--------------------------------------------------------------
co.getFilterDropdownTemplate = function (env)
{
return $('.sbm-dropdown-menu.CommodityList li.sbm-dropdown-item', env.$pnl.tmpls).clone();
return $('.sbm-dropdown-menu.CommodityList li.sbm-dropdown-item', env.$pnl.tmpl).clone();
}
co.getItemTemplate = function (env)
{
return $('table tr.sbm-row-item.Commodity', env.$pnl.tmpls).clone();
return $('table tr.sbm-row-item.Commodity', env.$pnl.tmpl).clone();
}
co.getItemDropdownTemplate = function (env)
{
return $('.sbm-dropdown-menu.Commodity li.sbm-dropdown-item', env.$pnl.tmpls).clone();
return $('.sbm-dropdown-menu.Commodity li.sbm-dropdown-item', env.$pnl.tmpl).clone();
}
//--------------------------------------------------------------
@@ -139,7 +131,8 @@
{
co.clearItem(env, cfg);
let $frm = env.$frm.item;
$('.CommodityStatus', $frm).val(env.data.defaultStatusCode);
$frm.find('.CommodityType').val(env.data.commodityTypeDefault);
$frm.find('.CommodityStatus').val(env.data.defaultStatusCode);
co.openItemDlg(env, cfg, sbm.dlg.title.createCommodity);
}
co.clearItem = function (env, cfg)
@@ -224,7 +217,7 @@
let item = response.commodity;
let $frm = env.$frm.item;
sbm.populateFormValues(cfg, $frm, item.field.value);
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', $frm);
let $ctrls = $frm.find('.sbm-input,.sbm-textarea,.sbm-select');
$ctrls.filter('.CommodityId').val(item.id);
$ctrls.filter('.CommodityExists').val(1);
sbm.selectOrAdd($ctrls.filter('.CommodityType'), item.typeCode, item.typeDesc);
@@ -318,7 +311,7 @@
env.$pnl.mnu = env.$pnl.bgr.find('ul.sbm-dropdown-menu');
env.$pnl.table = $items.find('.sbm-panel-item-table');
env.$pnl.msgs = env.$pnl.table.find('.sbm-panel-messages');
env.$pnl.tmpls = $items.find('.sbm-panel-item-template');
env.$pnl.tmpl = $items.find('.sbm-panel-item-template');
env.$frm.filter = $items.find('#frmCommodityFilter');
env.$frm.filter.on('input', '.FilterSearch', function () { co.refreshResults(env, 250); }).on('change', '.FilterCommodityType,.FilterStatusCat', function () { co.refreshResults(env, 50); });
@@ -345,7 +338,11 @@
$(function ()
{
co.env.maint = co.initEnv('.sbm-panel.Commodities');
if (co.env.maint.$pnl.items.length) setTimeout(function () { co.refreshResults(co.env.maint); }, 250);
if (co.env.maint.$pnl.items.length)
{
$('body').on('keydown', function (e) { let env = co.env.maint; if (e.which == 45/*Insert*/ && env.config.action.allow.create) co.createItem(env, env.configItemNew); });
setTimeout(function () { co.refreshResults(co.env.maint); }, 250);
}
co.env.select = co.initEnv('#dlgCommoditySelect');
if (co.env.select.$pnl.items.length) setTimeout(function () { co.refreshConfig(co.env.select); }, 250);
});
@@ -327,26 +327,23 @@
{
win.clearTimeout(sbm.toNotification);
var $win = $(win);
var $main = $('#sbm-page-body main');
var $not = $('#sbm-notification').hide();
if (!$not.length)
{
$not = $('<div id="sbm-notification"><div class="content"><div class="heading"><div class="close" onclick="sbm.hideNotification()">&#10006;</div><div class="title"></div></div><div class="message"></div></div></div>');
$('body').append($not);
($main.length ? $main : $('body')).append($not);
}
var $hdr = $('.heading', $not).css({ 'background-color': 'rgba(247,217,0,0.7)' });
$('.title', $not).html(title);
$('.message', $not).html(msg);
var $bdy = $('#sbm-page-body');
$not.find('.title').html(title).end().find('.message').html(msg);
//sbm.debug(sbm.topMargin($bdy));
var fbr = $bdy[0].getBoundingClientRect();
var fn = function () { $hdr.delay(2000).animate({ backgroundColor: '#f0f0f0' }, 1000); };
$not.css({ 'top': Math.max(0, fbr.top /*- sbm.topMargin($bdy)*/), 'right': $win.width() - fbr.right }).slideDown(500, fn);
$not.show(500, function () { $hdr.delay(2000).animate({ backgroundColor: '#f0f0f0' }, 1000); });
sbm.toNotification = setTimeout(sbm.hideNotification, 6000);
}
sbm.hideNotification = function ()
{
win.clearTimeout(sbm.toNotification);
$('#sbm-notification').slideUp(500);
$('#sbm-notification').hide(500);
}
sbm.doPleaseWait = function ()
{
@@ -5,41 +5,42 @@
(function (win, doc, undef)
{
"use strict";
let sc = sbm.mdl.Security = { env: {} };
//--------------------------------------------------------------
sbm.doSignin = function ()
sc.doSignin = function ()
{
sbm.clearControlErrors();
sbm.ajaxSignin = sbm.ajaxSignin || { url: sbm.url.base + 'Security/Ajax/Signin', formId: 'frmSignIn', callbackFn: sbm.onSignin };
sbm.ajaxSignin = sbm.ajaxSignin || { url: sbm.url.base + 'Security/Ajax/Signin', formId: 'frmSignIn', callbackFn: sc.onSignin };
sbm.doAjaxRequest(sbm.ajaxSignin, 50);
}
sbm.onSignin = function (response)
sc.onSignin = function (response)
{
sbm.refreshControlValues(response.controlValues,'#frmSignIn');
sbm.refreshControlValues(response.controlValues, '#frmSignIn');
if (!response.success) return;
sbm.goToPage('');
}
//--------------------------------------------------------------
sbm.doScorePassword = function ()
sc.doScorePassword = function ()
{
sbm.ajaxScorePassword = sbm.ajaxScorePassword || { url: sbm.url.base + 'Security/Ajax/ScorePassword', formId: 'frmChangePassword', callbackFn: sbm.onScorePassword, noWaitIcon: true };
sbm.ajaxScorePassword = sbm.ajaxScorePassword || { url: sbm.url.base + 'Security/Ajax/ScorePassword', formId: 'frmChangePassword', callbackFn: sc.onScorePassword, noWaitIcon: true };
sbm.doAjaxRequest(sbm.ajaxScorePassword, 250);
}
sbm.onScorePassword = function (response)
sc.onScorePassword = function (response)
{
var score = (response || {}).score || 0;
sbm.$prgPasswordStrength.progressbar("option", "value", score).removeClass('amber green').addClass(score > 3 ? 'green' : score > 2 ? 'amber' : '');
}
//--------------------------------------------------------------
sbm.doChangePassword = function ()
sc.doChangePassword = function ()
{
sbm.clearControlErrors();
sbm.ajaxChangePassword = sbm.ajaxChangePassword || { url: sbm.url.base + 'Security/Ajax/StorePassword', formId: 'frmChangePassword', callbackFn: sbm.onChangePassword };
sbm.ajaxChangePassword = sbm.ajaxChangePassword || { url: sbm.url.base + 'Security/Ajax/StorePassword', formId: 'frmChangePassword', callbackFn: sc.onChangePassword };
sbm.doAjaxRequest(sbm.ajaxChangePassword, 50);
}
sbm.onChangePassword = function (response)
sc.onChangePassword = function (response)
{
sbm.refreshControlValues(response.controlValues);
if (!response.success) return;
@@ -49,13 +50,13 @@
}
//--------------------------------------------------------------
sbm.doRequestPassword = function ()
sc.doRequestPassword = function ()
{
sbm.clearControlErrors();
sbm.ajaxRequestPassword = sbm.ajaxRequestPassword || { url: sbm.url.base + 'Security/Ajax/RequestPassword', formId: 'frmRequestPassword', callbackFn: sbm.onRequestPassword };
sbm.ajaxRequestPassword = sbm.ajaxRequestPassword || { url: sbm.url.base + 'Security/Ajax/RequestPassword', formId: 'frmRequestPassword', callbackFn: sc.onRequestPassword };
sbm.doAjaxRequest(sbm.ajaxRequestPassword, 50);
}
sbm.onRequestPassword = function (response)
sc.onRequestPassword = function (response)
{
sbm.refreshControlValues(response.controlValues);
if (!response.success) return;
@@ -71,17 +72,39 @@
//--------------------------------------------------------------
$(function ()
{
let env = { data: {}, ajax: {}, $pnl: {}, $frm: {}, $ctrl: {}, $dlg: {} };
$(':input:enabled:visible:first').trigger('focus');
$('#ifEmailAddress,#ifPasswordCurrent,#ifPassword,#ifPasswordConfirm').on('input', function () { sbm.clearControlError(this); });
$('#frmChangePassword #ifPassword').on('keyup', sbm.doScorePassword);
sbm.$prgPasswordStrength = $('#frmChangePassword .sbm-password-strength').progressbar({ 'max': 5 });
sbm.$frm.signIn = $('#frmSignIn');
sbm.$frm.signIn.on('keypress', '#ifEmailAddress,#ifPassword,#chkKeepMeSignedIn', function (e) { if (e.which == 13 && $('#ifEmailAddress', sbm.$frm.signIn).val() && $('#ifPassword', sbm.$frm.signIn).val()) sbm.doSignin(); });
sbm.$frm.signIn.on('click', '#pbSignIn', function () { sbm.doSignin(); }).on('keypress', '#pbSignIn', function (e) { if (e.which == 13) sbm.doSignin(); });
$('#ifPasswordCurrent,#ifPassword,#ifPasswordConfirm', $('#frmChangePassword')).on('keypress', function (e) { if (e.which == 13) sbm.doChangePassword(); });
$('#frmChangePassword #pbChangePassword').on('click', function () { sbm.doChangePassword(); });
$('#ifEmailAddress', $('#frmRequestPassword')).on('keypress', function (e) { if (e.which == 13) sbm.doRequestPassword(); });
$('#frmRequestPassword #pbRequestPassword').on('click', function () { sbm.doRequestPassword(); });
$('.sbm-input').on('input', function () { sbm.clearControlError(this); });
env.$frm.signIn = $('#frmSignIn');
if (env.$frm.signIn.length)
{
env.$frm.signIn.on('keypress', '#ifEmailAddress,#ifPassword,#chkKeepMeSignedIn', function (e) { if (e.which == 13 && $('#ifEmailAddress', env.$frm.signIn).val() && $('#ifPassword', env.$frm.signIn).val()) sc.doSignin(); });
env.$frm.signIn.on('click', '#pbSignIn', function () { sc.doSignin(); }).on('keypress', '#pbSignIn', function (e) { if (e.which == 13) sc.doSignin(); });
env.$ctrl.ctxt = env.$frm.signIn.find('#ifRepositoryContext');
env.$ctrl.email = env.$frm.signIn.find('#ifEmailAddress');
env.$ctrl.pwrd = env.$frm.signIn.find('#ifPassword');
if (env.$ctrl.ctxt.val())
{
env.$ctrl.email.focus();
if (env.$ctrl.email.val())
env.$ctrl.pwrd.focus();
}
}
env.$frm.chgPword = $('#frmChangePassword');
if (env.$frm.chgPword.length)
{
env.$frm.chgPword.on('keypress', '#ifPasswordCurrent,#ifPassword,#ifPasswordConfirm', function (e) { if (e.which == 13) sc.doChangePassword(); });
env.$frm.chgPword.on('click', '#pbChangePassword', function () { sc.doChangePassword(); });
env.$frm.chgPword.on('keyup', '#ifPassword', sc.doScorePassword);
sbm.$prgPasswordStrength = env.$frm.chgPword.find('.sbm-password-strength').progressbar({ max: 5 });
}
env.$frm.reqPword = $('#frmRequestPassword');
if (env.$frm.reqPword.length)
{
env.$frm.reqPword.on('keypress', '#ifEmailAddress', function (e) { if (e.which == 13) sc.doRequestPassword(); });
env.$frm.reqPword.on('click', '#pbRequestPassword', function () { sc.doRequestPassword(); });
}
});
}(window, window.document));
@@ -173,8 +173,6 @@
$('table tbody', $pnl.table).prepend($item).show();
}
vc.populateItem($item, item);
// Force repopulation of sprts.
delete vc.data.vehicleClasses;
}
//--------------------------------------------------------------