Files
BusinessMgr-2019/SaBusMgrStandardBase/Base/Mgr/SbmCoreMgr.cs
T

451 lines
18 KiB
C#

using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
using Sarand.BusinessMgr.Net.Standard.Base.Core;
using Sarand.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.Diary;
using Sarand.Net.Standard.Base.Interfaces;
using Sarand.Net.Standard.Base.ItemData;
using Sarand.Net.Standard.Base.ItemDocs;
using Sarand.Net.Standard.Base.ItemOptions;
using Sarand.Net.Standard.Base.ReferenceData;
using Sarand.Net.Standard.Base.Security;
using Sarand.Net.Standard.Base.UpdateLog;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr
{
//=======================================================================
public abstract class SbmCoreMgr : SbmItemMgr
{
//-------------------------------------------------------------------
// Code type cache.
public class CodeTypeCache
{
/// <summary>
/// Cached codes by code type.
/// <para>NB Likely to only contain a subset of code types depending on context.</para>
/// </summary>
private Dictionary<String, List<SaCode>> codesByCodeType { get; }
// Construction.
public CodeTypeCache(Dictionary<String, List<SaCode>> codes)
{
codesByCodeType = codes;
}
/// <summary>Are there any codes of the specified type.</summary>
public bool CodeTypeHasCodes(Sbm.ApplCodeType codeType)
{
String codeTypeCode = SbmSystem.GetCodeTypeCode(codeType);
return codesByCodeType.ContainsKey(codeTypeCode)
? codesByCodeType[codeTypeCode].Count > 0
: false;
}
/// <summary>Get the description for the code belonging to the specified code type.</summary>
public String GetDescForCodeTypeCode(Sbm.ApplCodeType codeType, String code, bool defaultToCode = true)
{
List<SaCode> codes = GetCodesForCodeType(codeType, false);
return codes?.GetDescForCode(code, defaultToCode ? code : "") ?? "";
}
/// <summary>Retrieve codes for specified code type.</summary>
public List<SaCode> GetCodesForCodeType(Sbm.ApplCodeType codeType, bool activeOnly = true)
{
String codeTypeCode = SbmSystem.GetCodeTypeCode(codeType);
return codesByCodeType.ContainsKey(codeTypeCode)
? new List<SaCode>(codesByCodeType[codeTypeCode].FindAll(code => !activeOnly || code.Status == SaCode.ActiveStatus))
: null;
}
/// <summary>Retrieve code descs for specified code type.</summary>
public List<CodeDesc> GetCodeDescsForCodeType(Sbm.ApplCodeType codeType, bool activeOnly = true)
{
String codeTypeCode = SbmSystem.GetCodeTypeCode(codeType);
return codesByCodeType.ContainsKey(codeTypeCode)
? new List<CodeDesc>(codesByCodeType[codeTypeCode].FindAll(code => !activeOnly || code.Status == SaCode.ActiveStatus).Select(code => new CodeDesc(code.Code, code.Description)))
: null;
}
}
//-------------------------------------------------------------------
// Data members.
private class DataMembers
{
// Externally supplied Internals - disposed elsewhere.
public SbmInternals internalsSupplied;
// Internally constructed Internals - disposed here.
public SbmInternals internals;
// Numeric control values.
public bool numericControlValuesInitialised { get; set; }
public int weightDecimals { get; set; }
public int lengthDecimals { get; set; }
public int volumeDecimals { get; set; }
public int densityDecimals { get; set; }
public int boxQuantityDecimals { get; set; }
public int orderQuantityDecimals { get; set; }
// Reference data.
public List<TypeCodeDesc> currencyCodes { get; set; }
// Locations.
public bool LocationIdsPopulated { get; set; }
public HashSet<SysId> LocationIds_All { get; } = new HashSet<SysId>();
public HashSet<SysId> LocationIds_Sales { get; } = new HashSet<SysId>();
public HashSet<SysId> LocationIds_NonSales { get; } = new HashSet<SysId>();
public HashSet<SysId> LocationIds_Calc { get; } = new HashSet<SysId>();
}
private readonly DataMembers mbr = new DataMembers();
//-------------------------------------------------------------------
// Static initialisation.
static SbmCoreMgr()
{
}
//-------------------------------------------------------------------
// Construction.
protected SbmCoreMgr(SbmInternals internals)
{
if (internals == null)
throw new NotSupportedException("SbmItemMgr Internals must be supplied");
mbr.internalsSupplied = internals;
UserContext = internals.UserContext;
Initialise();
}
protected SbmCoreMgr(ISbmUserOrganisationContext userContext)
{
if (userContext == null)
throw new NotSupportedException("SbmItemMgr User context must be supplied");
mbr.internalsSupplied = null;
this.UserContext = userContext;
Initialise();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (mbr.internals != null) mbr.internals.Dispose();
}
base.Dispose(disposing);
}
//-------------------------------------------------------------------
// Initialisation.
private void Initialise()
{
}
private void InitialiseNumericControlValues()
{
if (mbr.numericControlValuesInitialised) return;
mbr.numericControlValuesInitialised = true;
// Numeric formatting values.
mbr.weightDecimals = Internals.GetOwnerOption_NumericDecimals(Sbm.OrgOption_NumericDecimals.CommodityWeight);
mbr.lengthDecimals = Internals.GetOwnerOption_NumericDecimals(Sbm.OrgOption_NumericDecimals.CommodityLength);
mbr.volumeDecimals = Internals.GetOwnerOption_NumericDecimals(Sbm.OrgOption_NumericDecimals.CommodityVolume);
mbr.densityDecimals = Internals.GetOwnerOption_NumericDecimals(Sbm.OrgOption_NumericDecimals.CommodityDensity);
mbr.boxQuantityDecimals = 0;
mbr.orderQuantityDecimals = Internals.GetOwnerOption_NumericDecimals(Sbm.OrgOption_NumericDecimals.OrderQuantity);
}
//-------------------------------------------------------------------
// Async initialisation.
public async void InitialiseCodeTypesAsync()
{
if (codeTypeCache != null) return;
// Populate cache with codes for all supported code types.
// Intended to minimise db I/O to retrieve all required codes.
SaCode.Params prmCode = new SaCode.Params();
foreach (Sbm.ApplCodeType codeType in SupportedCodeTypes)
prmCode.CodeTypeCodes.Add(SbmSystem.GetCodeTypeCode(codeType));
prmCode.StatusCat = SaCode.StatusCat.Any;
codeTypeCache = new CodeTypeCache(await CodeTypeConsole.GetCodesByCodeTypeAsync(prmCode));
}
//-------------------------------------------------------------------
// Properties.
// System codes.
protected List<TypeCodeDesc> ItemTypes { get { return GetSystemCodes(Sbm.SystemCode.ItemType); } }
protected List<TypeCodeDesc> InterfaceOptionCodes { get { return GetSystemCodes(Sbm.SystemCode.InterfaceOption); } }
// Numeric control values.
protected int WeightDecimals { get { InitialiseNumericControlValues(); return mbr.weightDecimals; } }
protected int LengthDecimals { get { InitialiseNumericControlValues(); return mbr.lengthDecimals; } }
protected int VolumeDecimals { get { InitialiseNumericControlValues(); return mbr.volumeDecimals; } }
protected int DensityDecimals { get { InitialiseNumericControlValues(); return mbr.densityDecimals; } }
protected int BoxQuantityDecimals { get { InitialiseNumericControlValues(); return mbr.boxQuantityDecimals; } }
protected int OrderQuantityDecimals { get { InitialiseNumericControlValues(); return mbr.orderQuantityDecimals; } }
// Internals.
protected SbmInternals Internals
{
get
{
if (mbr.internalsSupplied != null) return mbr.internalsSupplied;
if (mbr.internals == null) mbr.internals = new SbmInternals(UserContext);
return mbr.internals;
}
}
// Session.
protected ISbmUserOrganisationContext UserContext { get; }
protected SbmSessionContext SessionContext { get { return UserContext.SessionContext; } }
public SysId AffiliateId_Owner { get { return UserContext.OrganisationAffiliateId; } }
protected SbmAccountsConsole AccountsDfn { get { return Internals.AccountsConsole; } }
protected DbUpdateInfo DbUpdateInfo { get { return Internals.DbUpdateInfo; } }
// User security profile.
public bool UserCanViewCommoditySalesFinancials() { return UserContext.SecurityProfile.UserCanViewFinancials(Sbm.FinancialType.CommoditySales); }
public bool UserCanViewCommoditySupplyFinancials() { return UserContext.SecurityProfile.UserCanViewFinancials(Sbm.FinancialType.CommoditySupply); }
// Managers.
protected SbmAccountMgr AccountMgr { get { return Internals.AccountMgr; } }
protected SbmCommodityMgr CommodityMgr { get { return Internals.CommodityMgr; } }
protected SbmAssetMgr AssetMgr { get { return Internals.AssetMgr; } }
protected SbmPriceMgr PriceMgr { get { return Internals.PriceMgr; } }
protected SbmTransactionMgr TransactionMgr { get { return Internals.TransactionMgr; } }
protected SbmStockMgr StockMgr { get { return Internals.StockMgr; } }
protected SbmProcessMgr ProcessMgr { get { return Internals.ProcessMgr; } }
protected SbmDataItemMgr DataItemMgr { get { return Internals.DataItemMgr; } }
// Consoles.
protected SbmSessionConsole SessionConsole { get { return Internals.SessionConsole; } }
protected SaDiaryConsole DiaryConsole { get { return Internals.DiaryConsole; } }
protected SaSecurityConsole SecurityConsole { get { return Internals.SecurityConsole; } }
protected SaCodeTypeConsole CodeTypeConsole { get { return Internals.CodeTypeConsole; } }
protected SaReferenceDataConsole ReferenceDataConsole { get { return Internals.ReferenceDataConsole; } }
protected SaUpdateLogConsole UpdateLogConsole { get { return Internals.UpdateLogConsole; } }
protected SaInterfaceConsole InterfaceConsole { get { return Internals.InterfaceConsole; } }
protected SaItemDocConsole ItemDocConsole { get { return Internals.ItemDocConsole; } }
protected SaItemOptionConsole ItemOptionConsole { get { return Internals.ItemOptionConsole; } }
protected SaItemDataConsole ItemDataConsole { get { return Internals.ItemDataConsole; } }
// Configurations.
protected SbmStockControlConfig StockControlConfig { get { return Internals.StockControlConfig; } }
protected SbmRequirementCostingConfig RequirementCostingConfig { get { return Internals.RequirementCostingConfig; } }
// Currencies.
protected List<TypeCodeDesc> CurrencyCodes
{
get
{
if (mbr.currencyCodes == null)
mbr.currencyCodes = SaReferenceDataConsole.GetReferenceDataCodes(ReferenceDataSystemCode.CurrencyCode);
return new List<TypeCodeDesc>(mbr.currencyCodes);
}
}
protected List<SaCurrency> GetCurrencies()
{
return Internals.GetCurrencies();
}
protected SaCurrency GetCurrencyById(SysId currencyId)
{
return Internals.GetCurrencyById(currencyId);
}
protected SaCurrency GetCurrencyByCode(String currencyCode)
{
return Internals.GetCurrencyByCode(currencyCode);
}
protected static byte CurrencyDecimalsDefault { get { return SbmInternals.CurrencyDecimalsDefault; } }
protected byte GetCurrencyDecimalsForCurrencyById(SysId currencyId)
{
return Internals.GetCurrencyDecimalsForCurrencyById(currencyId);
}
//-------------------------------------------------------------------
// Utilities.
public List<TypeCodeDesc> GetSystemCodes(Sbm.SystemCode systemCode)
{
return Internals.GetSystemCodes(systemCode);
}
// Database utilities.
public bool TableExists(SbmDbDfn.TableIdx tableIdx)
{
SbmApplication application = SbmGlobals.Application;
if (application != null)
{
ISacsDatabase busMgrDb = application.GetBusMgrDatabase(SessionContext);
return application.DbTableExists(busMgrDb, tableIdx);
}
return false;
}
public virtual bool ColumnExists(SbmDbDfn.ColumnIdx columnIdx)
{
SbmApplication application = SbmGlobals.Application;
if (application != null)
{
ISacsDatabase busMgrDb = application.GetBusMgrDatabase(SessionContext);
return application.DbColumnExists(busMgrDb, columnIdx);
}
return false;
}
//-------------------------------------------------------------------
// Session console utilities.
public bool AllowConfigOption(Sbm.ConfigOption configOption)
{
return SessionConsole.AllowOption(configOption);
}
public bool AllowAffiliateType(Sbm.AffiliateType affiliateType)
{
return SessionConsole.AllowAffiliateType(affiliateType);
}
public bool AllowAssociationType(Sbm.AssociationType associationType)
{
return SessionConsole.AllowAssociationType(associationType);
}
public bool AllowTransactionType(Sbm.TransactionType transactionType)
{
return SessionConsole.AllowTransactionType(transactionType);
}
public String GetAttributeCaption(SbmDbDfn.ColumnIdx columnIdx, String defaultValue)
{
return SessionConsole.GetAttributeCaption(columnIdx, defaultValue);
}
//-------------------------------------------------------------------
// C o d e T y p e s
//-------------------------------------------------------------------
public virtual List<Sbm.ApplCodeType> SupportedCodeTypes { get; } = new List<Sbm.ApplCodeType>();
private CodeTypeCache codeTypeCache;
public bool CodeTypeHasCodes(Sbm.ApplCodeType codeType)
{
if (DebugMode && !SupportedCodeTypes.Contains(codeType)) throw new NotSupportedException($"{SysUtil.Fn} Unsupported code type: {codeType}");
PopulateCodeTypes();
return codeTypeCache.CodeTypeHasCodes(codeType);
}
public String GetCodeTypeCodeDesc(Sbm.ApplCodeType codeType, String code, bool defaultToCode = true)
{
if (DebugMode && !SupportedCodeTypes.Contains(codeType)) throw new NotSupportedException($"{SysUtil.Fn} Unsupported code type: {codeType}");
PopulateCodeTypes();
List<SaCode> codes = codeTypeCache.GetCodesForCodeType(codeType, false);
if (codes != null)
return codes.GetDescForCode(code, defaultToCode ? code : "");
return "";
}
public List<SaCode> GetCodesForCodeType(Sbm.ApplCodeType codeType, bool activeOnly = true)
{
if (DebugMode && !SupportedCodeTypes.Contains(codeType)) throw new NotSupportedException($"{SysUtil.Fn} Unsupported code type: {codeType}");
PopulateCodeTypes();
return codeTypeCache.GetCodesForCodeType(codeType, activeOnly);
}
public List<CodeDesc> GetCodeDescsForCodeType(Sbm.ApplCodeType codeType, bool activeOnly = true)
{
if (DebugMode && !SupportedCodeTypes.Contains(codeType)) throw new NotSupportedException($"{SysUtil.Fn} Unsupported code type: {codeType}");
PopulateCodeTypes();
return codeTypeCache.GetCodeDescsForCodeType(codeType, activeOnly);
}
private void PopulateCodeTypes()
{
if (codeTypeCache != null) return;
// Populate cache with codes for all supported code types.
// Intended to minimise db I/O to retrieve all required codes.
SaCode.Params prmCode = new SaCode.Params();
foreach (Sbm.ApplCodeType codeType in SupportedCodeTypes)
prmCode.CodeTypeCodes.Add(SbmSystem.GetCodeTypeCode(codeType));
prmCode.StatusCat = SaCode.StatusCat.Any;
Dictionary<String, List<SaCode>> codesByCodeType = CodeTypeConsole.GetCodesByCodeType(prmCode);
// Populate any supported code types without codes.
foreach (Sbm.ApplCodeType codeType in SupportedCodeTypes)
{
String codeTypeCode = SbmSystem.GetCodeTypeCode(codeType);
if (!codesByCodeType.ContainsKey(codeTypeCode))
codesByCodeType[codeTypeCode] = new List<SaCode>();
}
codeTypeCache = new CodeTypeCache(codesByCodeType);
}
//-------------------------------------------------------------------
// R e f e r e n c e D a t a
//-------------------------------------------------------------------
// Currencies.
public SaCurrency GetDefaultCurrency()
{
String currencyCode = CurrencyCodes.GetCodeForType(SaCurrencyCode.Sterling);
return Internals.GetCurrencyByCode(currencyCode);
}
public SaCurrency GetCurrency(SysId currencyId)
{
return Internals.GetCurrencyById(currencyId);
}
// Regions.
public SaRegion FindRegionById(SysId regionId)
{
return Internals.GetRegionById(regionId);
}
// Tax codes.
public SaTaxCode FindTaxCodeById(SysId taxCodeId)
{
return Internals.GetTaxCodeById(taxCodeId);
}
public SaTaxCode FindTaxCodeEffectiveOn(String taxCode, DateTime effectiveOn)
{
return Internals.GetTaxCodes().FindByCodeEffectiveOn(taxCode, effectiveOn);
}
// Units of measure.
public SaUnitMeasure FindUnitOfMeasureById(SysId uomId)
{
return Internals.GetUnitOfMeasureById(uomId);
}
public List<SaUnitMeasure> FindUnitsOfMeasureByCategory(SaUomCategory uomCategory)
{
return Internals.GetUnitsOfMeasureByCategory(uomCategory);
}
//-------------------------------------------------------------------
// Locations.
private bool PopulateLocationIds()
{
if (mbr.LocationIdsPopulated) return true;
if (!StockMgr.StockDatabaseIsValid()) return false;
mbr.LocationIdsPopulated = true;
// Query active locations.
SbmLocation.Params prmLocation = new SbmLocation.Params();
prmLocation.StatusCat = SbmLocation.StatusCat.ActiveOnly;
foreach (SbmLocation location in StockMgr.GetLocationList(prmLocation))
{
if (location == null) break;
mbr.LocationIds_All.Add(location.Id);
if (location.CalculateStock)
mbr.LocationIds_Calc.Add(location.Id);
if (location.SalesStock)
mbr.LocationIds_Sales.Add(location.Id);
else
mbr.LocationIds_NonSales.Add(location.Id);
}
// Check if any Sales locations defined.
if (!mbr.LocationIds_Sales.Any())
{
// Assume that all locations are for sales.
mbr.LocationIds_Sales.UnionWith(mbr.LocationIds_NonSales);
mbr.LocationIds_NonSales.Clear();
}
return true;
}
protected HashSet<SysId> GetLocationIds_All()
{
PopulateLocationIds();
return new HashSet<SysId>(mbr.LocationIds_All);
}
protected HashSet<SysId> GetLocationIds_Sales()
{
PopulateLocationIds();
return new HashSet<SysId>(mbr.LocationIds_Sales);
}
protected HashSet<SysId> GetLocationIds_NonSales()
{
PopulateLocationIds();
return new HashSet<SysId>(mbr.LocationIds_NonSales);
}
protected HashSet<SysId> GetLocationIds_Calc()
{
PopulateLocationIds();
return new HashSet<SysId>(mbr.LocationIds_Calc);
}
//-------------------------------------------------------------------
}
//=======================================================================
}