diff --git a/SaBusMgrCoreProcs/Procs/Reports/SbmPrint_Footer.cs b/SaBusMgrCoreProcs/Procs/Reports/SbmPrint_Footer.cs index 80e8d31..2a4841b 100644 --- a/SaBusMgrCoreProcs/Procs/Reports/SbmPrint_Footer.cs +++ b/SaBusMgrCoreProcs/Procs/Reports/SbmPrint_Footer.cs @@ -6,12 +6,14 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Text; using System.Linq; +using System.Runtime.Versioning; using System.Text; using System.Threading.Tasks; namespace Sarand.BusinessMgr.Net.Core.Procs.Reports { //========================================================================== + [SupportedOSPlatform("windows")] public class SbmPrinter_Footer : SacsDisposable { //---------------------------------------------------------------------- diff --git a/SaBusMgrCoreProcs/Procs/Reports/SbmReport.cs b/SaBusMgrCoreProcs/Procs/Reports/SbmReport.cs index 06e6851..9f03a51 100644 --- a/SaBusMgrCoreProcs/Procs/Reports/SbmReport.cs +++ b/SaBusMgrCoreProcs/Procs/Reports/SbmReport.cs @@ -17,10 +17,12 @@ using System.Threading.Tasks; using Sarand.Net.Standard.Base.App; using Sarand.Net.Standard.Base.Utils; using Sarand.BusinessMgr.Net.Standard.Base.Core; +using System.Runtime.Versioning; namespace Sarand.BusinessMgr.Net.Core.Procs.Reports { //======================================================================= + [SupportedOSPlatform("windows")] public abstract class SbmReport : SbmReport_Base { //------------------------------------------------------------------- diff --git a/SaBusMgrCoreProcs/SaBusMgrCoreProcs.csproj b/SaBusMgrCoreProcs/SaBusMgrCoreProcs.csproj index a765282..ab5ee67 100644 --- a/SaBusMgrCoreProcs/SaBusMgrCoreProcs.csproj +++ b/SaBusMgrCoreProcs/SaBusMgrCoreProcs.csproj @@ -17,7 +17,7 @@ - + diff --git a/SaBusMgrCoreWeb/SaBusMgrCoreWeb.csproj b/SaBusMgrCoreWeb/SaBusMgrCoreWeb.csproj index 8cee9bf..7f045aa 100644 --- a/SaBusMgrCoreWeb/SaBusMgrCoreWeb.csproj +++ b/SaBusMgrCoreWeb/SaBusMgrCoreWeb.csproj @@ -6,7 +6,7 @@ - + diff --git a/SaBusinessMgrCoreWebPortal/Portal/App/SbmInstanceConfig_Portal.cs b/SaBusMgrCoreWeb/Web/App/SbmInstanceConfig_Control.cs similarity index 96% rename from SaBusinessMgrCoreWebPortal/Portal/App/SbmInstanceConfig_Portal.cs rename to SaBusMgrCoreWeb/Web/App/SbmInstanceConfig_Control.cs index 4d8e253..6682d4c 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/App/SbmInstanceConfig_Portal.cs +++ b/SaBusMgrCoreWeb/Web/App/SbmInstanceConfig_Control.cs @@ -1,6 +1,4 @@ -using DocumentFormat.OpenXml.Drawing.Diagrams; -using Sarand.BusinessMgr.Net.Core.Web.App; -using Sarand.BusinessMgr.Net.Standard.Base.App; +using Sarand.BusinessMgr.Net.Standard.Base.App; using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control; using Sarand.BusinessMgr.Net.Standard.Base.Mgr.Control; using Sarand.Net.Standard.Base.App; @@ -9,15 +7,12 @@ using Sarand.Net.Standard.Base.Core; using Sarand.Net.Standard.Base.Utils; using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Text.RegularExpressions; -using System.Threading.Tasks; -namespace Sarand.BusinessMgr.Web.Portal.App +namespace Sarand.BusinessMgr.Net.Core.Web.App { //======================================================================= - public class SbmInstanceConfig_Portal : SbmInstanceConfig + public class SbmInstanceConfig_Control : SbmInstanceConfig { //------------------------------------------------------------------- // Definitions. @@ -33,7 +28,7 @@ namespace Sarand.BusinessMgr.Web.Portal.App //------------------------------------------------------------------- // Construction. - public SbmInstanceConfig_Portal(SysId controlOwnerId, SysId controlRepositoryId) + public SbmInstanceConfig_Control(SysId controlOwnerId, SysId controlRepositoryId) { this.controlOwnerId = controlOwnerId; this.controlRepositoryId = controlRepositoryId; diff --git a/SaBusMgrCoreWeb/Web/Controllers/SbmController_Base.cs b/SaBusMgrCoreWeb/Web/Controllers/SbmController_Base.cs index 48ba1b0..e98e271 100644 --- a/SaBusMgrCoreWeb/Web/Controllers/SbmController_Base.cs +++ b/SaBusMgrCoreWeb/Web/Controllers/SbmController_Base.cs @@ -29,17 +29,17 @@ using System.Threading.Tasks; namespace Sarand.BusinessMgr.Net.Core.Web.Controllers { - //======================================================================= - public abstract class SbmController_Base : SaController + //======================================================================= + public abstract class SbmController_Base : SaController { - //------------------------------------------------------------------- - // Data members. - private SbmInternals internals; - private SbmInternals_Control internals_Control; + //------------------------------------------------------------------- + // Data members. + private SbmInternals internals; + private SbmInternals_Control internals_Control; - //------------------------------------------------------------------- - // Protected construction. - protected SbmController_Base(SbmLocaliser localiser) + //------------------------------------------------------------------- + // Protected construction. + protected SbmController_Base(SbmLocaliser localiser) { Localiser = localiser; @@ -52,12 +52,12 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Controllers { if (disposing) { - if (internals != null) internals.Dispose(); - internals = null; - if (internals_Control != null) internals_Control.Dispose(); - internals_Control = null; - } - base.Dispose(disposing); + if (internals != null) internals.Dispose(); + internals = null; + if (internals_Control != null) internals_Control.Dispose(); + internals_Control = null; + } + base.Dispose(disposing); } //------------------------------------------------------------------- @@ -67,11 +67,11 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Controllers public App.SbmAppConfig AppConfig { get { return App.AppConfig; } } public abstract SbmSessionContext SessionContext { get; } public abstract ISbmUserContext_Core UserContext_Core { get; } - // Business components. - public SbmInternals Internals { get { if (internals == null) internals = new SbmInternals(UserContext_Core); return internals; } } - public SbmInternals_Control Internals_Control { get { if (internals_Control == null) internals_Control = new SbmInternals_Control(); return internals_Control; } } - // Managers. - public SbmAccountMgr AccountMgr { get { return Internals.AccountMgr; } } + // Business components. + public SbmInternals Internals { get { if (internals == null && UserContext_Core != null) { internals = new SbmInternals(UserContext_Core); } return internals; } } + public SbmInternals_Control Internals_Control { get { if (internals_Control == null) { internals_Control = new SbmInternals_Control(); } return internals_Control; } } + // Managers. + public SbmAccountMgr AccountMgr { get { return Internals.AccountMgr; } } public SbmAssetMgr AssetMgr { get { return Internals.AssetMgr; } } public SbmCommodityMgr CommodityMgr { get { return Internals.CommodityMgr; } } public SbmPriceMgr PriceMgr { get { return Internals.PriceMgr; } } diff --git a/SaBusMgrStandardBase/Base/App/Sbm.cs b/SaBusMgrStandardBase/Base/App/Sbm.cs index 36fd4c3..33060d6 100644 --- a/SaBusMgrStandardBase/Base/App/Sbm.cs +++ b/SaBusMgrStandardBase/Base/App/Sbm.cs @@ -18,6 +18,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.App { public static class Password { + public static int MinLength { get; } = 8; + public static int MaxLength { get; } = 16; } public static class Activation { diff --git a/SaBusMgrStandardBase/Base/App/SbmInternals.cs b/SaBusMgrStandardBase/Base/App/SbmInternals.cs index d56f795..c25d2dd 100644 --- a/SaBusMgrStandardBase/Base/App/SbmInternals.cs +++ b/SaBusMgrStandardBase/Base/App/SbmInternals.cs @@ -121,6 +121,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.App public List AssociationTypeCodes { get { return GetCodesOfType(Sbm.SystemCode.AssociationType); } } public List CommodityTypeCodes { get { return GetCodesOfType(Sbm.SystemCode.CommodityType); } } public List AssetTypeCodes { get { return GetCodesOfType(Sbm.SystemCode.AssetType); } } + public List TransactionTypeCodes { get { return GetCodesOfType(Sbm.SystemCode.TransactionType); } } //------------------------------------------------------------------- // Code types. diff --git a/SaBusMgrStandardBase/Base/Bus/SbmAffiliate.cs b/SaBusMgrStandardBase/Base/Bus/SbmAffiliate.cs index 88f22dc..46ff3a5 100644 --- a/SaBusMgrStandardBase/Base/Bus/SbmAffiliate.cs +++ b/SaBusMgrStandardBase/Base/Bus/SbmAffiliate.cs @@ -782,6 +782,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Bus public String Search { get; set; } public String Name { get; set; } public String NamePartial { get; set; } + public String FirstName { get; set; } + public String LastName { get; set; } public String PhonePartial { get; set; } public String EmailPartial { get; set; } public String PostcodePartial { get; set; } diff --git a/SaBusMgrStandardBase/Base/Bus/SbmRequirement.cs b/SaBusMgrStandardBase/Base/Bus/SbmRequirement.cs index 30a574d..42dc143 100644 --- a/SaBusMgrStandardBase/Base/Bus/SbmRequirement.cs +++ b/SaBusMgrStandardBase/Base/Bus/SbmRequirement.cs @@ -742,6 +742,11 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Bus //------------------------------------------------------------------- // Utilities. + public ItemId GetItemId() + { + return new ItemId((short)Sbm.ItemType.Requirement, Id); + } + public String GetPromotionCodeNONE() { return "None"; diff --git a/SaBusMgrStandardBase/Base/Bus/SbmTransaction.cs b/SaBusMgrStandardBase/Base/Bus/SbmTransaction.cs index ea1dafd..0c94a39 100644 --- a/SaBusMgrStandardBase/Base/Bus/SbmTransaction.cs +++ b/SaBusMgrStandardBase/Base/Bus/SbmTransaction.cs @@ -9,8 +9,8 @@ using System.Collections.Generic; namespace Sarand.BusinessMgr.Net.Standard.Base.Bus { - //======================================================================= - public abstract class SbmTransaction : SbmHierarchyItem + //======================================================================= + public abstract class SbmTransaction : SbmHierarchyItem { //------------------------------------------------------------------- // Columns. @@ -661,7 +661,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Bus //------------------------------------------------------------------- // Transaction status. public static SaStatus DefaultStatus { get { return SaStatus.Preparation; } } - private static readonly List transactionStatuses = new List() + private static readonly HashSet transactionStatuses = new HashSet() { SaStatus.Preparation, SaStatus.Active, @@ -679,7 +679,11 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Bus { return DefaultStatus; } - public static List GetTransactionStatuses(Sbm.TransactionType transactionType) + public static List ValidStatuses() + { + return new List(transactionStatuses); + } + public static List ValidStatusesByType(Sbm.TransactionType transactionType) { switch (transactionType) { @@ -822,6 +826,12 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Bus //------------------------------------------------------------------- // Utilities. + public ItemId GetItemId() + { + return new ItemId((short)Sbm.ItemType.Transaction, Id); + } + + // Transaction type. public List GetAssociationTypes() { return GetAssociationTypes(TransactionType); @@ -1646,21 +1656,22 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Bus public new class Params : SacsHierarchyItem.Params { // List filtering. - public List IdsIncluded { get; set; } = new List(); - public List IdsExcluded { get; set; } = new List(); + public HashSet IdsIncluded { get; set; } = new HashSet(); + public HashSet IdsExcluded { get; set; } = new HashSet(); // Transaction. - public SysId AssocId { get; set; } - public SysId TransIdSource { get; set; } + public String Search { get; set; } + public SysId AssociationId { get; set; } public Sbm.TransactionType TransactionType { get; set; } = Sbm.TransactionType.Any; - public SysId LocationIdStock { get; set; } - public String AssocPartial { get; set; } - public String AddressPartial { get; set; } - public String PostcodePartial { get; set; } public String TransRefFull { get; set; } public String TransRefPartial { get; set; } public String TransRefExtFull { get; set; } public String TransRefExtPartial { get; set; } public String TransDescBriefPartial { get; set; } + public SysId TransIdSource { get; set; } + public SysId LocationIdStock { get; set; } + public String AddressPartial { get; set; } + public String PostcodePartial { get; set; } + public String AssocPartial { get; set; } public String DefaultNominalCodeFull { get; set; } public String DefaultNominalCodePartial { get; set; } public String ContactAreaCode { get; set; } @@ -1709,12 +1720,13 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Bus public StatusCat StatusCat { get; set; } = StatusCat.Default; /// Results will be throttled unless a significant filter is applied. public bool ForceFullResults { get; set; } = false; + // Linked table alises. + public String TableAlias_Association { get; set; } + public String TableAlias_AffiliateOwner { get; set; } + public String TableAlias_AffiliateTarget { get; set; } + public String TableAlias_AddressTarget { get; set; } + public String TableAlias_AddressDelivery { get; set; } // Utilities. - public List GetDisplayValues() - { - List values = new List(); - return values; - } public bool RequiresVolumeThrottle() { // The volume of transaction must be throttled if no 'significant' filter is requested. diff --git a/SaBusMgrStandardBase/Base/Consoles/SbmCoreInstanceConsole_Base.cs b/SaBusMgrStandardBase/Base/Consoles/SbmCoreInstanceConsole_Base.cs new file mode 100644 index 0000000..0d678cf --- /dev/null +++ b/SaBusMgrStandardBase/Base/Consoles/SbmCoreInstanceConsole_Base.cs @@ -0,0 +1,495 @@ +using Sarand.BusinessMgr.Net.Standard.Base.App; +using Sarand.BusinessMgr.Net.Standard.Base.Bus; +using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control; +using Sarand.Net.Standard.Base.App; +using Sarand.Net.Standard.Base.Bus; +using Sarand.Net.Standard.Base.Core; +using Sarand.Net.Standard.Base.Dbas; +using Sarand.Net.Standard.Base.Security; +using Sarand.Net.Standard.Base.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles +{ + /// + /// Utilitiy function relating to a core BusinessMgr database instance. + /// For instance: + /// - Initialisation of new repository. + /// - Bringing static (tax codes etc) and reference data up to date. + /// + public abstract class SbmCoreInstanceConsole_Base : SaErrorStateItem + { + //------------------------------------------------------------------- + // Definitions. + + public const String col_AffilId = "AffilId"; + public const String col_AssocId = "AssocId"; + public const String col_Name = "Name"; + public const String col_Website = "Website"; + public const String col_CompanyNo = "CompanyNo"; + public const String col_VatReg = "VatReg"; + public const String col_FirstName = "FirstName"; + public const String col_LastName = "LastName"; + public const String col_Email = "Email"; + public const String col_UserId = "UserId"; + public const String col_UserCode = "UserCode"; + + /// + /// Organisation and User info for Repository initialisation. + /// + public class RepositoryInitialisationData + { + public class UserData + { + public SysId AffiliateId { get; set; } + public String FirstName { get; set; } + public String LastName { get; set; } + public String Email { get; set; } + public SysId SecurityItemId { get; set; } + public String Code { get; set; } + public String Password { get; set; } + } + public UserData User { get; private set; } = new UserData(); + public void ClearUser() { User = new UserData(); } + public class OrganisationData + { + public String Name { get; set; } + public String VatReg { get; set; } + public String CompanyNo { get; set; } + public String Website { get; set; } + public SysId AffiliateId { get; set; } + public SysId AssociationId { get; set; } + } + public OrganisationData Organisation { get; private set; } = new OrganisationData(); + public void ClearOrganisation() { Organisation = new OrganisationData(); } + } + + //------------------------------------------------------------------- + // Data members. + + //------------------------------------------------------------------- + // Construction. + protected SbmCoreInstanceConsole_Base() + { + } + protected override void Dispose(bool disposing) + { + if (disposing) + { + } + base.Dispose(disposing); + } + + //------------------------------------------------------------------- + // Properties. + public String SecurityGroupCode_Super { get; } = SaSecurityConsole.GroupCode_Super; + // Core instance. + public abstract ISacsDatabase Database_Core { get; } + public abstract SbmInternals Internals_Core { get; } + public abstract DbUpdateInfo DbUpdateInfo_Core { get; } + + //------------------------------------------------------------------- + // Utilities. + public abstract SaSecurityConsole CreateSecurityConsole(); + + //------------------------------------------------------------------- + /// + /// Is repository database valid. + /// - Contains core tables (Affiliate, Association, Commodity etc). + /// + /// + /// + public bool IsRepositoryValid() + { + ClearErrorState(); + HashSet tablesExpected = new HashSet("Affiliate,Association,Commodity,Transaction,Requirement,SaSecItem,SaSecLink".Split(',')); + String sql = $"Select {col_Name} From sys.tables"; + try + { + using (DbResultSet resultSet = Database_Core.ExecuteQuery(sql)) + { + if (resultSet != null) + { + HashSet tablesFound = new HashSet(); + while (resultSet != null && resultSet.HasRows && resultSet.NextRecord()) + { + NamedValue.Map values = resultSet.GetRecordValues(); + tablesFound.Add(values.GetString(col_Name)); + } + HashSet tablesNotFound = new HashSet(tablesExpected.Where(item => !tablesFound.ContainsCI(item))); + if (tablesNotFound.Any()) + return SetErrorState($"Core tables not found: {String.Join(", ", tablesNotFound)}."); + } + } + } + catch (Exception exc) + { + String msg = "checking repository validity"; + SaLogger.Warn($"{SysUtil.Fn} {ExceptionUtil.GetLogMessage(exc, msg)}"); + return SetErrorState($"{exc.GetType().Name} {msg}"); + } + return OK; + } + + //------------------------------------------------------------------- + /// + /// Is repository database initialised. + /// - Has a valid internal association. + /// - Has at least one user. + /// + public bool IsRepositoryInitialised() + { + ClearErrorState(); + RepositoryInitialisationData initData = new RepositoryInitialisationData(); + try + { + // Query first internal association. + List sql = new List() + { + $"Select {col_AssocId}=ass.Id, {col_AffilId}=aff.Id, {col_Name}=aff.Name, {col_Website}=aff.Website, {col_CompanyNo}=aff.CompanyNo, {col_VatReg}=aff.VatReg", + $"From Association ass", + $"Left Join Affiliate aff On aff.Id=ass.AffIdOwner And aff.Id=ass.AffIdTarget And aff.Type<>{(int)Sbm.AffiliateType.Individual}", + $"Where ass.Type={(int)Sbm.AssociationType.Internal};" + }; + using (DbResultSet resultSet = Database_Core.ExecuteQuery(String.Join(" ", sql))) + { + while (resultSet != null && resultSet.HasRows && resultSet.NextRecord()) + { + NamedValue.Map values = resultSet.GetRecordValues(); + initData.ClearOrganisation(); + initData.Organisation.Name = values.GetString(col_Name); + initData.Organisation.Website = values.GetString(col_Website); + initData.Organisation.CompanyNo = values.GetString(col_CompanyNo); + initData.Organisation.VatReg = values.GetString(col_VatReg); + initData.Organisation.AffiliateId = new SysId(values.GetLong(col_AffilId)); + initData.Organisation.AssociationId = new SysId(values.GetLong(col_AssocId)); + if (SysId.IsValid(initData.Organisation.AssociationId) && SysId.IsValid(initData.Organisation.AffiliateId)) + break; + } + if (!SysId.IsValid(initData.Organisation.AssociationId)) + return SetErrorState("Internal association not found."); + if (!SysId.IsValid(initData.Organisation.AffiliateId)) + return SetErrorState("Owner affiliate not found."); + } + + // Query Employees for the Organisation. + sql = new List() + { + $"Select {col_AffilId}=aff.Id, {col_FirstName}=aff.FirstName, {col_LastName}=aff.LastName, {col_UserId}=aff.UserId, {col_UserCode}=seci.Code", + $"From Association ass", + $"Inner Join Affiliate aff On aff.Id=ass.AffIdTarget And aff.Type={(int)Sbm.AffiliateType.Individual} And IsNull(aff.UserId,0)>0", + $"Left Join SaSecItem seci On seci.Id=aff.UserId", + $"Where ass.AffIdOwner={SysId.ToLong(initData.Organisation.AffiliateId)} And ass.Type={(int)Sbm.AssociationType.Member};" + }; + using (DbResultSet resultSet = Database_Core.ExecuteQuery(String.Join(" ", sql))) + { + while (resultSet != null && resultSet.HasRows && resultSet.NextRecord()) + { + NamedValue.Map values = resultSet.GetRecordValues(); + initData.ClearUser(); + initData.User.AffiliateId = new SysId(values.GetLong(col_AffilId)); + initData.User.FirstName = values.GetString(col_FirstName); + initData.User.LastName = values.GetString(col_LastName); + initData.User.Email = values.GetString(col_Email); + initData.User.SecurityItemId = new SysId(values.GetLong(col_UserId)); + initData.User.Code = values.GetString(col_UserCode); + if (SysId.IsValid(initData.User.AffiliateId) && SysId.IsValid(initData.User.SecurityItemId)) + break; + } + if (!SysId.IsValid(initData.User.AffiliateId)) + return SetErrorState("User affiliate not found."); + if (!SysId.IsValid(initData.User.SecurityItemId)) + return SetErrorState("User security item not found."); + } + } + catch (Exception exc) + { + String msg = "checking repository initialisation"; + SaLogger.Warn($"{SysUtil.Fn} {ExceptionUtil.GetLogMessage(exc, msg)}"); + return SetErrorState($"{exc.GetType().Name} {msg}"); + } + return OK; + } + + //------------------------------------------------------------------- + /// + /// Validate repository initialisation data. + /// + public bool ValidateRepositoryInitialisionData(RepositoryInitialisationData initData) + { + ClearErrorState(); + + // Organisation name. + if (StringUtil.IsBlank(initData.Organisation.Name)) + return SetErrorState("Organisation name must be supplied."); + if ((ulong)StringUtil.GetLength(initData.Organisation.Name) > SbmDbDfn.GetColTextLen(SbmDbDfn.ColumnIdx.Affiliate_Name)) + return SetErrorState("Organisation name exceeds max chars."); + + // Organisation VAT reg. + if ((ulong)StringUtil.GetLength(initData.Organisation.VatReg) > SbmDbDfn.GetColTextLen(SbmDbDfn.ColumnIdx.Affiliate_VatReg)) + return SetErrorState("Company VAT reg exceeds max chars."); + + // Organisation Company Number. + if ((ulong)StringUtil.GetLength(initData.Organisation.CompanyNo) > SbmDbDfn.GetColTextLen(SbmDbDfn.ColumnIdx.Affiliate_CompanyNo)) + return SetErrorState("Company number exceeds max chars."); + + // Organisation Company Number. + if ((ulong)StringUtil.GetLength(initData.Organisation.Website) > SbmDbDfn.GetColTextLen(SbmDbDfn.ColumnIdx.Affiliate_Website)) + return SetErrorState("Company website address exceeds max chars."); + + // User first name. + if (StringUtil.IsBlank(initData.User.FirstName)) + return SetErrorState("User first name must be supplied."); + if ((ulong)StringUtil.GetLength(initData.User.FirstName) > SbmDbDfn.GetColTextLen(SbmDbDfn.ColumnIdx.Affiliate_FirstName)) + return SetErrorState("User first name exceeds max chars."); + + // User last name. + if (StringUtil.IsBlank(initData.User.LastName)) + return SetErrorState("User last name must be supplied."); + if ((ulong)StringUtil.GetLength(initData.User.LastName) > SbmDbDfn.GetColTextLen(SbmDbDfn.ColumnIdx.Affiliate_LastName)) + return SetErrorState("User last name exceeds max chars."); + + // User email. + if (StringUtil.IsBlank(initData.User.Email)) + return SetErrorState("User email must be supplied."); + if ((ulong)StringUtil.GetLength(initData.User.Email) > SbmDbDfn.GetColTextLen(SbmDbDfn.ColumnIdx.Affiliate_Email) || (ulong)StringUtil.GetLength(initData.User.Email) > SaSecurityDbDfn.GetColTextLen(SaSecurityDbDfn.ColumnIdx.SaSecItem_EmailAddress)) + return SetErrorState("User email exceeds max chars."); + + // User code. + if (StringUtil.IsBlank(initData.User.Code)) + return SetErrorState("User code must be supplied."); + if ((ulong)StringUtil.GetLength(initData.User.Code) > SaSecurityDbDfn.GetColTextLen(SaSecurityDbDfn.ColumnIdx.SaSecItem_Code)) + return SetErrorState("User code exceeds max chars."); + + // 'Super' security group. + if (StringUtil.IsBlank(SecurityGroupCode_Super)) + return SetErrorState($"Failed to identify code for 'Super' security group."); + + return OK; + } + + //------------------------------------------------------------------- + /// + /// Initialise repository. + /// + public bool InitialiseRepository(RepositoryInitialisationData initData) + { + ClearErrorState(); + if (!ValidateRepositoryInitialisionData(initData)) return false; + + using (DisposableCollection disposables = new DisposableCollection()) + { + //----------------------------------------------------------- + // Organisation Contact. + + // Retrieve existing Organisation. + SbmAffiliate affiliateOrganisation = Internals_Core.AccountMgr.GetAffiliateById(initData.Organisation.AffiliateId); + if (affiliateOrganisation != null && !affiliateOrganisation.IsOrganisation()) + return SetErrorState("Identified contact is not an organisation."); + if (affiliateOrganisation == null) + affiliateOrganisation = Internals_Core.AccountMgr.GetAffiliateByTypeName(Sbm.AffiliateType.AnyOrganisation, initData.Organisation.Name); + if (affiliateOrganisation == null) + { + // Create new organisation. + affiliateOrganisation = Internals_Core.AccountMgr.CreateAffiliate(Sbm.AffiliateType.Commercial); + } + disposables.Add(affiliateOrganisation); + + // Populate properties. + affiliateOrganisation.Name = initData.Organisation.Name; + if (!StringUtil.IsBlank(initData.Organisation.VatReg)) + affiliateOrganisation.VatReg = initData.Organisation.VatReg; + if (!StringUtil.IsBlank(initData.Organisation.CompanyNo)) + affiliateOrganisation.CompanyNo = initData.Organisation.CompanyNo; + if (!StringUtil.IsBlank(initData.Organisation.Website)) + affiliateOrganisation.Website = initData.Organisation.Website; + + // Store Organisation Contact. + if (!SysId.IsValid(affiliateOrganisation.Id)) + { + if (!Internals_Core.AccountMgr.InsertAffiliate(affiliateOrganisation, DbUpdateInfo_Core)) + return SetErrorState($"Failed to insert Organisation contact - {Internals_Core.AccountMgr.ErrorStateMessage}"); + } + else + { + if (!Internals_Core.AccountMgr.UpdateAffiliate(affiliateOrganisation, DbUpdateInfo_Core)) + return SetErrorState($"Failed to update Organisation contact - {Internals_Core.AccountMgr.ErrorStateMessage}"); + } + + //----------------------------------------------------------- + // Organisation Internal association. + + // Retrieve existing Internal Association for Organisation. + SbmAssociation associationInternal = Internals_Core.AccountMgr.GetAssociationByOwnerTypeTarget(affiliateOrganisation.Id, Sbm.AssociationType.Internal, affiliateOrganisation.Id); + disposables.Add(associationInternal); + if (associationInternal != null && SysId.IsValid(initData.Organisation.AssociationId) && !associationInternal.Id.Equals(initData.Organisation.AssociationId)) + // Failed to validate existing Internal Association against supplied Association Id. + return SetErrorState($"Supplied Internal Association Id ({initData.Organisation.AssociationId}) doesn't match existing association ({associationInternal.Id})."); + if (associationInternal == null && SysId.IsValid(initData.Organisation.AssociationId)) + { + // No existing Internal Association found for Organisation - retrieve specified Association. + associationInternal = Internals_Core.AccountMgr.GetAssociationById(initData.Organisation.AssociationId); + if (associationInternal == null) + return SetErrorState($"Failed to retrieve supplied Internal Association. Id: {initData.Organisation.AssociationId}."); + disposables.Add(associationInternal); + if (!associationInternal.AffiliateIdOwner.Equals(affiliateOrganisation.Id)) + return SetErrorState($"Supplied Internal Association has different Owner ({associationInternal.AffiliateIdOwner}) to Organisation ({affiliateOrganisation.Id})."); + if (!associationInternal.AffiliateIdTarget.Equals(affiliateOrganisation.Id)) + return SetErrorState($"Supplied Internal Association has different Target ({associationInternal.AffiliateIdTarget}) to Organisation ({affiliateOrganisation.Id})."); + } + if (associationInternal == null) + associationInternal = Internals_Core.AccountMgr.CreateAssociation(affiliateOrganisation.Id, Sbm.AssociationType.Internal, affiliateOrganisation.Id); + disposables.Add(associationInternal); + + // Store Internal Association. + if (!SysId.IsValid(associationInternal.Id)) + { + if (!Internals_Core.AccountMgr.InsertAssociation(associationInternal, DbUpdateInfo_Core)) + return SetErrorState($"Failed to insert Internal Association for Organisation - {Internals_Core.AccountMgr.ErrorStateMessage}"); + } + else + { + if (!Internals_Core.AccountMgr.UpdateAssociation(associationInternal, DbUpdateInfo_Core)) + return SetErrorState($"Failed to update Internal Association for Organisation - {Internals_Core.AccountMgr.ErrorStateMessage}"); + } + + //----------------------------------------------------------- + // Security. + + // Core security console. + SaSecurityConsole securityConsole = CreateSecurityConsole(); + disposables.Add(securityConsole); + + // Initialise security data if required. + if (securityConsole.RequiresPopulation() && !securityConsole.PopulateSecurityRights(DbUpdateInfo_Core)) + return SetErrorState(securityConsole.ErrorStateMessage); + + // User Security Item. + SaSecurityItem securityItemUser = null; + // Retrieve supplied Security Item. + if (SysId.IsValid(initData.User.SecurityItemId)) + { + securityItemUser = securityConsole.GetSecurityItemById(SaSecurity.ItemType.User, initData.User.SecurityItemId); + if (securityItemUser == null) + return SetErrorState($"Failed to retrieve supplied User Security Item. Id: {initData.User.SecurityItemId}."); + disposables.Add(securityItemUser); + if (!securityItemUser.Code.Equals(initData.User.Code)) + return SetErrorState($"Supplied User Security Item doesn't match supplied code. Expected: {initData.User.Code}. Found: {securityItemUser.Code}."); + } + if (securityItemUser == null) + { + // Retrieve Security Item by code. + securityItemUser = securityConsole.GetSecurityItemByCode(SaSecurity.ItemType.User, initData.User.Code); + disposables.Add(securityItemUser); + } + if (securityItemUser == null) + { + // Create User Security Item. + if (!securityConsole.CreateUser(initData.User.Code, $"{initData.User.LastName}, {initData.User.FirstName}", DbUpdateInfo_Core)) + return SetErrorState($"Failed to create User Security Item - {securityConsole.ErrorStateMessage}."); + securityItemUser = securityConsole.GetSecurityItemByCode(SaSecurity.ItemType.User, initData.User.Code); + if (securityItemUser == null) + return SetErrorState($"Failed to retrieve User Security Item after creation. Code: {initData.User.Code}."); + disposables.Add(securityItemUser); + } + + // Populate User Security Item properties. + securityItemUser.EmailAddress = initData.User.Email; + securityConsole.SetPassword(securityItemUser, initData.User.Password); + if (!securityConsole.UpdateSecurityItem(securityItemUser, DbUpdateInfo_Core)) + return SetErrorState($"Failed to update User Security Item - {securityConsole.ErrorStateMessage}."); + + // Assign to 'Super' Group. + SysId securityGroupIdSuper = securityConsole.GetIdForItemCode(SaSecurity.ItemType.Group, SecurityGroupCode_Super); + if (!SysId.IsValid(securityGroupIdSuper)) + return SetErrorState($"Failed to identify 'Super' security group. Code: '{SecurityGroupCode_Super}'."); + if (!securityConsole.ItemsAreLinked(securityItemUser.Id, securityGroupIdSuper) && !securityConsole.AssignUserToGroup(securityItemUser.Code, SecurityGroupCode_Super, DbUpdateInfo_Core)) + return SetErrorState($"Failed to assign User Security Item to Super Group - {securityConsole.ErrorStateMessage}."); + + //----------------------------------------------------------- + // User Contact. + + SbmAffiliate affiliateUser = null; + if (SysId.IsValid(initData.User.AffiliateId)) + { + // Retrieve supplied User Contact. + affiliateUser = Internals_Core.AccountMgr.GetAffiliateById(initData.User.AffiliateId); + if (affiliateUser == null) + return SetErrorState($"Failed to retrieve User Contact. Id: {initData.User.AffiliateId}."); + disposables.Add(affiliateUser); + } + + if (affiliateUser == null) + { + // Retrieve User Contact by User Code. + affiliateUser = Internals_Core.AccountMgr.GetAffiliateByUserId(securityItemUser.Id); + disposables.Add(affiliateUser); + } + + if (affiliateUser == null) + { + // Retrieve User Contact by name. + affiliateUser = Internals_Core.AccountMgr.GetIndividualByName(initData.User.FirstName, initData.User.LastName); + disposables.Add(affiliateUser); + } + + if (affiliateUser == null) + { + // Create User Contact. + affiliateUser = Internals_Core.AccountMgr.CreateAffiliate(Sbm.AffiliateType.Individual); + disposables.Add(affiliateUser); + } + + // Populate User Contact properties. + affiliateUser.FirstName = initData.User.FirstName; + affiliateUser.LastName = initData.User.LastName; + affiliateUser.Email = initData.User.Email; + affiliateUser.UserId = securityItemUser.Id; + + // Store User Contact. + if (!SysId.IsValid(affiliateUser.Id)) + { + if (!Internals_Core.AccountMgr.InsertAffiliate(affiliateUser, DbUpdateInfo_Core)) + return SetErrorState($"Failed to insert User contact - {Internals_Core.AccountMgr.ErrorStateMessage}"); + } + else + { + if (!Internals_Core.AccountMgr.UpdateAffiliate(affiliateUser, DbUpdateInfo_Core)) + return SetErrorState($"Failed to update User contact - {Internals_Core.AccountMgr.ErrorStateMessage}"); + } + + //----------------------------------------------------------- + // User Member Association. + + // Attempt to retrieve existing Member Association. + SbmAssociation associationMember = Internals_Core.AccountMgr.GetAssociationByOwnerTypeTarget(affiliateOrganisation.Id, Sbm.AssociationType.Member, affiliateUser.Id); + if (associationMember == null) + // Create Member Association. + associationMember = Internals_Core.AccountMgr.CreateAssociation(affiliateOrganisation.Id, Sbm.AssociationType.Member, affiliateUser.Id); + disposables.Add(associationMember); + + // Store User Association. + if (!SysId.IsValid(associationMember.Id)) + { + if (!Internals_Core.AccountMgr.InsertAssociation(associationMember, DbUpdateInfo_Core)) + return SetErrorState($"Failed to insert Member Association for User - {Internals_Core.AccountMgr.ErrorStateMessage}"); + } + else + { + if (!Internals_Core.AccountMgr.UpdateAssociation(associationMember, DbUpdateInfo_Core)) + return SetErrorState($"Failed to update Member Association for User - {Internals_Core.AccountMgr.ErrorStateMessage}"); + } + + //----------------------------------------------------------- + } + + return OK; + } + + //------------------------------------------------------------------- + } +} diff --git a/SaBusMgrStandardBase/Base/Consoles/SbmSessionConsole.cs b/SaBusMgrStandardBase/Base/Consoles/SbmSessionConsole.cs index fc0cb84..f3f7827 100644 --- a/SaBusMgrStandardBase/Base/Consoles/SbmSessionConsole.cs +++ b/SaBusMgrStandardBase/Base/Consoles/SbmSessionConsole.cs @@ -70,9 +70,9 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles //------------------------------------------------------------------- // Data members. + private SbmInternals internals; private List transactionTypes_Full = new List(); private SbmInstanceConfig instanceConfig; - private SbmAccountsDfn accountsDfn; private AccountsInterfaceDfn dfnSageInt = new AccountsInterfaceDfn(); private AccountsInterfaceDfn dfnQBooksInt = new AccountsInterfaceDfn(); private bool createTransaction_PurchaseOrder, createTransaction_SalesQuote, createTransaction_SalesOrder, createTrans_SalesInvoice; @@ -91,6 +91,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles { if (disposing) { + if (internals != null) internals.Dispose(); internals = null; } } @@ -102,6 +103,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles public SbmVersion AppVersion { get; } public SbmVersion ConsoleVersion { get; } public SbmInstanceConfig InstanceConfig { get { if (instanceConfig == null) instanceConfig = SbmGlobals.Application.GetInstanceConfig(SessionContext); return instanceConfig; } } + private SbmInternals Internals { get { if (internals == null) internals = new SbmInternals(UserContext); return internals; } } //------------------------------------------------------------------- // C r e a t e C o n s o l e @@ -178,16 +180,14 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles { if (InstanceConfig.AllowApplicationOption(option, false)) return true; - if (accountsDfn == null) accountsDfn = new SbmAccountsDfn(UserContext); - return accountsDfn.IsUsingSageInterface() && accountsDfn.IsAssociationTypeManagedByAccounts(Sbm.AssociationType.Customer) && !accountsDfn.UseLocalCustomerPricing(); + return Internals.AccountsDfn.IsUsingSageInterface() && Internals.AccountsDfn.IsAssociationTypeManagedByAccounts(Sbm.AssociationType.Customer) && !Internals.AccountsDfn.UseLocalCustomerPricing(); } case Sbm.ConfigOption.SupplierPriceSet: case Sbm.ConfigOption.SupplierDiscount: { if (InstanceConfig.AllowApplicationOption(option, false)) return true; - SbmAccountsDfn account = null; - return account.IsUsingSageInterface() && account.IsAssociationTypeManagedByAccounts(Sbm.AssociationType.Supplier) && !account.UseLocalSupplierPricing(); + return Internals.AccountsDfn.IsUsingSageInterface() && Internals.AccountsDfn.IsAssociationTypeManagedByAccounts(Sbm.AssociationType.Supplier) && !Internals.AccountsDfn.UseLocalSupplierPricing(); } } return InstanceConfig.AllowApplicationOption(option, false); @@ -502,37 +502,36 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles dfnQBooksInt.ClearConfig(); dfnQBooksInt.AffiliateId_Owner = UserContext.OrganisationAffiliateId; // Identify the interfaces. - SbmAccountsDfn accountsDfn = new SbmAccountsDfn(UserContext); - dfnSageInt.InterfaceId = accountsDfn.GetAccountInterfaceId(Sbm.InterfaceType_Accounts.SageLine50); - dfnQBooksInt.InterfaceId = accountsDfn.GetAccountInterfaceId(Sbm.InterfaceType_Accounts.QuickBooks); + dfnSageInt.InterfaceId = Internals.AccountsDfn.GetAccountInterfaceId(Sbm.InterfaceType_Accounts.SageLine50); + dfnQBooksInt.InterfaceId = Internals.AccountsDfn.GetAccountInterfaceId(Sbm.InterfaceType_Accounts.QuickBooks); // Sales and purchase orders/invoices can only be created locally if they are not imported from one of these interfaces. if (SysId.IsValid(dfnSageInt.InterfaceId)) { // Interpret interface options. - dfnSageInt.importPurchaseOrder = accountsDfn.GetSageImportOption(Sage.ItemType.PurchaseOrder); - dfnSageInt.importSalesOrder = accountsDfn.GetSageImportOption(Sage.ItemType.SalesOrder); - dfnSageInt.importProductInvoice = accountsDfn.GetSageImportOption(Sage.ItemType.Invoice_Product); - dfnSageInt.importServiceInvoice = accountsDfn.GetSageImportOption(Sage.ItemType.Invoice_Service); - dfnSageInt.importSalesOrderInvoice = accountsDfn.GetSageImportOption(Sage.ItemType.Invoice_SalesOrder); - dfnSageInt.exportPurchaseOrder = accountsDfn.GetSageExportOption(Sage.ItemType.PurchaseOrder); - dfnSageInt.exportSalesOrder = accountsDfn.GetSageExportOption(Sage.ItemType.SalesOrder); - dfnSageInt.exportProductInvoice = accountsDfn.GetSageExportOption(Sage.ItemType.Invoice_Product); - dfnSageInt.exportServiceInvoice = accountsDfn.GetSageExportOption(Sage.ItemType.Invoice_Service); - dfnSageInt.exportSalesOrder = accountsDfn.GetSageExportOption(Sage.ItemType.Invoice_SalesOrder); + dfnSageInt.importPurchaseOrder = Internals.AccountsDfn.GetSageImportOption(Sage.ItemType.PurchaseOrder); + dfnSageInt.importSalesOrder = Internals.AccountsDfn.GetSageImportOption(Sage.ItemType.SalesOrder); + dfnSageInt.importProductInvoice = Internals.AccountsDfn.GetSageImportOption(Sage.ItemType.Invoice_Product); + dfnSageInt.importServiceInvoice = Internals.AccountsDfn.GetSageImportOption(Sage.ItemType.Invoice_Service); + dfnSageInt.importSalesOrderInvoice = Internals.AccountsDfn.GetSageImportOption(Sage.ItemType.Invoice_SalesOrder); + dfnSageInt.exportPurchaseOrder = Internals.AccountsDfn.GetSageExportOption(Sage.ItemType.PurchaseOrder); + dfnSageInt.exportSalesOrder = Internals.AccountsDfn.GetSageExportOption(Sage.ItemType.SalesOrder); + dfnSageInt.exportProductInvoice = Internals.AccountsDfn.GetSageExportOption(Sage.ItemType.Invoice_Product); + dfnSageInt.exportServiceInvoice = Internals.AccountsDfn.GetSageExportOption(Sage.ItemType.Invoice_Service); + dfnSageInt.exportSalesOrder = Internals.AccountsDfn.GetSageExportOption(Sage.ItemType.Invoice_SalesOrder); } if (SysId.IsValid(dfnQBooksInt.InterfaceId)) { // Interpret interface options. - dfnQBooksInt.importPurchaseOrder = accountsDfn.GetQuickBooksImportOption(Qbk.EntityType.PurchaseOrder); - dfnQBooksInt.importSalesOrder = accountsDfn.GetQuickBooksImportOption(Qbk.EntityType.SalesOrder); - dfnQBooksInt.importProductInvoice = accountsDfn.GetQuickBooksImportOption(Qbk.EntityType.Invoice_Product); - dfnQBooksInt.importServiceInvoice = accountsDfn.GetQuickBooksImportOption(Qbk.EntityType.Invoice_Service); + dfnQBooksInt.importPurchaseOrder = Internals.AccountsDfn.GetQuickBooksImportOption(Qbk.EntityType.PurchaseOrder); + dfnQBooksInt.importSalesOrder = Internals.AccountsDfn.GetQuickBooksImportOption(Qbk.EntityType.SalesOrder); + dfnQBooksInt.importProductInvoice = Internals.AccountsDfn.GetQuickBooksImportOption(Qbk.EntityType.Invoice_Product); + dfnQBooksInt.importServiceInvoice = Internals.AccountsDfn.GetQuickBooksImportOption(Qbk.EntityType.Invoice_Service); dfnQBooksInt.importSalesOrderInvoice = false; - dfnQBooksInt.exportPurchaseOrder = accountsDfn.GetQuickBooksExportOption(Qbk.EntityType.PurchaseOrder); - dfnQBooksInt.exportSalesOrder = accountsDfn.GetQuickBooksExportOption(Qbk.EntityType.SalesOrder); - dfnQBooksInt.exportProductInvoice = accountsDfn.GetQuickBooksExportOption(Qbk.EntityType.Invoice_Product); - dfnQBooksInt.exportServiceInvoice = accountsDfn.GetQuickBooksExportOption(Qbk.EntityType.Invoice_Service); + dfnQBooksInt.exportPurchaseOrder = Internals.AccountsDfn.GetQuickBooksExportOption(Qbk.EntityType.PurchaseOrder); + dfnQBooksInt.exportSalesOrder = Internals.AccountsDfn.GetQuickBooksExportOption(Qbk.EntityType.SalesOrder); + dfnQBooksInt.exportProductInvoice = Internals.AccountsDfn.GetQuickBooksExportOption(Qbk.EntityType.Invoice_Product); + dfnQBooksInt.exportServiceInvoice = Internals.AccountsDfn.GetQuickBooksExportOption(Qbk.EntityType.Invoice_Service); dfnQBooksInt.bexport_SalesOrderInvoice = false; } diff --git a/SaBusMgrStandardBase/Base/Mgr/SbmAccountMgr_Affiliate.cs b/SaBusMgrStandardBase/Base/Mgr/SbmAccountMgr_Affiliate.cs index b7c4203..1bc5dbf 100644 --- a/SaBusMgrStandardBase/Base/Mgr/SbmAccountMgr_Affiliate.cs +++ b/SaBusMgrStandardBase/Base/Mgr/SbmAccountMgr_Affiliate.cs @@ -7,6 +7,7 @@ using Sarand.Net.Standard.Base.Dbas; using Sarand.Net.Standard.Base.Utils; using System; using System.Collections.Generic; +using static Sarand.BusinessMgr.Net.Standard.Base.App.Sbm; namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr { @@ -27,11 +28,11 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr return ""; } - //------------------------------------------------------------------- - // Retrieve individual affiliates. - //------------------------------------------------------------------- - // Affiliate exists. - public bool AffiliateExistsById(SysId affiliateId) + //------------------------------------------------------------------- + // Retrieve individual affiliates. + //------------------------------------------------------------------- + // Affiliate exists. + public bool AffiliateExistsById(SysId affiliateId) { ClearErrorState(); if (!SysId.IsValid(affiliateId)) return false; @@ -90,55 +91,61 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr if (!SysId.IsValid(userId)) return null; SbmAffiliate.Params prmAffiliate = new SbmAffiliate.Params(); prmAffiliate.UserId = userId; - prmAffiliate.StatusCat = SbmAffiliate.StatusCat.Any; + prmAffiliate.StatusCat = SbmAffiliate.StatusCat.NotDeleted; return GetAffiliate(prmAffiliate); } public SbmAffiliate GetAffiliateByTypeName(Sbm.AffiliateType affiliateType, String affiliateName) { ClearErrorState(); - if (!StringUtil.IsEmpty(affiliateName)) return null; + if (StringUtil.IsBlank(affiliateName)) return null; SbmAffiliate.Params prmAffiliate = new SbmAffiliate.Params(); + prmAffiliate.AffiliateType = affiliateType; prmAffiliate.Name = affiliateName; - prmAffiliate.StatusCat = SbmAffiliate.StatusCat.Any; - return GetAffiliate(prmAffiliate); + prmAffiliate.StatusCat = SbmAffiliate.StatusCat.NotDeleted; + prmAffiliate.ResultsPaging.Set(1,2); + foreach (SbmAffiliate affiliate in GetAffiliateList(prmAffiliate)) + return affiliate; + return null; } public SbmAffiliate GetIndividualByName(String firstName, String lastName) { ClearErrorState(); - if (!StringUtil.IsEmpty(firstName) || !StringUtil.IsEmpty(lastName)) return null; + if (StringUtil.IsBlank(firstName) || StringUtil.IsBlank(lastName)) return null; SbmAffiliate.Params prmAffiliate = new SbmAffiliate.Params(); - prmAffiliate.Name = firstName; - prmAffiliate.Name = lastName; - prmAffiliate.StatusCat = SbmAffiliate.StatusCat.Any; - return GetAffiliate(prmAffiliate); + prmAffiliate.AffiliateType = AffiliateType.Individual; + prmAffiliate.FirstName = firstName; + prmAffiliate.LastName = lastName; + prmAffiliate.StatusCat = SbmAffiliate.StatusCat.NotDeleted; + prmAffiliate.ResultsPaging.Set(1, 2); + foreach (SbmAffiliate affiliate in GetAffiliateList(prmAffiliate)) + return affiliate; + return null; } public SbmAffiliate GetOrganisationByName(String organisationName) { - ClearErrorState(); - if (!StringUtil.IsEmpty(organisationName)) return null; - SbmAffiliate.Params prmAffiliate = new SbmAffiliate.Params(); - prmAffiliate.Name = organisationName; - prmAffiliate.StatusCat = SbmAffiliate.StatusCat.Any; - return GetAffiliate(prmAffiliate); + return GetAffiliateByTypeName(Sbm.AffiliateType.AnyOrganisation, organisationName); } public SbmAffiliate GetTargetAffiliateByAssocId(SysId associationId) { ClearErrorState(); if (!SysId.IsValid(associationId)) return null; - SbmAffiliate.Params prmAffiliate = new SbmAffiliate.Params(); - prmAffiliate.IdsIncluded.Add(associationId); - prmAffiliate.StatusCat = SbmAffiliate.StatusCat.Any; - return GetAffiliate(prmAffiliate); + using (SbmAssociation association = GetAssociationById(associationId)) + { + if (association != null) + return GetAffiliateById(association.AffiliateIdTarget); + } + return null; } public SbmAffiliate GetTargetAffiliateByAssocTypeCode(Sbm.AssociationType associationType, String associationCode) { ClearErrorState(); - if ((int)associationType < 1 || !StringUtil.IsEmpty(associationCode)) return null; - SbmAffiliate.Params prmAffiliate = new SbmAffiliate.Params(); - prmAffiliate.AssociationType = associationType; - //prmAffiliate.Code = associationCode; - prmAffiliate.StatusCat = SbmAffiliate.StatusCat.Any; - return GetAffiliate(prmAffiliate); + if ((int)associationType < 1 || StringUtil.IsBlank(associationCode)) return null; + using (SbmAssociation association = GetAssociationByTypeCode(associationType, associationCode)) + { + if (association != null) + return GetAffiliateById(association.AffiliateIdTarget); + } + return null; } //------------------------------------------------------------------- diff --git a/SaBusMgrStandardBase/Base/Mgr/SbmTransactionMgr_Transaction.cs b/SaBusMgrStandardBase/Base/Mgr/SbmTransactionMgr_Transaction.cs index 17078f9..3ed85ad 100644 --- a/SaBusMgrStandardBase/Base/Mgr/SbmTransactionMgr_Transaction.cs +++ b/SaBusMgrStandardBase/Base/Mgr/SbmTransactionMgr_Transaction.cs @@ -76,7 +76,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr return GetTransaction(prmTransaction); } - public abstract List GetRequirementByIds(SbmTransaction.Params prmTrans); + public abstract List GetRequirementIds(SbmTransaction.Params prmTrans); public SbmTransaction GetTransactionByOwnerTypeRef(SysId affIdOwner, Sbm.TransactionType transactionType, String transRef) { @@ -129,12 +129,19 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr } } - // NB Ref, RefInt is optional. + // References. + if (errField.Ref != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.RefExt, "external", (long)SbmDbDfn.GetColTextLen(SbmDbDfn.ColumnIdx.Transaction_Ref))) + { + errField.Ref = SacsHierarchyItem.ValidValue.Invalid; + return false; + } if (errField.RefExt != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.RefExt, "external ref", (long)SbmDbDfn.GetColTextLen(SbmDbDfn.ColumnIdx.Transaction_RefExt))) { errField.RefExt = SacsHierarchyItem.ValidValue.Invalid; return false; } + + // Raised by. if (errField.RaisedBy != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.RaisedBy, "raised by", (long)SbmDbDfn.GetColTextLen(SbmDbDfn.ColumnIdx.Transaction_RaisedBy))) { errField.RaisedBy = SacsHierarchyItem.ValidValue.Invalid; @@ -146,6 +153,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr errField.ContactName = SacsHierarchyItem.ValidValue.Invalid; return false; } + if (errField.Likelihood != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Likelihood, "likelihood", (long)SbmDbDfn.GetColTextLen(SbmDbDfn.ColumnIdx.Transaction_Likelihood))) { errField.Likelihood = SacsHierarchyItem.ValidValue.Invalid; @@ -281,7 +289,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr errField.Status = SacsHierarchyItem.ValidValue.Invalid; return false; } - if (!SbmTransaction.GetTransactionStatuses(data.TransactionType).Contains(data.Status)) + if (!SbmTransaction.ValidStatusesByType(data.TransactionType).Contains(data.Status)) { errField.Status = SacsHierarchyItem.ValidValue.Invalid; return SetErrorState(ErrorMessage.InvalidStatus); diff --git a/SaBusMgrStandardDbas/Dbas/Consoles/SbmSecurityConsole_Dbas.cs b/SaBusMgrStandardDbas/Dbas/Consoles/SbmSecurityConsole_Dbas.cs index 02c959d..ee77fe4 100644 --- a/SaBusMgrStandardDbas/Dbas/Consoles/SbmSecurityConsole_Dbas.cs +++ b/SaBusMgrStandardDbas/Dbas/Consoles/SbmSecurityConsole_Dbas.cs @@ -191,6 +191,9 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Consoles // Register Security Rights. public override void RegisterSecurityRights() { + // Reset. + ClearRegisteredSecurityRights(); + //--------------------------------------------------------------- // Register data item types. [Not used - to demonstrate option] RegisterDataItemType((short)Sbm.ItemType.Commodity, "Commodity"); diff --git a/SaBusMgrStandardDbas/Dbas/Mgr/Control/SbmcAccountMgr_Dbas-UserAccount.cs b/SaBusMgrStandardDbas/Dbas/Mgr/Control/SbmcAccountMgr_Dbas-UserAccount.cs index d935597..20e037d 100644 --- a/SaBusMgrStandardDbas/Dbas/Mgr/Control/SbmcAccountMgr_Dbas-UserAccount.cs +++ b/SaBusMgrStandardDbas/Dbas/Mgr/Control/SbmcAccountMgr_Dbas-UserAccount.cs @@ -416,6 +416,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr filter.Add(searchFilter.Concat(" OR ", "(", ")")); } } + // Common Properties. // Notes. diff --git a/SaBusMgrStandardDbas/Dbas/Mgr/SbmAccountMgr_Dbas-Affiliate.cs b/SaBusMgrStandardDbas/Dbas/Mgr/SbmAccountMgr_Dbas-Affiliate.cs index e295201..2e9e14b 100644 --- a/SaBusMgrStandardDbas/Dbas/Mgr/SbmAccountMgr_Dbas-Affiliate.cs +++ b/SaBusMgrStandardDbas/Dbas/Mgr/SbmAccountMgr_Dbas-Affiliate.cs @@ -610,6 +610,13 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr if (!StringUtil.IsEmpty(prm.NamePartial)) filter.Add(colAffiliate_Name + " LIKE '%" + DbQuery.FormatForLike(prm.NamePartial) + "%' OR " + colAffiliate_FirstName + " LIKE '%" + DbQuery.FormatForLike(prm.NamePartial) + "%' OR " + colAffiliate_LastName + " LIKE '%" + DbQuery.FormatForLike(prm.NamePartial) + "%'"); + // First Name. + if (!StringUtil.IsEmpty(prm.FirstName)) + filter.Add(colAffiliate_FirstName + "='" + DbQuery.FormatForCondition(prm.FirstName) + "'"); + // Last Name. + if (!StringUtil.IsEmpty(prm.LastName)) + filter.Add(colAffiliate_LastName + "='" + DbQuery.FormatForCondition(prm.LastName) + "'"); + // Partial Email. if (!StringUtil.IsEmpty(prm.EmailPartial)) filter.Add(colAffiliate_Email + " LIKE '%" + DbQuery.FormatForLike(prm.EmailPartial) + "%'"); diff --git a/SaBusMgrStandardDbas/Dbas/Mgr/SbmStockMgr_Dbas-Movement.cs b/SaBusMgrStandardDbas/Dbas/Mgr/SbmStockMgr_Dbas-Movement.cs index 095d0af..8fffdff 100644 --- a/SaBusMgrStandardDbas/Dbas/Mgr/SbmStockMgr_Dbas-Movement.cs +++ b/SaBusMgrStandardDbas/Dbas/Mgr/SbmStockMgr_Dbas-Movement.cs @@ -732,8 +732,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr // Performance of querying requirements for transaction(s) within movement query is very poor - eg. ItemIdSource in (Select Id From Requirement Where TransactionId in (1,2,3)). // Get list of requirement Ids first and then explicitly query against these in the movement query. SbmTransaction.Params prmTrans = new SbmTransaction.Params(); - prmTrans.IdsIncluded = prm.ItemIdSource; - List requirementId = TransactionMgr.GetRequirementByIds(prmTrans); + prmTrans.IdsIncluded.UnionWith(prm.ItemIdSource); + List requirementId = TransactionMgr.GetRequirementIds(prmTrans); // Movements can be matched: either directly to one of the transactions or to any of their associated requirements. List filtersTrans = new List(); diff --git a/SaBusMgrStandardDbas/Dbas/Mgr/SbmTransactionMgr_Dbas-Transaction.cs b/SaBusMgrStandardDbas/Dbas/Mgr/SbmTransactionMgr_Dbas-Transaction.cs index 7570591..c5df080 100644 --- a/SaBusMgrStandardDbas/Dbas/Mgr/SbmTransactionMgr_Dbas-Transaction.cs +++ b/SaBusMgrStandardDbas/Dbas/Mgr/SbmTransactionMgr_Dbas-Transaction.cs @@ -14,6 +14,7 @@ using System; using System.Collections.Generic; using System.Data.Common; using System.Linq; +using System.Text.RegularExpressions; namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr { @@ -429,7 +430,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr return prmTransaction; } - public override List GetRequirementByIds(SbmTransaction.Params prmTrans) + public override List GetRequirementIds(SbmTransaction.Params prmTrans) { ClearErrorState(); List ids = new List(); @@ -1270,15 +1271,86 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr // Column names. String colTransaction_Id = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_Id, tableAlias); String colTransaction_Type = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_Type, tableAlias); + String colTransaction_Ref = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_Ref, tableAlias); + String colTransaction_RefInt = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_RefInt, tableAlias); + String colTransaction_RefExt = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_RefExt, tableAlias); + String colTransaction_DescBrief = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_DescBrief, tableAlias); String colTransaction_StatusCat = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_StatusCat, tableAlias); String colTransaction_Status = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_Status, tableAlias); + String colTransaction_Notes = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_Notes, tableAlias); //--------------------------------------------------------------- // Transaction Id. if (prm.IdsIncluded.HasValidIds()) - filter.Add(colTransaction_Id + " IN (" + prm.IdsIncluded.Concat(",") + ")"); + filter.Add($"{colTransaction_Id} IN ({prm.IdsIncluded.Concat(",")})"); if (prm.IdsExcluded.HasValidIds()) - filter.Add(colTransaction_Id + " NOT IN (" + prm.IdsExcluded.Concat(",") + ")"); + filter.Add($"{colTransaction_Id} NOT IN ({prm.IdsExcluded.Concat(",")})"); + + //--------------------------------------------------------------- + // Transaction search. + if (!StringUtil.IsBlank(prm.Search)) + { + foreach (String search in Regex.Split(prm.Search, "[\\s,;\\-+]+")) + { + if (StringUtil.IsBlank(search)) continue; + String searchForLike = DbQuery.FormatForLike(search, true); + List searchFilter = new List(); + searchFilter.Add($"{colTransaction_Ref} LIKE '%{searchForLike}%'"); + searchFilter.Add($"{colTransaction_RefExt} LIKE '%{searchForLike}%'"); + searchFilter.Add($"{colTransaction_DescBrief} LIKE '%{searchForLike}%'"); + if (!StringUtil.IsBlank(prm.TableAlias_AffiliateTarget)) + { + searchFilter.Add($"{SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Affiliate_Name, prm.TableAlias_AffiliateTarget)} LIKE '%{searchForLike}%'"); + } + if (searchFilter.Any()) + filter.Add(searchFilter.Concat(" OR ", "(", ")")); + } + } + + // Restrict transactions to the current owner if required. + if (SysId.IsValid(AffiliateId_Owner)) + { + // Only need to filter on owner if no association specified, no transaction Ids and no source transaction id. + if (!SysId.IsValid(prm.AssociationId) && !prm.IdsIncluded.HasValidIds() && !SysId.IsValid(prm.TransIdSource)) + filter.Add($"{SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_AffIdOwner, tableAlias)}={SysId.ToLong(AffiliateId_Owner)}"); + } + + // Association Id. + String colTransaction_AssocId = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_AssocId, tableAlias); + if (SysId.IsValid(prm.AssociationId)) + filter.Add($"{colTransaction_AssocId}={SysId.ToLong(prm.AssociationId)}"); + + // Transaction Type. + if (prm.TransactionType > 0) + filter.Add($"{colTransaction_Type}={(int)prm.TransactionType}"); + + //--------------------------------------------------------------- + // Transaction Reference. + if (!StringUtil.IsEmpty(prm.TransRefFull)) + { + String filterTransRef = $"{colTransaction_Ref}='{DbQuery.FormatForCondition(prm.TransRefFull)})'"; + if (prm.TransRefFull.IsNumeric() && prm.TransRefFull.ToLong() >= 1) + filterTransRef += $" OR {colTransaction_RefInt}={prm.TransRefFull}"; + filter.Add(filterTransRef); + } + else if (!StringUtil.IsEmpty(prm.TransRefPartial)) + { + String filterTranRefPartial = $"{colTransaction_Ref} Like '%{DbQuery.FormatForLike(prm.TransRefPartial)}%'"; + if (prm.TransRefPartial.IsNumeric() && prm.TransRefPartial.ToLong() >= 1) + filterTranRefPartial += $" OR {colTransaction_RefInt}={prm.TransRefPartial.ToLong()}"; + filter.Add(filterTranRefPartial); + } + + // Transaction External reference. + if (!StringUtil.IsEmpty(prm.TransRefExtFull)) + filter.Add($"{colTransaction_RefExt}='{DbQuery.FormatForCondition(prm.TransRefExtFull)}'"); + else if (!StringUtil.IsEmpty(prm.TransRefExtPartial)) + filter.Add($"{colTransaction_RefExt} Like '%{DbQuery.FormatForLike(prm.TransRefExtPartial)}%'"); + + // Transaction DescBrief. + String sTransDescBrief = DbQuery.FormatForLike(prm.TransDescBriefPartial); + if (!StringUtil.IsEmpty(prm.TransDescBriefPartial)) + filter.Add($"{colTransaction_DescBrief} LIKE '%{DbQuery.FormatForLike(prm.TransDescBriefPartial)}%'"); //--------------------------------------------------------------- // Transaction Source. @@ -1396,9 +1468,6 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr } //--------------------------------------------------------------- - // Transaction Type. - if (prm.TransactionType > 0) - filter.Add(colTransaction_Type + "=" + ((int)prm.TransactionType).ToString()); // Location Id Stock. if (SysId.IsValid(prm.LocationIdStock)) @@ -1416,51 +1485,6 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr else if (!StringUtil.IsEmpty(TransactionStatusCats.GetCodeForType(prm.StatusCat))) filter.Add(colTransaction_StatusCat + "='" + TransactionStatusCats.GetCodeForType(prm.StatusCat) + "'"); - // Restrict transactions to the current owner if required. - if (SysId.IsValid(AffiliateId_Owner)) - { - // Only need to filter on owner if no association specified, no transaction Ids and no source transaction id. - if (!SysId.IsValid(prm.AssocId) && !prm.IdsIncluded.HasValidIds() && !SysId.IsValid(prm.TransIdSource)) - filter.Add(SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_AffIdOwner, tableAlias) + "=" + SysId.ToString(AffiliateId_Owner)); - } - - //--------------------------------------------------------------- - // Transaction Reference. - String colTransaction_Ref = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_Ref, tableAlias); - String colTransaction_RefInt = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_RefInt, tableAlias); - if (!StringUtil.IsEmpty(prm.TransRefFull)) - { - String filterTransRef = colTransaction_Ref + "='" + DbQuery.FormatForCondition(prm.TransRefFull) + "'"; - if (prm.TransRefFull.IsNumeric() && prm.TransRefFull.ToLong() >= 1) - filterTransRef += " OR " + colTransaction_RefInt + "=" + prm.TransRefFull; - filter.Add(filterTransRef); - } - else if (!StringUtil.IsEmpty(prm.TransRefPartial)) - { - //String sFilter (DbQuery.FormatFn_Left(sColRef,prm.sTransRefPartial.Len())+"='"+sTransRefPartial+"'"); - String filterTranRefPartial = colTransaction_Ref + " Like '%" + DbQuery.FormatForLike(prm.TransRefPartial) + "%'"; - if (prm.TransRefPartial.IsNumeric() && prm.TransRefPartial.ToLong() >= 1) - filterTranRefPartial += " OR " + colTransaction_RefInt + "=" + prm.TransRefPartial; - filter.Add(filterTranRefPartial); - } - - // Transaction External reference. - String colTransaction_RefExt = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_RefExt, tableAlias); - if (!StringUtil.IsEmpty(prm.TransRefExtFull)) - filter.Add(colTransaction_RefExt + "='" + DbQuery.FormatForCondition(prm.TransRefExtFull) + "'"); - else if (!StringUtil.IsEmpty(prm.TransRefExtPartial)) - { - //filter.Add(DbQuery.FormatFn_Left(sColRefExt,prm.TransRefExtPartial.Len())+"='"+TransRefExtPartial+"'"); - filter.Add(colTransaction_RefExt + " Like '%" + DbQuery.FormatForLike(prm.TransRefExtPartial) + "%'"); - } - - // Transaction DescBrief. - String sTransDescBrief = DbQuery.FormatForLike(prm.TransDescBriefPartial); - String colTransaction_DescBrief = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_DescBrief, tableAlias); - if (!StringUtil.IsEmpty(prm.TransDescBriefPartial)) - //filter.Add(DbQuery.FormatFn_Left(sColDescBrief,prm.sTransDescBriefPartial.Len())+"='"+sTransDescBrief+"'"); - filter.Add(colTransaction_DescBrief + " LIKE '%" + DbQuery.FormatForLike(prm.TransDescBriefPartial) + "%'"); - //--------------------------------------------------------------- // Raised date. if (DateUtil.IsValid(prm.RaisedFrom)) @@ -1542,12 +1566,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr } //--------------------------------------------------------------- - // Association Id. - String colTransaction_AssocId = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_AssocId, tableAlias); - if (SysId.IsValid(prm.AssocId)) - filter.Add(colTransaction_AssocId + "=" + prm.AssocId.ToString()); - // Association Target. + String assocFilter = DbQuery.FormatForCondition(prm.AssocPartial); String defaultNominalCodeFull = DbQuery.FormatForCondition(prm.DefaultNominalCodeFull); String defaultNominalCodePartial = DbQuery.FormatForLike(prm.DefaultNominalCodePartial); @@ -1854,8 +1874,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr if (hasAssocCols || hasOwnerAffCols || hasTgtAffCols || hasTgtAddrCols) { //--------------------------------------------------------------------- - //Association. // Join to the Association. + prm.TableAlias_Association = aliasTransaction_Association; DbQueryJoin joinAssoc = new DbQueryJoin(DbJoinType.LeftOuter); joinAssoc.Table = new StringPair(SbmDbDfn.GetTableName(SbmDbDfn.TableIdx.Association), aliasTransaction_Association); joinAssoc.Filters.Add(SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Association_Id, aliasTransaction_Association, false) + "=" + SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Transaction_AssocId, aliasTransaction)); @@ -1874,7 +1894,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr // Owner Affiliate. if (hasOwnerAffCols) { - // Join to the Owner affiliate. + // Join to the Owner Affiliate. + prm.TableAlias_AffiliateOwner = aliasTransaction_AffiliateOwner; DbQueryJoin joinAffOwner = new DbQueryJoin(DbJoinType.LeftOuter); joinAffOwner.Table = new StringPair(SbmDbDfn.GetTableName(SbmDbDfn.TableIdx.Affiliate), aliasTransaction_AffiliateOwner); joinAffOwner.Filters.Add(SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Affiliate_Id, aliasTransaction_AffiliateOwner, false) + "=" + SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Association_AffIdOwner, aliasTransaction_Association, false)); @@ -1889,7 +1910,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr // Target Affiliate. if (hasTgtAffCols || hasTgtAddrCols) { - // Join to the target affiliate. + // Join to the Target Affiliate. + prm.TableAlias_AffiliateTarget = aliasTransaction_AffiliateTarget; DbQueryJoin joinAffTarget = new DbQueryJoin(DbJoinType.LeftOuter); joinAffTarget.Table = new StringPair(SbmDbDfn.GetTableName(SbmDbDfn.TableIdx.Affiliate), aliasTransaction_AffiliateTarget); joinAffTarget.Filters.Add(SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Affiliate_Id, aliasTransaction_AffiliateTarget, false) + "=" + SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Association_AffIdTarget, aliasTransaction_Association, false)); @@ -1905,7 +1927,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr // Target Address. if (hasTgtAddrCols) { - // Join to the target affiliate - NB Use an alias to avoid clashing with the owner affiliate. + // Join to the Primary Target Address. + prm.TableAlias_AddressTarget = aliasTransaction_AddressTarget; DbQueryJoin joinAddr = new DbQueryJoin(DbJoinType.LeftOuter); joinAddr.Table = new StringPair(SbmDbDfn.GetTableName(SbmDbDfn.TableIdx.Address), aliasTransaction_AddressTarget); joinAddr.Filters.Add(SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Address_ItemType, aliasTransaction_AddressTarget, false) + "=" + Sbm.ItemType.Affiliate.ToString()); @@ -1935,7 +1958,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr bool hasColDelAddr_Email = columns.HasId((int)SbmTransaction.Column.DeliveryAddress_Email); if (hasColDeliveryAddress || hasColDelAddr_Line1 || hasColDelAddr_Postcode || hasColDelAddr_Phone || hasColDelAddr_Email) { - // Join to the address table. + // Join to the Delivery Address. + prm.TableAlias_AddressDelivery = aliasTransaction_DeliveryAddress; DbQueryJoin joinDelAddr = new DbQueryJoin(DbJoinType.LeftOuter); joinDelAddr.Table = new StringPair(SbmDbDfn.GetTableName(SbmDbDfn.TableIdx.Address), aliasTransaction_DeliveryAddress); joinDelAddr.Filters.Add(SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Address_Type, aliasTransaction_DeliveryAddress, false) + "=" + Sbm.AddressType.Delivery); diff --git a/SaBusMgrStandardDbas/Dbas/Utils/QuickBooksDdDfnGenerator.cs b/SaBusMgrStandardDbas/Dbas/Utils/QuickBooksDdDfnGenerator.cs index 0b57c6c..d5bfdc2 100644 --- a/SaBusMgrStandardDbas/Dbas/Utils/QuickBooksDdDfnGenerator.cs +++ b/SaBusMgrStandardDbas/Dbas/Utils/QuickBooksDdDfnGenerator.cs @@ -31,7 +31,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Utils // Open database. // NB Must be ODBC connection - especially to retrieve index columns. SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig(); - config.connectionString = connectionString; + config.ConnectionString = connectionString; SacsDatabase database = SacsDatabaseConsole.OpenOdbcDatabase(config); // Generate database definition. diff --git a/SaBusMgrStandardDbas/Dbas/Utils/SbmDbDfnGenerator.cs b/SaBusMgrStandardDbas/Dbas/Utils/SbmDbDfnGenerator.cs index 33d6a09..28a15ea 100644 --- a/SaBusMgrStandardDbas/Dbas/Utils/SbmDbDfnGenerator.cs +++ b/SaBusMgrStandardDbas/Dbas/Utils/SbmDbDfnGenerator.cs @@ -37,7 +37,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Utils // Open database. // NB Must be ODBC connection - especially to retrieve index columns. SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig(); - config.connectionString = connectionString; + config.ConnectionString = connectionString; SacsDatabase database = SacsDatabaseConsole.OpenOdbcDatabase(config); // Generate database definition. diff --git a/SaBusMgrTest_Control/SaBusMgrTest_Control.csproj b/SaBusMgrTest_Control/SaBusMgrTest_Control.csproj index 88e22e1..ac555be 100644 --- a/SaBusMgrTest_Control/SaBusMgrTest_Control.csproj +++ b/SaBusMgrTest_Control/SaBusMgrTest_Control.csproj @@ -15,11 +15,10 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - + - - + + diff --git a/SaBusMgrTest_Control/Web/Control/App/SbmControlApp_Tester_Base.cs b/SaBusMgrTest_Control/Web/Control/App/SbmControlApp_Tester_Base.cs index 017ec7d..4cccda5 100644 --- a/SaBusMgrTest_Control/Web/Control/App/SbmControlApp_Tester_Base.cs +++ b/SaBusMgrTest_Control/Web/Control/App/SbmControlApp_Tester_Base.cs @@ -1,71 +1,78 @@ -using Microsoft.AspNetCore.Hosting; +using DocumentFormat.OpenXml.EMMA; +using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Moq; using Sarand.BusinessMgr.Net.Core.Web.App; using Sarand.BusinessMgr.Net.Standard.Base.App; +using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control; using Sarand.BusinessMgr.Net.Standard.Base.Mgr.Control; using Sarand.BusinessMgr.Web.Control.App; +using Sarand.BusinessMgr.Web.Control.Consoles; +using Sarand.Net.Standard.Base.Core; using Sarand.Net.Standard.Base.Dbas; +using System; namespace Sarand.BusinessMgr.Test.Web.Control.App { - //======================================================================= - public class SbmControlApp_Tester_Base - { - //------------------------------------------------------------------- - // Application. - private class SbmApplication_Control_Test : SbmApplication_Control - { - public SbmApplication_Control_Test(IConfiguration configuration, IWebHostEnvironment env) : - base(configuration) - { - InitEnvironment(env); - } - } + //======================================================================= + public class SbmControlApp_Tester_Base + { + //------------------------------------------------------------------- + // Application. + private class SbmApplication_Control_Test : SbmApplication_Control + { + public SbmApplication_Control_Test(IConfiguration configuration, IWebHostEnvironment env) : + base(configuration) + { + InitEnvironment(env); + } + } - //------------------------------------------------------------------- - // Data members. + //------------------------------------------------------------------- + // Data members. - //------------------------------------------------------------------- - // Construction. - protected SbmControlApp_Tester_Base() - { - // Application. - Mock mockConfiguration = new Mock(); - Mock mockEnvironment = new Mock(); - mockEnvironment.Setup(m => m.EnvironmentName).Returns(Environments.Development); - mockEnvironment.Setup(m => m.ContentRootPath).Returns(@"D:\Sarand\Projects\Users\AHoward\VS2022\BusinessMgr\Workspace\SaBusinessMgrCoreWebControl"); - App = new SbmApplication_Control_Test(mockConfiguration.Object, mockEnvironment.Object); - - // Session configuration. - SessionContextIdx = App.GetSessionContextIdxs()[0]; - SessionContext = App.GetSessionContextByIndex(SessionContextIdx); - Internals = new SbmInternals(GetUserContext(SessionContext)); + //------------------------------------------------------------------- + // Construction. + protected SbmControlApp_Tester_Base() + { + // Application. + Mock mockConfiguration = new Mock(); + Mock mockEnvironment = new Mock(); + mockEnvironment.Setup(m => m.EnvironmentName).Returns(Environments.Development); + mockEnvironment.Setup(m => m.ContentRootPath).Returns(@"D:\Sarand\Projects\Users\AHoward\VS2022\BusinessMgr\Workspace\SaBusinessMgrCoreWebControl"); + App = new SbmApplication_Control_Test(mockConfiguration.Object, mockEnvironment.Object); Internals_Control = new SbmInternals_Control(); - UserContext = GetUserContext(SessionContext); - } + } - //------------------------------------------------------------------- - // Properties. - protected ushort SessionContextIdx { get; } - protected SbmApplication_Control App { get; } - protected SbmSessionContext SessionContext { get; } - protected ISacsDatabase BusMgrDatabase { get { return App.GetBusMgrDatabase(SessionContext); } } - protected SbmInternals Internals { get; } + //------------------------------------------------------------------- + // Properties. + protected SbmApplication_Control App { get; } protected SbmInternals_Control Internals_Control { get; } - protected SbmUserContext UserContext { get; } - //------------------------------------------------------------------- - // User Context. - public static SbmUserContext GetUserContext(SbmSessionContext sessionContext) - { - SbmUserContext userContext = new SbmUserContext_Web(sessionContext); + //------------------------------------------------------------------- + // User Context. + public static SbmUserContext GetUserContext(SbmSessionContext sessionContext) + { + SbmUserContext userContext = new SbmUserContext_Web(sessionContext); - return userContext; - } + return userContext; + } - //------------------------------------------------------------------- - } - //======================================================================= + //------------------------------------------------------------------- + // Core Instance Console. + protected SbmCoreInstanceConsole_Control CreateCoreInstanceConsole(String instanceContext) + { + // Record disposable items as they are created so all can be disposed when needed. + using (DisposableCollection disposables = new DisposableCollection()) + { + SbmcRepository repository = Internals_Control.ControlInstanceMgr.GetRepositoryByContext(instanceContext); + disposables.Add(repository); + return new SbmCoreInstanceConsole_Control(repository); + } + } + + //------------------------------------------------------------------- + } + //======================================================================= } diff --git a/SaBusMgrTest_Control/Web/Control/App/SbmSessionData_Control_Test.cs b/SaBusMgrTest_Control/Web/Control/App/SbmSessionData_Control_Test.cs index 8bbe429..3987904 100644 --- a/SaBusMgrTest_Control/Web/Control/App/SbmSessionData_Control_Test.cs +++ b/SaBusMgrTest_Control/Web/Control/App/SbmSessionData_Control_Test.cs @@ -1,4 +1,5 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.ApplicationInsights.Extensibility.Implementation; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; using Sarand.BusinessMgr.Net.Core.Web.Controllers; using Sarand.BusinessMgr.Net.Standard.Base.App; @@ -34,8 +35,6 @@ namespace Sarand.BusinessMgr.Test.Web.Control.App { // Internals. - SaSecurityConsole securityConsole = App.CreateSecurityConsole(UserContext); - Assert.IsNotNull(securityConsole); SbmcAccountMgr accountMgr = Internals_Control.ControlAccountMgr; Assert.IsNotNull(accountMgr); @@ -43,10 +42,15 @@ namespace Sarand.BusinessMgr.Test.Web.Control.App SbmcUserAccount userAccount = accountMgr.GetUserAccountByEmailAddress("andy@sarand.com"); Assert.IsNotNull(userAccount); + // Session Context? + SbmSessionContext sessionContext_Core = null; // Populate User Session. - SbmSessionData_Control sessionData = new SbmSessionData_Control(SessionContext, userAccount); + SbmSessionData_Control sessionData = new SbmSessionData_Control(sessionContext_Core, userAccount); Assert.IsNotNull(sessionData); + Assert.IsTrue(!StringUtil.IsBlank(sessionData.Base64IV_ControlApp)); + Assert.IsTrue(sessionData.SessionIdx >= 1000); + Assert.IsTrue(sessionData.ItemIdx >= 1000); // Validate user session. Assert.IsNotNull(sessionData.User); @@ -68,12 +72,9 @@ namespace Sarand.BusinessMgr.Test.Web.Control.App Assert.IsNotNull(sessionDataDeserialized); // Validate deserialised data. - Assert.IsTrue(!StringUtil.IsBlank(sessionData.Base64IV_ControlApp)); Assert.IsTrue(!StringUtil.IsBlank(sessionDataDeserialized.Base64IV_ControlApp)); Assert.AreEqual(sessionData.Base64IV_ControlApp, sessionDataDeserialized.Base64IV_ControlApp); - Assert.IsTrue(sessionData.SessionIdx >= 1000); Assert.AreEqual(sessionData.SessionIdx, sessionDataDeserialized.SessionIdx); - Assert.IsTrue(sessionData.ItemIdx >= 1000); Assert.AreEqual(sessionData.ItemIdx, sessionDataDeserialized.ItemIdx); // User details. diff --git a/SaBusMgrTest_Portal/SaBusMgrTest_Portal.csproj b/SaBusMgrTest_Portal/SaBusMgrTest_Portal.csproj index de20bc4..a70b898 100644 --- a/SaBusMgrTest_Portal/SaBusMgrTest_Portal.csproj +++ b/SaBusMgrTest_Portal/SaBusMgrTest_Portal.csproj @@ -14,11 +14,10 @@ Sarand.BusinessMgr.Test - - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/SaBusMgrTest_Portal/Web/Portal/App/SbmApplication_Database_Tester.cs b/SaBusMgrTest_Portal/Web/Portal/App/SbmApplication_Database_Tester.cs new file mode 100644 index 0000000..c3fa010 --- /dev/null +++ b/SaBusMgrTest_Portal/Web/Portal/App/SbmApplication_Database_Tester.cs @@ -0,0 +1,56 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Sarand.Net.Standard.Base.App; +using Sarand.Net.Standard.Base.Dbas; +using Sarand.Net.Standard.Base.Helpers; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; + +namespace Sarand.BusinessMgr.Test.Web.Portal.App +{ + //======================================================================= + [TestClass] + public class SbmApplication_Database_Tester : SbmPortalApp_Tester_Base + { + //------------------------------------------------------------------- + private static Regex reHex = new Regex("^(?:[A-F0-9]{2})+$", RegexOptions.IgnoreCase); + + //------------------------------------------------------------------- + [TestMethod] + public void Test_PasswordEncoding() + { + Assert.IsNotNull(BusMgrDatabase); + StringAssert.Matches(BusMgrDatabase.EncodePassword_Hex(""), reHex); + + // Iterate using random filename (8.3). + for (int i = 0; i < 1000; i++) + StringAssert.Matches(BusMgrDatabase.EncodePassword_Hex(Path.GetRandomFileName()), reHex); + } + + //------------------------------------------------------------------- + [TestMethod] + public void Test_PasswordCompare() + { + Assert.IsNotNull(BusMgrDatabase); + Dictionary passwordHashes = new Dictionary(); + + // Iterate using random filename (8.3). + for (int i = 0; i < 200; i++) + { + string password = Path.GetRandomFileName(); + string passwordHash = BusMgrDatabase.EncodePassword_Hex(password); + StringAssert.Matches(passwordHash, reHex); + passwordHashes.Add(password, passwordHash); + } + foreach (string password in passwordHashes.Keys) + { + string passwordHash = passwordHashes.GetValueOrDefault(password); + StringAssert.Matches(passwordHash, reHex); + Assert.IsTrue(BusMgrDatabase.ComparePassword_Hex(password, passwordHash)); + } + } + + //------------------------------------------------------------------- + } + //======================================================================= +} diff --git a/SaBusMgrTest_Portal/Web/Portal/App/SbmApplication_Portal_Tester.cs b/SaBusMgrTest_Portal/Web/Portal/App/SbmApplication_Portal_Tester.cs index 2babba8..cb0ef2e 100644 --- a/SaBusMgrTest_Portal/Web/Portal/App/SbmApplication_Portal_Tester.cs +++ b/SaBusMgrTest_Portal/Web/Portal/App/SbmApplication_Portal_Tester.cs @@ -13,7 +13,7 @@ namespace Sarand.BusinessMgr.Test.Web.Portal.App Assert.IsNotNull(App); } - //------------------------------------------------------------------- - } - //======================================================================= + //------------------------------------------------------------------- + } + //======================================================================= } diff --git a/SaBusinessMgrCoreWebControl/Control/App/SbmApplication_Control.cs b/SaBusinessMgrCoreWebControl/Control/App/SbmApplication_Control.cs index 9303125..a7f764f 100644 --- a/SaBusinessMgrCoreWebControl/Control/App/SbmApplication_Control.cs +++ b/SaBusinessMgrCoreWebControl/Control/App/SbmApplication_Control.cs @@ -20,6 +20,11 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Sarand.Net.Standard.Base.ReferenceData; +using Sarand.Net.Standard.Base.Bus; +using static Sarand.Net.Standard.Dbas.Base.SacsDatabaseConsole; +using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control; +using Sarand.BusinessMgr.Net.Standard.Base.Mgr.Control; +using Sarand.Net.Standard.Base.Security; namespace Sarand.BusinessMgr.Web.Control.App { @@ -30,6 +35,7 @@ namespace Sarand.BusinessMgr.Web.Control.App // Data members. private bool generateDatabaseDefinitions_Control = false; private bool generateDatabaseDefinitions_BusMgr = false; + private static SbmApplication_Control appInstance; private PropertySet propertySet; private Dictionary appConfigs = new Dictionary(); private Dictionary emailConfigs = new Dictionary(); @@ -37,29 +43,45 @@ namespace Sarand.BusinessMgr.Web.Control.App // Singular databases. private ISacsDatabase controlDatabase = null; private ISacsDatabase templateDatabase = null; - // Session contexts. - private static ushort sessionContextIdx_Next = 100; - private class SessionContextData + // Core Session contexts - to access Core database via repository configuration. + private static ushort sessionContextIdx_Next = 101; + private class CoreInstanceContextData { - public SessionContextData(SbmSessionContext_Web sessionContext) + public CoreInstanceContextData(SbmSessionContext_Web sessionContext, SysId controlOwnerId, SysId controlRepositoryId) { SessionContext = sessionContext; + ControlOwnerId = controlOwnerId; + ControlRepositoryId = controlRepositoryId; } public SbmSessionContext_Web SessionContext { get; } + public SysId ControlOwnerId { get; } + public SysId ControlRepositoryId { get; } public HashSet RepositoryContexts { get; } = new HashSet(); public ISacsDatabase BusMgrDatabase { get; set; } + // Core Instance config. + private SbmInstanceConfig instanceConfig = null; + public SbmInstanceConfig InstanceConfig + { + get + { + if (instanceConfig == null) + instanceConfig = new SbmInstanceConfig_Control(ControlOwnerId, ControlRepositoryId); + return instanceConfig; + } + } } - private readonly Dictionary sessionContexts = new Dictionary(); + private readonly Dictionary coreInstances = new Dictionary(); //------------------------------------------------------------------- // Construction. public SbmApplication_Control(IConfiguration configuration) { + appInstance = this; InitialiseTemporaryLoggingFolder(); try { propertySet = new PropertySet(); - SbmGlobals.System = (System_Web = new SbmSystem_Web(propertySet)); + SbmGlobals.System = (SbmGlobals_Web.System = (System_Web = new SbmSystem_Web(propertySet))); Configuration = configuration; } catch (Exception exc) @@ -71,53 +93,94 @@ namespace Sarand.BusinessMgr.Web.Control.App //------------------------------------------------------------------- // Properties. + public static SbmApplication_Control Instance { get { return appInstance; } } // Application Configuration. public override Net.Core.Web.App.SbmAppConfig AppConfig { get { return appConfigs.Values.ToList().getConfigForApplication(); } } // Session Configuration. public override String SessionCookieName { get { return Sbm.Config.Control.Session.Cookie.Name; } } public override List GetSessionContextIdxs() { - return sessionContexts.Values.Select(item => item.SessionContext.Index).ToList(); + return coreInstances.Values.Select(item => item.SessionContext.Index).ToList(); } public override SbmSessionContext GetSessionContextByIndex(ushort index) { - return sessionContexts.GetValue(index, null)?.SessionContext ?? null; + return coreInstances.GetValue(index, null)?.SessionContext ?? null; } public override List GetSessionContexts() { - return new List(sessionContexts.Values.Select(item => item.SessionContext)); + return new List(coreInstances.Values.Select(item => item.SessionContext)); } + /// + /// Identify the Core session context by the Repository Id. + /// If context not yet defined for Repository, load and then return index. + /// If repository not found, return 0. + /// + public ushort GetCoreSessionIndexForControlRepository(SysId ownerId, SysId repositoryId) + { + using (DisposableCollection disposables = new DisposableCollection()) + { + CoreInstanceContextData sessionContext = coreInstances.Values.FirstOrDefault(item => item.ControlRepositoryId.Equals(repositoryId)); + if (sessionContext != null) return sessionContext.SessionContext.Index; + // Repository context not yet loaded. + SbmcInstanceMgr instanceMgr = System.CreateControlInstanceMgr(); + disposables.Add(instanceMgr); + SbmcRepository repository = instanceMgr.GetRepositoryById(repositoryId); + disposables.Add(repository); + if (repository != null) + { + // Core database connection. + SacsDatabaseConsole.OdbcConfig odbcConfig = SbmCoreInstanceConsole_Control.GetRepositoryOdbcConfig(repository); + SacsDatabase busMgrDatabase = SacsDatabaseConsole.OpenOdbcDatabase(odbcConfig); + if (busMgrDatabase.HasErrorState()) + SaLogger.Warn($"{SysUtil.Fn} BusMgr Database: " + busMgrDatabase.DatabaseName + ". Initialisation error: " + busMgrDatabase.ErrorStateMessage); + + // Session context. + ushort sessionContextIdx = sessionContextIdx_Next++; + if (sessionContextIdx_Control < 1) + sessionContextIdx_Control = sessionContextIdx; + CoreInstanceContextData sessionContextData = new CoreInstanceContextData(new SbmSessionContext_Web(sessionContextIdx, Sbm.Application.WebControl), ownerId, repositoryId); + sessionContextData.RepositoryContexts.Add(repository.Context); + sessionContextData.BusMgrDatabase = busMgrDatabase; + coreInstances.Add(sessionContextData.SessionContext.Index, sessionContextData); + return sessionContextData.SessionContext.Index; + } + } + return 0; + } + // Databases. - public override ISacsDatabase GetControlDatabase() - { - return controlDatabase; - } - public override ISacsDatabase GetTemplateDatabase() - { - return templateDatabase; - } + public override ISacsDatabase GetControlDatabase() { return controlDatabase; } + public override ISacsDatabase GetTemplateDatabase() { return templateDatabase; } public override HashSet GetRepositoryContexts(SbmSessionContext sessionContext) { - return sessionContexts.GetValue(sessionContext.Index, null)?.RepositoryContexts ?? new HashSet(); + return coreInstances.GetValue(sessionContext.Index, null)?.RepositoryContexts ?? new HashSet(); } public override ISacsDatabase GetBusMgrDatabase(SbmSessionContext sessionContext) { - return sessionContexts.GetValue(sessionContext.Index, null)?.BusMgrDatabase; + return coreInstances.GetValue(sessionContext.Index, null)?.BusMgrDatabase; } // Instance configuration. public override SbmInstanceConfig GetInstanceConfig(SbmSessionContext sessionContext) { - throw new NotSupportedException("InstanceConfig not supported in Control application."); + return coreInstances.GetValue(sessionContext.Index, null)?.InstanceConfig; } // Email configuration. public override SbmEmailConfig EmailConfig { get { return emailConfigs.Values.ToList().getConfigForSession(AppConfig); } } //------------------------------------------------------------------- - // Create Consoles. + // Consoles. + //------------------------------------------------------------------- + + public override SaSecurityConsole CreateSecurityConsole(ISbmUserContext_Core userContext) + { + return new SbmSecurityConsole_Web(userContext); + } + public override SaReferenceDataConsole CreateReferenceDataConsole(ISbmUserContext_Core userContext) { return null; } + public override SbmEmailConsole CreateEmailConsole(ISbmUserContext_Core userContext) { return new SbmEmailConsole_Control(EmailConfig); @@ -173,9 +236,9 @@ namespace Sarand.BusinessMgr.Web.Control.App // Control database connection. SacsDatabaseConsole.OdbcConfig odbcConfig = new SacsDatabaseConsole.OdbcConfig(); - odbcConfig.location = AppConfig.ControlDatabase.Location; - odbcConfig.user = AppConfig.ControlDatabase.User; - odbcConfig.pword = AppConfig.ControlDatabase.Password; + odbcConfig.Location = AppConfig.ControlDatabase.Location; + odbcConfig.User = AppConfig.ControlDatabase.User; + odbcConfig.Password = AppConfig.ControlDatabase.Password; controlDatabase = SacsDatabaseConsole.OpenOdbcDatabase(odbcConfig); if (controlDatabase.HasErrorState()) SaLogger.Warn($"{SysUtil.Fn} Control Database initialisation error: " + controlDatabase.ErrorStateMessage); @@ -184,34 +247,13 @@ namespace Sarand.BusinessMgr.Web.Control.App if (AppConfig.TemplateDatabase != null) { odbcConfig = new SacsDatabaseConsole.OdbcConfig(); - odbcConfig.location = AppConfig.TemplateDatabase.Location; - odbcConfig.user = AppConfig.TemplateDatabase.User; - odbcConfig.pword = AppConfig.TemplateDatabase.Password; + odbcConfig.Location = AppConfig.TemplateDatabase.Location; + odbcConfig.User = AppConfig.TemplateDatabase.User; + odbcConfig.Password = AppConfig.TemplateDatabase.Password; templateDatabase = SacsDatabaseConsole.OpenOdbcDatabase(odbcConfig); if (templateDatabase.HasErrorState()) SaLogger.Warn($"{SysUtil.Fn} Template Database initialisation error: " + controlDatabase.ErrorStateMessage); } - - // BusinessMgr database connections. - foreach (Net.Core.Web.App.SbmAppConfig.DatabaseConfig dbConfig in AppConfig.BusMgrDatabases) - { - odbcConfig = new SacsDatabaseConsole.OdbcConfig(); - odbcConfig.location = dbConfig.Location; - odbcConfig.user = dbConfig.User; - odbcConfig.pword = dbConfig.Password; - SacsDatabase busMgrDatabase = SacsDatabaseConsole.OpenOdbcDatabase(odbcConfig); - if (busMgrDatabase.HasErrorState()) - SaLogger.Warn($"{SysUtil.Fn} BusMgr Database: " + busMgrDatabase.DatabaseName + ". Initialisation error: " + busMgrDatabase.ErrorStateMessage); - - // Session context. - ushort sessionContextIdx = sessionContextIdx_Next++; - if (sessionContextIdx_Control < 1) - sessionContextIdx_Control = sessionContextIdx; - SessionContextData sessionContextData = new SessionContextData(new SbmSessionContext_Web(sessionContextIdx, Sbm.Application.WebControl)); - sessionContextData.RepositoryContexts.UnionWith(dbConfig.Identifiers); - sessionContextData.BusMgrDatabase = busMgrDatabase; - sessionContexts.Add(sessionContextData.SessionContext.Index, sessionContextData); - } } catch (Exception exc) { @@ -225,9 +267,9 @@ namespace Sarand.BusinessMgr.Web.Control.App { // Use the 'template' database connection parameters. SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig(); - config.location = AppConfig.TemplateDatabase.Location; - config.user = AppConfig.TemplateDatabase.User; - config.pword = AppConfig.TemplateDatabase.Password; + config.Location = AppConfig.TemplateDatabase.Location; + config.User = AppConfig.TemplateDatabase.User; + config.Password = AppConfig.TemplateDatabase.Password; GenerateDatabaseDefinition(SbmDbDfnGenerator.DatabaseInstance.Core, GetTemplateDatabase()); } } diff --git a/SaBusinessMgrCoreWebControl/Control/App/SbmSessionData_Control.cs b/SaBusinessMgrCoreWebControl/Control/App/SbmSessionData_Control.cs index 8215101..1491731 100644 --- a/SaBusinessMgrCoreWebControl/Control/App/SbmSessionData_Control.cs +++ b/SaBusinessMgrCoreWebControl/Control/App/SbmSessionData_Control.cs @@ -85,7 +85,7 @@ namespace Sarand.BusinessMgr.Web.Control.App { UserAccountId = userData_Control.UserAccountId; UserAccountSupplied = userData_Control.UserAccountSupplied; - KeepLoggedIn= userData_Control.KeepLoggedIn; + KeepLoggedIn = userData_Control.KeepLoggedIn; } DisplayName = userData.DisplayName; Title = userData.Title; @@ -106,6 +106,28 @@ namespace Sarand.BusinessMgr.Web.Control.App /// User - JSON deserialisation route. public UserData_Control User { get; private set; } + //------------------------------------------------------------------- + /// + /// User Profile. + /// - Filter settings. + /// + public class UserProfileData + { + public UserProfileData() { } + + // Common filter. + public class FilterData + { + /// Id for currently selected Association. + public String InstanceContext { get; set; } + } + /// + /// Common filter properties. + /// + public FilterData Filter { get; private set; } = new FilterData(); + } + public UserProfileData Profile { get; protected set; } = new UserProfileData(); + //------------------------------------------------------------------- // Control application encryption IV value - for consistent encryption during session. public String Base64IV_ControlApp { get; private set; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(SbmController_Control.Base64Key_ControlApp); diff --git a/SaBusinessMgrCoreWebControl/Control/Consoles/SbmCoreInstanceConsole_Control.cs b/SaBusinessMgrCoreWebControl/Control/Consoles/SbmCoreInstanceConsole_Control.cs new file mode 100644 index 0000000..1bad76c --- /dev/null +++ b/SaBusinessMgrCoreWebControl/Control/Consoles/SbmCoreInstanceConsole_Control.cs @@ -0,0 +1,94 @@ +using Sarand.BusinessMgr.Net.Core.Web.App; +using Sarand.BusinessMgr.Net.Standard.Base.App; +using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control; +using Sarand.BusinessMgr.Net.Standard.Base.Consoles; +using Sarand.BusinessMgr.Web.Control.App; +using Sarand.Net.Standard.Base.App; +using Sarand.Net.Standard.Base.Bus; +using Sarand.Net.Standard.Base.Core; +using Sarand.Net.Standard.Base.Dbas; +using Sarand.Net.Standard.Base.Security; +using Sarand.Net.Standard.Base.Utils; +using Sarand.Net.Standard.Dbas.Base; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Sarand.BusinessMgr.Web.Control.Consoles +{ + //======================================================================= + public class SbmCoreInstanceConsole_Control : SbmCoreInstanceConsole_Base + { + //------------------------------------------------------------------- + // Definitions. + + //------------------------------------------------------------------- + // Data members. + private readonly SacsDatabase coreDatabase; + private readonly SysId organisationId; + private readonly SysId repositoryId; + private SbmInternals internals; + + //------------------------------------------------------------------- + // Construction. + public SbmCoreInstanceConsole_Control(SbmcRepository repository) + { + organisationId = repository.OwnerId; + repositoryId = repository.Id; + + // Repository connection. + SacsDatabaseConsole.OdbcConfig config = GetRepositoryOdbcConfig(repository); + coreDatabase = SacsDatabaseConsole.OpenOdbcDatabase(config); + if (coreDatabase.HasErrorState()) + SetErrorState(coreDatabase.ErrorStateMessage); + } + protected override void Dispose(bool disposing) + { + if (disposing) + { + } + base.Dispose(disposing); + } + + //------------------------------------------------------------------- + // Properties. + public SbmApplication_Control App { get { return SbmApplication_Control.Instance; } } + public override ISacsDatabase Database_Core { get { return coreDatabase; } } + public override SbmInternals Internals_Core { get { if (internals == null) { internals = CreateCoreInternals(); } return internals; } } + public override DbUpdateInfo DbUpdateInfo_Core { get { return Internals_Core.DbUpdateInfo; } } + + //------------------------------------------------------------------- + // Utilities. + + public static SacsDatabaseConsole.OdbcConfig GetRepositoryOdbcConfig(SbmcRepository repository) + { + SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig(); + config.Location = $"MsSql:{repository.ServerName}\\{repository.InstanceName}.{repository.DatabaseName}"; + config.User = repository.UserName; + config.Password = repository.Password; + return config; + } + + /// Core internals for accessing core managers etc. + public SbmInternals CreateCoreInternals() + { + ushort sessionIndex = App.GetCoreSessionIndexForControlRepository(organisationId, repositoryId); + SbmSessionContext sessionContext = new SbmSessionContext_Web(sessionIndex, Sbm.Application.WebControl); + SbmUserContext userContext = new SbmUserContext_Web(sessionContext); + return new SbmInternals(userContext); + } + + /// + /// Create core security console. + /// + /// + public override SaSecurityConsole CreateSecurityConsole() + { + return App.CreateSecurityConsole(internals.UserContext); + } + + + //------------------------------------------------------------------- + } + //======================================================================= +} diff --git a/SaBusinessMgrCoreWebControl/Control/Controllers/Account/UserAccountController-Ajax.cs b/SaBusinessMgrCoreWebControl/Control/Controllers/Account/UserAccountController-Ajax.cs index 59586f6..7a53bf9 100644 --- a/SaBusinessMgrCoreWebControl/Control/Controllers/Account/UserAccountController-Ajax.cs +++ b/SaBusinessMgrCoreWebControl/Control/Controllers/Account/UserAccountController-Ajax.cs @@ -14,8 +14,8 @@ using System.Linq; namespace Sarand.BusinessMgr.Web.Control.Controllers.Account { - //======================================================================= - partial class UserAccountController + //======================================================================= + partial class UserAccountController { //------------------------------------------------------------------- // Definitions. @@ -185,7 +185,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Account { // Identify item. - SysId userAccountId = model.User.Id.ToSysId(); + SysId userAccountId = SysId.ToSysId(model.User.Id); if (!SysId.IsValid(userAccountId)) return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); @@ -265,7 +265,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Account RefreshModel(model); // Validate item Id. - SysId userAccountId = model.User.Id.ToSysId(); + SysId userAccountId = SysId.ToSysId(model.User.Id); if (StringUtil.ToBool(model.User.Exists) && !SysId.IsValid(userAccountId)) { SaLogger.Warn($"{SysUtil.Fn} User Id not supplied for existing item."); @@ -366,7 +366,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Account { // Retrieve user. - SysId userAccountId = model.User.Id.ToSysId(); + SysId userAccountId = SysId.ToSysId(model.User.Id); SbmcUserAccount userAccount = ControlAccountMgr.GetUserAccountById(userAccountId); disposables.Add(userAccount); if (userAccount == null) diff --git a/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/CoreDatabaseController-Ajax.cs b/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/CoreDatabaseController-Ajax.cs new file mode 100644 index 0000000..e217812 --- /dev/null +++ b/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/CoreDatabaseController-Ajax.cs @@ -0,0 +1,139 @@ +using DocumentFormat.OpenXml.Drawing.Charts; +using Microsoft.AspNetCore.Mvc; +using NPOI.SS.Formula.Functions; +using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control; +using Sarand.BusinessMgr.Web.Control.Consoles; +using Sarand.BusinessMgr.Web.Control.Models; +using Sarand.BusinessMgr.Web.Control.Models.Instance; +using Sarand.Net.Standard.Base.App; +using Sarand.Net.Standard.Base.Bus; +using Sarand.Net.Standard.Base.Core; +using Sarand.Net.Standard.Base.Dbas; +using Sarand.Net.Standard.Base.Utils; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance +{ + //======================================================================= + partial class CoreDatabaseController + { + //------------------------------------------------------------------- + // Definitions. + + // Core Database Table list data. + private class TableListData : AjaxResponse_Data.ItemData_Base + { + public String SchemaName { get; set; } + public String TableName { get; set; } + public long? ColumnCount { get; set; } + public long? IndexCount { get; set; } + public long? RowCount { get; set; } + } + + //------------------------------------------------------------------- + // Get Core Database Table list ajax request. + //------------------------------------------------------------------- + private class AjaxResponse_CoreDatabaseTableList : AjaxResponse_Data + { + // Construction. + public AjaxResponse_CoreDatabaseTableList(SbmModel_Control model) : base(model) { } + // CoreDatabase list. + public List Tables { get; } = new List(); + } + //------------------------------------------------------------------- + [HttpPost] + [Route("Instance/CoreDatabase/Ajax/GetTableList")] + [Route("Instance/CoreDatabase/Ajax/GetTables")] + public IActionResult Ajax_GetTableList(Model_CoreDatabase model) + { + String messageTitle = Localiser["label.database"]; + AjaxResponse_CoreDatabaseTableList responseData = new AjaxResponse_CoreDatabaseTableList(model); + + // Validate session and referrer. + if (!ValidReferer) return Forbid(); + if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + RefreshModel(model); + + // Record disposable items as they are created so all can be disposed when needed. + using (DisposableCollection disposables = new DisposableCollection()) + { + + // Validate Repository. + SessionData_Control.Profile.Filter.InstanceContext = model.Filter.Context; + if (StringUtil.IsBlank(model.Filter.Context)) + { + SaLogger.Warn($"{SysUtil.Fn} Instance Context not supplied."); + return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); + } + SbmcRepository repository = ControlInstanceMgr.GetRepositoryByContext(model.Filter.Context); + disposables.Add(repository); + if (repository == null) + { + SaLogger.Warn($"{SysUtil.Fn} Repository does not exist. Context: {model.Filter.Context}."); + return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); + } + + // Repository Console. + SbmCoreInstanceConsole_Control instanceConsole = new SbmCoreInstanceConsole_Control(repository); + disposables.Add(instanceConsole); + + // Columns. + String colSchemaName = "SchemaName"; + String colTableName = "TableName"; + String colColumnCount = "ColumnCount"; + String colIndexCount = "IndexCount"; + String colRowCount = "RowCount"; + + // Table filter. + List filter = new List(); + if (!StringUtil.IsBlank(model.Filter.Search)) + filter.Add($"tbl.name Like '%{DbQuery.FormatForLike(model.Filter.Search)}%'"); + if (!filter.Any()) filter.Add("1=1"); + + // Construction query. + List sql = new List() + { + $"Select Top 2000", + $"[{colSchemaName}]=sch.name, [{colTableName}]=tbl.name,", + $"[{colColumnCount}]=(Select Count(*) From sys.columns col Where col.object_id=tbl.object_id),", + $"[{colIndexCount}]=(Select Count(*) From sys.indexes idx Where idx.object_id=tbl.object_id),", + $"[{colRowCount}]=(Select Sum(ptn.rows) From sys.partitions ptn Where ptn.object_id=tbl.object_id And ptn.index_id<2)", + $"From sys.tables tbl", + $"Left Join sys.schemas sch On sch.schema_id=tbl.schema_id", + $"Where tbl.type='U' And {filter.Concat(" And ","(",")")}", + $"Order By tbl.name, sch.name;" + }; + + // Query items. + using (DbResultSet resultSet = instanceConsole.Database_Core.ExecuteQuery(String.Join("\n", sql))) + { + while (resultSet != null && resultSet.HasRows && resultSet.NextRecord()) + { + NamedValue.Map values = resultSet.GetRecordValues(); + TableListData tableData = new TableListData() + { + SchemaName = values.GetString(colSchemaName), + TableName = values.GetString(colTableName), + ColumnCount = values.GetLong(colColumnCount), + IndexCount = values.GetLong(colIndexCount), + RowCount = values.GetLong(colRowCount), + }; + responseData.Tables.Add(tableData); + } + } + if (model.Paging.IsPaged) + model.Paging.ItemCount = (ushort)responseData.Tables.Count; + } + + // Complete response. + responseData.SetPaging(model); + responseData.Success = true; + return Json(responseData); + } + + //------------------------------------------------------------------- + } + //======================================================================= +} diff --git a/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/CoreDatabaseController.cs b/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/CoreDatabaseController.cs new file mode 100644 index 0000000..0e57d39 --- /dev/null +++ b/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/CoreDatabaseController.cs @@ -0,0 +1,46 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Sarand.BusinessMgr.Net.Core.Web.App; +using Sarand.BusinessMgr.Web.Control.Models.Instance; + +namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance +{ + //====================================================================== + public partial class CoreDatabaseController : SbmController_Control + { + //------------------------------------------------------------------- + // Data members. + + //------------------------------------------------------------------- + // Construction. + public CoreDatabaseController(SbmLocaliser localiser, ILogger logger) : + base(localiser, logger) + { + } + + //------------------------------------------------------------------- + [Route("Instance/CoreDatabase")] + public IActionResult Index(Model_CoreDatabase model) + { + if (!ValidUserSession) + AutoLoginUser(); + + // Redirect to sign-in if not signed-in. + if (!ValidUserSession) + { + ClearKeepLoggedInCookie(); + return RedirectToAction("", "Security"); + } + + // Refresh model. + RefreshModel(model); + model.Filter.Context = SessionData_Control.Profile.Filter.InstanceContext; + + // Core Database view. + return View("Views/Instance/CoreDatabase/Index.cshtml", model); + } + + //------------------------------------------------------------------- + } + //====================================================================== +} diff --git a/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/OwnerController-Ajax.cs b/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/OwnerController-Ajax.cs index 4386eb0..4190553 100644 --- a/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/OwnerController-Ajax.cs +++ b/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/OwnerController-Ajax.cs @@ -169,7 +169,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance { // Identify item. - SysId ownerId = model.Owner.Id.ToSysId(); + SysId ownerId = SysId.ToSysId(model.Owner.Id); if (!SysId.IsValid(ownerId)) return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); @@ -206,7 +206,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance RefreshModel(model); // Validate item Id. - SysId ownerId = model.Owner.Id.ToSysId(); + SysId ownerId = SysId.ToSysId(model.Owner.Id); if (StringUtil.ToBool(model.Owner.Exists) && !SysId.IsValid(ownerId)) { SaLogger.Warn($"{SysUtil.Fn} Owner Id not supplied for existing item."); diff --git a/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/RepositoryController-Ajax.cs b/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/RepositoryController-Ajax.cs index b2bb0b0..76564bc 100644 --- a/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/RepositoryController-Ajax.cs +++ b/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/RepositoryController-Ajax.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Mvc; using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control; +using Sarand.BusinessMgr.Web.Control.Consoles; using Sarand.BusinessMgr.Web.Control.Models; using Sarand.BusinessMgr.Web.Control.Models.Instance; using Sarand.Net.Standard.Base.App; @@ -7,6 +8,7 @@ using Sarand.Net.Standard.Base.Bus; using Sarand.Net.Standard.Base.Core; using Sarand.Net.Standard.Base.Dbas; using Sarand.Net.Standard.Base.Utils; +using Sarand.Net.Standard.Dbas.Base; using System; using System.Collections.Generic; using static Sarand.BusinessMgr.Net.Standard.Base.App.Sbm.Config.Security; @@ -168,7 +170,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance { // Identify item. - SysId repositoryId = model.Repository.Id.ToSysId(); + SysId repositoryId = SysId.ToSysId(model.Repository.Id); if (!SysId.IsValid(repositoryId)) return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); @@ -197,6 +199,82 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance return Json(responseData); } + //------------------------------------------------------------------- + // Get Repository ajax request. + //------------------------------------------------------------------- + private class AjaxResponse_RepositoryInfo : AjaxResponse_Data + { + // Construction. + public AjaxResponse_RepositoryInfo(SbmModel_Control model) : base(model) { } + // Repository details. + public class RepositoryInfoData : AjaxResponse_Data.ItemData_Base + { + public byte? Initialised { get; set; } + /// Tooltip text if database uninitialised. + public String Uninitialised { get; set; } + /// Tooltip text if database unavailable. + public String Unavailable { get; set; } + } + public RepositoryInfoData repository { get; } = new RepositoryInfoData(); + } + //------------------------------------------------------------------- + [HttpPost] + [Route("Instance/Repository/Ajax/GetItemInfo")] + [Route("Instance/Repository/Ajax/GetRepositoryInfo")] + [Route("Instance/Repository/Ajax/GetRepoInfo")] + public IActionResult Ajax_GetRepositoryInfo(Model_Repository model) + { + String messageTitle = Localiser["label.repository"]; + AjaxResponse_RepositoryInfo responseData = new AjaxResponse_RepositoryInfo(model); + + // Validate session and referrer. + if (!ValidReferer) return Forbid(); + if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + RefreshModel(model); + + // Record disposable items as they are created so all can be disposed when needed. + using (DisposableCollection disposables = new DisposableCollection()) + { + + // Identify item. + SysId repositoryId = SysId.ToSysId(model.Repository.Id); + if (!SysId.IsValid(repositoryId)) + return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); + + // Retrieve item. + SbmcRepository repository = ControlInstanceMgr.GetRepositoryById(repositoryId); + disposables.Add(repository); + if (repository == null) + { + SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve repository for Id: '" + repositoryId + "'"); + return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"])); + } + responseData.repository.Id = SysId.ToString(repository.Id); + + // Repository console. + SbmCoreInstanceConsole_Control instanceConsole = new SbmCoreInstanceConsole_Control(repository); + if (!instanceConsole.HasErrorState()) + { + // Validate database. + if (instanceConsole.IsRepositoryValid()) + { + // Check whether repository is initialised. + if (instanceConsole.IsRepositoryInitialised()) + { + responseData.repository.Initialised = 1; + } + else responseData.repository.Uninitialised = instanceConsole.ErrorStateMessage; + } + else responseData.repository.Unavailable = instanceConsole.ErrorStateMessage; + } + else responseData.repository.Unavailable = instanceConsole.ErrorStateMessage; + + // Complete response. + responseData.Success = true; + } + return Json(responseData); + } + //------------------------------------------------------------------- // Store Repository ajax request. //------------------------------------------------------------------- @@ -214,7 +292,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance RefreshModel(model); // Validate item Id. - SysId repositoryId = model.Repository.Id.ToSysId(); + SysId repositoryId = SysId.ToSysId(model.Repository.Id); if (StringUtil.ToBool(model.Repository.Exists) && !SysId.IsValid(repositoryId)) { SaLogger.Warn($"{SysUtil.Fn} Repository Id not supplied for existing item."); @@ -245,7 +323,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance } // Owner. - SysId ownerId = repository?.OwnerId ?? StringUtil.ToSysId(model.Repository.OwnerId); + SysId ownerId = repository?.OwnerId ?? SysId.ToSysId(model.Repository.OwnerId); SbmcOwner owner = ControlInstanceMgr.GetOwnerById(ownerId); disposables.Add(owner); if (owner == null) diff --git a/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/RepositoryInitController-Ajax.cs b/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/RepositoryInitController-Ajax.cs new file mode 100644 index 0000000..f6e0f94 --- /dev/null +++ b/SaBusinessMgrCoreWebControl/Control/Controllers/Instance/RepositoryInitController-Ajax.cs @@ -0,0 +1,279 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Sarand.BusinessMgr.Net.Core.Web.App; +using Sarand.BusinessMgr.Net.Core.Web.Consoles; +using Sarand.BusinessMgr.Net.Standard.Base.App; +using Sarand.BusinessMgr.Net.Standard.Base.Bus; +using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control; +using Sarand.BusinessMgr.Net.Standard.Base.Consoles; +using Sarand.BusinessMgr.Web.Control.Consoles; +using Sarand.BusinessMgr.Web.Control.Models; +using Sarand.BusinessMgr.Web.Control.Models.Instance; +using Sarand.Net.Standard.Base.App; +using Sarand.Net.Standard.Base.Bus; +using Sarand.Net.Standard.Base.Core; +using Sarand.Net.Standard.Base.Dbas; +using Sarand.Net.Standard.Base.Security; +using Sarand.Net.Standard.Base.Utils; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance +{ + //======================================================================= + public partial class RepositoryInitController : SbmController_Control + { + //------------------------------------------------------------------- + // Definitions. + + // Repository data. + /// + /// Repository initialisation data. + /// - May have multiple (internal) Organisations. + /// - Each Organisation may have multiple 'Superuser' users. + /// + public class RepositoryData + { + // Repository data. + public String Id { get; set; } + public String OwnerId { get; set; } + public String OwnerName { get; set; } + public String Context { get; set; } + // Organisations. + public List Organisations { get; } = new List(); + } + public class RepositoryOrganisationData + { + // Organisation data. + public String AffiliateId { get; set; } + public String AssociationId { get; set; } + public String Name { get; set; } + public String Website { get; set; } + public String CompanyNo { get; set; } + public String VatReg { get; set; } + // Registered users. + public List Users { get; } = new List(); + } + public class RepositoryUserData + { + public String AffiliateId { get; set; } + public String SecurityItemId { get; set; } + public String FirstName { get; set; } + public String LastName { get; set; } + public String Email { get; set; } + public String Code { get; set; } + public String Password { get; set; } + } + + //------------------------------------------------------------------- + // Construction. + public RepositoryInitController(SbmLocaliser localiser, ILogger logger) : + base(localiser, logger) + { + } + + //------------------------------------------------------------------- + // Get Repository Initialisation Info ajax request. + //------------------------------------------------------------------- + private class AjaxResponse_RepositoryInitInfo : AjaxResponse_Data + { + // Construction. + public AjaxResponse_RepositoryInitInfo(SbmModel_Control model) : base(model) { } + // Repository initialisation info. + public RepositoryData Repository { get; } = new RepositoryData(); + } + //------------------------------------------------------------------- + [HttpPost] + [Route("Instance/Repository/Ajax/GetInitInfo")] + public IActionResult Ajax_GetRepositoryInitInfo(Model_RepositoryInit model) + { + String messageTitle = Localiser["label.repository"]; + AjaxResponse_RepositoryInitInfo responseData = new AjaxResponse_RepositoryInitInfo(model); + + // Validate session and referrer. + if (!ValidReferer) return Forbid(); + if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + RefreshModel(model); + + // Record disposable items as they are created so all can be disposed when needed. + using (DisposableCollection disposables = new DisposableCollection()) + { + + // Validate Repository. + SysId repositoryId = SysId.ToSysId(model.Repository.Id); + if (!SysId.IsValid(repositoryId)) + { + SaLogger.Warn($"{SysUtil.Fn} Repository Id not supplied."); + return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); + } + SbmcRepository repository = ControlInstanceMgr.GetRepositoryById(repositoryId); + disposables.Add(repository); + if (repository == null) + { + SaLogger.Warn($"{SysUtil.Fn} Repository does not exist. Id: {repositoryId}."); + return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); + } + responseData.Repository.Id = $"{SysId.ToLong(repository.Id)}"; + responseData.Repository.Context = repository.Context; + + // Owner. + SbmcOwner owner = ControlInstanceMgr.GetOwnerById(repository.OwnerId); + disposables.Add(owner); + if (owner == null) + { + SaLogger.Warn($"{SysUtil.Fn} Owner does not exist. Id: {repository.OwnerId}."); + return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); + } + responseData.Repository.OwnerId = $"{SysId.ToLong(owner.Id)}"; + responseData.Repository.OwnerName = owner.Name; + + // Repository Console. + SbmCoreInstanceConsole_Control instanceConsole = new SbmCoreInstanceConsole_Control(repository); + disposables.Add(instanceConsole); + + // Core internals. + SbmInternals internals = instanceConsole.CreateCoreInternals(); + disposables.Add(internals); + + // Core security console. + SaSecurityConsole securityConsole = App.CreateSecurityConsole(internals.UserContext); + disposables.Add(securityConsole); + + // Query Organisations. + SbmAssociation.Params prm = new SbmAssociation.Params(); + prm.AssociationType = Sbm.AssociationType.Internal; + prm.StatusCat = SbmAssociation.StatusCat.Current; + foreach (SbmAssociation association in internals.AccountMgr.GetAssociationList(prm)) + { + // Retrieve Organisation details. + disposables.Add(association); + SbmAffiliate affiliateOrganisation = internals.AccountMgr.GetAffiliateById(association.AffiliateIdOwner); + disposables.Add(affiliateOrganisation); + + // Organisation details. + RepositoryOrganisationData organisation = new RepositoryOrganisationData() + { + AssociationId = SysId.ToString(association.Id), + AffiliateId = SysId.ToString(affiliateOrganisation.Id), + Name = affiliateOrganisation.Name, + Website = affiliateOrganisation.Website, + CompanyNo = affiliateOrganisation.CompanyNo, + VatReg = affiliateOrganisation.VatReg, + }; + + // Retrieve user details. + SbmAffiliate.Params prmAffiliateUser = new SbmAffiliate.Params(); + prmAffiliateUser.AffiliateIdAssocOwner = affiliateOrganisation.Id; + prmAffiliateUser.AssociationType = Sbm.AssociationType.Member; + prmAffiliateUser.StatusCat = SbmAffiliate.StatusCat.CurrentOnly; + foreach (SbmAffiliate affiliateUser in internals.AccountMgr.GetAffiliateList(prmAffiliateUser)) + { + disposables.Add(affiliateUser); + + // Lookup security details. + if (!SysId.IsValid(affiliateUser.UserId)) continue; + SaSecurityItem securityUser = securityConsole.GetSecurityItemById(SaSecurity.ItemType.User, affiliateUser.UserId); + disposables.Add(securityUser); + if (securityUser == null) continue; + + // Confirm security rights (SuperUser). + SaSecurityProfile securityProfile = securityConsole.GetUserSecurityProfile(securityUser.Id); + if (!securityProfile.Rights.Any(right => right.Code.EqualsCI(SaSecurityConsole.GroupCode_Super))) continue; + + // Add User to the Organisation. + RepositoryUserData userData = new RepositoryUserData() + { + FirstName = affiliateUser.FirstName, + LastName = affiliateUser.LastName, + Email = StringUtil.OnBlank(securityUser.EmailAddress, affiliateUser.Email), + Code = securityUser.Code, + }; + organisation.Users.Add(userData); + } + + // Add this Organisation to the list. + responseData.Repository.Organisations.Add(organisation); + } + + // Complete response. + responseData.Success = true; + } + return Json(responseData); + } + + //------------------------------------------------------------------- + // Initialise Repository ajax request. + //------------------------------------------------------------------- + private class AjaxResponse_RepositoryInitialise : AjaxResponse_Data + { + // Construction. + public AjaxResponse_RepositoryInitialise(SbmModel_Control model) : base(model) { } + } + [HttpPost] + [Route("Instance/Repository/Ajax/Initialise")] + public IActionResult Ajax_StoreRepository(Model_RepositoryInit model) + { + String messageTitle = Localiser["label.repository"]; + AjaxResponse_RepositoryInitialise responseData = new AjaxResponse_RepositoryInitialise(model); + + // Validate session and referrer. + if (!ValidReferer) return Forbid(); + if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + RefreshModel(model); + + // Record disposable items as they are created so all can be disposed when needed. + using (DisposableCollection disposables = new DisposableCollection()) + { + + // Validate Repository. + SysId repositoryId = SysId.ToSysId(model.Repository.Id); + if (!SysId.IsValid(repositoryId)) + { + SaLogger.Warn($"{SysUtil.Fn} Repository Id not supplied."); + return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); + } + SbmcRepository repository = ControlInstanceMgr.GetRepositoryById(repositoryId); + disposables.Add(repository); + if (repository == null) + { + SaLogger.Warn($"{SysUtil.Fn} Repository does not exist. Id: {repositoryId}."); + return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); + } + + // Validate item properties. + model.ValidateRepositoryData(responseData, repository); + if (responseData.HasControlErrors()) + return Json(responseData); + + // Repository Console. + SbmCoreInstanceConsole_Control repositoryConsole = new SbmCoreInstanceConsole_Control(repository); + disposables.Add(repositoryConsole); + + SbmCoreInstanceConsole_Base.RepositoryInitialisationData repoInitData = new SbmCoreInstanceConsole_Base.RepositoryInitialisationData(); + repoInitData.Organisation.AffiliateId = SysId.ToSysId(model.Organisation.AffiliateId); + repoInitData.Organisation.AssociationId = SysId.ToSysId(model.Organisation.AssociationId); + repoInitData.Organisation.Name = model.Organisation.Name; + repoInitData.Organisation.VatReg = model.Organisation.VatReg; + repoInitData.Organisation.CompanyNo = model.Organisation.CompanyNo; + repoInitData.Organisation.Website = model.Organisation.Website; + repoInitData.User.AffiliateId = SysId.ToSysId(model.User.AffiliateId); + repoInitData.User.FirstName = model.User.FirstName; + repoInitData.User.LastName = model.User.LastName; + repoInitData.User.Email = model.User.Email; + repoInitData.User.SecurityItemId = SysId.ToSysId(model.User.SecurityItemId); + repoInitData.User.Code = model.User.Code; + repoInitData.User.Password = model.User.Password; + if (!repositoryConsole.InitialiseRepository(repoInitData)) + return Json(responseData.SetMessage(messageTitle, repositoryConsole.ErrorStateMessage)); + + // Complete response. + responseData.Success = true; + } + return Json(responseData); + } + + //------------------------------------------------------------------- + } + //======================================================================= +} diff --git a/SaBusinessMgrCoreWebControl/Control/Controllers/Param/ParamController-Ajax.cs b/SaBusinessMgrCoreWebControl/Control/Controllers/Param/ParamController-Ajax.cs index f864a63..d492663 100644 --- a/SaBusinessMgrCoreWebControl/Control/Controllers/Param/ParamController-Ajax.cs +++ b/SaBusinessMgrCoreWebControl/Control/Controllers/Param/ParamController-Ajax.cs @@ -200,7 +200,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Param // Item filter. SbmcItemParam.Params prmParam = new SbmcItemParam.Params(); - ItemId itemId = new ItemId(StringUtil.ToShort(model.Filter.ItemType), StringUtil.ToSysId(model.Filter.ItemId)); + ItemId itemId = new ItemId(StringUtil.ToShort(model.Filter.ItemType), SysId.ToSysId(model.Filter.ItemId)); if (ItemId.IsValid(itemId)) prmParam.ItemIdsIncluded.Add(itemId); prmParam.Search = model.Filter.Search; @@ -284,7 +284,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Param { // Identify item. - SysId itemParamId = model.Param.Id.ToSysId(); + SysId itemParamId = SysId.ToSysId(model.Param.Id); if (!SysId.IsValid(itemParamId)) return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); @@ -321,7 +321,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Param RefreshModel(model); // Validate item Id. - SysId itemParamId = model.Param.Id.ToSysId(); + SysId itemParamId = SysId.ToSysId(model.Param.Id); if (StringUtil.ToBool(model.Param.Exists) && !SysId.IsValid(itemParamId)) { SaLogger.Warn($"{SysUtil.Fn} Id not supplied for existing Item Param."); @@ -352,7 +352,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Param } // Contruct item id. - ItemId itemId = new ItemId(StringUtil.ToShort(model.Param.ItemType), model.Param.ItemId.ToSysId()); + ItemId itemId = new ItemId(StringUtil.ToShort(model.Param.ItemType), SysId.ToSysId(model.Param.ItemId)); if (itemParam != null && !itemParam.ItemId.Equals(itemId)) { diff --git a/SaBusinessMgrCoreWebControl/Control/Models/Account/Model_UserAccount.cs b/SaBusinessMgrCoreWebControl/Control/Models/Account/Model_UserAccount.cs index b85e3b9..191b41f 100644 --- a/SaBusinessMgrCoreWebControl/Control/Models/Account/Model_UserAccount.cs +++ b/SaBusinessMgrCoreWebControl/Control/Models/Account/Model_UserAccount.cs @@ -86,7 +86,7 @@ namespace Sarand.BusinessMgr.Web.Control.Models.Account { // Check for duplicate email address. SbmcUserAccount.Params prmUserAccount = new SbmcUserAccount.Params(); - SysId userAccountId = User.Id.ToSysId(); + SysId userAccountId = SysId.ToSysId(User.Id); if (SysId.IsValid(userAccountId)) prmUserAccount.IdsExcluded.Add(userAccountId); prmUserAccount.EmailAddress = User.EmailAddress; diff --git a/SaBusinessMgrCoreWebControl/Control/Models/Instance/Model_CoreDatabase.cs b/SaBusinessMgrCoreWebControl/Control/Models/Instance/Model_CoreDatabase.cs new file mode 100644 index 0000000..acc01fe --- /dev/null +++ b/SaBusinessMgrCoreWebControl/Control/Models/Instance/Model_CoreDatabase.cs @@ -0,0 +1,28 @@ +using Sarand.BusinessMgr.Net.Core.Web.App; +using System; + +namespace Sarand.BusinessMgr.Web.Control.Models.Instance +{ + //======================================================================= + public class Model_CoreDatabase : SbmModel_Control + { + //------------------------------------------------------------------- + // Construction. + public Model_CoreDatabase(SbmLocaliser localiser) : + base(localiser) + { + } + + //------------------------------------------------------------------- + // Filter properties. + public class FilterData + { + public String Context { get; set; } + public String Search { get; set; } + } + public FilterData Filter { get; } = new FilterData(); + + //------------------------------------------------------------------- + } + //======================================================================= +} diff --git a/SaBusinessMgrCoreWebControl/Control/Models/Instance/Model_Repository.cs b/SaBusinessMgrCoreWebControl/Control/Models/Instance/Model_Repository.cs index 38052a1..68b8033 100644 --- a/SaBusinessMgrCoreWebControl/Control/Models/Instance/Model_Repository.cs +++ b/SaBusinessMgrCoreWebControl/Control/Models/Instance/Model_Repository.cs @@ -68,7 +68,7 @@ namespace Sarand.BusinessMgr.Web.Control.Models.Instance if (Repository.OwnerId != null) { String controlName = "RepositoryOwner"; - SysId ownerId = Repository.OwnerId.ToSysId(); + SysId ownerId = SysId.ToSysId(Repository.OwnerId); if (!SysId.IsValid(ownerId)) responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]); else @@ -93,7 +93,7 @@ namespace Sarand.BusinessMgr.Web.Control.Models.Instance { // Check for duplicate context. SbmcRepository.Params prmRepository = new SbmcRepository.Params(); - SysId repositoryId = Repository.Id.ToSysId(); + SysId repositoryId = SysId.ToSysId(Repository.Id); if (SysId.IsValid(repositoryId)) prmRepository.IdsExcluded.Add(repositoryId); prmRepository.ContextsIncluded.Add(Repository.Context); diff --git a/SaBusinessMgrCoreWebControl/Control/Models/Instance/Model_RepositoryInit.cs b/SaBusinessMgrCoreWebControl/Control/Models/Instance/Model_RepositoryInit.cs new file mode 100644 index 0000000..1d77d7f --- /dev/null +++ b/SaBusinessMgrCoreWebControl/Control/Models/Instance/Model_RepositoryInit.cs @@ -0,0 +1,254 @@ +using DocumentFormat.OpenXml.Spreadsheet; +using NPOI.OpenXml4Net.Exceptions; +using Sarand.BusinessMgr.Net.Core.Web.App; +using Sarand.BusinessMgr.Net.Core.Web.Controllers; +using Sarand.BusinessMgr.Net.Standard.Base.App; +using Sarand.BusinessMgr.Net.Standard.Base.Bus; +using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control; +using Sarand.BusinessMgr.Web.Control.Consoles; +using Sarand.Net.Standard.Base.App; +using Sarand.Net.Standard.Base.Bus; +using Sarand.Net.Standard.Base.Core; +using Sarand.Net.Standard.Base.Helpers; +using Sarand.Net.Standard.Base.Security; +using Sarand.Net.Standard.Base.Utils; +using System; + +namespace Sarand.BusinessMgr.Web.Control.Models.Instance +{ + //======================================================================= + public class Model_RepositoryInit : SbmModel_Control + { + //------------------------------------------------------------------- + // Definitions. + + public enum Control + { + RepositoryOwnerName, + RepositoryContext, + OrganisationName, + OrganisationWebsite, + OrganisationCompanyNo, + OrganisationVatReg, + UserFirstName, + UserLastName, + UserEmail, + UserCode, + UserPassword, + } + + //------------------------------------------------------------------- + // Construction. + public Model_RepositoryInit(SbmLocaliser localiser) : + base(localiser) + { + } + + //------------------------------------------------------------------- + // Item properties. + + // Repository. + public class RepositoryData + { + public String Id { get; set; } + } + public RepositoryData Repository { get; } = new RepositoryData(); + public SysId GetRepositoryId() + { + return SysId.ToSysId(Repository.Id); + } + + // Organisation. + public class OrganisationData + { + public String AffiliateId { get; set; } + public String AssociationId { get; set; } + public String Name { get; set; } + public String Website { get; set; } + public String CompanyNo { get; set; } + public String VatReg { get; set; } + } + public OrganisationData Organisation { get; } = new OrganisationData(); + public SysId GetOrganisationAffiliateId() + { + return SysId.ToSysId(Organisation.AffiliateId); + } + public SysId GetOrganisationAssociationId() + { + return SysId.ToSysId(Organisation.AssociationId); + } + + // User. + public class UserData + { + public String AffiliateId { get; set; } + public String SecurityItemId { get; set; } + public String FirstName { get; set; } + public String LastName { get; set; } + public String Email { get; set; } + public String Code { get; set; } + public String Password { get; set; } + } + public UserData User { get; } = new UserData(); + public SysId GetUserAffiliateId() + { + return SysId.ToSysId(User.AffiliateId); + } + public SysId GetUserSecurityItemId() + { + return SysId.ToSysId(User.SecurityItemId); + } + + //------------------------------------------------------------------- + // Configuration. + //------------------------------------------------------------------- + public static String GetControlName(Control control) + { + return $"{control}"; + } + + //------------------------------------------------------------------- + // Validation. + //------------------------------------------------------------------- + // Repository. + public bool ValidateRepositoryData(SbmController_Base.AjaxResponse_Data responseData, SbmcRepository repository) + { + // Record disposable items as they are created so all can be disposed when needed. + using (DisposableCollection disposables = new DisposableCollection()) + { + + //----------------------------------------------------------- + // Repository Console. + SbmCoreInstanceConsole_Control instanceConsole = new SbmCoreInstanceConsole_Control(repository); + disposables.Add(instanceConsole); + + // Core internals. + SbmInternals internals = instanceConsole.CreateCoreInternals(); + disposables.Add(internals); + + // Core security console. + SaSecurityConsole securityConsole = ControlApp.CreateSecurityConsole(internals.UserContext); + disposables.Add(securityConsole); + + //----------------------------------------------------------- + // Organisation Name. + if (Organisation.Name != null) + { + String controlName = GetControlName(Control.OrganisationName); + responseData.SetControlValue(controlName, Organisation.Name); + if (StringUtil.IsBlank(Organisation.Name)) + responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]); + else if (StringUtil.GetLength(Organisation.Name) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name)]); + else + { + // Check that organisation name is not already in use. + if (internals.AccountMgr.OrganisationExistsByName(Organisation.Name, GetOrganisationAffiliateId())) + responseData.SetControlError(controlName, Localiser["msg.validation.duplicate.value"]); + } + } + + // Organisation Website. + if (Organisation.Website != null) + { + String controlName = GetControlName(Control.OrganisationWebsite); + responseData.SetControlValue(controlName, Organisation.Website); + if (StringUtil.GetLength(Organisation.Website) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Website)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Website)]); + } + + // Organisation CompanyNo. + if (Organisation.CompanyNo != null) + { + String controlName = GetControlName(Control.OrganisationCompanyNo); + responseData.SetControlValue(controlName, Organisation.CompanyNo); + if (StringUtil.GetLength(Organisation.CompanyNo) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_CompanyNo)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_CompanyNo)]); + } + + // Organisation VatReg. + if (Organisation.VatReg != null) + { + String controlName = GetControlName(Control.OrganisationVatReg); + responseData.SetControlValue(controlName, Organisation.VatReg); + if (StringUtil.GetLength(Organisation.VatReg) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_VatReg)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_VatReg)]); + } + + //----------------------------------------------------------- + // User FirstName. + if (User.FirstName != null) + { + String controlName = GetControlName(Control.UserFirstName); + responseData.SetControlValue(controlName, User.FirstName); + if (StringUtil.IsBlank(User.FirstName)) + responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]); + else if (StringUtil.GetLength(User.FirstName) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_FirstName)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_FirstName)]); + } + + // User LastName. + if (User.LastName != null) + { + String controlName = GetControlName(Control.UserLastName); + responseData.SetControlValue(controlName, User.LastName); + if (StringUtil.IsBlank(User.LastName)) + responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]); + else if (StringUtil.GetLength(User.LastName) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_LastName)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_LastName)]); + } + + // User Email. + if (User.Email != null) + { + String controlName = GetControlName(Control.UserEmail); + responseData.SetControlValue(controlName, User.Email); + if (StringUtil.IsBlank(User.Email)) + responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]); + else if (StringUtil.GetLength(User.Email) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Email)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Email)]); + } + + // User Code. + if (User.Code != null) + { + String controlName = GetControlName(Control.UserCode); + responseData.SetControlValue(controlName, User.Code); + if (StringUtil.IsBlank(User.Code)) + responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]); + else if (StringUtil.GetLength(User.Code) > GetControlMaxLength(SaSecurityDbDfn.ColumnIdx.SaSecItem_Code)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SaSecurityDbDfn.ColumnIdx.SaSecItem_Code)]); + else + { + // Ensure that user name is not already in use. + SysId securityItemId = securityConsole.GetIdForItemCode(SaSecurity.ItemType.User, User.Code); + if (SysId.IsValid(securityItemId) && !securityItemId.Equals(GetUserSecurityItemId())) + { + + } + } + } + + // User Password. + if (User.Password != null) + { + String controlName = GetControlName(Control.UserPassword); + responseData.SetControlValue(controlName, User.Password); + if (StringUtil.IsBlank(User.Password)) + responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]); + else if (StringUtil.GetLength(User.Password) < Sbm.Config.Security.Password.MinLength) + responseData.SetControlError(controlName, Localiser["msg.validation.minimum.length", Sbm.Config.Security.Password.MinLength]); + else if (StringUtil.GetLength(User.Password) > Sbm.Config.Security.Password.MaxLength) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", Sbm.Config.Security.Password.MaxLength]); + } + + //----------------------------------------------------------- + } + + return !responseData.HasControlErrors(); + } + + //------------------------------------------------------------------- + } + //======================================================================= +} diff --git a/SaBusinessMgrCoreWebControl/Control/Models/Param/Model_Param.cs b/SaBusinessMgrCoreWebControl/Control/Models/Param/Model_Param.cs index 34fdd87..2ed032f 100644 --- a/SaBusinessMgrCoreWebControl/Control/Models/Param/Model_Param.cs +++ b/SaBusinessMgrCoreWebControl/Control/Models/Param/Model_Param.cs @@ -80,13 +80,13 @@ namespace Sarand.BusinessMgr.Web.Control.Models.Param using (DisposableCollection disposables = new DisposableCollection()) { // Check whether data suggests that Param exists. - bool paramExists = StringUtil.ToBool(Param.Exists) && SysId.IsValid(Param.Id.ToSysId()); + bool paramExists = StringUtil.ToBool(Param.Exists) && SysId.IsValid(SysId.ToSysId(Param.Id)); // Item. if (Param.ItemType != null || Param.ItemId != null) { string controlName = "ParamItem"; - ItemId itemId = new ItemId(StringUtil.ToShort(Param.ItemType), Param.ItemId.ToSysId()); + ItemId itemId = new ItemId(StringUtil.ToShort(Param.ItemType), SysId.ToSysId(Param.ItemId)); if (!paramExists && (Param.ItemType.IsBlank() || Param.ItemId.IsBlank())) responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]); else if (StringUtil.IsBlank(ControlItemMgr.GetItemCaption(itemId))) diff --git a/SaBusinessMgrCoreWebControl/Control/Models/SbmModel_Control.cs b/SaBusinessMgrCoreWebControl/Control/Models/SbmModel_Control.cs index 9de5cb3..041ef1b 100644 --- a/SaBusinessMgrCoreWebControl/Control/Models/SbmModel_Control.cs +++ b/SaBusinessMgrCoreWebControl/Control/Models/SbmModel_Control.cs @@ -1,9 +1,13 @@ -using Sarand.BusinessMgr.Net.Core.Web.App; +using Microsoft.AspNetCore.Mvc.Rendering; +using Sarand.BusinessMgr.Net.Core.Web.App; using Sarand.BusinessMgr.Net.Core.Web.Models; using Sarand.BusinessMgr.Net.Standard.Base.App; +using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control; using Sarand.BusinessMgr.Net.Standard.Base.Core; using Sarand.BusinessMgr.Web.Control.App; +using Sarand.Net.Standard.Base.Core; using System; +using System.Collections.Generic; namespace Sarand.BusinessMgr.Web.Control.Models { @@ -19,9 +23,21 @@ namespace Sarand.BusinessMgr.Web.Control.Models //------------------------------------------------------------------- // Properties. + protected SbmApplication_Control ControlApp { get { return SbmApplication_Control.Instance; } } public SbmSessionData_Control SessionData_Control { get { return SessionData as SbmSessionData_Control; } } public override ISbmUserContext_Core UserContext_Core { get { return new SbmUserContext_Control(SessionData_Control); } } + //------------------------------------------------------------------- + public IEnumerable GetInstanceContextsForSelect() + { + List items = new List(); + SbmcRepository.Params prmRepository = new SbmcRepository.Params(); + prmRepository.StatusCat = SbmcRepository.StatusCat.NotDeleted; + foreach (SbmcRepository repository in ControlInstanceMgr.GetRepositoryList(prmRepository)) + items.Add(new SelectListItem(repository.Context, repository.Context)); + return items; + } + //------------------------------------------------------------------- /// /// Form control value max length - BusinessMgr tables. diff --git a/SaBusinessMgrCoreWebControl/Localisation/SbmControlProperties.resx b/SaBusinessMgrCoreWebControl/Localisation/SbmControlProperties.resx index e7484df..62bc10a 100644 --- a/SaBusinessMgrCoreWebControl/Localisation/SbmControlProperties.resx +++ b/SaBusinessMgrCoreWebControl/Localisation/SbmControlProperties.resx @@ -405,4 +405,52 @@ Item must be selected. + + Initialised + + + Value must be at least {0} characters + + + Login code + + + Initialise + + + Organisation + + + Website + + + Company No + + + VAT reg. + + + Initialise Instance + + + Core database + + + Core Database + + + Schema + + + Table + + + Columns + + + Indices + + + Rows + \ No newline at end of file diff --git a/SaBusinessMgrCoreWebControl/SaBusinessMgrCoreWebControl.csproj b/SaBusinessMgrCoreWebControl/SaBusinessMgrCoreWebControl.csproj index 089c100..fa025ad 100644 --- a/SaBusinessMgrCoreWebControl/SaBusinessMgrCoreWebControl.csproj +++ b/SaBusinessMgrCoreWebControl/SaBusinessMgrCoreWebControl.csproj @@ -8,9 +8,9 @@ - - - + + + @@ -55,6 +55,10 @@ true PreserveNewest + + true + PreserveNewest + diff --git a/SaBusinessMgrCoreWebControl/Views/Instance/CoreDatabase/Index.cshtml b/SaBusinessMgrCoreWebControl/Views/Instance/CoreDatabase/Index.cshtml new file mode 100644 index 0000000..f1599e6 --- /dev/null +++ b/SaBusinessMgrCoreWebControl/Views/Instance/CoreDatabase/Index.cshtml @@ -0,0 +1,110 @@ +@* Instance - Core Database*@ +@model Model_CoreDatabase +@inject SbmLocaliser Localiser +@{ + ViewData["Title"] = "Instance - Core Database"; + Model.AdditionalFiles_JS.Add("js/sbc-ins-coredb.js"); +} + +
+ + + +
+ + @* Filter form - wrap header to include paging controls. *@ + @using (@Html.BeginForm(FormMethod.Post, new { @id = "frmTableFilter", @class = "sbc-form", @onSubmit = "return false;" })) + { + +
+
+
+ @* *@ +
+
@Localiser["caption.database.core"]
+
+ @* Burger menu *@ + +
+
+
+ + @* Filter Panel *@ +
+
+
+
@Localiser["label.context"]
+
+ @Html.DropDownListFor(model => model.Filter.Context, Model.GetInstanceContextsForSelect(), "", new { @id = "", @class = "FilterContext" }) +
+
+
+
@Localiser["label.search"]
+
+ @Html.TextBoxFor(model => model.Filter.Search, new { @id = "", @class = "FilterSearch", @maxlength = "32" }) +
+
+
+
+ + } + +
+ + + + + + + + + + + + + +
@Localiser["label.schema"]@Localiser["label.table"]@Localiser["label.columns"]@Localiser["label.indices"]@Localiser["label.rows"]
+
+ + @* Element templates *@ +
+ @* Filter Burger option template - ul is ignored *@ +
    +
  • XXX
  • +
+ @* Table row template - table is ignored. *@ + + + + + + + + + +
+
+ @* Burger menu *@ + +
+
+ @* Item Burger option template - ul is ignored *@ +
    +
  • XXX
  • +
+
+ +
+ +
diff --git a/SaBusinessMgrCoreWebControl/Views/Instance/Owner/Index.cshtml b/SaBusinessMgrCoreWebControl/Views/Instance/Owner/Index.cshtml index b0de754..4133342 100644 --- a/SaBusinessMgrCoreWebControl/Views/Instance/Owner/Index.cshtml +++ b/SaBusinessMgrCoreWebControl/Views/Instance/Owner/Index.cshtml @@ -2,7 +2,7 @@ @model Model_Owner @inject SbmLocaliser Localiser @{ - ViewData["Title"] = "Owner Accounts"; + ViewData["Title"] = "Instance - Owner"; Model.AdditionalFiles_JS.Add("js/sbc-res-pag.js"); Model.AdditionalFiles_JS.Add("js/sbc-ins-own.js"); } diff --git a/SaBusinessMgrCoreWebControl/Views/Instance/Repository/Index.cshtml b/SaBusinessMgrCoreWebControl/Views/Instance/Repository/Index.cshtml index 3710d99..b700538 100644 --- a/SaBusinessMgrCoreWebControl/Views/Instance/Repository/Index.cshtml +++ b/SaBusinessMgrCoreWebControl/Views/Instance/Repository/Index.cshtml @@ -2,7 +2,7 @@ @model Model_Repository @inject SbmLocaliser Localiser @{ - ViewData["Title"] = "Repository Accounts"; + ViewData["Title"] = "Instance - Repository"; Model.AdditionalFiles_JS.Add("js/sbc-res-pag.js"); Model.AdditionalFiles_JS.Add("js/sbc-ins-rep.js"); } @@ -60,6 +60,7 @@ @Localiser["label.server"] @Localiser["label.instance"] @Localiser["label.database"] + @Localiser["label.initialised"] @Localiser["label.status"] @@ -83,6 +84,7 @@
+
@@ -266,7 +268,10 @@
- @* Select Item dialog and script *@ - - + +@* Repository Initialisation view. *@ + + +@* Select Item view. *@ + diff --git a/SaBusinessMgrCoreWebControl/Views/Instance/Repository/Initialise.cshtml b/SaBusinessMgrCoreWebControl/Views/Instance/Repository/Initialise.cshtml new file mode 100644 index 0000000..695de0d --- /dev/null +++ b/SaBusinessMgrCoreWebControl/Views/Instance/Repository/Initialise.cshtml @@ -0,0 +1,223 @@ +@* Instance - Repository - Initialise *@ +@model SbmModel_Control +@inject SbmLocaliser Localiser +@{ + Model.AdditionalFiles_JS.Add("js/sbc-ins-rep-init.js"); +} + +
+ + @using (@Html.BeginForm(FormMethod.Post, new { @id = "", @class = "RepositoryIdForm", @onSubmit = "return false;" })) + { + @Html.Hidden("Repository.Id", "", new { @id = "", @class = "RepositoryId" }) + } +
+ + @using (@Html.BeginForm(FormMethod.Post, new { @id = "", @class = "RepositoryInitForm sbc-form", @onSubmit = "return false;" })) + { + @Html.Hidden("Repository.Id", "", new { @id = "", @class = "RepositoryId sbc-input" }) + +
@Localiser["label.instance"]
+ + @* Owner *@ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ + @* Context *@ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ +
+
@Localiser["label.organisation"]
+ @Html.Hidden("Organisation.AffiliateId", "", new { @id = "", @class = "OrganisationAffiliateId sbc-input" }) + @Html.Hidden("Organisation.AssociationId", "", new { @id = "", @class = "OrganisationAssociationId sbc-input" }) + + @* Organisation Name *@ +
+
+
+
+ +
+
+
+
+ @Html.TextBox("Organisation.Name", "", new { @id = "", @class = "OrganisationName sbc-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name) }) +
+
+
+
+
+ + @* Organisation Website *@ +
+
+
+
+ +
+
+
+
+ @Html.TextBox("Organisation.Website", "", new { @id = "", @class = "OrganisationWebsite sbc-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Website) }) +
+
+
+
+
+ + @* Organisation CompanyNo *@ +
+
+
+
+ +
+
+
+
+ @Html.TextBox("Organisation.CompanyNo", "", new { @id = "", @class = "OrganisationCompanyNo sbc-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_CompanyNo) }) +
+
+
+
+
+ + @* Organisation VatReg *@ +
+
+
+
+ +
+
+
+
+ @Html.TextBox("Organisation.VatReg", "", new { @id = "", @class = "OrganisationVatReg sbc-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_VatReg) }) +
+
+
+
+
+ +
+
@Localiser["label.user"]
+ @Html.Hidden("User.AffiliateId", "", new { @id = "", @class = "UserAffiliateId sbc-input" }) + @Html.Hidden("User.AssociationId", "", new { @id = "", @class = "UserSecurityItemId sbc-input" }) + + @* User FirstName *@ +
+
+
+
+ +
+
+
+
+ @Html.TextBox("User.FirstName", "", new { @id = "", @class = "UserFirstName sbc-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_FirstName) }) +
+
+
+
+
+ + @* User LastName *@ +
+
+
+
+ +
+
+
+
+ @Html.TextBox("User.LastName", "", new { @id = "", @class = "UserLastName sbc-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_LastName) }) +
+
+
+
+
+ + @* User Email *@ +
+
+
+
+ +
+
+
+
+ @Html.TextBox("User.Email", "", new { @id = "", @class = "UserEmail sbc-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Email) }) +
+
+
+
+
+ + @* User Code *@ +
+
+
+
+ +
+
+
+
+ @Html.TextBox("User.Code", "", new { @id = "", @class = "UserCode sbc-input", @maxlength = @Model.GetControlMaxLength(Sarand.Net.Standard.Base.Security.SaSecurityDbDfn.ColumnIdx.SaSecItem_Code) }) +
+
+
+
+
+ + @* User Password *@ +
+
+
+
+ +
+
+
+
+ @Html.Password("User.Password", "", new { @id = "", @class = "UserPassword sbc-input", @maxlength = Sbm.Config.Security.Password.MaxLength }) +
+
+
+
+
+ + } +
+
+ +
diff --git a/SaBusinessMgrCoreWebControl/Views/Shared/_Layout.cshtml b/SaBusinessMgrCoreWebControl/Views/Shared/_Layout.cshtml index ab684b6..796055a 100644 --- a/SaBusinessMgrCoreWebControl/Views/Shared/_Layout.cshtml +++ b/SaBusinessMgrCoreWebControl/Views/Shared/_Layout.cshtml @@ -71,6 +71,7 @@ sbc.lbl.refresh = '@(Localiser.GetJavascriptText("label.refresh"))'; sbc.lbl.create = '@(Localiser.GetJavascriptText("label.create"))'; sbc.lbl.edit = '@(Localiser.GetJavascriptText("label.edit"))'; + sbc.lbl.init = '@(Localiser.GetJavascriptText("label.initialise"))'; sbc.lbl.emails = '@(Localiser.GetJavascriptText("label.emails"))'; sbc.lbl.charAvailable = '@Localiser.GetJavascriptText("info.char.available")'; sbc.lbl.charsAvailable = '@Localiser.GetJavascriptText("info.chars.available", "{0}")'; @@ -118,14 +119,8 @@ - + + @* Instances *@
public FilterData Filter { get; private set; } = new FilterData(); - // Contacts filter. - public class ContactsData + // Contact filter. + public class ContactData { public class FilterData { @@ -240,10 +240,10 @@ namespace Sarand.BusinessMgr.Web.Portal.App public FilterData Filter { get; } = new FilterData(); } /// Contacts filter properties. - public ContactsData Contacts { get; } = new ContactsData(); + public ContactData Contact { get; } = new ContactData(); - // Associations filter. - public class AssociationsData + // Association filter. + public class AssociationData { public class FilterData { @@ -253,10 +253,10 @@ namespace Sarand.BusinessMgr.Web.Portal.App public FilterData Filter { get; } = new FilterData(); } /// Associations filter properties. - public AssociationsData Associations { get; } = new AssociationsData(); + public AssociationData Association { get; } = new AssociationData(); - // Commodities filter. - public class CommoditiesData + // Commodity filter. + public class CommodityData { public class FilterData { @@ -266,7 +266,20 @@ namespace Sarand.BusinessMgr.Web.Portal.App public FilterData Filter { get; } = new FilterData(); } /// Commodities filter properties. - public CommoditiesData Commodities { get; } = new CommoditiesData(); + public CommodityData Commodity { get; } = new CommodityData(); + + // Transaction filter. + public class TransactionData + { + public class FilterData + { + public uint PageNo { get; set; } = 1; + public ushort PageLength { get; set; } = 200; + } + public FilterData Filter { get; } = new FilterData(); + } + /// Transaction filter properties. + public TransactionData Transaction { get; } = new TransactionData(); } public UserProfileData Profile { get; protected set; } = new UserProfileData(); diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Assets/AssetCategoryController-Ajax.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Assets/AssetCategoryController-Ajax.cs index e55b7b5..8425625 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Assets/AssetCategoryController-Ajax.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Assets/AssetCategoryController-Ajax.cs @@ -166,7 +166,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets { // Identify item. - SysId assetCategoryId = model.AssetCategory.Id.ToSysId(); + SysId assetCategoryId = SysId.ToSysId(model.AssetCategory.Id); if (!SysId.IsValid(assetCategoryId)) return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); @@ -203,7 +203,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets RefreshModel(model); // Validate item Id. - SysId assetCategoryId = model.AssetCategory.Id.ToSysId(); + SysId assetCategoryId = SysId.ToSysId(model.AssetCategory.Id); if (StringUtil.ToBool(model.AssetCategory.Exists) && !SysId.IsValid(assetCategoryId)) { SaLogger.Warn($"{SysUtil.Fn} AssetCategory Id not supplied for existing item."); diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Assets/AssetController-Ajax.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Assets/AssetController-Ajax.cs index a7c78bc..c6bfb09 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Assets/AssetController-Ajax.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Assets/AssetController-Ajax.cs @@ -172,7 +172,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets { // Identify item. - SysId assetId = model.Asset.Id.ToSysId(); + SysId assetId = SysId.ToSysId(model.Asset.Id); if (!SysId.IsValid(assetId)) return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); @@ -218,7 +218,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets RefreshModel(model); // Validate item Id. - SysId assetId = model.Asset.Id.ToSysId(); + SysId assetId = SysId.ToSysId(model.Asset.Id); if (StringUtil.ToBool(model.Asset.Exists) && !SysId.IsValid(assetId)) { SaLogger.Warn($"{SysUtil.Fn} Asset Id not supplied for existing item."); @@ -262,7 +262,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets } else { - assetCategory = AssetMgr.GetAssetCategoryById(model.Asset.CategoryId.ToSysId()); + assetCategory = AssetMgr.GetAssetCategoryById(SysId.ToSysId(model.Asset.CategoryId)); disposables.Add(assetCategory); if (assetCategory == null) { diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Assets/VehicleClassController-Ajax.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Assets/VehicleClassController-Ajax.cs index 3694ef9..bb3a94a 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Assets/VehicleClassController-Ajax.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Assets/VehicleClassController-Ajax.cs @@ -174,7 +174,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets { // Identify item. - SysId vehicleClassId = model.VehicleClass.Id.ToSysId(); + SysId vehicleClassId = SysId.ToSysId(model.VehicleClass.Id); if (!SysId.IsValid(vehicleClassId)) return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); @@ -211,7 +211,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Assets RefreshModel(model); // Validate item Id. - SysId vehicleClassId = model.VehicleClass.Id.ToSysId(); + SysId vehicleClassId = SysId.ToSysId(model.VehicleClass.Id); if (StringUtil.ToBool(model.VehicleClass.Exists) && !SysId.IsValid(vehicleClassId)) { SaLogger.Warn($"{SysUtil.Fn} VehicleClass Id not supplied for existing item."); diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Codes/CodeController-Ajax.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Codes/CodeController-Ajax.cs index 3319255..6960115 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Codes/CodeController-Ajax.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Codes/CodeController-Ajax.cs @@ -175,7 +175,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes { // Identify item. - SysId codeId = model.Code.Id.ToSysId(); + SysId codeId = SysId.ToSysId(model.Code.Id); if (!SysId.IsValid(codeId)) return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); @@ -221,7 +221,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes RefreshModel(model); // Validate item Id. - SysId codeId = model.Code.Id.ToSysId(); + SysId codeId = SysId.ToSysId(model.Code.Id); if (StringUtil.ToBool(model.Code.Exists) && !SysId.IsValid(codeId)) { SaLogger.Warn($"{SysUtil.Fn} Code Id not supplied for existing item."); @@ -265,7 +265,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes } else { - codeType = CodeTypeConsole.GetCodeTypeById(model.Code.CodeTypeId.ToSysId()); + codeType = CodeTypeConsole.GetCodeTypeById(SysId.ToSysId(model.Code.CodeTypeId)); disposables.Add(codeType); if (codeType == null) { diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Codes/CodeTypeController-Ajax.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Codes/CodeTypeController-Ajax.cs index e84c84f..72cab76 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Codes/CodeTypeController-Ajax.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Codes/CodeTypeController-Ajax.cs @@ -167,7 +167,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes { // Identify item. - SysId codeTypeId = model.CodeType.Id.ToSysId(); + SysId codeTypeId = SysId.ToSysId(model.CodeType.Id); if (!SysId.IsValid(codeTypeId)) return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); @@ -204,7 +204,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Codes RefreshModel(model); // Validate item Id. - SysId codeTypeId = model.CodeType.Id.ToSysId(); + SysId codeTypeId = SysId.ToSysId(model.CodeType.Id); if (StringUtil.ToBool(model.CodeType.Exists) && !SysId.IsValid(codeTypeId)) { SaLogger.Warn($"{SysUtil.Fn} CodeType Id not supplied for existing item."); diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Commodities/CommodityController-Ajax.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Commodities/CommodityController-Ajax.cs index 5c0852a..c1986a5 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Commodities/CommodityController-Ajax.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Commodities/CommodityController-Ajax.cs @@ -268,8 +268,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities // Refresh paging info. if (model.Paging.IsPaged) model.Paging.ItemCount = (ushort)responseData.Commodities.Count; - SessionData_Portal.Profile.Commodities.Filter.PageNo = model.Paging.PageNo; - SessionData_Portal.Profile.Commodities.Filter.PageLength = model.Paging.PageLength; + SessionData_Portal.Profile.Commodity.Filter.PageNo = model.Paging.PageNo; + SessionData_Portal.Profile.Commodity.Filter.PageLength = model.Paging.PageLength; responseData.SetPaging(model); // Complete response. @@ -304,7 +304,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities RefreshModel(model); // Identify item. - SysId commodityId = model.Commodity.Id.ToSysId(); + SysId commodityId = SysId.ToSysId(model.Commodity.Id); if (!SysId.IsValid(commodityId)) return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); @@ -348,7 +348,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities return Json(responseData); // Validate item Id against 'Exists' flag. - SysId commodityId = model.Commodity.Id.ToSysId(); + SysId commodityId = SysId.ToSysId(model.Commodity.Id); bool commodityExists = StringUtil.ToBool(model.Commodity.Exists); if (commodityExists && !SysId.IsValid(commodityId)) { diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Commodities/CommodityController.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Commodities/CommodityController.cs index 7414738..089365d 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Commodities/CommodityController.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Commodities/CommodityController.cs @@ -48,8 +48,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities // Commodity page. RefreshModel(model); model.PopulateListConfig(); - model.Paging.PageNo = SessionData_Portal.Profile.Commodities.Filter.PageNo; - model.Paging.PageLength = SessionData_Portal.Profile.Commodities.Filter.PageLength; + model.Paging.PageNo = SessionData_Portal.Profile.Commodity.Filter.PageNo; + model.Paging.PageLength = SessionData_Portal.Profile.Commodity.Filter.PageLength; return View(model); } diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Contacts/AssociationController-Ajax.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Contacts/AssociationController-Ajax.cs index aeb78c2..76506da 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Contacts/AssociationController-Ajax.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Contacts/AssociationController-Ajax.cs @@ -211,11 +211,11 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts // Item filter. SbmAssociation.Params prmAssociation = new SbmAssociation.Params(); - if (SysId.IsValid(StringUtil.ToSysId(model.Filter.OwnerId))) - prmAssociation.AffiliateIdOwner = StringUtil.ToSysId(model.Filter.OwnerId); + if (SysId.IsValid(SysId.ToSysId(model.Filter.OwnerId))) + prmAssociation.AffiliateIdOwner = SysId.ToSysId(model.Filter.OwnerId); else prmAssociation.AffiliateIdOwner = SessionData_Portal.Organisation.AffiliateId; - if (SysId.IsValid(StringUtil.ToSysId(model.Filter.TargetId))) - prmAssociation.AffiliateIdTarget = StringUtil.ToSysId(model.Filter.TargetId); + if (SysId.IsValid(SysId.ToSysId(model.Filter.TargetId))) + prmAssociation.AffiliateIdTarget = SysId.ToSysId(model.Filter.TargetId); prmAssociation.AssociationType = model.GetFilterAssociationType(); if (prmAssociation.AssociationType <= 0) prmAssociation.AssociationType = Sbm.AssociationType.NotInternal; @@ -270,8 +270,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts // Refresh paging info. if (model.Paging.IsPaged) model.Paging.ItemCount = (ushort)responseData.Associations.Count; - SessionData_Portal.Profile.Associations.Filter.PageNo = model.Paging.PageNo; - SessionData_Portal.Profile.Associations.Filter.PageLength = model.Paging.PageLength; + SessionData_Portal.Profile.Association.Filter.PageNo = model.Paging.PageNo; + SessionData_Portal.Profile.Association.Filter.PageLength = model.Paging.PageLength; responseData.SetPaging(model); // Complete response. @@ -310,7 +310,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts { // Identify item. - SysId associationId = model.Association.Id.ToSysId(); + SysId associationId = SysId.ToSysId(model.Association.Id); if (!SysId.IsValid(associationId)) return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); @@ -363,7 +363,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts { // Validate item Id against 'Exists' flag. - SysId associationId = model.Association.Id.ToSysId(); + SysId associationId = SysId.ToSysId(model.Association.Id); bool associationExists = StringUtil.ToBool(model.Association.Exists); if (associationExists && !SysId.IsValid(associationId)) { @@ -395,7 +395,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); } // New item. - association = AccountMgr.CreateAssociation(SessionData_Portal.Organisation.AffiliateId, associationType, model.Association.ContactIdTarget.ToSysId()); + association = AccountMgr.CreateAssociation(SessionData_Portal.Organisation.AffiliateId, associationType, SysId.ToSysId(model.Association.ContactIdTarget)); disposables.Add(association); } @@ -442,7 +442,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts association.LastCall = model.ParseDateFromForm(model.Association.LastCallDate); // Customer. if (model.Association.CommodityIdSalesDefault != null) - association.CommodityIdSalesDefault = model.Association.CommodityIdSalesDefault.ToSysId(); + association.CommodityIdSalesDefault = SysId.ToSysId(model.Association.CommodityIdSalesDefault); if (model.Association.OrderLeadTimeCode != null) association.OrderLeadTimeCode = model.Association.OrderLeadTimeCode; if (model.Association.DeliveryTypeCode != null) @@ -467,9 +467,9 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts if (model.Association.DiscountRate != null) association.DiscountRate = StringUtil.ToDecimal(model.Association.DiscountRate); if (model.Association.PriceSetId != null) - association.PriceSetId = model.Association.PriceSetId.ToSysId(); + association.PriceSetId = SysId.ToSysId(model.Association.PriceSetId); if (model.Association.TaxCodeId != null) - association.TaxCodeId = model.Association.TaxCodeId.ToSysId(); + association.TaxCodeId = SysId.ToSysId(model.Association.TaxCodeId); if (model.Association.PaymentTerms != null) association.PaymentTerms = StringUtil.ToShort(model.Association.PaymentTerms); if (model.Association.InvoiceDesc != null) diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Contacts/AssociationController.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Contacts/AssociationController.cs index c36898a..200ec60 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Contacts/AssociationController.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Contacts/AssociationController.cs @@ -58,8 +58,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts else if (Request.Path.Value.MatchCI("/Suppliers/?$")) model.Filter.AssociationType = Internals.AssociationTypeCodes.GetCodeForType(Sbm.AssociationType.Supplier); model.PopulateListConfig(); - model.Paging.PageNo = SessionData_Portal.Profile.Associations.Filter.PageNo; - model.Paging.PageLength = SessionData_Portal.Profile.Associations.Filter.PageLength; + model.Paging.PageNo = SessionData_Portal.Profile.Association.Filter.PageNo; + model.Paging.PageLength = SessionData_Portal.Profile.Association.Filter.PageLength; return View(model); } diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Contacts/ContactController-Ajax.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Contacts/ContactController-Ajax.cs index df5a99b..44d824a 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Contacts/ContactController-Ajax.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Contacts/ContactController-Ajax.cs @@ -291,8 +291,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts // Refresh paging info. if (model.Paging.IsPaged) model.Paging.ItemCount = (ushort)responseData.Contacts.Count; - SessionData_Portal.Profile.Contacts.Filter.PageNo = model.Paging.PageNo; - SessionData_Portal.Profile.Contacts.Filter.PageLength = model.Paging.PageLength; + SessionData_Portal.Profile.Contact.Filter.PageNo = model.Paging.PageNo; + SessionData_Portal.Profile.Contact.Filter.PageLength = model.Paging.PageLength; responseData.SetPaging(model); // Complete response. @@ -327,7 +327,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts RefreshModel(model); // Identify item. - SysId affiliateId = model.Contact.Id.ToSysId(); + SysId affiliateId = SysId.ToSysId(model.Contact.Id); if (!SysId.IsValid(affiliateId)) return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); @@ -371,7 +371,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts return Json(responseData); // Validate item Id against 'Exists' flag. - SysId affiliateId = model.Contact.Id.ToSysId(); + SysId affiliateId = SysId.ToSysId(model.Contact.Id); bool contactExists = StringUtil.ToBool(model.Contact.Exists); if (contactExists && !SysId.IsValid(affiliateId)) { diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Contacts/ContactController.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Contacts/ContactController.cs index c9cf8d8..f2f1f7f 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Contacts/ContactController.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Contacts/ContactController.cs @@ -48,8 +48,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts // Contact page. RefreshModel(model); model.PopulateListConfig(); - model.Paging.PageNo = SessionData_Portal.Profile.Contacts.Filter.PageNo; - model.Paging.PageLength = SessionData_Portal.Profile.Contacts.Filter.PageLength; + model.Paging.PageNo = SessionData_Portal.Profile.Contact.Filter.PageNo; + model.Paging.PageLength = SessionData_Portal.Profile.Contact.Filter.PageLength; return View(model); } diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/SbmController_Portal.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/SbmController_Portal.cs index b1f88d6..1087d71 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/SbmController_Portal.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/SbmController_Portal.cs @@ -384,9 +384,9 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers NameValueCollection linkParams = DecryptParameters(encryptedParams, KeepLoggedIn.Base64IV, KeepLoggedIn.Base64Key); keepLoggedInParams.RepositoryContext = linkParams.Get(ParamName_KeepLoggedIn_RepositoryContext); keepLoggedInParams.EmailAddress = linkParams.Get(ParamName_KeepLoggedIn_EmailAddress); - keepLoggedInParams.SecurityItemId = linkParams.Get(ParamName_KeepLoggedIn_SecurityItemId).ToSysId(); - keepLoggedInParams.AffiliateIdUser = linkParams.Get(ParamName_KeepLoggedIn_AffiliateIdUser).ToSysId(); - keepLoggedInParams.AssociationIdOrganisation = linkParams.Get(ParamName_KeepLoggedIn_AssociationIdOrganisation).ToSysId(); + 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) SaLogger.Info($"{SysUtil.Fn} UserAccountId: {SysId.ToString(keepLoggedInParams.AffiliateIdUser)}"); return keepLoggedInParams; diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Security/SecurityController-Ajax.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Security/SecurityController-Ajax.cs index 82d4295..3d21749 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Security/SecurityController-Ajax.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Security/SecurityController-Ajax.cs @@ -132,7 +132,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Security Item. Database: {busMgrDatabase.DatabaseName}. Email: {model.EmailAddress}."); return false; } - if (!securityItemUser.PasswordMatches(model.Password)) + if (!securityConsoleForUser.PasswordMatches(securityItemUser, model.Password)) { SaLogger.Warn($"{SysUtil.Fn} Supplied password doesn't match Security Item. Database: {busMgrDatabase.DatabaseName}. Email: {model.EmailAddress}."); return false; @@ -242,7 +242,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security { // Previously selected organisation is stored in user params (SysParam table). SbmSysParamCache sysParamCache = new SbmSysParamCache(userContext, userContext.UserAffiliateId); - SysId affiliateIdOrganisation = StringUtil.ToSysId(sysParamCache.GetUserParamValue(SbmSysParamCache.ParamName_SelectedCompany)); + SysId affiliateIdOrganisation = SysId.ToSysId(sysParamCache.GetUserParamValue(SbmSysParamCache.ParamName_SelectedCompany)); SbmAssociation associationOrganisation = null; foreach (SysIdString supervisedOrganisation in userContext.SupervisedOrganisations) { diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Transactions/TransactionController-Ajax.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Transactions/TransactionController-Ajax.cs new file mode 100644 index 0000000..8e0a69c --- /dev/null +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Transactions/TransactionController-Ajax.cs @@ -0,0 +1,436 @@ +using Microsoft.AspNetCore.Mvc; +using Sarand.BusinessMgr.Net.Standard.Base.App; +using Sarand.BusinessMgr.Net.Standard.Base.Bus; +using Sarand.BusinessMgr.Web.Portal.Models; +using Sarand.BusinessMgr.Web.Portal.Models.Transactions; +using Sarand.BusinessMgr.Web.Portal.Models.Contacts; +using Sarand.Net.Standard.Base.App; +using Sarand.Net.Standard.Base.Bus; +using Sarand.Net.Standard.Base.Core; +using Sarand.Net.Standard.Base.Dbas; +using Sarand.Net.Standard.Base.Security; +using Sarand.Net.Standard.Base.Utils; +using System; +using System.Collections.Generic; +using static Sarand.BusinessMgr.Net.Standard.Base.App.Sbm; + +namespace Sarand.BusinessMgr.Web.Portal.Controllers.Transactions +{ + //======================================================================= + // Portal Transaction Controller - Ajax actions. + //======================================================================= + partial class TransactionController + { + //------------------------------------------------------------------- + // Item data. + private class TransactionListData : AjaxResponse_Data.ItemData_Base + { + // Item properties with specific handling. + public String Reference { get; set; } + public String Narrative { get; set; } + // Fields. + public class FieldData + { + // Item property values keyed to match field name. + public Dictionary Value { get; } = new Dictionary(); + } + public FieldData Field { get; } = new FieldData(); + } + private enum TransactionDataGroup + { + Core, Delivery + } + private class TransactionItemData : TransactionListData + { + // Affiliate properties with specific handling. + public String TypeCode { get; set; } + public String TypeDesc { get; set; } + } + private void PopulateTransactionResponseListData(SbmTransaction transaction, TransactionListData data) + { + data.Id = SysId.ToString(transaction.Id); + } + private void PopulateTransactionResponseItemData(SbmTransaction transaction, TransactionItemData data, HashSet dataGroups = null) + { + PopulateTransactionResponseListData(transaction, data as TransactionListData); + // Prominent properties for selecting and editing. + data.Reference = transaction.Ref; + data.Narrative = transaction.DescBrief; + // Affiliate type - populate for list ('Type' property populated with desc) and form (Type Code & Desc). + data.TypeCode = Internals.TransactionTypeCodes.GetCodeForType(transaction.TransactionType); + data.TypeDesc = Internals.TransactionTypeCodes.GetDescForType(transaction.TransactionType); + data.Field.Value.Add($"{Model_Transaction.ItemField.Type}", Internals.TransactionTypeCodes.GetDescForType(transaction.TransactionType)); + // Transaction properties. + data.Field.Value.Add($"{Model_Transaction.ItemField.Reference}", transaction.Ref); + data.Field.Value.Add($"{Model_Transaction.ItemField.ReferenceExt}", transaction.RefExt); + data.Field.Value.Add($"{Model_Transaction.ItemField.DescBrief}", transaction.DescBrief); + if (dataGroups != null && dataGroups.Contains(TransactionDataGroup.Core)) + { + // Core. + } + if (dataGroups != null && dataGroups.Contains(TransactionDataGroup.Delivery)) + { + // Delivery. + data.Field.Value.Add($"{Model_Transaction.ItemField.DeliveryStatus}", transaction.DeliveryStatusCode); + data.Field.Value.Add($"{Model_Transaction.ItemField.DeliveryType}", transaction.DeliveryTypeCode); + data.Field.Value.Add($"{Model_Transaction.ItemField.DeliveryMethod}", transaction.DeliveryMethodCode); + data.Field.Value.Add($"{Model_Transaction.ItemField.DeliveryCourier}", transaction.DeliveryCourierCode); + } + // Common properties. + data.StatusCode = transaction.StatusCode; + data.StatusDesc = transaction.StatusDesc; + data.Field.Value.Add($"{Model_Contact.ItemField.Status}", transaction.StatusDesc); + // Cleanse field values. + data.Field.Value.RemoveAll(item => StringUtil.IsBlank(item.Value)); + // Populate item list values that might be cleared during update after removing blank values to ensure that blank values are published. + data.Field.Value.Add($"{Model_Transaction.ItemField.Notes}", transaction.Notes); + data.Field.Value.Add($"{Model_Transaction.ItemField.UpdatedOn}", Localiser.FormatDate(transaction.UpdateStamp.On)); + } + + //------------------------------------------------------------------- + // Transaction configuration. + //------------------------------------------------------------------- + private class AjaxResponse_TransactionConfig : AjaxResponse_Data + { + // Construction. + public AjaxResponse_TransactionConfig(SbmModel_Portal model) : base(model) { } + // Configuration. + public Model_Transaction.ListConfigData Config { get; } = new Model_Transaction.ListConfigData(); + public Model_Transaction.ItemConfigData ConfigCmd { get; } = new Model_Transaction.ItemConfigData(); + // Reference data. + public List TransactionTypes { get; } = new List(); + public List Statuses { get; } = new List(); + public String DefaultStatusCode { get; set; } + } + // Ajax request. + [HttpPost] + [Route("Transaction/Ajax/Config")] + [Route("Transaction/Ajax/GetConfig")] + public IActionResult Ajax_TransactionConfig(Model_Transaction model) + { + AjaxResponse_TransactionConfig responseData = new AjaxResponse_TransactionConfig(model); + String messageTitle = Localiser["caption.transactions"]; + + // Validate session and referrer. + if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + if (!ValidReferer) return Forbid(); + RefreshModel(model); + + // Populate configuration data. + PopulateTransactionConfig(model, responseData); + + // Complete response. + responseData.Success = true; + return Json(responseData); + } + private void PopulateTransactionConfig(Model_Transaction model, AjaxResponse_TransactionConfig responseData) + { + // Configuration. + model.PopulateListConfig(responseData.Config); + model.PopulateItemConfig(responseData.ConfigCmd, null, Sbm.TransactionType.Unknown); + + // Reference data - transaction types. + foreach (TypeCodeDesc transactionType in GetCodesOfType(Sbm.SystemCode.TransactionType)) + responseData.TransactionTypes.Add(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.DefaultStatusCode = SacsSystem.GetStatusCode(SbmTransaction.DefaultStatus); + } + + //------------------------------------------------------------------- + // Transaction list. + //------------------------------------------------------------------- + private class AjaxResponse_TransactionList : AjaxResponse_TransactionConfig + { + // Construction. + public AjaxResponse_TransactionList(SbmModel_Portal model) : base(model) { } + // View mode. + public class ModeData + { + public bool? Search { get; set; } + public bool? Maintain { get; set; } + public bool? SearchRequirement { get; set; } + public bool? DeliveryPlanning { get; set; } + public bool? TransactionsForSourceTrans { get; set; } + public bool? TransactionsForAssociation { get; set; } + } + public ModeData Mode { get; set; } + // Transaction list. + public List Transactions { get; } = new List(); + } + // Ajax request. + [HttpPost] + [Route("Transaction/Ajax/List")] + [Route("Transaction/Ajax/GetList")] + public IActionResult Ajax_TransactionList(Model_Transaction model) + { + AjaxResponse_TransactionList responseData = new AjaxResponse_TransactionList(model); + String messageTitle = Localiser["caption.transactions"]; + + // Validate session and referrer. + if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + if (!ValidReferer) return Forbid(); + RefreshModel(model); + + // Populate configuration data. + PopulateTransactionConfig(model, responseData); + + // View mode. + responseData.Mode = new AjaxResponse_TransactionList.ModeData(); + Model_Transaction.TransactionViewMode viewMode = model.GetFilterMode(); + if (viewMode == Model_Transaction.TransactionViewMode.Maintain) + responseData.Mode.Maintain = true; + else if (viewMode == Model_Transaction.TransactionViewMode.SearchRequirement) + responseData.Mode.SearchRequirement = true; + else if (viewMode == Model_Transaction.TransactionViewMode.DeliveryPlanning) + responseData.Mode.DeliveryPlanning = true; + else if (viewMode == Model_Transaction.TransactionViewMode.TransactionsForSourceTrans) + responseData.Mode.TransactionsForSourceTrans = true; + else if (viewMode == Model_Transaction.TransactionViewMode.TransactionsForAssociation) + responseData.Mode.TransactionsForAssociation = true; + else + responseData.Mode.Search = true; + + // Item filter. + SbmTransaction.Params prmTransaction = new SbmTransaction.Params(); + prmTransaction.Search = model.Filter.Search; + prmTransaction.TransactionType = model.GetFilterTransactionType(); + prmTransaction.StatusCat = SbmTransaction.StatusCat.NotDeleted; + if (model.GetFilterTransactionType() <= 0) + prmTransaction.SortColumns.Add(TransactionMgr.GetTransactionColumnDfn(SbmTransaction.Column.Type_Desc)); + prmTransaction.SortColumns.Add(TransactionMgr.GetTransactionColumnDfn(SbmTransaction.Column.Ref)); + model.Paging.ItemTotal = (ulong)TransactionMgr.GetTransactionCount(prmTransaction); + model.PopulatePagingTo(prmTransaction.ResultsPaging); + + // Item columns. + ColumnDfn colId = TransactionMgr.GetTransactionColumnDfn(SbmTransaction.Column.Id); + ColumnDfn colType = TransactionMgr.GetTransactionColumnDfn(SbmTransaction.Column.Type_Desc); + ColumnDfn colRef = TransactionMgr.GetTransactionColumnDfn(SbmTransaction.Column.Ref); + ColumnDfn colRefExt = TransactionMgr.GetTransactionColumnDfn(SbmTransaction.Column.RefExt); + ColumnDfn colDescBrief = TransactionMgr.GetTransactionColumnDfn(SbmTransaction.Column.DescBrief); + ColumnDfn colAmountNet = TransactionMgr.GetTransactionColumnDfn(SbmTransaction.Column.AmountNet); + ColumnDfn colAmountTax = TransactionMgr.GetTransactionColumnDfn(SbmTransaction.Column.AmountTax); + ColumnDfn colAmountTot = TransactionMgr.GetTransactionColumnDfn(SbmTransaction.Column.AmountTot); + ColumnDfn colNotes = TransactionMgr.GetTransactionColumnDfn(SbmTransaction.Column.Notes); + ColumnDfn colStatus = TransactionMgr.GetTransactionColumnDfn(SbmTransaction.Column.Status); + ColumnDfn colCreatedOn = TransactionMgr.GetTransactionColumnDfn(SbmTransaction.Column.CreateOn_Date); + ColumnDfn colUpdatedOn = TransactionMgr.GetTransactionColumnDfn(SbmTransaction.Column.UpdateOn_Date); + List columns = new List() + { + colId, colType, colRef, colRefExt, colDescBrief, + colNotes, colStatus, colCreatedOn, colUpdatedOn + }; + if (model.UserCanViewFinancials()) + columns.AddRange(new[] { colAmountNet, colAmountTax, colAmountTot }); + + // Query items. + using (DbResultSet resultSet = TransactionMgr.ExecuteTransactionQuery(columns, prmTransaction)) + { + while (resultSet != null && resultSet.HasRows && resultSet.NextRecord()) + { + NamedValue.Map values = resultSet.GetRecordValues(); + Sbm.TransactionType transactionType = (Sbm.TransactionType)values.GetLong(colType.DataName); + TransactionListData transactionData = new TransactionListData() + { + Id = values.GetString(colId.DataName), + Reference = values.GetString(colRef.DataName), + Narrative = values.GetString(colDescBrief.DataName), + StatusCode = values.GetString(colStatus.DataName), + }; + transactionData.Field.Value.Add($"{Model_Transaction.ItemField.Type}", Internals.TransactionTypeCodes.GetDescForType(transactionType)); + transactionData.Field.Value.Add($"{Model_Transaction.ItemField.Reference}", values.GetString(colRef.DataName)); + transactionData.Field.Value.Add($"{Model_Transaction.ItemField.ReferenceExt}", values.GetString(colRefExt.DataName)); + transactionData.Field.Value.Add($"{Model_Transaction.ItemField.DescBrief}", values.GetString(colDescBrief.DataName)); + if (model.UserCanViewFinancials()) + { + transactionData.Field.Value.Add($"{Model_Transaction.ItemField.AmountNet}", colAmountNet.FormatValue(values)); + transactionData.Field.Value.Add($"{Model_Transaction.ItemField.AmountTax}", colAmountTax.FormatValue(values)); + transactionData.Field.Value.Add($"{Model_Transaction.ItemField.AmountTotal}", colAmountTot.FormatValue(values)); + } + transactionData.Field.Value.Add($"{Model_Transaction.ItemField.Notes}", TransactionMgr.GetTransactionDataValue(colNotes, values).ToString()); + transactionData.Field.Value.Add($"{Model_Transaction.ItemField.Status}", SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName))); + transactionData.Field.Value.Add($"{Model_Transaction.ItemField.CreatedOn}", Localiser.FormatDate(values.GetDate(colCreatedOn.DataName))); + transactionData.Field.Value.Add($"{Model_Transaction.ItemField.UpdatedOn}", Localiser.FormatDate(values.GetDate(colUpdatedOn.DataName))); + // Cleanse item values. + transactionData.Field.Value.RemoveAll(item => StringUtil.IsBlank(item.Value)); + responseData.Transactions.Add(transactionData); + } + } + + // Refresh paging info. + if (model.Paging.IsPaged) + model.Paging.ItemCount = (ushort)responseData.Transactions.Count; + SessionData_Portal.Profile.Transaction.Filter.PageNo = model.Paging.PageNo; + SessionData_Portal.Profile.Transaction.Filter.PageLength = model.Paging.PageLength; + responseData.SetPaging(model); + + // Complete response. + responseData.Success = true; + return Json(responseData); + } + + //------------------------------------------------------------------- + // Get Transaction ajax request. + //------------------------------------------------------------------- + private class AjaxResponse_Transaction : AjaxResponse_Data + { + // Construction. + public AjaxResponse_Transaction(SbmModel_Portal model) : base(model) { } + // Configuration. + public Model_Transaction.ItemConfigData Config { get; } = new Model_Transaction.ItemConfigData(); + // Transaction details. + public TransactionItemData transaction { get; } = new TransactionItemData(); + } + //------------------------------------------------------------------- + [HttpPost] + [Route("Transaction/Ajax/Item")] + [Route("Transaction/Ajax/GetItem")] + public IActionResult Ajax_GetItem(Model_Transaction model) + { + String messageTitle = Localiser["caption.transaction"]; + AjaxResponse_Transaction responseData = new AjaxResponse_Transaction(model); + + // Validate session and referrer. + if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + if (!ValidReferer) return Forbid(); + RefreshModel(model); + + // Identify item. + SysId transactionId = SysId.ToSysId(model.Transaction.Id); + if (!SysId.IsValid(transactionId)) + return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); + + // Retrieve item. + SbmTransaction transaction = TransactionMgr.GetTransactionById(transactionId); + if (transaction == null) + { + SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve transaction for Id: '{model.Transaction.Id}'"); + return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"])); + } + + // Construct response. + model.PopulateItemConfig(responseData.Config, transaction); + PopulateTransactionResponseItemData(transaction, responseData.transaction); + + // Complete response. + responseData.Success = true; + + return Json(responseData); + } + + //------------------------------------------------------------------- + // Store Transaction ajax request. + //------------------------------------------------------------------- + [HttpPost] + [Route("Transaction/Ajax/Store")] + [Route("Transaction/Ajax/StoreItem")] + public IActionResult Ajax_StoreItem(Model_Transaction model) + { + String messageTitle = Localiser["caption.transaction"]; + AjaxResponse_Transaction responseData = new AjaxResponse_Transaction(model); + + // Validate session and referrer. + if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + if (!ValidReferer) return Forbid(); + RefreshModel(model); + + // Validate item properties. + model.ValidateTransactionData(responseData); + if (responseData.HasControlErrors()) + return Json(responseData); + + // Validate item Id against 'Exists' flag. + SysId transactionId = SysId.ToSysId(model.Transaction.Id); + bool transactionExists = StringUtil.ToBool(model.Transaction.Exists); + if (transactionExists && !SysId.IsValid(transactionId)) + { + SaLogger.Warn($"{SysUtil.Fn} Id not specified for existing Transaction."); + return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); + } + if (!transactionExists && SysId.IsValid(transactionId)) + { + SaLogger.Warn($"{SysUtil.Fn} Id specified for new Transaction: '{model.Transaction.Id}'"); + return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); + } + + // Retrieve existing item. + SbmTransaction transaction = TransactionMgr.GetTransactionById(transactionId); + if (transaction == null && SysId.IsValid(transactionId)) + { + SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve transaction for Id: '{model.Transaction.Id}'"); + return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"])); + } + + // Create new item if required. + if (transaction == null) + { + SysId associationId = SysId.ToSysId(model.Transaction.AssociationId); + if (!SysId.IsValid(associationId)) + { + SaLogger.Warn($"{SysUtil.Fn} Association not specified for new Transaction."); + return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); + } + transaction = TransactionMgr.CreateTransaction(associationId, model.GetTransactionType()); + } + + // Populate item properties. + if (model.Transaction.Type != null) + transaction.TransactionType = model.GetTransactionType(); + if (model.Transaction.ReferenceExt != null) + transaction.RefExt = model.Transaction.ReferenceExt; + if (model.Transaction.DescBrief != null) + transaction.DescBrief = model.Transaction.DescBrief; + // Common properties. + if (model.Transaction.Notes != null) + transaction.Notes = model.Transaction.Notes; + if (model.Transaction.StatusCode != null) + transaction.Status = model.GetTransactionStatus(); + + // Store item. + if (!SysId.IsValid(transaction.Id)) + { + if (!TransactionMgr.InsertTransaction(transaction, DbUpdateInfo)) + { + SaLogger.Warn($"{SysUtil.Fn} Failed to insert transaction: {TransactionMgr.ErrorStateMessage}"); + return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"])); + } + responseData.SetNotification(messageTitle, Localiser["msg.item.created"]); + } + else + { + if (!TransactionMgr.UpdateTransaction(transaction, DbUpdateInfo)) + { + SaLogger.Warn($"{SysUtil.Fn} Failed to update transaction [Id:{SysId.ToLong(transaction.Id)}]: {TransactionMgr.ErrorStateMessage}"); + return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"])); + } + responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]); + } + UpdateAssociatedData(transaction); + + // Construct response. + model.PopulateItemConfig(responseData.Config, transaction); + PopulateTransactionResponseItemData(transaction, responseData.transaction); + + // Complete response. + responseData.Success = true; + + return Json(responseData); + } + + //------------------------------------------------------------------- + /// + /// Bring associated data into line with the transaction. + /// + /// + /// + private bool UpdateAssociatedData(SbmTransaction transaction) + { + return true; + } + + //------------------------------------------------------------------- + } + //======================================================================= +} diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/Transactions/TransactionController.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Transactions/TransactionController.cs new file mode 100644 index 0000000..63aabc5 --- /dev/null +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/Transactions/TransactionController.cs @@ -0,0 +1,59 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Sarand.BusinessMgr.Net.Core.Web.App; +using Sarand.BusinessMgr.Net.Core.Web.Helpers; +using Sarand.BusinessMgr.Net.Standard.Base.App; +using Sarand.BusinessMgr.Net.Standard.Base.Bus; +using Sarand.BusinessMgr.Net.Standard.Base.Mgr; +using Sarand.Net.Standard.Base.App; +using Sarand.Net.Standard.Base.Bus; +using Sarand.Net.Standard.Base.Security; +using Sarand.Net.Standard.Base.Utils; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; +using Sarand.BusinessMgr.Web.Portal.Models.Transactions; + +namespace Sarand.BusinessMgr.Web.Portal.Controllers.Transactions +{ + //======================================================================= + public partial class TransactionController : SbmController_Portal + { + //------------------------------------------------------------------- + // Data members. + + //------------------------------------------------------------------- + // Construction. + public TransactionController(SbmLocaliser localiser, ILogger logger) : + base(localiser, logger) + { + } + + //------------------------------------------------------------------- + [HttpGet] + public IActionResult Index(Model_Transaction model) + { + if (!ValidUserSession) + AutoLoginUser(); + + // Redirect to sign-in if not signed-in. + if (!ValidUserSession) + { + ClearKeepLoggedInCookie(); + return RedirectToAction("", "Security"); + } + + // Transaction page. + RefreshModel(model); + model.PopulateListConfig(); + model.Paging.PageNo = SessionData_Portal.Profile.Transaction.Filter.PageNo; + model.Paging.PageLength = SessionData_Portal.Profile.Transaction.Filter.PageLength; + return View(model); + } + + //------------------------------------------------------------------- + } + //======================================================================= +} diff --git a/SaBusinessMgrCoreWebPortal/Portal/Models/Assets/Model_Asset.cs b/SaBusinessMgrCoreWebPortal/Portal/Models/Assets/Model_Asset.cs index 7d6cf9d..c16c8ce 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Models/Assets/Model_Asset.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Models/Assets/Model_Asset.cs @@ -68,7 +68,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Assets String controlName = "AssetCategory"; if (StringUtil.IsBlank(Asset.CategoryId)) responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]); - else if (!AssetMgr.AssetCategoryExistsById(Asset.CategoryId.ToSysId())) + else if (!AssetMgr.AssetCategoryExistsById(SysId.ToSysId(Asset.CategoryId))) responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]); } diff --git a/SaBusinessMgrCoreWebPortal/Portal/Models/Codes/Model_Code.cs b/SaBusinessMgrCoreWebPortal/Portal/Models/Codes/Model_Code.cs index 28a7140..bf80a98 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Models/Codes/Model_Code.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Models/Codes/Model_Code.cs @@ -84,7 +84,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Codes String controlName = "CodeType"; if (StringUtil.IsBlank(Code.CodeTypeId)) responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]); - else if (!CodeTypeConsole.CodeTypeExistsById(Code.CodeTypeId.ToSysId())) + else if (!CodeTypeConsole.CodeTypeExistsById(SysId.ToSysId(Code.CodeTypeId))) responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]); } diff --git a/SaBusinessMgrCoreWebPortal/Portal/Models/Codes/Model_CodeType.cs b/SaBusinessMgrCoreWebPortal/Portal/Models/Codes/Model_CodeType.cs index 02f0dc3..d71518b 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Models/Codes/Model_CodeType.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Models/Codes/Model_CodeType.cs @@ -76,8 +76,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Codes else { SaCodeType.Params prmCodeType = new SaCodeType.Params(); - if (StringUtil.ToBool(CodeType.Exists) && SysId.IsValid(CodeType.Id.ToSysId())) - prmCodeType.IdsExcluded.Add(CodeType.Id.ToSysId()); + if (StringUtil.ToBool(CodeType.Exists) && SysId.IsValid(SysId.ToSysId(CodeType.Id))) + prmCodeType.IdsExcluded.Add(SysId.ToSysId(CodeType.Id)); prmCodeType.Code = CodeType.Code; if (CodeTypeConsole.GetCodeTypeCount(prmCodeType) > 0) responseData.SetControlError(controlName, Localiser["msg.validation.duplicate.value"]); diff --git a/SaBusinessMgrCoreWebPortal/Portal/Models/Commodities/Model_Commodity-Config.cs b/SaBusinessMgrCoreWebPortal/Portal/Models/Commodities/Model_Commodity-Config.cs index 47a72c1..8bf18f6 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Models/Commodities/Model_Commodity-Config.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Models/Commodities/Model_Commodity-Config.cs @@ -141,7 +141,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Commodities HandlingCode, DeliveryCode, //--------------------------------------------------------------- - // Inages. + // Images. ImagePath, Image, //--------------------------------------------------------------- @@ -168,7 +168,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Commodities // Projected sales. ProjectedSales, //--------------------------------------------------------------- - // Common properties. + // Common. Notes, Status, CreatedOn, diff --git a/SaBusinessMgrCoreWebPortal/Portal/Models/Commodities/Model_Commodity.cs b/SaBusinessMgrCoreWebPortal/Portal/Models/Commodities/Model_Commodity.cs index 5e97e57..37fa1b0 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Models/Commodities/Model_Commodity.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Models/Commodities/Model_Commodity.cs @@ -150,9 +150,9 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Commodities { // Retrieve existing commodity. SbmCommodity commodity = null; - if (StringUtil.ToBool(Commodity.Exists) && SysId.IsValid(Commodity.Id.ToSysId())) + if (StringUtil.ToBool(Commodity.Exists) && SysId.IsValid(SysId.ToSysId(Commodity.Id))) { - commodity = CommodityMgr.GetCommodityById(Commodity.Id.ToSysId()); + commodity = CommodityMgr.GetCommodityById(SysId.ToSysId(Commodity.Id)); disposables.Add(commodity); if (commodity == null) responseData.SetMessage(Localiser["caption.commodity"], Localiser["msg.something.gone.wrong"]); @@ -167,16 +167,16 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Commodities // Check that no other current commodity exists with this code. SbmCommodity.Params prmCommodity = new SbmCommodity.Params(); // Ignore this commodity if it already exists. - if (StringUtil.ToBool(Commodity.Exists) && SysId.IsValid(Commodity.Id.ToSysId())) - prmCommodity.PriceSetIdsExcluded.Add(Commodity.Id.ToSysId()); + if (StringUtil.ToBool(Commodity.Exists) && SysId.IsValid(SysId.ToSysId(Commodity.Id))) + prmCommodity.PriceSetIdsExcluded.Add(SysId.ToSysId(Commodity.Id)); // Ignore the commodity being superseded, if any. - if (SysId.IsValid(Commodity.IdSupersede.ToSysId())) - prmCommodity.PriceSetIdsExcluded.Add(Commodity.IdSupersede.ToSysId()); + if (SysId.IsValid(SysId.ToSysId(Commodity.IdSupersede))) + prmCommodity.PriceSetIdsExcluded.Add(SysId.ToSysId(Commodity.IdSupersede)); // Same code and issue. prmCommodity.CodeFull = Commodity.Code; prmCommodity.DrawingIssueFull = Commodity.DrawingIssue; // Restrict to same customer. - prmCommodity.AssociationIdCustomer = Commodity.AssocIdCustomer != null ? Commodity.AssocIdCustomer.ToSysId() : commodity.AssociationIdCustomer; + prmCommodity.AssociationIdCustomer = Commodity.AssocIdCustomer != null ? SysId.ToSysId(Commodity.AssocIdCustomer) : commodity.AssociationIdCustomer; prmCommodity.StatusCat = SbmCommodity.StatusCat.Current; List commodities = CommodityMgr.GetCommodityList(prmCommodity); disposables.AddRange(commodities); @@ -204,8 +204,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Commodities // Check that a current commodity exists with this code. SbmCommodity.Params prmCommodity = new SbmCommodity.Params(); // Ignore this commodity if it already exists. - if (StringUtil.ToBool(Commodity.Exists) && SysId.IsValid(Commodity.Id.ToSysId())) - prmCommodity.PriceSetIdsExcluded.Add(Commodity.Id.ToSysId()); + if (StringUtil.ToBool(Commodity.Exists) && SysId.IsValid(SysId.ToSysId(Commodity.Id))) + prmCommodity.PriceSetIdsExcluded.Add(SysId.ToSysId(Commodity.Id)); // Same code. prmCommodity.CodeFull = Commodity.Code; prmCommodity.StatusCat = SbmCommodity.StatusCat.Current; diff --git a/SaBusinessMgrCoreWebPortal/Portal/Models/Contacts/Model_Association-Config.cs b/SaBusinessMgrCoreWebPortal/Portal/Models/Contacts/Model_Association-Config.cs index afa2426..5ee5a9a 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Models/Contacts/Model_Association-Config.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Models/Contacts/Model_Association-Config.cs @@ -213,7 +213,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts config.Column.Hide.Add($"{ItemField.CommodityCount}"); // Members. - if (!typeIsMember || !StringUtil.ToSysId(Filter.OwnerId).Equals(SessionData_Portal.Organisation.AffiliateId)) + if (!typeIsMember || !SysId.ToSysId(Filter.OwnerId).Equals(SessionData_Portal.Organisation.AffiliateId)) config.Column.Hide.Add($"{ItemField.Technician}"); if (!typeIsMember) config.Column.Hide.Add($"{ItemField.Terminated}"); diff --git a/SaBusinessMgrCoreWebPortal/Portal/Models/Contacts/Model_Contact.cs b/SaBusinessMgrCoreWebPortal/Portal/Models/Contacts/Model_Contact.cs index dbce3b3..f57e19e 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Models/Contacts/Model_Contact.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Models/Contacts/Model_Contact.cs @@ -101,7 +101,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts public String StatusCode { get; set; } } public ContactData Contact { get; } = new ContactData(); - public SysId GetAffiliateId() { return StringUtil.ToSysId(Contact.Id); } + public SysId GetAffiliateId() { return SysId.ToSysId(Contact.Id); } public Sbm.AffiliateType GetAffiliateType() { if (StringUtil.ToBool(Contact.IsIndividual)) diff --git a/SaBusinessMgrCoreWebPortal/Portal/Models/Transactions/Model_Transaction-Config.cs b/SaBusinessMgrCoreWebPortal/Portal/Models/Transactions/Model_Transaction-Config.cs new file mode 100644 index 0000000..43649fd --- /dev/null +++ b/SaBusinessMgrCoreWebPortal/Portal/Models/Transactions/Model_Transaction-Config.cs @@ -0,0 +1,604 @@ +using Sarand.BusinessMgr.Net.Standard.Base.App; +using Sarand.BusinessMgr.Net.Standard.Base.Bus; +using Sarand.Net.Standard.Base.Bus; +using System; +using System.Collections.Generic; +using System.Drawing; + +namespace Sarand.BusinessMgr.Web.Portal.Models.Transactions +{ + //======================================================================= + // Transaction model - Configuration. + //======================================================================= + partial class Model_Transaction + { + //------------------------------------------------------------------- + // Transaction fields. + //------------------------------------------------------------------- + + /// Prefix for field names. + public const String FieldNamePrefix = "Transaction"; + + //------------------------------------------------------------------- + // Legacy Transaction dialog tabs and panels. + // - Transaction. + // - Tab 1: + // - Tab 2: + // - Tab 3: + // - Tab 4: + // - Tab 5: + // - Tab 6: + // - Tab 7: + // - Other. + + //------------------------------------------------------------------- + /// Item fields. + public enum ItemField + { + //--------------------------------------------------------------- + // Transaction. + Pos, + Id, + AssociationTarget, + AssociationIdTarget, + Type, + Reference, + ReferenceExt, + RaisedBy, + AffiliateIdRaise, + AssociationIdOffice, + ContactName, + Likelihood, + TransactionIdSource, + ReferCode, + ReferSource, + AffiliateIdRefer, + AssociationIdContract, + AssociationIdDelivery, + //--------------------------------------------------------------- + // Addresses and contact. + TargetAddress, + TargetPostcode, + DeliveryAddress, + DeliveryPostcode, + TargetPhone, + //--------------------------------------------------------------- + // Requirements. + ItemCount, + //--------------------------------------------------------------- + // Status dates. + Raised, + Required, + InProgress, + DeliveredEst, + DeliveredAct, + Closed, + Department, + DescBrief, + DescIntro, + DescOutline, + DescDetail, + ResponseCode, + ContactAreaCode, + Postcode, + CurrencyId, + //--------------------------------------------------------------- + // Costing. + TaxCodeId, + AmountEst, + AmountMax, + AmountNet, + AmountTax, + AmountTotal, + //--------------------------------------------------------------- + // Time recording. + TimeCount, + TimeEstimate, + TimeActual, + TimeTotal, + //--------------------------------------------------------------- + // Job costing. + CostLabourRateHour, + CostTotal, + PercentMargin, + //--------------------------------------------------------------- + // Stock. + AllocationInd, + //--------------------------------------------------------------- + // Specification. + LocationIdStock, + Weight, + UomIdWeight, + //--------------------------------------------------------------- + // Codes. + /// Account Manager - determined by association or address. List only. + AccountManager, + /// Account Handler - determined by association or address. List only. + AccountHandler, + /// Account Handler - determined by transaction, association or address. + ContactArea, + //--------------------------------------------------------------- + // Delivery. + DeliveryStatus, + /// Delivery Type - determined by transaction, association or address. + DeliveryType, + /// Delivery Method - determined by transaction, association or address. + DeliveryMethod, + /// Delivery Courier - determined by transaction or association. + DeliveryCourier, + DeliveryBookIn, + StockPicker, + DeliveryRef, + DeliveryComment, + DeliveryAmountNet, + TaxCodeIdDelivery, + DeliveryAmountTax, + DeliveryAmountTot, + DeliveryDepartment, + DeliveryNominalCode, + BoxCount, + //--------------------------------------------------------------- + // Common. + Notes, + Status, + OnHold, + CreatedOn, + UpdatedOn, + Actions, + } + + /// + /// Identifier used by form fields to show control specific messages generated by model validation etc. + /// - Both page and model should use this method to consistently generate the field name. + /// + public static String GetFieldName(ItemField field) + { + return $"{FieldNamePrefix}{field}"; + } + + //------------------------------------------------------------------- + + // List configuration. + public class ListConfigData + { + // List columns. + public class ColumnData + { + // Column name prefix. + public String Prefix { get; } = Model_Transaction.FieldNamePrefix; + // Hide column. + public HashSet Hide { get; } = new HashSet(StringComparer.InvariantCultureIgnoreCase); + // Column labels. + public Dictionary Label { get; } = new Dictionary(StringComparer.InvariantCultureIgnoreCase); + } + public ColumnData Column { get; } = new ColumnData(); + } + public ListConfigData ListConfig { get; private set; } + + //------------------------------------------------------------------- + /// + /// Populate Transaction list configuration data in this model - only required on initial page construction. + /// + public void PopulateListConfig() + { + ListConfig = new ListConfigData(); + PopulateListConfig(ListConfig); + } + /// + /// Populate Transaction list configuration data. + /// + public void PopulateListConfig(ListConfigData config) + { + // View properties. + TransactionViewMode viewMode = GetFilterMode(); + bool modeIsSearch = viewMode == TransactionViewMode.Search; + bool modeIsMaintain = viewMode == TransactionViewMode.Maintain; + bool modeIsRequirementSearch = viewMode == TransactionViewMode.SearchRequirement; + bool modeIsDeliveryPlanning = viewMode == TransactionViewMode.DeliveryPlanning; + bool modeIsTransactionsForSourceTrans = viewMode == TransactionViewMode.TransactionsForSourceTrans; + bool modeIsTransactionsForAssociation = viewMode == TransactionViewMode.TransactionsForAssociation; + + // Item type. + Sbm.TransactionType transactionType = GetFilterTransactionType(); + bool isProject = transactionType == Sbm.TransactionType.Project; + bool isSales = SbmTransaction.IsSalesType(transactionType); + bool isSalesLead = transactionType == Sbm.TransactionType.SalesLead; + bool isSalesQuote = transactionType == Sbm.TransactionType.SalesQuote; + bool isSalesOrder = transactionType == Sbm.TransactionType.SalesOrder || transactionType == Sbm.TransactionType.ProformaSalesOrder; + bool isSalesPO = transactionType == Sbm.TransactionType.SalesPO; + bool isSalesDispatch = transactionType == Sbm.TransactionType.SalesDispatch; + bool isSalesInvoice = transactionType == Sbm.TransactionType.SalesInvoice || transactionType == Sbm.TransactionType.ProformaSalesInvoice; + bool isPurchase = SbmTransaction.IsPurchaseType(transactionType); + bool isPurchaseQuote = transactionType == Sbm.TransactionType.PurchaseQuote; + bool isPurchaseOrder = transactionType == Sbm.TransactionType.PurchaseOrder || transactionType == Sbm.TransactionType.ProformaPurchaseOrder; + bool isPurchaseSO = transactionType == Sbm.TransactionType.PurchaseSO; + bool isPurchaseDelivery = transactionType == Sbm.TransactionType.PurchaseDelivery; + bool isPurchaseInvoice = transactionType == Sbm.TransactionType.PurchaseInvoice || transactionType == Sbm.TransactionType.ProformaPurchaseInvoice; + + // Status. + SbmTransaction.StatusCat transactionStatusCat = GetFilterTransactionStatusCat(); + + // Options. + bool allowTimeRecording = SessionConsole.AllowOption(Sbm.ConfigOption.TimeRecording); + bool allowJobCosting = SessionConsole.GetRequirementCostingConfig().AllowRequirementCosting(transactionType) && TransactionMgr.CostColumnsAreAvailable() && UserCanViewFinancials(); + + //--------------------------------------------------------------- + // Transaction list columns. + + // Position. + + // Id + if (!SbmSystem.DebugMode) + config.Column.Hide.Add($"{ItemField.Id}"); + + // Reference. + config.Column.Label.Add($"{ItemField.Reference}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Transaction_Ref, Localiser["label.reference"])); + + // External Reference. + if (!isSalesLead) + { + config.Column.Label.Add($"{ItemField.ReferenceExt}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Transaction_RefExt, Localiser["label.reference.ext"])); + } + else + config.Column.Hide.Add($"{ItemField.ReferenceExt}"); + + // Transaction type. + if (transactionType <= 0) + config.Column.Label.Add($"{ItemField.Type}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Transaction_Type, Localiser["label.type"])); + else + config.Column.Hide.Add($"{ItemField.Type}"); + + // Association. + if (!modeIsTransactionsForAssociation) + { + String associationLabel = Localiser["label.target"]; + if (isSales) associationLabel = Localiser["label.customer"]; + else if (isPurchase) associationLabel = Localiser["label.supplier"]; + config.Column.Label.Add($"{ItemField.AssociationTarget}", associationLabel); + } + config.Column.Hide.Add($"{ItemField.AssociationTarget}"); + + // Narrative. + config.Column.Label.Add($"{ItemField.DescBrief}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Transaction_DescBrief, Localiser["label.narrative"])); + + //--------------------------------------------------------------- + // Addresses and contact. + + // Delivery address. + if (modeIsDeliveryPlanning || (isSalesOrder && SessionConsole.AllowOption(Sbm.ConfigOption.ShowSiteAddrOnTransView))) + { + config.Column.Label.Add($"{ItemField.DeliveryAddress}", Localiser["label.delivery.address"]); + config.Column.Label.Add($"{ItemField.DeliveryPostcode}", Localiser["label.delivery.postcode"]); + } + else + { + config.Column.Hide.Add($"{ItemField.DeliveryAddress}"); + config.Column.Hide.Add($"{ItemField.DeliveryPostcode}"); + } + + // Target address. + if (modeIsDeliveryPlanning) + { + config.Column.Label.Add($"{ItemField.TargetAddress}", Localiser["label.target.address"]); + config.Column.Label.Add($"{ItemField.TargetPostcode}", Localiser["label.target.postcode"]); + } + else + { + config.Column.Hide.Add($"{ItemField.TargetAddress}"); + config.Column.Hide.Add($"{ItemField.TargetPostcode}"); + } + + // Target phone. + if (isSalesLead) + { + config.Column.Label.Add($"{ItemField.TargetPhone}", Localiser["label.phone"]); + } + else + config.Column.Hide.Add($"{ItemField.TargetPhone}"); + + //--------------------------------------------------------------- + // Requirements. + + // Item count. + if (modeIsDeliveryPlanning || (transactionType > 0 && !isSalesLead)) + { + config.Column.Label.Add($"{ItemField.ItemCount}", Localiser["label.items"]); + } + else + config.Column.Hide.Add($"{ItemField.ItemCount}"); + + //--------------------------------------------------------------- + // Status dates. + + // Raised date. + if (!modeIsDeliveryPlanning) + { + config.Column.Label.Add($"{ItemField.Raised}", Localiser["label.raised"]); + } + else + config.Column.Hide.Add($"{ItemField.Raised}"); + + // In Progress date. + if (!modeIsDeliveryPlanning && !isSalesLead && !isSalesDispatch && transactionStatusCat != SbmTransaction.StatusCat.Pending) + { + config.Column.Label.Add($"{ItemField.InProgress}", Localiser["label.in.progress"]); + } + else + config.Column.Hide.Add($"{ItemField.InProgress}"); + + // Required date. + if (modeIsDeliveryPlanning && !isSalesLead && !isSalesDispatch || transactionStatusCat != SbmTransaction.StatusCat.Closed) + { + String requiredLabel = Localiser["label.required"]; + if (isSalesLead) requiredLabel = Localiser["label.expected"]; + config.Column.Label.Add($"{ItemField.Required}", requiredLabel); + } + else + config.Column.Hide.Add($"{ItemField.Required}"); + + // Closed date. + if (modeIsDeliveryPlanning || transactionStatusCat != SbmTransaction.StatusCat.Open) + { + config.Column.Label.Add($"{ItemField.Closed}", Localiser["label.closed"]); + } + else + config.Column.Hide.Add($"{ItemField.Closed}"); + + //--------------------------------------------------------------- + // Amounts. + + // Amount net. + if (UserCanViewFinancials() && (isSales || modeIsDeliveryPlanning)) + { + config.Column.Label.Add($"{ItemField.AmountNet}", Localiser["label.amount.net"]); + } + else + config.Column.Hide.Add($"{ItemField.AmountNet}"); + + // Amount tax. + if (UserCanViewFinancials() && (transactionType > 0 && (isSalesQuote || isSalesOrder))) + { + config.Column.Label.Add($"{ItemField.AmountTax}", Localiser["label.amount.tax"]); + } + else + config.Column.Hide.Add($"{ItemField.AmountTax}"); + + // Amount total. + if (UserCanViewFinancials() && (transactionType > 0 && (isSalesQuote || isSalesOrder))) + { + config.Column.Label.Add($"{ItemField.AmountTotal}", Localiser["label.amount.total"]); + } + else + config.Column.Hide.Add($"{ItemField.AmountTotal}"); + + //--------------------------------------------------------------- + // Codes. + + // Account Manager. + if (CodeTypeConsole.CodeTypeHasCodes(Internals.GetCodeTypeCode(Sbm.ApplCodeType.AccountManager)) && + modeIsDeliveryPlanning) + { + config.Column.Label.Add($"{ItemField.AccountManager}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Association_AccountManagerCode, Localiser["label.account.manager"])); + } + else + config.Column.Hide.Add($"{ItemField.AccountManager}"); + + // Account Handler. + if (CodeTypeConsole.CodeTypeHasCodes(Internals.GetCodeTypeCode(Sbm.ApplCodeType.AccountHandler)) && + modeIsDeliveryPlanning) + { + config.Column.Label.Add($"{ItemField.AccountHandler}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Association_AccountHandlerCode, Localiser["label.account.handler"])); + } + else + config.Column.Hide.Add($"{ItemField.AccountHandler}"); + + // Contact Area. + if (CodeTypeConsole.CodeTypeHasCodes(Internals.GetCodeTypeCode(Sbm.ApplCodeType.ContactArea)) && + SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Transaction_ContactArea) && + (modeIsDeliveryPlanning || isSalesOrder)) + { + config.Column.Label.Add($"{ItemField.ContactArea}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Transaction_ContactAreaCode, Localiser["label.contact.area"])); + } + else + config.Column.Hide.Add($"{ItemField.ContactArea}"); + + //--------------------------------------------------------------- + // Delivery. + + // Delivery Status. + if (CodeTypeConsole.CodeTypeHasCodes(Internals.GetCodeTypeCode(Sbm.ApplCodeType.DeliveryStatus)) && + modeIsDeliveryPlanning) + { + config.Column.Label.Add($"{ItemField.DeliveryStatus}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Transaction_DeliveryStatusCode, Localiser["label.delivery.status"])); + } + else + config.Column.Hide.Add($"{ItemField.DeliveryStatus}"); + + // Delivery Type. + if (CodeTypeConsole.CodeTypeHasCodes(Internals.GetCodeTypeCode(Sbm.ApplCodeType.DeliveryType)) && + modeIsDeliveryPlanning) + { + config.Column.Label.Add($"{ItemField.DeliveryType}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Transaction_DeliveryTypeCode, Localiser["label.delivery.type"])); + } + else + config.Column.Hide.Add($"{ItemField.DeliveryType}"); + + // Delivery Method. + if (CodeTypeConsole.CodeTypeHasCodes(Internals.GetCodeTypeCode(Sbm.ApplCodeType.DeliveryMethod)) && + modeIsDeliveryPlanning) + { + config.Column.Label.Add($"{ItemField.DeliveryMethod}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Transaction_DeliveryMethodCode, Localiser["label.delivery.method"])); + } + else + config.Column.Hide.Add($"{ItemField.DeliveryMethod}"); + + // Delivery Courier. + if (CodeTypeConsole.CodeTypeHasCodes(Internals.GetCodeTypeCode(Sbm.ApplCodeType.DeliveryCourier)) && + (modeIsDeliveryPlanning || isSalesOrder)) + { + config.Column.Label.Add($"{ItemField.DeliveryCourier}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Transaction_DeliveryCourierCode, Localiser["label.delivery.courier"])); + } + else + config.Column.Hide.Add($"{ItemField.DeliveryCourier}"); + + // Box Count. + if (modeIsDeliveryPlanning) + { + config.Column.Label.Add($"{ItemField.BoxCount}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Transaction_BoxCount, Localiser["label.box.count"])); + } + else + config.Column.Hide.Add($"{ItemField.BoxCount}"); + + //--------------------------------------------------------------- + // Stock. + + //--------------------------------------------------------------- + // Time recording. + + if (allowTimeRecording && (isProject || isSalesQuote || isSalesOrder)) + { + config.Column.Label.Add($"{ItemField.TimeCount}", Localiser["label.time.count"]); + config.Column.Label.Add($"{ItemField.TimeTotal}", Localiser["label.time.total"]); + } + else + { + config.Column.Hide.Add($"{ItemField.TimeCount}"); + config.Column.Hide.Add($"{ItemField.TimeTotal}"); + } + + //--------------------------------------------------------------- + // Job costing. + + if (allowJobCosting) + { + config.Column.Label.Add($"{ItemField.CostLabourRateHour}", Localiser["label.cost.rate.hour"]); + config.Column.Label.Add($"{ItemField.CostTotal}", Localiser["label.cost.total"]); + config.Column.Label.Add($"{ItemField.PercentMargin}", Localiser["label.cost.percent.margin"]); + } + else + { + config.Column.Hide.Add($"{ItemField.CostLabourRateHour}"); + config.Column.Hide.Add($"{ItemField.CostTotal}"); + config.Column.Hide.Add($"{ItemField.PercentMargin}"); + } + + //--------------------------------------------------------------- + // Common. + + // Allocation. + if (modeIsDeliveryPlanning) + { + config.Column.Label.Add($"{ItemField.AllocationInd}", Localiser["label.allocation"]); + } + else + config.Column.Hide.Add($"{ItemField.AllocationInd}"); + + // Status. + if (modeIsSearch) + config.Column.Hide.Add($"{ItemField.Status}"); + + // Actions. + if (!modeIsMaintain) + config.Column.Hide.Add($"{ItemField.Actions}"); + } + + //------------------------------------------------------------------- + // Item configuration. + //------------------------------------------------------------------- + + // Contact item configuration. + public class ItemConfigData + { + // Item type. + public bool? IsOrganisation { get; set; } + public bool? IsIndividual { get; set; } + public bool? IsGroup { get; set; } + // Item fields. + public class FieldData + { + // Field name prefix. + public String Prefix { get; } = Model_Transaction.FieldNamePrefix; + // Hide field. + public HashSet Hide { get; } = new HashSet(StringComparer.InvariantCultureIgnoreCase); + // Read-only field. + public HashSet Readonly { get; } = new HashSet(StringComparer.InvariantCultureIgnoreCase); + // Field labels. + public Dictionary Label { get; } = new Dictionary(StringComparer.InvariantCultureIgnoreCase); + } + public FieldData Field { get; } = new FieldData(); + } + + //------------------------------------------------------------------- + /// + /// Populate item configuration for existing association. + /// + public void PopulateItemConfig(ItemConfigData config, SbmTransaction transaction) + { + PopulateItemConfig(config, transaction.GetItemId(), transaction.TransactionType); + } + + /// + /// Populate item configuration for new or existing association. + /// + public void PopulateItemConfig(ItemConfigData config, ItemId transactionItemId, Sbm.TransactionType transactionType) + { + // Item type. + bool isSales = SbmTransaction.IsSalesType(transactionType); + bool isPurchase = SbmTransaction.IsPurchaseType(transactionType); + + bool importedFromAccounts = Internals.AccountsDfn.ItemIsImportedFromAccounts(transactionItemId); + bool managedByAccounts = Internals.AccountsDfn.IsItemTypeManagedByAccounts(Sbm.ItemType.Transaction); + bool showNotes = true; + + //--------------------------------------------------------------- + // Transaction. + + // Id. + if (SbmSystem.DebugMode) + config.Field.Readonly.Add($"{ItemField.Id}"); + else + config.Field.Hide.Add($"{ItemField.Id}"); + + // Transaction type. + config.Field.Label.Add($"{ItemField.Type}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Transaction_Type, Localiser["label.type"])); + config.Field.Readonly.Add($"{ItemField.Type}"); + + // Reference. + config.Field.Label.Add($"{ItemField.Reference}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Transaction_Ref, Localiser["label.reference"])); + + // External Reference. + if (transactionType != Sbm.TransactionType.SalesLead) + { + config.Field.Label.Add($"{ItemField.ReferenceExt}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Transaction_RefExt, Localiser["label.reference.ext"])); + } + else + config.Field.Hide.Add($"{ItemField.ReferenceExt}"); + + // Narrative. + config.Field.Label.Add($"{ItemField.DescBrief}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Transaction_DescBrief, Localiser["label.narrative"])); + if (managedByAccounts) + config.Field.Readonly.Add($"{ItemField.DescBrief}"); + + //--------------------------------------------------------------- + // Sales order. + + //--------------------------------------------------------------- + // Purchase order. + + //--------------------------------------------------------------- + // Common. + + // Notes. + if (!showNotes) + config.Field.Hide.Add($"{ItemField.Notes}"); + + // Status. + // Read-only if transaction being superceded. + if (managedByAccounts) + config.Field.Readonly.Add($"{ItemField.Status}"); + + } + + //------------------------------------------------------------------- + } +} diff --git a/SaBusinessMgrCoreWebPortal/Portal/Models/Transactions/Model_Transaction.cs b/SaBusinessMgrCoreWebPortal/Portal/Models/Transactions/Model_Transaction.cs new file mode 100644 index 0000000..e675395 --- /dev/null +++ b/SaBusinessMgrCoreWebPortal/Portal/Models/Transactions/Model_Transaction.cs @@ -0,0 +1,418 @@ +using Microsoft.AspNetCore.Http; +using Sarand.BusinessMgr.Net.Core.Web.App; +using Sarand.BusinessMgr.Net.Core.Web.Controllers; +using Sarand.BusinessMgr.Net.Standard.Base.App; +using Sarand.BusinessMgr.Net.Standard.Base.Bus; +using Sarand.BusinessMgr.Net.Standard.Base.Helpers; +using Sarand.Net.Standard.Base.App; +using Sarand.Net.Standard.Base.Bus; +using Sarand.Net.Standard.Base.Core; +using Sarand.Net.Standard.Base.Helpers; +using Sarand.Net.Standard.Base.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using static Sarand.BusinessMgr.Net.Standard.Base.App.Sbm; +using static Sarand.BusinessMgr.Web.Portal.Models.Contacts.Model_Contact; + +namespace Sarand.BusinessMgr.Web.Portal.Models.Transactions +{ + //======================================================================= + // Transaction model. + //======================================================================= + /// + /// Transaction model - Filter, Form, validation and configuration. + /// + public partial class Model_Transaction : SbmModel_Portal + { + //------------------------------------------------------------------- + // Definitions. + public enum TransactionViewMode + { + Search, Maintain, SearchRequirement, DeliveryPlanning, TransactionsForSourceTrans, TransactionsForAssociation + } + + //------------------------------------------------------------------- + // Construction. + public Model_Transaction(SbmLocaliser localiser) : + base(localiser) + { + } + + //------------------------------------------------------------------- + // Filter properties. + public class FilterData + { + public String Mode { get; set; } + public String TransactionType { get; set; } + public String Search { get; set; } + public String StatusCat { get; set; } + } + public FilterData Filter { get; } = new FilterData(); + public TransactionViewMode GetFilterMode() + { + return EnumUtil.ParseEnum(Filter.Mode, TransactionViewMode.Search); + } + public Sbm.TransactionType GetFilterTransactionType() + { + Sbm.TransactionType transactionType = (Sbm.TransactionType)Internals.TransactionTypeCodes.GetTypeForCode(Filter.TransactionType); + if (transactionType == 0 && !StringUtil.IsBlank(Filter.TransactionType) && StringUtil.IsNumeric(Filter.TransactionType, true)) + transactionType = (Sbm.TransactionType)StringUtil.ToInt(Filter.TransactionType); + return transactionType; + } + public SbmTransaction.StatusCat GetFilterTransactionStatusCat() + { + return (SbmTransaction.StatusCat)StringUtil.ToInt(Filter.StatusCat); + } + + //------------------------------------------------------------------- + // Transaction properties. + public class TransactionData + { + public String Exists { get; set; } + public String Id { get; set; } + public String AssociationId { get; set; } + public String Type { get; set; } + public String Reference { get; set; } + public String ReferenceExt { get; set; } + public String RaisedBy { get; set; } + public String AffiliateIdRaise { get; set; } + public String AssociationIdOffice { get; set; } + public String ContactName { get; set; } + public String Likelihood { get; set; } + public String TransactionIdSource { get; set; } + public String ReferCode { get; set; } + public String ReferSource { get; set; } + public String AffiliateIdRefer { get; set; } + public String AssociationIdContract { get; set; } + public String AssociationIdDelivery { get; set; } + // Status dates. + public String Raised { get; set; } + public String Required { get; set; } + public String InProgress { get; set; } + public String DeliveredEst { get; set; } + public String DeliveredAct { get; set; } + public String Closed { get; set; } + public String Department { get; set; } + public String DescBrief { get; set; } + public String DescIntro { get; set; } + public String DescOutline { get; set; } + public String DescDetail { get; set; } + public String ResponseCode { get; set; } + public String ContactAreaCode { get; set; } + public String Postcode { get; set; } + public String CurrencyId { get; set; } + // Costing. + public String TaxCodeId { get; set; } + public String AmountEst { get; set; } + public String AmountMax { get; set; } + public String AmountNet { get; set; } + public String AmountTax { get; set; } + public String AmountTot { get; set; } + public String TimeEst { get; set; } + public String TimeAct { get; set; } + public String TimeTot { get; set; } + // Specification. + public String LocationIdStock { get; set; } + public String Weight { get; set; } + public String UomIdWeight { get; set; } + public String BoxCount { get; set; } + // Delivery. + public String DeliveryStatusCode { get; set; } + public String DeliveryTypeCode { get; set; } + public String DeliveryMethodCode { get; set; } + public String DeliveryCourierCode { get; set; } + public String DeliveryBookInCode { get; set; } + public String StockPickerCode { get; set; } + public String DeliveryRef { get; set; } + public String DeliveryComment { get; set; } + public String DeliveryAmountNet { get; set; } + public String TaxCodeIdDelivery { get; set; } + public String DeliveryAmountTax { get; set; } + public String DeliveryAmountTot { get; set; } + public String CostLabourRateHour { get; set; } + public String DeliveryDepartment { get; set; } + public String DeliveryNominalCode { get; set; } + // Common properties. + public String Notes { get; set; } + public String StatusCode { get; set; } + } + public TransactionData Transaction { get; } = new TransactionData(); + public Sbm.TransactionType GetTransactionType() + { + return (Sbm.TransactionType)Internals.TransactionTypeCodes.GetTypeForCode(Transaction.Type); + } + public SaStatus GetTransactionStatus() + { + return SacsSystem.GetStatusForCode(Transaction.StatusCode); + } + + //------------------------------------------------------------------- + // Validation. + //------------------------------------------------------------------- + // Transaction validation. + public bool ValidateTransactionData(Sacs.Web.Components.SaController.AjaxResponse_Data responseData) + { + // Transaction Type. + Sbm.TransactionType transactionType = GetTransactionType(); + if (Transaction.Type != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.Type); + if (Transaction.Type.IsEmpty() || GetTransactionType() <= 0) + responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]); + else if (!SessionConsole.AllowTransactionType(transactionType)) + responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]); + } + + // Association. + if (Transaction.AssociationId != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.AssociationTarget); + SysId associationId = SysId.ToSysId(Transaction.AssociationId); + if (!SysId.IsValid(associationId)) + responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]); + } + + // Reference. + if (Transaction.Reference != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.Reference); + responseData.SetControlValue(controlName, Transaction.Reference); + if (StringUtil.GetLength(Transaction.Reference) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_Ref)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_Ref)]); + } + + // Ext Reference. + if (Transaction.ReferenceExt != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.ReferenceExt); + responseData.SetControlValue(controlName, Transaction.ReferenceExt); + if (StringUtil.GetLength(Transaction.ReferenceExt) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_RefExt)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_RefExt)]); + } + + // Narrative. + if (Transaction.DescBrief != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.DescBrief); + responseData.SetControlValue(controlName, Transaction.DescBrief); + if (StringUtil.GetLength(Transaction.DescBrief) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DescBrief)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DescBrief)]); + } + + // Contact Name. + if (Transaction.ContactName != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.ContactName); + responseData.SetControlValue(controlName, Transaction.ContactName); + if (StringUtil.GetLength(Transaction.ContactName) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_ContactName)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_ContactName)]); + } + + // Likelihood. + if (Transaction.Likelihood != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.Likelihood); + responseData.SetControlValue(controlName, Transaction.Likelihood); + if (StringUtil.GetLength(Transaction.Likelihood) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_Likelihood)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_Likelihood)]); + } + + // Referral code. + if (Transaction.ReferCode != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.ReferCode); + responseData.SetControlValue(controlName, Transaction.ReferCode); + if (StringUtil.GetLength(Transaction.ReferCode) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_ReferCode)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_ReferCode)]); + } + + // Refer source. + if (Transaction.ReferSource != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.ReferSource); + responseData.SetControlValue(controlName, Transaction.ReferSource); + if (StringUtil.GetLength(Transaction.ReferSource) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_ReferSource)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_ReferSource)]); + } + + // Department. + if (Transaction.Department != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.Department); + responseData.SetControlValue(controlName, Transaction.Department); + if (StringUtil.GetLength(Transaction.Department) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_Department)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_Department)]); + } + + // Desc Intro. + if (Transaction.DescIntro != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.DescIntro); + responseData.SetControlValue(controlName, Transaction.DescIntro); + if (StringUtil.GetLength(Transaction.DescIntro) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DescIntro)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DescIntro)]); + } + + // Desc Outline. + if (Transaction.DescOutline != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.DescOutline); + responseData.SetControlValue(controlName, Transaction.DescOutline); + if (StringUtil.GetLength(Transaction.DescOutline) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DescOutline)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DescOutline)]); + } + + // Desc Detail. + if (Transaction.DescDetail != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.DescDetail); + responseData.SetControlValue(controlName, Transaction.DescDetail); + if (StringUtil.GetLength(Transaction.DescDetail) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DescDetail)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DescDetail)]); + } + + // Contact Area code. + if (Transaction.ContactAreaCode != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.ContactAreaCode); + responseData.SetControlValue(controlName, Transaction.ContactAreaCode); + if (StringUtil.GetLength(Transaction.ContactAreaCode) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_ContactAreaCode)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_ContactAreaCode)]); + } + + // Response code. + if (Transaction.ResponseCode != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.ResponseCode); + responseData.SetControlValue(controlName, Transaction.ResponseCode); + if (StringUtil.GetLength(Transaction.ResponseCode) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_ResponseCode)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_ResponseCode)]); + } + + // Box Count. + if (Transaction.BoxCount != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.BoxCount); + responseData.SetControlValue(controlName, Transaction.BoxCount); + if (StringUtil.GetLength(Transaction.BoxCount) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_BoxCount)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_BoxCount)]); + } + + // Delivery Status code. + if (Transaction.DeliveryStatusCode != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.DeliveryStatus); + responseData.SetControlValue(controlName, Transaction.DeliveryStatusCode); + if (StringUtil.GetLength(Transaction.DeliveryStatusCode) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryStatusCode)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryStatusCode)]); + } + + // Delivery Type code. + if (Transaction.DeliveryTypeCode != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.DeliveryType); + responseData.SetControlValue(controlName, Transaction.DeliveryTypeCode); + if (StringUtil.GetLength(Transaction.DeliveryTypeCode) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryTypeCode)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryTypeCode)]); + } + + // Delivery Method code. + if (Transaction.DeliveryMethodCode != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.DeliveryMethod); + responseData.SetControlValue(controlName, Transaction.DeliveryMethodCode); + if (StringUtil.GetLength(Transaction.DeliveryMethodCode) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryMethodCode)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryMethodCode)]); + } + + // Delivery Courier code. + if (Transaction.DeliveryCourierCode != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.DeliveryCourier); + responseData.SetControlValue(controlName, Transaction.DeliveryCourierCode); + if (StringUtil.GetLength(Transaction.DeliveryCourierCode) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryCourierCode)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryCourierCode)]); + } + + // Delivery Book In code. + if (Transaction.DeliveryBookInCode != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.DeliveryBookIn); + responseData.SetControlValue(controlName, Transaction.DeliveryBookInCode); + if (StringUtil.GetLength(Transaction.DeliveryBookInCode) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryBookInCode)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryBookInCode)]); + } + + // Stock Picker code. + if (Transaction.StockPickerCode != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.StockPicker); + responseData.SetControlValue(controlName, Transaction.StockPickerCode); + if (StringUtil.GetLength(Transaction.StockPickerCode) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_StockPickerCode)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_StockPickerCode)]); + } + + // Delivery Ref. + if (Transaction.DeliveryRef != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.DeliveryRef); + responseData.SetControlValue(controlName, Transaction.DeliveryRef); + if (StringUtil.GetLength(Transaction.DeliveryRef) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryRef)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryRef)]); + } + + // Delivery Comment. + if (Transaction.DeliveryComment != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.DeliveryComment); + responseData.SetControlValue(controlName, Transaction.DeliveryComment); + if (StringUtil.GetLength(Transaction.DeliveryComment) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryComment)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryComment)]); + } + + // Delivery Department. + if (Transaction.DeliveryDepartment != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.DeliveryDepartment); + responseData.SetControlValue(controlName, Transaction.DeliveryDepartment); + if (StringUtil.GetLength(Transaction.DeliveryDepartment) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryDepartment)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryDepartment)]); + } + + // Delivery Nominal code. + if (Transaction.DeliveryNominalCode != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.DeliveryNominalCode); + responseData.SetControlValue(controlName, Transaction.DeliveryNominalCode); + if (StringUtil.GetLength(Transaction.DeliveryNominalCode) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryNominalCode)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_DeliveryNominalCode)]); + } + + // Transaction Notes. + if (Transaction.Notes != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.Notes); + responseData.SetControlValue(controlName, Transaction.Notes); + if (!Transaction.Notes.IsEmpty() && StringUtil.GetLength(Transaction.Notes) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_Notes)) + responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Transaction_Notes)]); + } + + // Transaction status. + if (Transaction.StatusCode != null) + { + String controlName = Model_Transaction.GetFieldName(Model_Transaction.ItemField.Status); + if (Transaction.StatusCode.IsEmpty()) + responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]); + else if (!SbmTransaction.ValidStatusesByType(transactionType).Contains(GetTransactionStatus())) + responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]); + } + + return !responseData.HasControlErrors(); + } + + //------------------------------------------------------------------- + } + //======================================================================= +} diff --git a/SaBusinessMgrCoreWebPortal/SaBusinessMgrCoreWebPortal.csproj b/SaBusinessMgrCoreWebPortal/SaBusinessMgrCoreWebPortal.csproj index 1f171e0..8123112 100644 --- a/SaBusinessMgrCoreWebPortal/SaBusinessMgrCoreWebPortal.csproj +++ b/SaBusinessMgrCoreWebPortal/SaBusinessMgrCoreWebPortal.csproj @@ -13,9 +13,9 @@ - - - + + + diff --git a/SaBusinessMgrCoreWebPortal/Views/Commodity/Panel-CommodityList.cshtml b/SaBusinessMgrCoreWebPortal/Views/Commodity/Panel-CommodityList.cshtml index 755f957..c0cc6da 100644 --- a/SaBusinessMgrCoreWebPortal/Views/Commodity/Panel-CommodityList.cshtml +++ b/SaBusinessMgrCoreWebPortal/Views/Commodity/Panel-CommodityList.cshtml @@ -68,3 +68,5 @@
  • XXX
+ + \ No newline at end of file diff --git a/SaBusinessMgrCoreWebPortal/Views/Commodity/Panel-CommodityMaintain.cshtml b/SaBusinessMgrCoreWebPortal/Views/Commodity/Panel-CommodityMaintain.cshtml index 785c78a..9468bf8 100644 --- a/SaBusinessMgrCoreWebPortal/Views/Commodity/Panel-CommodityMaintain.cshtml +++ b/SaBusinessMgrCoreWebPortal/Views/Commodity/Panel-CommodityMaintain.cshtml @@ -62,9 +62,7 @@ - - diff --git a/SaBusinessMgrCoreWebPortal/Views/Shared/_Layout.cshtml b/SaBusinessMgrCoreWebPortal/Views/Shared/_Layout.cshtml index ff82845..239ea31 100644 --- a/SaBusinessMgrCoreWebPortal/Views/Shared/_Layout.cshtml +++ b/SaBusinessMgrCoreWebPortal/Views/Shared/_Layout.cshtml @@ -169,8 +169,8 @@ @* Page body *@ -
-
+
+
@RenderBody()
diff --git a/SaBusinessMgrCoreWebPortal/wwwroot/css/sbm-data.css b/SaBusinessMgrCoreWebPortal/wwwroot/css/sbm-data.css index 6ffddfe..1bfe5d0 100644 --- a/SaBusinessMgrCoreWebPortal/wwwroot/css/sbm-data.css +++ b/SaBusinessMgrCoreWebPortal/wwwroot/css/sbm-data.css @@ -26,7 +26,7 @@ .sbm-panel-data { - margin: 6px auto; + margin: 0 auto; background-color: #f8f8f8; border: solid 1px var(--color-panel-data); border-radius: 6px; diff --git a/SaBusinessMgrCoreWebPortal/wwwroot/css/sbm-main.css b/SaBusinessMgrCoreWebPortal/wwwroot/css/sbm-main.css index ebee47b..1a272fd 100644 --- a/SaBusinessMgrCoreWebPortal/wwwroot/css/sbm-main.css +++ b/SaBusinessMgrCoreWebPortal/wwwroot/css/sbm-main.css @@ -59,6 +59,7 @@ body { flex: 1; min-height: 0; + overflow-y: auto; } } diff --git a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-asset-cat.js b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-asset-cat.js index 6a7ea05..46a14c1 100644 --- a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-asset-cat.js +++ b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-asset-cat.js @@ -52,7 +52,7 @@ } ac.populateItem = function ($item, item) { - if (!item) return; + if (!item) return $item; $pnl.msgs.hide().empty(); $item.prop('id', ac.getItemId(item)); $('.AssetCategoryType', $item).text(item.typeDesc); diff --git a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-asset.js b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-asset.js index 1efe08e..8612b28 100644 --- a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-asset.js +++ b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-asset.js @@ -51,7 +51,7 @@ } ac.populateItem = function ($item, item) { - if (!item) return; + if (!item) return $item; $pnl.msgs.hide().empty(); $item.prop('id', ac.getItemId(item)); $('.AssetCategory', $item).text(item.categoryDesc); diff --git a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-assoc.js b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-assoc.js index b43eb3b..f4c479d 100644 --- a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-assoc.js +++ b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-assoc.js @@ -74,7 +74,7 @@ } as.populateItem = function (env, $item, item) { - if (!item) return; + if (!item) return $item; $item.prop('id', as.getItemId(item)); let cfg = env.config; sbm.populateItemValues(cfg, $item, item.field.value); diff --git a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-cod-typ.js b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-cod-typ.js index f7603c3..7156f9a 100644 --- a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-cod-typ.js +++ b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-cod-typ.js @@ -51,7 +51,7 @@ } ac.populateItem = function ($item, item) { - if (!item) return; + if (!item) return $item; $pnl.msgs.hide().empty(); $item.prop('id', ac.getItemId(item)); $('.CodeTypeCode', $item).text(item.code); diff --git a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-cod.js b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-cod.js index be6ad70..6a86e6c 100644 --- a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-cod.js +++ b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-cod.js @@ -52,7 +52,7 @@ } ac.populateItem = function ($item, item) { - if (!item) return; + if (!item) return $item; $pnl.msgs.hide().empty(); $item.prop('id', ac.getItemId(item)); $('.CodeType', $item).text(item.typeName); diff --git a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-commodity.js b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-commodity.js index 0ebe947..fed302e 100644 --- a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-commodity.js +++ b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-commodity.js @@ -68,7 +68,7 @@ } co.populateItem = function (env, $item, item) { - if (!item) return; + if (!item) return $item; $item.prop('id', co.getItemId(item)); let cfg = env.config; if (cfg) sbm.populateItemValues(cfg, $item, item.field.value); diff --git a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-contact.js b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-contact.js index 994d60d..5f32590 100644 --- a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-contact.js +++ b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-contact.js @@ -75,7 +75,7 @@ } co.populateItem = function (env, $item, item) { - if (!item) return; + if (!item) return $item; $item.prop('id', co.getItemId(item)); let cfg = env.config; if (cfg) sbm.populateItemValues(cfg, $item, item.field.value); diff --git a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-veh-cls.js b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-veh-cls.js index f599fdd..eb84e67 100644 --- a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-veh-cls.js +++ b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-veh-cls.js @@ -51,7 +51,7 @@ } vc.populateItem = function ($item, item) { - if (!item) return; + if (!item) return $item; $pnl.msgs.hide().empty(); $item.prop('id', vc.getItemId(item)); $('.VehicleClassMake', $item).text(item.makeDesc);