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.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.Interfaces; 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 { //------------------------------------------------------------------- // System code cache. /// Central repository for system codes used by manager. private class SystemCodeCache { public SystemCodeCache(ISbmUserContext_Core userContext) { this.userContext = userContext; } private readonly ISbmUserContext_Core userContext; private Dictionary> systemCodes = new Dictionary>(); public List GetCodesOfType(Sbm.SystemCode systemCode) { if (!systemCodes.ContainsKey(systemCode)) systemCodes[systemCode] = SbmSystem.GetCodesOfType(userContext, systemCode); return new List(systemCodes.GetValue(systemCode, new List())); } } //------------------------------------------------------------------- // Code type cache. public class CodeTypeCache { /// /// Cached codes by code type. /// NB Likely to only contain a subset of code types depending on context. /// private Dictionary> codesByCodeType { get; } // Construction. public CodeTypeCache(Dictionary> codes) { codesByCodeType = codes; } /// Are there any codes of the specified type. public bool CodeTypeHasCodes(Sbm.ApplCodeType codeType) { String codeTypeCode = SbmSystem.GetCodeTypeCode(codeType); return codesByCodeType.ContainsKey(codeTypeCode) ? codesByCodeType[codeTypeCode].Count > 0 : false; } /// Get the description for the code belonging to the specified code type. public String GetDescForCodeTypeCode(Sbm.ApplCodeType codeType, String code, bool defaultToCode = true) { List codes = GetCodesForCodeType(codeType, false); return codes?.GetDescForCode(code, defaultToCode ? code : "") ?? ""; } /// Retrieve codes for specified code type. public List GetCodesForCodeType(Sbm.ApplCodeType codeType, bool activeOnly = true) { String codeTypeCode = SbmSystem.GetCodeTypeCode(codeType); return codesByCodeType.ContainsKey(codeTypeCode) ? new List(codesByCodeType[codeTypeCode].FindAll(code => !activeOnly || code.Status == SaCode.ActiveStatus)) : null; } /// Retrieve code descs for specified code type. public List GetCodeDescsForCodeType(Sbm.ApplCodeType codeType, bool activeOnly = true) { String codeTypeCode = SbmSystem.GetCodeTypeCode(codeType); return codesByCodeType.ContainsKey(codeTypeCode) ? new List(codesByCodeType[codeTypeCode].FindAll(code => !activeOnly || code.Status == SaCode.ActiveStatus).Select(code => new CodeDesc(code.Code, code.Description))) : null; } } //------------------------------------------------------------------- // Data members. private SbmInternals internals; private readonly SystemCodeCache systemCodeCache; private readonly List currencyCodes; private List currencies; private List languages; private List regions; private List taxCodes; private List unitsOfMeasure; //------------------------------------------------------------------- // Static initialisation. static SbmCoreMgr() { } //------------------------------------------------------------------- // Construction. protected SbmCoreMgr(ISbmUserContext_Core userContext) { if (userContext == null) throw new NotSupportedException("SbmItemMgr User context must be supplied"); UserContext = userContext; systemCodeCache = new SystemCodeCache(userContext); // Numeric formatting values. WeightDecimals = UserContext.GetOwnerOption_NumericDecimals(Sbm.OrgOption_NumericDecimals.CommodityWeight); LengthDecimals = UserContext.GetOwnerOption_NumericDecimals(Sbm.OrgOption_NumericDecimals.CommodityLength); VolumeDecimals = UserContext.GetOwnerOption_NumericDecimals(Sbm.OrgOption_NumericDecimals.CommodityVolume); DensityDecimals = UserContext.GetOwnerOption_NumericDecimals(Sbm.OrgOption_NumericDecimals.CommodityDensity); BoxQuantityDecimals = 0; // Reference data. currencyCodes = SaReferenceDataConsole.GetReferenceDataCodes(ReferenceDataSystemCode.CurrencyCode); } protected override void Dispose(bool disposing) { if (disposing) { if (internals != null) internals.Dispose(); } base.Dispose(disposing); } //------------------------------------------------------------------- // 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 ItemTypes { get { return GetCodesOfType(Sbm.SystemCode.ItemType); } } protected List InterfaceOptionCodes { get { return GetCodesOfType(Sbm.SystemCode.InterfaceOption); } } // Numeric control values. protected int WeightDecimals { get; set; } = 0; protected int LengthDecimals { get; set; } = 0; protected int VolumeDecimals { get; set; } = 0; protected int DensityDecimals { get; set; } = 0; protected int BoxQuantityDecimals { get; set; } = 0; protected int OrderQuantityDecimals { get; set; } = 0; // Session. protected ISbmUserContext_Core UserContext { get; } protected SbmSessionContext SessionContext { get { return UserContext.SessionContext; } } protected SbmInternals Internals { get { if (internals == null) internals = new SbmInternals(UserContext); return internals; } } public SysId AffiliateId_Owner { get { return UserContext.OrganisationAffiliateId; } } protected SbmAccountsDfn AccountsDfn { get { return Internals.AccountsDfn; } } protected DbUpdateInfo DbUpdateInfo { get { return Internals.DbUpdateInfo; } } // Managers. protected SbmAccountMgr AccountMgr { get { return Internals.AccountMgr; } } protected SbmCommodityMgr CommodityMgr { get { return Internals.CommodityMgr; } } 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 SbmConfigConsole ConfigConsole { get { return Internals.ConfigConsole; } } 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 SaItemOptionConsole ItemOptionConsole { get { return Internals.ItemOptionConsole; } } protected SaInterfaceConsole InterfaceConsole { get { return Internals.InterfaceConsole; } } protected SaItemDocConsole ItemDocConsole { get { return Internals.ItemDocConsole; } } // Configurations. protected SbmStockControlConfig StockControlConfig { get { return Internals.StockControlConfig; } } protected SbmRequirementCostingConfig RequirementCostingConfig { get { return Internals.RequirementCostingConfig; } } // Currencies. protected List CurrencyCodes { get { return new List(currencyCodes); } } protected List 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 GetCodesOfType(Sbm.SystemCode systemCode) { return systemCodeCache.GetCodesOfType(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 bool ColumnExists(SbmDbDfn.ColumnIdx columnIdx) { SbmApplication application = SbmGlobals.Application; if (application != null) { ISacsDatabase busMgrDb = application.GetBusMgrDatabase(SessionContext); return application.DbColumnExists(busMgrDb, columnIdx); } return false; } //------------------------------------------------------------------- // Configuration console utilities. public bool AllowConfigOption(Sbm.ConfigOption configOption) { return ConfigConsole.AllowOption(UserContext, configOption); } public bool AllowAffiliateType(Sbm.AffiliateType affiliateType) { return ConfigConsole.AllowAffiliateType(UserContext, affiliateType); } public bool AllowAssociationType(Sbm.AssociationType associationType) { return ConfigConsole.AllowAssociationType(UserContext, associationType); } public bool AllowTransactionType(Sbm.TransactionType transactionType) { return ConfigConsole.AllowTransactionType(UserContext, transactionType); } public String GetAttributeCaption(SbmDbDfn.ColumnIdx columnIdx, String defaultValue) { return ConfigConsole.GetAttributeCaption(UserContext, columnIdx, defaultValue); } //------------------------------------------------------------------- // C o d e T y p e s //------------------------------------------------------------------- public virtual List SupportedCodeTypes { get; } = new List(); 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 codes = codeTypeCache.GetCodesForCodeType(codeType, false); if (codes != null) return codes.GetDescForCode(code, defaultToCode ? code : ""); return ""; } public List 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 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> 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(); } codeTypeCache = new CodeTypeCache(codesByCodeType); } //------------------------------------------------------------------- // R e f e r e n c e D a t a //------------------------------------------------------------------- // Currencies. private void PopulateCurrencies() { if (currencies != null) return; SaCurrency.Params prmCurrency = new SaCurrency.Params(); prmCurrency.StatusCat = SaCurrency.StatusCat.Any; currencies = ReferenceDataConsole.GetCurrencyList(prmCurrency); } public SaCurrency GetDefaultCurrency() { PopulateCurrencies(); String currencyCode = CurrencyCodes.GetCodeForType(SaCurrencyCode.Sterling); return currencies.Find(item => item.Code.EqualsCI(currencyCode)); } public SaCurrency GetCurrency(SysId currencyId) { PopulateCurrencies(); return currencies.Find(item => item.Id.Equals(currencyId)); } //------------------------------------------------------------------- // Regions. private void PopulateRegions() { if (regions != null) return; SaRegion.Params prmRegion = new SaRegion.Params(); regions = ReferenceDataConsole.GetRegionList(prmRegion); } public SaRegion FindRegionById(SysId regionId) { PopulateRegions(); return regions.FindById(regionId); } //------------------------------------------------------------------- // Tax codes. private void PopulateTaxCodes() { if (taxCodes != null) return; SaTaxCode.Params prmTaxCode = new SaTaxCode.Params(); taxCodes = ReferenceDataConsole.GetTaxCodeList(prmTaxCode); } public SaTaxCode FindTaxCodeById(SysId taxCodeId) { PopulateTaxCodes(); return taxCodes.Find(item => item.Id.Equals(taxCodeId)); } public SaTaxCode FindTaxCodeEffectiveOn(String taxCode, DateTime effectiveOn) { PopulateTaxCodes(); return taxCodes.FindByCodeEffectiveOn(taxCode, effectiveOn); } //------------------------------------------------------------------- // Units of measure. private void PopulateUnitsOfMeasure() { if (taxCodes != null) return; SaUnitMeasure.Params prmUnitOfMeasure = new SaUnitMeasure.Params(); prmUnitOfMeasure.StatusCat = SaUnitMeasure.StatusCat.Any; unitsOfMeasure = ReferenceDataConsole.GetUnitMeasureList(prmUnitOfMeasure); } public SaUnitMeasure FindUnitOfMeasureById(SysId uomId) { PopulateUnitsOfMeasure(); return unitsOfMeasure.FindById(uomId); } public List FindUnitsOfMeasureByCategory(SaUomCategory uomCategory) { PopulateUnitsOfMeasure(); return unitsOfMeasure.FindAll(item => item.Category == uomCategory); } //------------------------------------------------------------------- } //======================================================================= }