628 lines
29 KiB
C#
628 lines
29 KiB
C#
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.Core;
|
|
using Sarand.BusinessMgr.Net.Standard.Base.Data;
|
|
using Sarand.Net.Standard.Base.App;
|
|
using Sarand.Net.Standard.Base.Bus;
|
|
using Sarand.Net.Standard.Base.CodeTypes;
|
|
using Sarand.Net.Standard.Base.Core;
|
|
using Sarand.Net.Standard.Base.Dbas;
|
|
using Sarand.Net.Standard.Base.Security;
|
|
using Sarand.Net.Standard.Base.Utils;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using static Sarand.BusinessMgr.Net.Standard.Base.Data.SbmRepositoryPopulationData;
|
|
|
|
namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles
|
|
{
|
|
//=======================================================================
|
|
/// <summary>
|
|
/// Utilitiy functions relating to a core BusinessMgr database instance.
|
|
/// <para>For instance:</para>
|
|
/// <para>- Verifying repository status.</para>
|
|
/// <para>- Initialisation of new repository.</para>
|
|
/// <para>- Bringing static (tax codes etc) and reference data up to date.</para>
|
|
/// </summary>
|
|
public abstract class SbmCoreInstanceConsole : SaErrorStateItem, ISbmCoreInstanceConsole
|
|
{
|
|
//-------------------------------------------------------------------
|
|
// 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";
|
|
|
|
//-------------------------------------------------------------------
|
|
// Data members.
|
|
|
|
//-------------------------------------------------------------------
|
|
// Construction.
|
|
protected SbmCoreInstanceConsole()
|
|
{
|
|
}
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
}
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Properties.
|
|
public String SecurityGroupCode_Super { get; } = SaSecurityConsole.GroupCode_Super;
|
|
// Core instance.
|
|
public abstract SbmInternals Internals { get; }
|
|
public SaSecurityConsole SecurityConsole { get { return Internals.SecurityConsole; } }
|
|
public ISacsDatabase Database { get { return Internals.BusMgrDatabase; } }
|
|
public DbUpdateInfo DbUpdateInfo { get { return Internals.DbUpdateInfo; } }
|
|
|
|
//-------------------------------------------------------------------
|
|
// Utilities.
|
|
|
|
//-------------------------------------------------------------------
|
|
/// <summary>
|
|
/// Is repository database valid.
|
|
/// <para>- Contains core tables (Affiliate, Association, Commodity etc).</para>
|
|
/// </summary>
|
|
public bool IsRepositoryValid()
|
|
{
|
|
ClearErrorState();
|
|
HashSet<String> tablesExpected = new HashSet<String>("Affiliate,Association,Commodity,Transaction,Requirement,SaSecItem,SaSecLink".Split(','));
|
|
String sql = $"Select {col_Name} From sys.tables";
|
|
try
|
|
{
|
|
HashSet<String> tablesFound = new HashSet<string>();
|
|
using (DbResultSet resultSet = Database.ExecuteQuery(sql))
|
|
{
|
|
if (resultSet != null)
|
|
{
|
|
// Check for query error.
|
|
if (resultSet.HasErrorState())
|
|
return SetErrorState($"{resultSet.ErrorStateMessage.TrimEnd('.')}.");
|
|
// Extract list of tables found.
|
|
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
|
|
{
|
|
NamedValue.Map values = resultSet.GetRecordValues();
|
|
tablesFound.Add(values.GetString(col_Name));
|
|
}
|
|
}
|
|
}
|
|
HashSet<String> tablesNotFound = new HashSet<string>(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;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
/// <summary>
|
|
/// Is repository database initialised.
|
|
/// <para>- Has a valid internal association.</para>
|
|
/// <para>- Has at least one user.</para>
|
|
/// </summary>
|
|
public bool IsRepositoryInitialised()
|
|
{
|
|
ClearErrorState();
|
|
SbmRepositoryInitialisationData initData = new SbmRepositoryInitialisationData();
|
|
try
|
|
{
|
|
// Query first internal association.
|
|
List<String> sql = new List<string>()
|
|
{
|
|
$"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.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<string>()
|
|
{
|
|
$"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.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.");
|
|
}
|
|
|
|
if (SecurityConsole.RequiresPopulation())
|
|
return SetErrorState("Security Database requires population.");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
String msg = "checking repository initialisation";
|
|
SaLogger.Warn($"{SysUtil.Fn} {ExceptionUtil.GetLogMessage(exc, msg)}");
|
|
return SetErrorState($"{exc.GetType().Name} {msg}");
|
|
}
|
|
return OK;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
/// <summary>
|
|
/// Validate repository initialisation data.
|
|
/// <para>- Organisation properties.</para>
|
|
/// <para>- User properties.</para>
|
|
/// <para>- User security properties.</para>
|
|
/// </summary>
|
|
public bool ValidateRepositoryInitialisionData(SbmRepositoryInitialisationData initData)
|
|
{
|
|
ClearErrorState();
|
|
|
|
// Organisation name.
|
|
if (StringUtil.IsBlank(initData.Organisation.Name))
|
|
return SetErrorState("Organisation name must be supplied.");
|
|
if ((ulong)StringUtil.GetLength(initData.Organisation.Name) > Internals.GetColTextLen(SbmDbDfn.ColumnIdx.Affiliate_Name))
|
|
return SetErrorState("Organisation name exceeds max chars.");
|
|
|
|
// Organisation VAT reg.
|
|
if ((ulong)StringUtil.GetLength(initData.Organisation.VatReg) > Internals.GetColTextLen(SbmDbDfn.ColumnIdx.Affiliate_VatReg))
|
|
return SetErrorState("Company VAT reg exceeds max chars.");
|
|
|
|
// Organisation Company Number.
|
|
if ((ulong)StringUtil.GetLength(initData.Organisation.CompanyNo) > Internals.GetColTextLen(SbmDbDfn.ColumnIdx.Affiliate_CompanyNo))
|
|
return SetErrorState("Company number exceeds max chars.");
|
|
|
|
// Organisation Company Number.
|
|
if ((ulong)StringUtil.GetLength(initData.Organisation.Website) > Internals.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) > Internals.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) > Internals.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) > Internals.GetColTextLen(SbmDbDfn.ColumnIdx.Affiliate_Email) || (ulong)StringUtil.GetLength(initData.User.Email) > Internals.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) > Internals.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;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
/// <summary>
|
|
/// Initialise repository.
|
|
/// <para>- Organisation contact.</para>
|
|
/// <para>- Internal association.</para>
|
|
/// <para>- Security item and 'Super' group.</para>
|
|
/// <para>- User contact.</para>
|
|
/// <para>- User member association.</para>
|
|
/// </summary>
|
|
public bool InitialiseRepository(SbmRepositoryInitialisationData initData)
|
|
{
|
|
ClearErrorState();
|
|
if (!ValidateRepositoryInitialisionData(initData)) return false;
|
|
|
|
using (DisposableCollection<SacsDisposable> disposables = new DisposableCollection<SacsDisposable>())
|
|
{
|
|
//-----------------------------------------------------------
|
|
// Organisation Contact.
|
|
|
|
// Retrieve existing Organisation.
|
|
SbmAffiliate affiliateOrganisation = Internals.AccountMgr.GetAffiliateById(initData.Organisation.AffiliateId);
|
|
if (affiliateOrganisation == null && SysId.IsValid(initData.Organisation.AffiliateId))
|
|
return SetErrorState("Identified Organisation Contact not found.");
|
|
if (affiliateOrganisation != null && !affiliateOrganisation.IsOrganisation())
|
|
return SetErrorState("Identified Contact is not an organisation.");
|
|
if (affiliateOrganisation == null)
|
|
affiliateOrganisation = Internals.AccountMgr.GetAffiliateByTypeName(Sbm.AffiliateType.AnyOrganisation, initData.Organisation.Name);
|
|
if (affiliateOrganisation == null)
|
|
{
|
|
// Create new organisation.
|
|
affiliateOrganisation = Internals.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.AccountMgr.InsertAffiliate(affiliateOrganisation, DbUpdateInfo))
|
|
return SetErrorState($"Failed to insert Organisation contact - {Internals.AccountMgr.ErrorStateMessage}");
|
|
}
|
|
else
|
|
{
|
|
if (!Internals.AccountMgr.UpdateAffiliate(affiliateOrganisation, DbUpdateInfo))
|
|
return SetErrorState($"Failed to update Organisation contact - {Internals.AccountMgr.ErrorStateMessage}");
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// Organisation Internal association.
|
|
|
|
// Retrieve existing Internal Association for Organisation.
|
|
SbmAssociation associationInternal = Internals.AccountMgr.GetInternalAssociation(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($"Identified 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.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.AccountMgr.CreateAssociation(affiliateOrganisation.Id, Sbm.AssociationType.Internal, affiliateOrganisation.Id);
|
|
disposables.Add(associationInternal);
|
|
|
|
// Store Internal Association.
|
|
if (!SysId.IsValid(associationInternal.Id))
|
|
{
|
|
if (!Internals.AccountMgr.InsertAssociation(associationInternal, DbUpdateInfo))
|
|
return SetErrorState($"Failed to insert Internal Association for Organisation - {Internals.AccountMgr.ErrorStateMessage}");
|
|
}
|
|
else
|
|
{
|
|
if (!Internals.AccountMgr.UpdateAssociation(associationInternal, DbUpdateInfo))
|
|
return SetErrorState($"Failed to update Internal Association for Organisation - {Internals.AccountMgr.ErrorStateMessage}");
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// Security.
|
|
|
|
// Initialise security data if required.
|
|
if (SecurityConsole.RequiresPopulation() && !SecurityConsole.PopulateSecurityRights(DbUpdateInfo))
|
|
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(StringUtil.OnBlank(initData.User.Code, initData.User.Email), $"{initData.User.LastName}, {initData.User.FirstName}", DbUpdateInfo))
|
|
return SetErrorState($"Failed to create User Security Item - {SecurityConsole.ErrorStateMessage.TrimEnd('.')}.");
|
|
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;
|
|
if (initData.User.PasswordSet || SecurityConsole.PasswordIsBlank(securityItemUser))
|
|
SecurityConsole.SetPassword(securityItemUser, initData.User.Password);
|
|
if (!SecurityConsole.UpdateSecurityItem(securityItemUser, DbUpdateInfo))
|
|
return SetErrorState($"Failed to update User Security Item - {SecurityConsole.ErrorStateMessage.TrimEnd('.')}.");
|
|
|
|
// 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))
|
|
return SetErrorState($"Failed to assign User Security Item to Super Group - {SecurityConsole.ErrorStateMessage.TrimEnd('.')}.");
|
|
|
|
//-----------------------------------------------------------
|
|
// User Contact.
|
|
|
|
SbmAffiliate affiliateUser = null;
|
|
if (SysId.IsValid(initData.User.AffiliateId))
|
|
{
|
|
// Retrieve supplied User Contact.
|
|
affiliateUser = Internals.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.AccountMgr.GetAffiliateByUserId(securityItemUser.Id);
|
|
disposables.Add(affiliateUser);
|
|
}
|
|
|
|
if (affiliateUser == null)
|
|
{
|
|
// Retrieve User Contact by name.
|
|
affiliateUser = Internals.AccountMgr.GetIndividualByName(initData.User.FirstName, initData.User.LastName);
|
|
disposables.Add(affiliateUser);
|
|
}
|
|
|
|
if (affiliateUser == null)
|
|
{
|
|
// Create User Contact.
|
|
affiliateUser = Internals.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.AccountMgr.InsertAffiliate(affiliateUser, DbUpdateInfo))
|
|
return SetErrorState($"Failed to insert User contact - {Internals.AccountMgr.ErrorStateMessage}");
|
|
}
|
|
else
|
|
{
|
|
if (!Internals.AccountMgr.UpdateAffiliate(affiliateUser, DbUpdateInfo))
|
|
return SetErrorState($"Failed to update User contact - {Internals.AccountMgr.ErrorStateMessage}");
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// User Member Association.
|
|
|
|
// Attempt to retrieve existing Member Association.
|
|
SbmAssociation associationMember = Internals.AccountMgr.GetAssociationByOwnerTypeTarget(affiliateOrganisation.Id, Sbm.AssociationType.Member, affiliateUser.Id);
|
|
if (associationMember == null)
|
|
// Create Member Association.
|
|
associationMember = Internals.AccountMgr.CreateAssociation(affiliateOrganisation.Id, Sbm.AssociationType.Member, affiliateUser.Id);
|
|
disposables.Add(associationMember);
|
|
associationMember.Supervised = true;
|
|
|
|
// Store User Association.
|
|
if (!SysId.IsValid(associationMember.Id))
|
|
{
|
|
if (!Internals.AccountMgr.InsertAssociation(associationMember, DbUpdateInfo))
|
|
return SetErrorState($"Failed to insert Member Association for User - {Internals.AccountMgr.ErrorStateMessage}");
|
|
}
|
|
else
|
|
{
|
|
if (!Internals.AccountMgr.UpdateAssociation(associationMember, DbUpdateInfo))
|
|
return SetErrorState($"Failed to update Member Association for User - {Internals.AccountMgr.ErrorStateMessage}");
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// Populate reference data.
|
|
PopulateReferenceData();
|
|
|
|
//-----------------------------------------------------------
|
|
// Populate initialisation data Identifiers.
|
|
|
|
initData.Organisation.AffiliateId = affiliateOrganisation.Id;
|
|
initData.Organisation.AssociationId = associationInternal.Id;
|
|
initData.User.AffiliateId = affiliateUser.Id;
|
|
initData.User.SecurityItemId = securityItemUser.Id;
|
|
|
|
//-----------------------------------------------------------
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
/// <summary>
|
|
/// Add User Account.
|
|
/// </summary>
|
|
public bool AddUserAccount(SbmRepositoryPopulationData.UserAccount userAccount)
|
|
{
|
|
// Logic is similar to setting up User Account during repository initialisation above, except:
|
|
// - Owner must exist before user is populated.
|
|
// - User Security Item must not exist.
|
|
// - User is assigned to Security group by code rather than specifically to 'Super' group.
|
|
// - User Affiliate and Member Association must not exist.
|
|
ClearErrorState();
|
|
|
|
//-----------------------------------------------------------
|
|
// Owner.
|
|
if (!SysId.IsValid(userAccount.AffiliateIdOwner))
|
|
return SetErrorState("Owner affiliate must be identified.");
|
|
SbmAffiliate affiliateOwner = Internals.AccountMgr.GetAffiliateById(userAccount.AffiliateIdOwner);
|
|
if (affiliateOwner == null)
|
|
return SetErrorState("Owner affiliate not found.");
|
|
if (affiliateOwner.Status != SaStatus.Current)
|
|
return SetErrorState("Owner affiliate is not active.");
|
|
|
|
// Internal association.
|
|
SbmAssociation associationOwner = Internals.AccountMgr.GetInternalAssociation(userAccount.AffiliateIdOwner);
|
|
if (associationOwner == null)
|
|
return SetErrorState("Internal Association not found.");
|
|
if (associationOwner.Status != SaStatus.Current)
|
|
return SetErrorState("Internal Association is not active.");
|
|
|
|
//-----------------------------------------------------------
|
|
// User Security Item.
|
|
String userCode = StringUtil.OnBlank(userAccount.UserCode, userAccount.Email);
|
|
|
|
// Retrieve Security Item by code.
|
|
SaSecurityItem securityItemUser = SecurityConsole.GetSecurityItemByCode(SaSecurity.ItemType.User, userCode);
|
|
if (securityItemUser != null)
|
|
return SetErrorState("User Security Item already exists.");
|
|
|
|
// Create User Security Item.
|
|
if (!SecurityConsole.CreateUser(StringUtil.OnBlank(userCode), $"{userAccount.LastName}, {userAccount.FirstName}", DbUpdateInfo))
|
|
return SetErrorState($"Failed to create User Security Item - {SecurityConsole.ErrorStateMessage.TrimEnd('.')}.");
|
|
securityItemUser = SecurityConsole.GetSecurityItemByCode(SaSecurity.ItemType.User, userCode);
|
|
if (securityItemUser == null)
|
|
return SetErrorState($"Failed to retrieve User Security Item after creation. Code: {userCode}.");
|
|
|
|
// Populate User Security Item properties.
|
|
securityItemUser.EmailAddress = userAccount.Email;
|
|
SecurityConsole.SetPassword(securityItemUser, userAccount.Password);
|
|
if (!SecurityConsole.UpdateSecurityItem(securityItemUser, DbUpdateInfo))
|
|
return SetErrorState($"Failed to update User Security Item - {SecurityConsole.ErrorStateMessage.TrimEnd('.')}.");
|
|
|
|
// Assign to Security Group.
|
|
if (!StringUtil.IsBlank(userAccount.SecurityGroupCode))
|
|
{
|
|
SysId securityGroupId = SecurityConsole.GetIdForItemCode(SaSecurity.ItemType.Group, userAccount.SecurityGroupCode);
|
|
if (!SysId.IsValid(securityGroupId))
|
|
return SetErrorState($"Failed to identify security group. Code: '{userAccount.SecurityGroupCode}'.");
|
|
if (!SecurityConsole.ItemsAreLinked(securityItemUser.Id, securityGroupId) && !SecurityConsole.AssignUserToGroup(securityItemUser.Code, SecurityGroupCode_Super, DbUpdateInfo))
|
|
return SetErrorState($"Failed to assign User Security Item to Group '{userAccount.SecurityGroupCode}' - {SecurityConsole.ErrorStateMessage.TrimEnd('.')}.");
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// User Contact.
|
|
|
|
// Retrieve User Contact by User Code.
|
|
SbmAffiliate affiliateUser = Internals.AccountMgr.GetAffiliateByUserId(securityItemUser.Id);
|
|
if (affiliateUser != null)
|
|
return SetErrorState($"User Affiliate already exists for the Security User.");
|
|
|
|
// Retrieve User Contact by name.
|
|
affiliateUser = Internals.AccountMgr.GetIndividualByName(userAccount.FirstName, userAccount.LastName);
|
|
if (affiliateUser != null)
|
|
return SetErrorState($"User Affiliate already exists for the Security User.");
|
|
|
|
// Create User Contact.
|
|
affiliateUser = Internals.AccountMgr.CreateAffiliate(Sbm.AffiliateType.Individual);
|
|
affiliateUser.FirstName = userAccount.FirstName;
|
|
affiliateUser.LastName = userAccount.LastName;
|
|
affiliateUser.Email = userAccount.Email;
|
|
affiliateUser.UserId = securityItemUser.Id;
|
|
|
|
// Store User Contact.
|
|
if (!Internals.AccountMgr.InsertAffiliate(affiliateUser, DbUpdateInfo))
|
|
return SetErrorState($"Failed to insert User contact - {Internals.AccountMgr.ErrorStateMessage}");
|
|
|
|
//-----------------------------------------------------------
|
|
// User Member Association.
|
|
|
|
// Attempt to retrieve existing Member Association.
|
|
SbmAssociation associationMember = Internals.AccountMgr.GetAssociationByOwnerTypeTarget(userAccount.AffiliateIdOwner, Sbm.AssociationType.Member, affiliateUser.Id);
|
|
if (associationMember != null)
|
|
return SetErrorState($"User Member Association already exists.");
|
|
|
|
// Create Member Association.
|
|
associationMember = Internals.AccountMgr.CreateAssociation(userAccount.AffiliateIdOwner, Sbm.AssociationType.Member, affiliateUser.Id);
|
|
associationMember.Code = userAccount.MemberCode;
|
|
associationMember.Supervised = true;
|
|
|
|
// Store Member Association.
|
|
if (!Internals.AccountMgr.InsertAssociation(associationMember, DbUpdateInfo))
|
|
return SetErrorState($"Failed to insert Member Association for User - {Internals.AccountMgr.ErrorStateMessage}");
|
|
|
|
return true;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
/// <summary>
|
|
/// POpulate reference data.
|
|
/// <br/>- Code Types.
|
|
/// </summary>
|
|
public bool PopulateReferenceData()
|
|
{
|
|
ClearErrorState();
|
|
|
|
// Code types.
|
|
List<SaCodeTypeDfn> codeTypeDfns = Internals.CodeTypeConsole.CodeTypeDefinitions;
|
|
foreach (SaCodeTypeDfn codeTypeDfn in codeTypeDfns)
|
|
{
|
|
if (Internals.CodeTypeConsole.PopulateCodeType(codeTypeDfn.Code, DbUpdateInfo))
|
|
{
|
|
//foreach (var code in codeTypeDfn.Codes)
|
|
// Internals.CodeTypeConsole.PopulateCode(codeTypeDfn.sCode, code.Code, code.Desc);
|
|
}
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
}
|
|
//=======================================================================
|
|
}
|