using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
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 SbmItemMgr : SacsItemMgr
{
//-------------------------------------------------------------------
// System code cache.
/// Central repository for system codes used by manager.
private class SystemCodeCache
{
public SystemCodeCache(ISbmUserContext userContext)
{
this.userContext = userContext;
}
private readonly ISbmUserContext 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 SbmItemMgr()
{
}
//-------------------------------------------------------------------
// Construction.
protected SbmItemMgr(ISbmUserContext userContext)
{
if (userContext == null)
throw new NotSupportedException("SbmItemMgr User context must be supplied");
UserContext = userContext;
ElapsedLogger = new ElapsedTimeLogger(GetType().Name);
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.
protected bool DebugMode { get; } = SacsSystem.DebugMode;
protected ElapsedTimeLogger ElapsedLogger { get; }
// 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;
// System codes.
protected List ItemTypes { get { return GetCodesOfType(Sbm.SystemCode.ItemType); } }
protected List InterfaceOptionCodes { get { return GetCodesOfType(Sbm.SystemCode.InterfaceOption); } }
// Status.
protected String StatusActive { get; } = SacsSystem.GetStatusCode(SaStatus.Active);
protected String StatusProvisional { get; } = SacsSystem.GetStatusCode(SaStatus.Provisional);
protected String StatusAwaiting { get; } = SacsSystem.GetStatusCode(SaStatus.Awaiting);
protected String StatusCurrent { get; } = SacsSystem.GetStatusCode(SaStatus.Current);
protected String StatusCompleted { get; } = SacsSystem.GetStatusCode(SaStatus.Completed);
protected String StatusCancelled { get; } = SacsSystem.GetStatusCode(SaStatus.Cancelled);
protected String StatusDisabled { get; } = SacsSystem.GetStatusCode(SaStatus.Disabled);
protected String StatusDeleted { get; } = SacsSystem.GetStatusCode(SaStatus.Deleted);
// Session.
protected ISbmUserContext 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.Organisation.AffiliateId; } }
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(GetType().Name + ".CodeTypeHasCodes 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(GetType().Name + ".GetCodeTypeCodeDesc 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(GetType().Name + ".GetCodesForCodeType 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(GetType().Name + ".GetCodeDescsForCodeType 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);
}
//-------------------------------------------------------------------
}
//=======================================================================
}