451 lines
18 KiB
C#
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; } }
|
|
protected 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);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
}
|
|
//=======================================================================
|
|
}
|