Extract paired business object projects

This commit is contained in:
Andy Howard
2026-10-06 17:48:37 +01:00
parent 5daf7ce97f
commit d3c5ceaf7a
170 changed files with 168 additions and 13 deletions
+264
View File
@@ -0,0 +1,264 @@
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Sarand.Net.Standard.Base.CodeTypes
{
//=======================================================================
public class SaCode : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Pos = 0,
// Code type properties.
CodeTypeId,
CodeType_Code,
CodeType_Name,
// Code properties.
Id,
Code,
Description,
Sequence,
DataValue,
Flag1_Y,
Flag1_Tick,
Flag2_Y,
Flag2_Tick,
// Common properties.
Notes,
Flags,
Status,
Status_Desc,
Status_Ind,
CreateOn_Date,
UpdateOn_Date,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public SysId CodeTypeId { get; set; } = new SysId();
public string Code { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public ushort Sequence { get; set; } = 0;
public string DataValue { get; set; } = string.Empty;
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data()
{
Status = DefaultStatus;
}
// Properties.
public SysId CodeTypeId
{
get { return data.CodeTypeId; }
set { CheckChanged(data.CodeTypeId, value); data.CodeTypeId = value; }
}
public string Code
{
get { return data.Code; }
set { CheckChanged(data.Code, value); data.Code = value; }
}
public string Description
{
get { return data.Description; }
set { CheckChanged(data.Description, value); data.Description = value; }
}
public ushort Sequence
{
get { return data.Sequence; }
set { CheckChanged(data.Sequence, value); data.Sequence = value; }
}
public string DataValue
{
get { return data.DataValue; }
set { CheckChanged(data.DataValue, value); data.DataValue = value; }
}
// Population.
internal void PopulateFrom(Data data)
{
CodeTypeId = data.CodeTypeId;
Code = data.Code;
Description = data.Description;
Sequence = data.Sequence;
DataValue = data.DataValue;
base.PopulateFrom(data);
}
public Data Clone()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
// Error field - identify properties with validation error.
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue CodeType { get; set; } = ValidValue.Valid;
public ValidValue Code { get; set; } = ValidValue.Valid;
public ValidValue Description { get; set; } = ValidValue.Valid;
public ValidValue Sequence { get; set; } = ValidValue.Valid;
public ValidValue DataValue { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
// Flags.
//-------------------------------------------------------------------
// Construction.
public SaCode(SysId id, SysId codeTypeId, string code) :
base(id)
{
base.SetData(data);
CodeTypeId = codeTypeId;
Code = code;
Status = DefaultStatus;
}
//-------------------------------------------------------------------
// Statuses.
private static readonly List<SaStatus> validStatuses = new List<SaStatus>()
{
SaStatus.Current,
SaStatus.Redundant
};
public static SaStatus DefaultStatus { get { return ActiveStatus; } }
public static SaStatus ActiveStatus { get { return SaStatus.Current; } }
public static SaStatus InactiveStatus { get { return SaStatus.Redundant; } }
public static List<SaStatus> ValidStatuses { get { return new List<SaStatus>(validStatuses); } }
public static DataValue.TriStateType GetStatusTriState(SaStatus status)
{
switch (status)
{
case SaStatus.Current:
return Core.DataValue.TriStateType.Green;
case SaStatus.Redundant:
return Core.DataValue.TriStateType.Red;
case SaStatus.Deleted:
return Core.DataValue.TriStateType.Purple;
}
return Core.DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Properties.
public Data GetData() { return data.Clone(); }
public void SetData(Data data)
{
// Properties that cannot be changed if previously specified.
if (SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id))
throw new NotSupportedException($"{SysUtil.Fn} Id cannot be changed");
if (!StringUtil.IsEmpty(Code) && !Code.Equals(data.Code))
throw new NotSupportedException($"{SysUtil.Fn} Code cannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
public SysId CodeTypeId
{
get { return data.CodeTypeId; }
set { data.CodeTypeId = value; }
}
public string Code
{
get { return data.Code; }
set { data.Code = value; }
}
public string Description
{
get { return data.Description; }
set { data.Description = value; }
}
public ushort Sequence
{
get { return data.Sequence; }
set { data.Sequence = value; }
}
public string DataValue
{
get { return data.DataValue; }
set { data.DataValue = value; }
}
//-------------------------------------------------------------------
// Flags - specific to code type definition.
//-------------------------------------------------------------------
// List parameters.
public enum StatusCat
{
Any,
ActiveOnly,
InactiveOnly,
NotDeleted,
DeletedOnly,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
public HashSet<SysId> IdsIncluded { get; } = new HashSet<SysId>();
public HashSet<SysId> IdsExcluded { get; } = new HashSet<SysId>();
public HashSet<SysId> CodeTypeIds { get; } = new HashSet<SysId>();
public HashSet<String> CodeTypeCodes { get; } = new HashSet<string>();
/// <summary>Generic search - code, description etc.</summary>
public string Search { get; set; }
public string Code { get; set; }
public string CodePartial { get; set; }
public string Desc { get; set; }
public string DescPartial { get; set; }
public StatusCat StatusCat { get; set; } = StatusCat.ActiveOnly;
}
//-------------------------------------------------------------------
}
//=======================================================================
public static class SaCodeList
{
// Contents.
public static bool ContainsCode(this List<SaCode> codes, String code, bool currentOnly = true)
{
if (StringUtil.IsEmpty(code)) return false;
return codes.Any(item => item.Code.EqualsCI(code) && (!currentOnly || item.IsStatusCurrent));
}
// Retrieve code.
public static SaCode GetCodeById(this List<SaCode> codes, SysId id)
{
return codes.Find(item => item.Id.Equals(id));
}
public static SaCode GetCodeByCode(this List<SaCode> codes, string code)
{
return codes.Find(item => item.Code.EqualsCI(code));
}
// Retrieve code's description.
public static string GetDescForCode(this List<SaCode> codes, string code, String defaultDesc = "")
{
SaCode saCode = codes.Find(item => item.Code.EqualsCI(code));
if (saCode != null)
return saCode.Description;
return defaultDesc;
}
}
//=======================================================================
}
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
namespace Sarand.Net.Standard.Base.CodeTypes
{
//=======================================================================
public class SaCodeDfn
{
//-------------------------------------------------------------------
public SaCodeDfn (String code, String description)
{
Code = code;
Description = description;
}
//-------------------------------------------------------------------
// Properties.
public String Code { get; private set; } = String.Empty;
public String Description { get; private set; } = String.Empty;
public String Data { get; set; } = String.Empty;
public String Notes { get; set; } = String.Empty;
public ushort Sequence { get; private set; } = 0;
//-------------------------------------------------------------------
}
//=======================================================================
public static class SaCodeDfnList
{
public static void Add(this List<SaCodeDfn> values, String code, String description)
{
values.Add(new SaCodeDfn(code, description));
}
}
//=======================================================================
}
@@ -0,0 +1,232 @@
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.Net.Standard.Base.CodeTypes
{
//=======================================================================
public class SaCodeType : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Pos = 0,
// Code type properties.
Id,
Code,
Name,
MaxCodeLen,
CodeFormat,
NextCode,
AutoAssignCode_Y,
AutoAssignCode_Tick,
Codes_Count,
// Common properties.
Notes,
Flags,
Status,
Status_Desc,
Status_Ind,
CreateOn_Date,
UpdateOn_Date,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public String Code { get; set; } = String.Empty;
public String Name { get; set; } = String.Empty;
public byte MaxCodeLen { get; set; } = 0;
public String CodeFormat { get; set; } = String.Empty;
public String NextCode { get; set; } = String.Empty;
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data()
{
Status = DefaultStatus;
}
// Properties.
public String Code
{
get { return data.Code; }
set { CheckChanged(data.Code, value); data.Code = value; }
}
public String Name
{
get { return data.Name; }
set { CheckChanged(data.Name, value); data.Name = value; }
}
public byte MaxCodeLen
{
get { return data.MaxCodeLen; }
set { CheckChanged(data.MaxCodeLen, value); data.MaxCodeLen = value; }
}
public String CodeFormat
{
get { return data.CodeFormat; }
set { CheckChanged(data.CodeFormat, value); data.CodeFormat = value; }
}
public String NextCode
{
get { return data.NextCode; }
set { CheckChanged(data.NextCode, value); data.NextCode = value; }
}
// Population.
internal void PopulateFrom(Data data)
{
Code = data.Code;
Name = data.Name;
MaxCodeLen = data.MaxCodeLen;
CodeFormat = data.CodeFormat;
NextCode = data.NextCode;
base.PopulateFrom(data);
}
public Data Clone()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
// Error field - identify properties with validation error.
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue Code { get; set; } = ValidValue.Valid;
public ValidValue Name { get; set; } = ValidValue.Valid;
public ValidValue MaxCodeLen { get; set; } = ValidValue.Valid;
public ValidValue CodeFormat { get; set; } = ValidValue.Valid;
public ValidValue NextCode { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
// Flags.
public static readonly Byte Flag_AutoAssignCode = 0x01;
//-------------------------------------------------------------------
// Construction.
public SaCodeType(SysId id, String code) :
base(id)
{
base.SetData(data);
Code = code;
Status = DefaultStatus;
}
//-------------------------------------------------------------------
// Statuses.
private static readonly List<SaStatus> validStatuses = new List<SaStatus>()
{
SaStatus.Current
};
public static SaStatus DefaultStatus { get { return CurrentStatus; } }
public static SaStatus CurrentStatus { get { return SaStatus.Current; } }
public static List<SaStatus> ValidStatuses { get { return new List<SaStatus>(validStatuses); } }
public static DataValue.TriStateType GetStatusTriState(SaStatus status)
{
switch (status)
{
case SaStatus.Current:
return Core.DataValue.TriStateType.Green;
case SaStatus.Deleted:
return Core.DataValue.TriStateType.Purple;
}
return Core.DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Properties.
public Data GetData() { return data.Clone(); }
public void SetData(Data data)
{
// Properties that cannot be changed if previously specified.
if (SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id))
throw new NotSupportedException($"{SysUtil.Fn} Id cannot be changed");
if (!StringUtil.IsEmpty(Code) && !Code.Equals(data.Code))
throw new NotSupportedException($"{SysUtil.Fn} Code cannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
public String Code
{
get { return data.Code; }
set { data.Code = value; }
}
public String Name
{
get { return data.Name; }
set { data.Name = value; }
}
public byte MaxCodeLen
{
get { return data.MaxCodeLen; }
set { data.MaxCodeLen = value; }
}
public String CodeFormat
{
get { return data.CodeFormat; }
set { data.CodeFormat = value; }
}
public String NextCode
{
get { return data.NextCode; }
set { data.NextCode = value; }
}
//-------------------------------------------------------------------
// Flags.
public bool AutoAssignCode
{
get { return GetFlag(Flag_AutoAssignCode); }
set { SetFlag(Flag_AutoAssignCode, value); }
}
//-------------------------------------------------------------------
// List parameters.
public enum StatusCat
{
Any,
ActiveOnly,
NotDeleted,
DeletedOnly,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
public HashSet<SysId> IdsIncluded { get; } = new HashSet<SysId>();
public HashSet<SysId> IdsExcluded { get; } = new HashSet<SysId>();
/// <summary>Generic search - code or name etc.</summary>
public String Search { get; set; }
public String Code { get; set; }
public String CodePartial { get; set; }
public String Name { get; set; }
public String NamePartial { get; set; }
public StatusCat StatusCat { get; set; } = StatusCat.NotDeleted;
}
//-------------------------------------------------------------------
}
//=======================================================================
public static class SaCodeTypeList
{
}
//=======================================================================
}
@@ -0,0 +1,190 @@
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Sarand.Net.Standard.Base.CodeTypes
{
//=======================================================================
public abstract class SaCodeTypeConsole : SacsDisposableStateItem
{
//-------------------------------------------------------------------
// Data members.
protected readonly List<SaCodeTypeDfn> codeTypeDfns = new List<SaCodeTypeDfn>();
//-------------------------------------------------------------------
// Static initialisation.
static SaCodeTypeConsole()
{
}
//-------------------------------------------------------------------
// Construction.
protected SaCodeTypeConsole()
{
}
//-------------------------------------------------------------------
// Properties.
public abstract bool DatabaseIsValid { get; }
public abstract bool CanUpdateDatabase { get; }
//-------------------------------------------------------------------
// C o d e T y p e D e f i n i t i o n s
//-------------------------------------------------------------------
public List<SaCodeTypeDfn> CodeTypeDefinitions { get { return new List<SaCodeTypeDfn>(codeTypeDfns); } }
public SaCodeTypeDfn GetCodeTypeDefinition(String codeTypeCode)
{
ClearErrorState();
foreach (SaCodeTypeDfn codeTypeDfn in codeTypeDfns)
if (codeTypeDfn.Code.EqualsCI(codeTypeCode))
return codeTypeDfn;
return null;
}
public abstract SaCodeTypeDfn GetCodeTypeDefinition(SysId codeTypeId);
public virtual String GetNameForCodeType(String codeTypeCode)
{
ClearErrorState();
SaCodeTypeDfn codeTypeDfn = GetCodeTypeDefinition(codeTypeCode);
if (codeTypeDfn != null) return codeTypeDfn.Description;
return "";
}
public bool IsCodeTypeSequenceAllowed(String codeTypeCode)
{
ClearErrorState();
SaCodeTypeDfn codeTypeDfn = GetCodeTypeDefinition(codeTypeCode);
if (codeTypeDfn != null) return codeTypeDfn.AllowSequence;
return false;
}
//-------------------------------------------------------------------
// Code Type registration - for use in validation and population of default database.
public bool RegisterCodeType(SaCodeTypeDfn codeTypeDfn)
{
ClearErrorState();
if (codeTypeDfns.GetCodeTypeDfnByCode(codeTypeDfn.Code) != null) return false;
codeTypeDfns.Add(codeTypeDfn);
return true;
}
public bool RegisterCodesOfType(String codeTypeCode, List<CodeDesc> codeDfns)
{
ClearErrorState();
SaCodeTypeDfn codeTypeDfn = GetCodeTypeDefinition(codeTypeCode);
if (codeTypeDfn == null) return false;
codeTypeDfn.DefaultCodeDefinitions.Clear();
foreach (CodeDesc codeDFn in codeDfns)
codeTypeDfn.DefaultCodeDefinitions.Add(new SaCodeDfn(codeDFn.Code, codeDFn.Desc));
return true;
}
//-------------------------------------------------------------------
/// <summary>
/// Populate Code Types.
/// <para>- Population continues even if one or more Code Types fail to populate.</para>
/// <para>- Error message will reflect the first error encountered.</para>
/// </summary>
public bool Populate(DbUpdateInfo dbUpdateInfo)
{
ClearErrorState();
String errorMessage = "";
foreach (SaCodeTypeDfn codeTypeDfn in CodeTypeDefinitions)
{
// Continue with Code Type population if one or more fail.
if (PopulateCodeType(codeTypeDfn.Code, dbUpdateInfo))
{
//foreach (var code in codeTypeDfn.Codes)
// Internals.CodeTypeConsole.PopulateCode(codeTypeDfn.sCode, code.Code, code.Desc);
}
else if (StringUtil.IsBlank(errorMessage))
errorMessage = ErrorStateMessage;
}
if (StringUtil.IsBlank(errorMessage))
SetErrorState(errorMessage);
return OK;
}
//*******************************************************************
// C o d e T y p e s
//*******************************************************************
public abstract SaCodeType CreateCodeType(String code);
public abstract bool CodeTypeExistsById(SysId codeTypeId);
public abstract bool CodeTypeExistsByCode(String codeTypeCode);
public abstract int GetCodeTypeCount(SaCodeType.Params prmCodeType);
public abstract int GetCodeTypeCountById(SysId codeTypeId);
public abstract int GetCodeTypeCountByCode(String codeTypeCode);
public abstract SaCodeType GetCodeTypeById(SysId codeTypeId);
public abstract SaCodeType GetCodeTypeByCode(String codeTypeCode);
public abstract List<SaCodeType> GetCodeTypeList(SaCodeType.Params prmCodeType);
// Code type list.
public abstract ColumnDfn GetCodeTypeColumnDfn(SaCodeType.Column columnId, String caption = "", int width = 0);
public abstract DbResultSet ExecuteCodeTypeQuery(List<ColumnDfn> columns, SaCodeType.Params prm);
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public abstract DataValue GetCodeTypeDataValue(ColumnDfn column, NamedValue.Map values);
// Population.
public abstract bool PopulateCodeType(String codeTypeCode, DbUpdateInfo dbUpdateInfo);
// Code Type updates.
public abstract bool InsertCodeType(SaCodeType codeType, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateCodeType(SaCodeType codeType, DbUpdateInfo dbUpdateInfo);
public abstract bool DeleteCodeType(SaCodeType codeType, DbUpdateInfo dbUpdateInfo);
// Maintain code types - returns true if changes made.
// NB Only relevant to desktop application.
public abstract bool MaintainCodeTypes(bool userCanManageCodeTypes, DbUpdateInfo dbUpdateInfo);
public abstract bool MaintainCodeType(String codeTypeCode, DbUpdateInfo dbUpdateInfo);
//*******************************************************************
// C o d e s
//*******************************************************************
// Create code.
public abstract SaCode CreateCode(SysId codeTypeId, String code);
// Check whether code exists.
public abstract bool CodeExistsForCodeType(String codeTypeCode, String code, bool activeOnly = true);
// Codes for code type.
public abstract bool CodeTypeHasCodes(String codeTypeCode, bool activeOnly = true);
public abstract int GetCodeCountForCodeType(String codeTypeCode, bool activeOnly = true);
public abstract SaCode GetCodeById(SysId codeId);
public abstract SaCode GetCodeForCodeType(String codeTypeCode, String code, bool activeOnly = true);
public abstract List<CodeDesc> GetCodeDescsForCodeType(String codeTypeCode, bool activeOnly = true);
public abstract List<SaCode> GetCodesForCodeType(String codeTypeCode, bool activeOnly = true);
// Code list.
public abstract ColumnDfn GetCodeColumnDfn(SaCode.Column columnId, String caption = "", int width = 0);
public abstract List<SaCode> GetCodeList(SaCode.Params prmCode);
public abstract DbResultSet ExecuteCodeQuery(List<ColumnDfn> columns, SaCode.Params prm);
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public abstract DataValue GetCodeDataValue(ColumnDfn column, NamedValue.Map values);
// Codes by filter.
public abstract int GetCodeCount(SaCode.Params prmCode);
public abstract SaCode GetCode(SaCode.Params prmCode);
/// <summary>Get filtered code type codes, indexed by Code Type code.</summary>
public abstract Dictionary<String, List<SaCode>> GetCodes(SaCode.Params prmCode);
public abstract Task<Dictionary<String, List<SaCode>>> GetCodesAsync(SaCode.Params prmCode);
/// <summary>Get filtered codes and descriptions, indexed by Code Type code.</summary>
public abstract Dictionary<String, List<CodeDesc>> GetCodeDescsByCodeType(SaCode.Params prmCode);
// Code updates.
public abstract bool InsertCode(SaCode code, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateCode(SaCode code, DbUpdateInfo dbUpdateInfo);
public abstract bool DeleteCode(SaCode code, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Create codes.
public abstract bool CreateCodeOfType(SysId codeTypeId, String code, String desc, DbUpdateInfo dbUpdateInfo);
public abstract bool CreateCodeOfType(String codeTypeCode, String code, String desc, DbUpdateInfo dbUpdateInfo);
// Population.
public abstract bool PopulateCode(String codeTypeCode, String code, String desc, bool active, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Select codes.
public abstract List<String> SelectCodes(String codeTypeCode, List<String> codesSelected);
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,383 @@
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
//---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Thu 30-Oct-2025 11:28:12
//---------------------------------------------------------------------------
namespace Sarand.Net.Standard.Base.CodeTypes
{
public class SaCodeTypeDbDfn
{
//-------------------------------------------------------------------
// Table identifiers.
public enum TableIdx
{
Unknown = 0,
SaCode,
SaCodeType,
}
//-------------------------------------------------------------------
// Column identifiers.
public enum ColumnIdx
{
Unknown = 0,
SaCode_Id,
SaCode_CodeTypeId,
SaCode_Code,
SaCode_Description,
SaCode_Seq,
SaCode_Data,
SaCode_Notes,
SaCode_Flags,
SaCode_Status,
SaCode_CreateOn,
SaCode_CreateBy,
SaCode_CreateHost,
SaCode_UpdateOn,
SaCode_UpdateBy,
SaCode_UpdateHost,
SaCodeType_Id,
SaCodeType_Code,
SaCodeType_Name,
SaCodeType_MaxCodeLen,
SaCodeType_CodeFormat,
SaCodeType_NextCode,
SaCodeType_Notes,
SaCodeType_Flags,
SaCodeType_Status,
SaCodeType_CreateOn,
SaCodeType_CreateBy,
SaCodeType_CreateHost,
SaCodeType_UpdateOn,
SaCodeType_UpdateBy,
SaCodeType_UpdateHost,
}
//-------------------------------------------------------------------
// Data members.
private static readonly int tableCount = 2;
private static readonly int columnCount = 30;
public static ulong MaxTextLen { get; private set; }
//-------------------------------------------------------------------
// Retrieve Table details.
public static int GetTableCount ()
{
return tableCount;
}
public static String GetSchemaName (TableIdx table, bool delimitReservedWords = true)
{
int tableIdx = (int)table - 1;
if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;
String schemaName = tables[(int)tableIdx].Schema;
if (delimitReservedWords) { schemaName = DelimitReservedWord(schemaName); }
return schemaName;
}
public static String GetTableName (TableIdx table, bool delimitReservedWords = true)
{
int tableIdx = (int)table - 1;
if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;
String tableName = tables[(int)tableIdx].Name;
if (delimitReservedWords) tableName = DelimitReservedWord(tableName);
return tableName;
}
public static String GetTableNameQual (TableIdx table, bool delimitReservedWords = true)
{
int tableIdx = (int)table - 1;
if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;
String schemaName = tables[(int)tableIdx].Schema;
String tableName = tables[(int)tableIdx].Name;
if (delimitReservedWords) { schemaName = DelimitReservedWord(schemaName); tableName = DelimitReservedWord(tableName); }
return (StringUtil.IsBlank(schemaName) ? "" : schemaName + ".") + tableName;
}
//-------------------------------------------------------------------
// Identify the table that corresponds with the specified column.
public static TableIdx GetTableForColumn (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return TableIdx.Unknown;
return columns[columnIdx].TableIdx;
}
//-------------------------------------------------------------------
// Retrieve the specified Column's name (Qualified include table name: '(<Table>.Column>)').
public static String GetColumnName (ColumnIdx column, bool delimitReservedWords = true)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return String.Empty;
String columnName = columns[columnIdx].Name;
if (delimitReservedWords) columnName = DelimitReservedWord(columnName);
return columnName;
}
public static String GetColumnNameQual (ColumnIdx column, String tableAlias = "", bool braces = false)
{
String columnName = GetColumnName(column);
if (!String.IsNullOrEmpty(columnName))
{
String tableName = StringUtil.EmptyOnNull(tableAlias);
if (tableName.IsEmpty()) tableName = GetTableName(GetTableForColumn(column));
columnName = tableName + (tableName.Length > 0 ? "." : "") + columnName;
if (braces) columnName = $"({columnName})";
}
return columnName;
}
//-------------------------------------------------------------------
// Reserved words.
private static DbReservedWordDelim reservedWordDelim = DbReservedWordDelim.SquareBrackets;
public static void SetReservedWordDelim (DbReservedWordDelim reservedWordDelim)
{
SaCodeTypeDbDfn.reservedWordDelim = reservedWordDelim;
}
public static bool IsReservedWord (String word)
{
if (String.IsNullOrEmpty(word)) return false;
if (reservedWords.Contains(word, StringComparer.OrdinalIgnoreCase)) return true;
return false;
}
public static String DelimitReservedWord (String word)
{
return IsReservedWord(word) ? DelimitWord(word) : word;
}
public static String DelimitWord (String word)
{
return DelimitWord(word, reservedWordDelim);
}
public static String DelimitWord (String word, DbReservedWordDelim wordDelim)
{
switch (wordDelim)
{
case DbReservedWordDelim.None:
break;
case DbReservedWordDelim.DoubleQuotes:
word = $"\"{word}\"";
break;
case DbReservedWordDelim.SquareBrackets:
default:
word = $"[{word}]";
break;
}
return word;
}
//-------------------------------------------------------------------
// Retrieve information about the specified Column.
public static DbColumnDataType GetColDataType (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return DbColumnDataType.Unknown;
return columns[columnIdx].DataType;
}
public static short GetColNativeDataType (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return 0;
return columns[columnIdx].NativeDataType;
}
public static void SetMaxTextLen (ulong maxTextLen)
{
SaCodeTypeDbDfn.MaxTextLen = maxTextLen;
}
public static bool IsColFmtText (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
return (columns[columnIdx].DataType == DbColumnDataType.VarChar);
}
public static ulong GetColTextLen (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return 0;
if (columns[columnIdx].DataType == DbColumnDataType.VarChar)
{
ulong textLen = columns[columnIdx].DataLen;
if (MaxTextLen > 0 && textLen > MaxTextLen) textLen = MaxTextLen;
return textLen;
}
return 0;
}
public static bool IsColFmtBool (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
return (columns[columnIdx].DataType == DbColumnDataType.Bit);
}
public static bool IsColFmtNumeric (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
switch (columns[columnIdx].DataType)
{
case DbColumnDataType.TinyInt:
case DbColumnDataType.SmallInt:
case DbColumnDataType.Int:
case DbColumnDataType.BigInt:
case DbColumnDataType.Single:
case DbColumnDataType.Double:
case DbColumnDataType.Decimal:
return true;
}
return false;
}
//-------------------------------------------------------------------
// Table definitions.
private class TableDfn
{
internal String Schema { get; set; }
internal String Name { get; set; }
internal TableDfn (String schema, String name)
{
this.Schema= schema;
this.Name = name;
}
}
private static readonly TableDfn[] tables =
{
new TableDfn("dbo","SaCode"),
new TableDfn("dbo","SaCodeType"),
};
//-------------------------------------------------------------------
// Table column definitions.
private class ColumnDfn
{
internal TableIdx TableIdx { get; set; }
internal String Name { get; set; }
internal DbColumnDataType DataType { get; set; }
internal short NativeDataType { get; set; }
internal bool IsIdentity { get; set; }
internal ulong DataLen { get; set; }
internal ColumnDfn (int tableIdx, String name, int dataType, short nativeDataType, bool isIdentity, ulong dataLen)
{
this.TableIdx = (TableIdx)tableIdx;
this.Name = name;
this.DataType = (DbColumnDataType)dataType;
this.NativeDataType = nativeDataType;
this.IsIdentity = isIdentity;
this.DataLen = dataLen;
}
}
private static readonly ColumnDfn[] columns =
{
new ColumnDfn(1,"Id",4,4,false,10),
new ColumnDfn(1,"CodeTypeId",4,4,false,10),
new ColumnDfn(1,"Code",0,-9,false,32),
new ColumnDfn(1,"Description",0,-9,false,128),
new ColumnDfn(1,"Seq",3,5,false,5),
new ColumnDfn(1,"Data",0,-9,false,255),
new ColumnDfn(1,"Notes",0,-9,false,255),
new ColumnDfn(1,"Flags",3,5,false,5),
new ColumnDfn(1,"Status",0,-9,false,3),
new ColumnDfn(1,"CreateOn",9,93,false,23),
new ColumnDfn(1,"CreateBy",4,4,false,10),
new ColumnDfn(1,"CreateHost",0,-9,false,64),
new ColumnDfn(1,"UpdateOn",9,93,false,23),
new ColumnDfn(1,"UpdateBy",4,4,false,10),
new ColumnDfn(1,"UpdateHost",0,-9,false,64),
new ColumnDfn(2,"Id",4,4,false,10),
new ColumnDfn(2,"Code",0,-9,false,32),
new ColumnDfn(2,"Name",0,-9,false,128),
new ColumnDfn(2,"MaxCodeLen",2,-6,false,3),
new ColumnDfn(2,"CodeFormat",0,-9,false,32),
new ColumnDfn(2,"NextCode",0,-9,false,32),
new ColumnDfn(2,"Notes",0,-9,false,255),
new ColumnDfn(2,"Flags",3,5,false,5),
new ColumnDfn(2,"Status",0,-9,false,3),
new ColumnDfn(2,"CreateOn",9,93,false,23),
new ColumnDfn(2,"CreateBy",4,4,false,10),
new ColumnDfn(2,"CreateHost",0,-9,false,64),
new ColumnDfn(2,"UpdateOn",9,93,false,23),
new ColumnDfn(2,"UpdateBy",4,4,false,10),
new ColumnDfn(2,"UpdateHost",0,-9,false,64),
};
//-------------------------------------------------------------------
// Reserved words.
private static readonly HashSet<String> reservedWords = new HashSet<String>()
{
"ADD",
"ALL",
"ALTER",
"AND",
"ANY",
"AS",
"ASC",
"AVG",
"BEGIN",
"BETWEEN",
"BY",
"CASE",
"CAST",
"COLUMN",
"COMMIT",
"CONSTRAINT",
"CONVERT",
"COUNT",
"CREATE",
"CURRENCY",
"DEFAULT",
"DELETE",
"DESC",
"DISTINCT",
"DROP",
"ELSE",
"END",
"EXECUTE",
"EXISTS",
"FALSE",
"FROM",
"GRANT",
"GROUP",
"HAVING",
"IN",
"INDEX",
"INNER",
"INSERT",
"INTO",
"IS",
"JOIN",
"KEY",
"LEFT",
"LIKE",
"MAX",
"MIN",
"NOT",
"NULL",
"ON",
"OR",
"ORDER",
"OUTER",
"OUTPUT",
"PRIMARY",
"PROCEDURE",
"REVOKE",
"ROLLBACK",
"ROWCOUNT",
"SELECT",
"SET",
"SQL",
"SUM",
"TABLE",
"THEN",
"TRANSACTION",
"TRUE",
"UNION",
"UNIQUE",
"UPDATE",
"USER",
"VALUES",
"VIEW",
"WHEN",
"WHERE"
};
//-------------------------------------------------------------------
}
}
@@ -0,0 +1,53 @@
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.Net.Standard.Base.CodeTypes
{
//=======================================================================
public class SaCodeTypeDfn
{
//-------------------------------------------------------------------
public SaCodeTypeDfn (String code, String description, byte maxCodeLen = 0, String notes = "")
{
Code = code;
Description = description;
MaxCodeLen = maxCodeLen;
Notes = notes;
}
//-------------------------------------------------------------------
// Properties.
public String Code { get; } = String.Empty;
public String Description { get; } = String.Empty;
public byte MaxCodeLen { get; } = 0;
public String Notes { get; } = String.Empty;
public bool AllowMixedCode { get; set; } = false;
public bool AllowSequence { get; set; } = false;
public bool AllowData { get; set; } = false;
public bool AllowMixedData { get; set; } = false;
public String DataLabel { get; set; } = String.Empty;
public List<FlagDfn> FlagDefinitions { get; } = new List<FlagDfn>();
public List<SaCodeDfn> DefaultCodeDefinitions { get; } = new List<SaCodeDfn>();
//-------------------------------------------------------------------
}
//=======================================================================
public static class SaCodeTypeDfnList
{
// Retrieve definition from the list.
public static SaCodeTypeDfn GetCodeTypeDfnByCode (this List<SaCodeTypeDfn> values, String code)
{
return values.Find(item => item.Code.EqualsCI(code));
}
// Add definition to the list.
public static void Add(this List<SaCodeTypeDfn> values, String code, String description)
{
values.Add(new SaCodeTypeDfn(code, description));
}
}
//=======================================================================
}
@@ -0,0 +1,320 @@
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Sarand.Net.Standard.Base.CodeTypes
{
//=======================================================================
public abstract class SaCodeTypeMgr : SacsItemMgr
{
//-------------------------------------------------------------------
// Data members.
//-------------------------------------------------------------------
// Static initialisation.
static SaCodeTypeMgr()
{
}
//-------------------------------------------------------------------
// Construction.
protected SaCodeTypeMgr()
{
}
//-------------------------------------------------------------------
// Properties.
public abstract bool DatabaseIsValid { get; }
public abstract bool CanUpdateDatabase { get; }
//*******************************************************************
// C o d e T y p e s
//*******************************************************************
// Associated data.
public abstract bool CodeTypeHasCodes(SysId codeTypeId);
//-------------------------------------------------------------------
// Create Item.
public abstract SaCodeType CreateCodeType(String code);
//-------------------------------------------------------------------
// Retrieve individual Items.
public abstract bool CodeTypeExists(SaCodeType.Params prmCodeType);
public abstract bool CodeTypeExistsById(SysId codeTypeId);
public abstract bool CodeTypeExistsByCode(String codeTypeCode);
public abstract SaCodeType GetCodeType(SaCodeType.Params prmCodeType);
public abstract SaCodeType GetCodeTypeById(SysId codeTypeId);
public abstract SaCodeType GetCodeTypeByCode(String codeTypeCode);
//-------------------------------------------------------------------
// Validate Code Type.
public bool IsValidCodeType(SaCodeType codeType)
{
ClearErrorState();
if (codeType == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidCodeTypeData(codeType.GetData(), new SaCodeType.ErrField());
}
public virtual bool IsValidCodeTypeData(SaCodeType.Data codeTypeData, SaCodeType.ErrField errField)
{
ClearErrorState();
if (!IsValidValue(codeTypeData.Code, "code", (long)SaCodeTypeDbDfn.GetColTextLen(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_Code), true))
{
errField.Code = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!IsValidValue(codeTypeData.Name, "description", (long)SaCodeTypeDbDfn.GetColTextLen(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_Name), true))
{
errField.Name = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!IsValidValue(codeTypeData.CodeFormat, "code format", (long)SaCodeTypeDbDfn.GetColTextLen(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_CodeFormat)))
{
errField.CodeFormat = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!IsValidValue(codeTypeData.NextCode, "next code", (long)SaCodeTypeDbDfn.GetColTextLen(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_NextCode)))
{
errField.NextCode = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
// Common properties.
if (!IsValidValue(codeTypeData.Notes, "notes", (long)SaCodeTypeDbDfn.GetColTextLen(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_Notes)))
{
errField.Notes = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!SaCodeType.ValidStatuses.Contains(codeTypeData.Status))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.InvalidStatus);
}
return true;
}
//-------------------------------------------------------------------
// CodeType database interface.
public abstract bool InsertCodeType(SaCodeType codeType, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateCodeType(SaCodeType codeType, DbUpdateInfo dbUpdateInfo);
public virtual bool CodeTypeCanBeDeleted(SaCodeType codeType)
{
ClearErrorState();
if (CodeTypeHasCodes(codeType.Id)) return SetErrorState("code type has codes");
return true;
}
public abstract bool DeleteCodeType(SaCodeType codeType, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Code Type list.
public abstract ColumnDfn GetCodeTypeColumnDfn(SaCodeType.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetCodeTypeQueryFilter(SaCodeType.Params prm);
public abstract long GetCodeTypeCount(SaCodeType.Params prm);
public abstract List<SaCodeType> GetCodeTypeList(SaCodeType.Params prm);
public abstract Task<List<SaCodeType>> GetCodeTypeListAsync(SaCodeType.Params prm);
public abstract DbResultSet ExecuteCodeTypeQuery(List<ColumnDfn> columns, SaCodeType.Params prm);
public abstract Task<DbResultSet> ExecuteCodeTypeQueryAsync(List<ColumnDfn> columns, SaCodeType.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public virtual DataValue GetCodeTypeDataValue(ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
switch ((SaCodeType.Column)column.Id)
{
//-----------------------------------------------------------
// Item type.
case SaCodeType.Column.AutoAssignCode_Y:
case SaCodeType.Column.AutoAssignCode_Tick:
{
ushort flags = (ushort)values.GetValue(column.DataName).AsLong();
bool autoAssignCode = SacsHierarchyItem.GetFlag(flags, SaCodeType.Flag_AutoAssignCode);
if (column.Id == (int)SaCodeType.Column.AutoAssignCode_Y)
value = new DataValue(autoAssignCode ? "Y" : "");
else
value = new DataValue(autoAssignCode);
}
break;
//-----------------------------------------------------------
// Notes.
case SaCodeType.Column.Notes:
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
break;
//-----------------------------------------------------------
// Status.
case SaCodeType.Column.Status_Desc:
case SaCodeType.Column.Status_Ind:
{
String statusCode = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusCode);
if (column.Id == (int)SaCodeType.Column.Status_Desc)
{
String statusDesc = SacsSystem.GetStatusDescForCode(statusCode);
value = new DataValue(statusDesc);
}
else if (column.Id == (int)SaCodeType.Column.Status_Ind)
{
DataValue.TriStateType triState = DataValue.TriStateType.Unknown;
if (status == SaStatus.Current || status == SaStatus.Active)
triState = DataValue.TriStateType.Green;
value = new DataValue(triState);
}
}
break;
//-----------------------------------------------------------
}
return value;
}
//*******************************************************************
// C o d e s
//*******************************************************************
// Retrieve individual codes.
public abstract bool CodeExistsById(SysId id);
public abstract SaCode GetCode(SaCode.Params prmCode);
public abstract SaCode GetCodeById(SysId id);
public abstract SaCode GetCodeByCodeTypeCode(String codeTypeCode, String code);
// Create code.
public abstract SaCode CreateCode(SysId codeTypeId, String code);
//-------------------------------------------------------------------
// Validate code data.
public bool IsValidCode(SaCode code)
{
ClearErrorState();
if (code == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidCodeData(code.GetData(), new SaCode.ErrField());
}
public virtual bool IsValidCodeData(SaCode.Data codeData, SaCode.ErrField errField)
{
ClearErrorState();
if (!SysId.IsValid(codeData.CodeTypeId))
{
errField.CodeType = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("code type must be specified");
}
if (!IsValidValue(codeData.Code, "code", (long)SaCodeTypeDbDfn.GetColTextLen(SaCodeTypeDbDfn.ColumnIdx.SaCode_Code), true))
{
errField.Code = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!IsValidValue(codeData.Description, "description", (long)SaCodeTypeDbDfn.GetColTextLen(SaCodeTypeDbDfn.ColumnIdx.SaCode_Description), true))
{
errField.Description = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (codeData.Sequence < 0)
{
errField.Sequence = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("sequence must be positive");
}
if (!IsValidValue(codeData.DataValue, "data value", (long)SaCodeTypeDbDfn.GetColTextLen(SaCodeTypeDbDfn.ColumnIdx.SaCode_Data)))
{
errField.DataValue = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
// Common properties.
if (!IsValidValue(codeData.Notes, "notes", (long)SaCodeTypeDbDfn.GetColTextLen(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_Notes)))
{
errField.Notes = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!SaCode.ValidStatuses.Contains(codeData.Status))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.InvalidStatus);
}
return true;
}
//-------------------------------------------------------------------
// Code database interface.
public abstract bool InsertCode(SaCode code, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateCode(SaCode code, DbUpdateInfo dbUpdateInfo);
public virtual bool CodeCanBeDeleted(SaCode code)
{
ClearErrorState();
return true;
}
public abstract bool DeleteCode(SaCode code, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Code list.
public abstract ColumnDfn GetCodeColumnDfn(SaCode.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetCodeQueryFilter(SaCode.Params prm);
public abstract long GetCodeCount(SaCode.Params prm);
public abstract List<SaCode> GetCodeList(SaCode.Params prm);
public abstract Task<List<SaCode>> GetCodeListAsync(SaCode.Params prm);
public abstract DbResultSet ExecuteCodeQuery(List<ColumnDfn> columns, SaCode.Params prm);
public abstract Task<DbResultSet> ExecuteCodeQueryAsync(List<ColumnDfn> columns, SaCode.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public virtual DataValue GetCodeDataValue(ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
SaCode.Column colId = (SaCode.Column)column.Id;
switch (colId)
{
//-----------------------------------------------------------
// Context Item description.
case SaCode.Column.Flag1_Y:
case SaCode.Column.Flag1_Tick:
case SaCode.Column.Flag2_Y:
case SaCode.Column.Flag2_Tick:
{
ushort flags = (ushort)values.GetValue(column.DataName).AsLong();
bool flag1 = SacsHierarchyItem.GetFlag(flags, 1);
bool flag2 = SacsHierarchyItem.GetFlag(flags, 2);
if (column.Id == (int)SaCode.Column.Flag1_Y)
value = new DataValue(flag1 ? "Y" : "");
else if (column.Id == (int)SaCode.Column.Flag1_Tick)
value = new DataValue(flag1);
else if (column.Id == (int)SaCode.Column.Flag2_Y)
value = new DataValue(flag2 ? "Y" : "");
else if (column.Id == (int)SaCode.Column.Flag2_Tick)
value = new DataValue(flag2);
}
break;
//-----------------------------------------------------------
// Notes.
case SaCode.Column.Notes:
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
break;
//-----------------------------------------------------------
// Status.
case SaCode.Column.Status_Desc:
case SaCode.Column.Status_Ind:
{
String statusValue = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusValue);
if (column.Id == (int)SaCode.Column.Status_Desc)
value = new DataValue(SacsSystem.GetStatusDescForCode(statusValue));
else if (column.Id == (int)SaCode.Column.Status_Ind)
value = new DataValue(SaCode.GetStatusTriState(status));
}
break;
//-----------------------------------------------------------
}
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,42 @@
using Sarand.Net.Standard.Base.Bus;
using System;
using System.Collections.Generic;
using System.Text;
namespace Sarand.Net.Standard.Base.Diary
{
//=======================================================================
public abstract class SaDiaryConsole : SacsDisposableStateItem
{
//-------------------------------------------------------------------
// Definitions.
//-------------------------------------------------------------------
// Data members.
//-------------------------------------------------------------------
// Static initialisation.
static SaDiaryConsole ()
{
}
//-------------------------------------------------------------------
// Construction.
protected SaDiaryConsole ()
{
}
//-------------------------------------------------------------------
// Properties.
// Database.
public abstract bool DatabaseIsValid { get; }
public abstract bool CanUpdateDatabase { get; }
//-------------------------------------------------------------------
// D i a r y E n t r i e s
//-------------------------------------------------------------------
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,294 @@
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.Net.Standard.Base.Interfaces
{
//=======================================================================
public class SaInterface : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Pos = 0,
// Interface.
Id,
Context,
Category,
Category_Desc,
Type,
Type_Desc,
Code,
Caption,
Active_Y,
Active_TickCross,
Active_Ind,
// Derived properties.
Process_Count,
DataItem_Count,
// Common properties.
Notes,
Status,
Status_Desc,
Status_Ind,
CreateOn_Date,
UpdateOn_Date,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public String Context { get; set; } = String.Empty;
public SaInterfaceCategory Category { get; set; } = SaInterfaceCategory.Unknown;
public short Type { get; set; } = 0;
public String Code { get; set; } = String.Empty;
public String Caption { get; set; } = String.Empty;
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data()
{
Status = DefaultStatus;
}
// Properties.
public String Context
{
get { return data.Context; }
set { CheckChanged(data.Context, value); data.Context = value; }
}
public SaInterfaceCategory Category
{
get { return data.Category; }
set { CheckChanged((int)data.Category, (int)value); data.Category = value; }
}
public short Type
{
get { return data.Type; }
set { CheckChanged(data.Type, value); data.Type = value; }
}
public String Code
{
get { return data.Code; }
set { CheckChanged(data.Code, value); data.Code = value; }
}
public String Caption
{
get { return data.Caption; }
set { CheckChanged(data.Caption, value); data.Caption = value; }
}
// Flags.
public bool Active
{
get { return GetFlag(Flag_Active); }
set { SetFlag(Flag_Active, value); }
}
// Population.
internal void PopulateFrom(Data data)
{
Context = data.Context;
Category = data.Category;
Type = data.Type;
Code = data.Code;
Caption = data.Caption;
base.PopulateFrom(data);
}
public Data Clone()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
// Error field - identify properties with validation error.
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue Context { get; set; } = ValidValue.Valid;
public ValidValue Category { get; set; } = ValidValue.Valid;
public ValidValue Type { get; set; } = ValidValue.Valid;
public ValidValue Code { get; set; } = ValidValue.Valid;
public ValidValue Caption { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
// Flags.
public static readonly Byte Flag_Active = 0x01;
//-------------------------------------------------------------------
// Construction.
public SaInterface(SysId id, String context, SaInterfaceCategory category, short type) :
base(id)
{
base.SetData(data);
Context = context;
Category = category;
Type = type;
Status = DefaultStatus;
}
//-------------------------------------------------------------------
// Statuses.
private static readonly List<SaStatus> validStatuses = new List<SaStatus>()
{
SaStatus.Active,
};
public static SaStatus DefaultStatus { get { return ActiveStatus; } }
public static SaStatus ActiveStatus { get { return SaStatus.Active; } }
public static List<SaStatus> ValidStatuses { get { return new List<SaStatus>(validStatuses); } }
public static DataValue.TriStateType GetStatusTriState(SaStatus status)
{
switch (status)
{
case SaStatus.Active:
return Core.DataValue.TriStateType.Green;
case SaStatus.Deleted:
return Core.DataValue.TriStateType.Purple;
}
return Core.DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Utilities.
public ItemId GetItemId()
{
return new ItemId((short)SaDataItemType.Interface, Id);
}
//-------------------------------------------------------------------
// Properties.
public Data GetData() { return data.Clone(); }
public void SetData(Data data)
{
// Properties that cannot be changed if previously specified.
if (SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id))
throw new NotSupportedException($"{SysUtil.Fn} Id cannot be changed");
if (!StringUtil.IsEmpty(Context) && !Context.Equals(data.Context))
throw new NotSupportedException($"{SysUtil.Fn} Context cannot be changed");
if ((int)Category >= 0 && (int)Category != (int)data.Category)
throw new NotSupportedException($"{SysUtil.Fn} Category cannot be changed");
if (Type >= 0 && Type != data.Type)
throw new NotSupportedException($"{SysUtil.Fn} Type cannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
public String Context
{
get { return data.Context; }
protected set { data.Context = value; }
}
public SaInterfaceCategory Category
{
get { return data.Category; }
protected set { data.Category = value; }
}
public short Type
{
get { return data.Type; }
protected set { data.Type = value; }
}
public String Code
{
get { return data.Code; }
set { data.Code = value; }
}
public String Caption
{
get { return data.Caption; }
set { data.Caption = value; }
}
//-------------------------------------------------------------------
// Flags.
public bool Active
{
get { return GetFlag(Flag_Active); }
set { SetFlag(Flag_Active, value); }
}
//-------------------------------------------------------------------
// List parameters.
public enum StatusCat
{
Any,
/// <summary>NB Interface activity controlled by flag rather than status.</summary>
ActiveOnly,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
public HashSet<SysId> IdsIncluded { get; } = new HashSet<SysId>();
public HashSet<SysId> IdsExcluded { get; } = new HashSet<SysId>();
public String Context { get; set; }
public SaInterfaceCategory InterfaceCategory { get; set; } = SaInterfaceCategory.Unknown;
public HashSet<short> InterfaceTypesIncluded { get; } = new HashSet<short>();
public String Search { get; set; }
/// <summary>Exact code match</summary>
public String Code { get; set; }
public String CaptionPartial { get; set; }
/// <summary>Text to parially match code or caption</summary>
public String InterfaceText { get; set; }
/// <summary>Active flag</summary>
public bool ActiveOnly { get; set; } = true;
public StatusCat StatusCat { get; set; } = StatusCat.Any;
}
//-------------------------------------------------------------------
}
//=======================================================================
// L i s t
//=======================================================================
public static class SaInterfaceList
{
//-------------------------------------------------------------------
// E x i s t s
//-------------------------------------------------------------------
public static bool ExistsByContextCategoryType(this List<SaInterface> interfaces, String context, SaInterfaceCategory interfaceCategory, short interfaceType)
{
return interfaces.Exists(item => item.Context.EqualsCI(context) && item.Category == interfaceCategory && item.Type == interfaceType);
}
public static bool ExistsByContextCategoryType(this List<SaInterface.Data> interfaces, String context, SaInterfaceCategory interfaceCategory, short interfaceType)
{
return interfaces.Exists(item => item.Context.EqualsCI(context) && item.Category == interfaceCategory && item.Type == interfaceType);
}
//-------------------------------------------------------------------
// F i n d A l l
//-------------------------------------------------------------------
public static List<SaInterface> FindAllByContextCategory(this List<SaInterface> interfaces, String context, SaInterfaceCategory interfaceCategory)
{
return interfaces.FindAll(item => item.Context.EqualsCI(context) && item.Category == interfaceCategory);
}
public static List<SaInterface.Data> FindAllByContextCategory(this List<SaInterface.Data> interfaces, String context, SaInterfaceCategory interfaceCategory)
{
return interfaces.FindAll(item => item.Context.EqualsCI(context) && item.Category == interfaceCategory);
}
public static List<SaInterface> FindAllByContextCategoryType(this List<SaInterface> interfaces, String context, SaInterfaceCategory interfaceCategory, short interfaceType)
{
return interfaces.FindAll(item => item.Context.EqualsCI(context) && item.Category == interfaceCategory && item.Type == interfaceType);
}
public static List<SaInterface.Data> FindAllByContextCategoryType(this List<SaInterface.Data> interfaces, String context, SaInterfaceCategory interfaceCategory, short interfaceType)
{
return interfaces.FindAll(item => item.Context.EqualsCI(context) && item.Category == interfaceCategory && item.Type == interfaceType);
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,223 @@
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.ItemOptions;
using Sarand.Net.Standard.Base.UpdateLog;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.Net.Standard.Base.Interfaces
{
//=======================================================================
public abstract class SaInterfaceConsole : SacsDisposableStateItem
{
//-------------------------------------------------------------------
// Interface definition.
public class SaInterfaceDfn
{
public SaInterfaceDfn(String context, SaInterfaceCategory category, TypeCodeDesc typeDfn, bool duplicatesAllowed)
{
Context = context;
Category = category;
TypeDfn = typeDfn;
DuplicatesAllowed = duplicatesAllowed;
}
public String Context { get; } = "";
public SaInterfaceCategory Category { get; } = SaInterfaceCategory.Unknown;
public short InterfaceType { get { return (short)TypeDfn.Type; } }
public TypeCodeDesc TypeDfn { get; } = null;
public bool DuplicatesAllowed { get; } = false;
}
//-------------------------------------------------------------------
// Data members.
private readonly List<SaInterfaceDfn> interfaceDfns = new List<SaInterfaceDfn>();
//-------------------------------------------------------------------
// Static initialisation.
static SaInterfaceConsole()
{
}
//-------------------------------------------------------------------
// Construction.
protected SaInterfaceConsole()
{
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
}
base.Dispose(disposing);
}
//-------------------------------------------------------------------
// Properties.
public abstract short InterfaceDataType { get; }
public abstract SaItemOptionConsole ItemOptionConsole { get; }
public abstract SaUpdateLogConsole UpdateLogConsole { get; }
// Database.
public abstract bool DatabaseIsValid { get; }
public abstract bool CanUpdateDatabase { get; }
//---------------------------------------------------------------
// Manage interfaces - displays dialog. [only implemented by desktop application]
public abstract bool ManageInterfaces(String interfaceContext, bool userCanManageInterfaces, bool userCanProcessInterfaces, DbUpdateInfo dbUpdateInfo);
//---------------------------------------------------------------
// Utilities.
public abstract String GetItemTypeDesc(short itemType);
public abstract String GetItemCaption(ItemId itemId);
//---------------------------------------------------------------
// Interface item option definitions.
public abstract List<SaItemOptionDfn> GetInterfaceItemOptionDfns(SaInterfaceCategory interfaceCategory, short interfaceType);
public abstract List<SaItemOptionDfn> GetInterfaceItemOptionDfns(SysId interfaceId);
//-------------------------------------------------------------------
// I n t e r f a c e R e g i s t r a t i o n
//-------------------------------------------------------------------
public bool HasRegisteredInterfaces()
{
return (interfaceDfns.Count > 0);
}
protected void RegisterInterfaces(String context, SaInterfaceCategory category, List<TypeCodeDesc> types, bool allowDuplicates)
{
foreach (TypeCodeDesc typeDfn in types)
{
// Remove any matches from the list.
interfaceDfns.RemoveAll(item => item.Context.EqualsCI(context) && item.Category == category && item.InterfaceType == typeDfn.Type);
// Add interface definition to list.
SaInterfaceDfn interfaceDfn = new SaInterfaceDfn(context, category, typeDfn, allowDuplicates);
interfaceDfns.Add(interfaceDfn);
}
}
public void ClearRegisteredInterfaces()
{
interfaceDfns.Clear();
}
public List<SaInterfaceDfn> GetInterfaceDfns(String context, bool createOnly)
{
List<SaInterfaceDfn> interfaceDfns = new List<SaInterfaceDfn>();
foreach (SaInterfaceDfn dfn in this.interfaceDfns.FindAll(item => item.Context.EqualsCI(context)))
{
if (!createOnly || CanCreateInterface(dfn.Context, dfn.Category, dfn.InterfaceType))
interfaceDfns.Add(dfn);
}
return interfaceDfns;
}
public bool HasInterfaceDfns(String context, SaInterfaceCategory interfaceCategory, short interfaceType, bool createOnly)
{
List<SaInterfaceDfn> interfaceDfns = new List<SaInterfaceDfn>();
foreach (SaInterfaceDfn dfn in this.interfaceDfns.FindAll(item => item.Context.EqualsCI(context) && ((int)interfaceCategory < 1 || item.Category == interfaceCategory) && ((int)interfaceType < 1 || item.InterfaceType == interfaceType)))
{
if (!createOnly || CanCreateInterface(dfn.Context, dfn.Category, dfn.InterfaceType))
return true;
}
return false;
}
public List<SaInterfaceDfn> GetInterfaceDfns(String context, SaInterfaceCategory interfaceCategory, short interfaceType, bool createOnly)
{
List<SaInterfaceDfn> interfaceDfns = new List<SaInterfaceDfn>();
foreach (SaInterfaceDfn dfn in this.interfaceDfns.FindAll(item => item.Context.EqualsCI(context) && ((int)interfaceCategory < 1 || item.Category == interfaceCategory) && ((int)interfaceType < 1 || item.InterfaceType == interfaceType)))
{
if (!createOnly || CanCreateInterface(dfn.Context, dfn.Category, dfn.InterfaceType))
interfaceDfns.Add(dfn);
}
return interfaceDfns;
}
public virtual String GetInterfaceTypeDesc(String context, SaInterfaceCategory category, short type)
{
SaInterfaceDfn dfn = interfaceDfns.Find(item => item.Context.EqualsCI(context) && item.Category == category && item.InterfaceType == type);
if (dfn != null)
return dfn.TypeDfn.Desc;
return "";
}
//-------------------------------------------------------------------
// I n t e r f a c e A c c e s s C o n t r o l
//-------------------------------------------------------------------
public abstract bool CanCreateInterfaces();
public abstract bool CanCreateInterfaces(String context, SaInterfaceCategory interfaceCategory);
public abstract bool CanCreateInterface(String context, SaInterfaceCategory interfaceCategory, short interfaceType);
public abstract bool AreMultipleInterfaceInstancesAllowed(String context, SaInterfaceCategory interfaceCategory, short interfaceType);
public abstract bool AreMultipleActiveInterfacesAllowed(String context, SaInterfaceCategory interfaceCategory);
public abstract bool CanUpdateInterface(SaInterface interfaceObj);
public abstract bool CanCopyInterfaces();
public abstract bool CanCopyInterfaces(String context, SaInterfaceCategory interfaceCategory);
public abstract bool CanCopyInterface(String context, SaInterfaceCategory interfaceCategory, short interfaceType);
public abstract bool CanCopyInterface(SaInterface interfaceObj);
public abstract bool IsCompatibleForInterfaceCopy(String context, SaInterfaceCategory interfaceCategory, int typeFrom, int typeTo);
public abstract bool CanRemoveInterface(SaInterface interfaceObj);
// Interface management.
public abstract SysId CreateInterface(String context, SaInterfaceCategory interfaceCategory, short interfaceType, String code, String caption, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateInterface(SaInterface interfaceObj, DbUpdateInfo dbUpdateInfo);
// Associated events.
public abstract void OnInterfaceCreated(SysId interfaceId);
public abstract void OnInterfaceUpdated(SysId interfaceId);
public abstract void OnInterfaceRemoved(SysId interfaceId);
// Clear configuration options, data items, processes etc.
public abstract bool ClearDependentData(SaInterface interfaceObj, DbUpdateInfo dbUpdateInfo);
//---------------------------------------------------------------
// Process interface.
public abstract bool CanProcessInterface(SaInterface interfaceObj);
public abstract bool ProcessInterface(SaInterface interfaceObj, DbUpdateInfo dbUpdateInfo);
//---------------------------------------------------------------
// Retrieve interfaces.
public abstract SaInterface GetInterfaceById(SysId interfaceId);
public abstract SaInterface GetInterface(SaInterface.Params prmInterface);
public abstract ColumnDfn GetInterfaceColumnDfn(SaInterface.Column columnId, string caption = "", int width = 0);
public abstract long GetInterfaceCount(SaInterface.Params prmInterface);
public abstract List<SaInterface> GetInterfaceList(SaInterface.Params prmInterface);
public abstract DbResultSet ExecuteInterfaceQuery(List<ColumnDfn> columns, SaInterface.Params prm);
public abstract DataValue GetInterfaceDataValue(ColumnDfn column, NamedValue.Map values);
//---------------------------------------------------------------
// Conversion between Interface Category & Code and the equivalent database Id.
public abstract SysId GetInterfaceIdForContextCategoryType(String context, SaInterfaceCategory interfaceCategory, short interfaceType);
public abstract SysId GetInterfaceIdForContextCategoryCode(String context, SaInterfaceCategory interfaceCategory, String code);
public abstract SaInterfaceCategory GetCategoryForInterfaceId(SysId interfaceId);
public abstract String GetCodeForInterfaceId(SysId interfaceId);
//---------------------------------------------------------------
// I n t e r f a c e P r o c e s s e s
//---------------------------------------------------------------
// Identify the highest sequence currently in use for an interface.
public abstract int GetMaxProcessSequence(SysId interfaceId, SaInterfaceProcessDirection processDirection, bool completedOnly = true);
// Create new process and imediately store details on database (status set to 'In Progress').
public abstract SaInterfaceProcess StartInterfaceProcess(SysId interfaceId, SaInterfaceProcessDirection eDirection, String batchRef, DateTime batchAt, int sequence, DbUpdateInfo dbUpdateInfo);
// Retrieve a process using its identity (restricted by interface).
public abstract SaInterfaceProcess GetInterfaceProcess(SysId interfaceId, SysId interfaceProcessId);
// Update the details for a process.
public abstract bool StoreInterfaceProcess(SaInterfaceProcess interfaceProcess, DbUpdateInfo dbUpdateInfo);
//---------------------------------------------------------------
// I n t e r f a c e P r o c e s s M e s s a g e s
//---------------------------------------------------------------
public abstract bool LogInterfaceProcessMessage(SysId interfaceProcessId, DbUpdateInfo dbUpdateInfo, String message, SaMessageLevel messageLevel = SaMessageLevel.Info, String Filename = "", int LineNumber = 0, ItemId ItemId = null);
//---------------------------------------------------------------
// I n t e r f a c e D a t a I t e m s
//---------------------------------------------------------------
public abstract bool ItemHasDataItems(ItemId itemId);
public abstract bool InterfaceDataItemExistsByRef(SysId interfaceId, SaInterfaceProcessDirection processDirection, short itemType, String externalReference);
public abstract SaInterfaceDataItem CreateInterfaceDataItem(SysId interfaceId, SaInterfaceProcessDirection processDirection, ItemId itemId, String externalReference);
public abstract SaInterfaceDataItem GetInterfaceDataItem(SysId interfaceDataItemId);
/// <summary><para>Fails if more than 1 matching data item.</para></summary>
public abstract SaInterfaceDataItem GetInterfaceDataItemByItemRef(SysId interfaceId, SaInterfaceProcessDirection processDirection, ItemId itemId, String externalReference);
/// <summary><para>Fails if more than 1 matching data item.</para></summary>
public abstract SaInterfaceDataItem GetInterfaceDataItemByRef(SysId interfaceId, SaInterfaceProcessDirection processDirection, short itemType, String externalReference);
/// <summary><para>Fails if more than 1 matching data item.</para></summary>
public abstract SaInterfaceDataItem GetInterfaceDataItemByItem(SysId interfaceId, SaInterfaceProcessDirection processDirection, ItemId itemId);
public abstract List<SaInterfaceDataItem> GetInterfaceDataItemsByItem(SysId interfaceId, SaInterfaceProcessDirection processDirection, ItemId itemId);
public abstract List<SaInterfaceDataItem> GetInterfaceDataItemsByRef(SysId interfaceId, SaInterfaceProcessDirection processDirection, short itemType, String externalReference);
public abstract bool StoreInterfaceDataItem(SaInterfaceDataItem interfaceDataItem, DbUpdateInfo dbUpdateInfo);
public abstract bool StoreInterfaceDataItems(List<SaInterfaceDataItem> interfaceDataItems, DbUpdateInfo dbUpdateInfo);
public abstract bool ClearInterfaceDataItem(SaInterfaceDataItem interfaceDataItem, DbUpdateInfo dbUpdateInfo);
public abstract bool ClearInterfaceDataItems(ItemId itemId, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,382 @@
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.Net.Standard.Base.Interfaces
{
//=======================================================================
public class SaInterfaceDataItem : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Pos = 0,
Id,
// Interface.
InterfaceId,
// Data item.
Direction,
Direction_Desc,
ExternalReference,
ItemType,
ItemType_Desc,
ItemId,
Item_Caption,
ProcessStatus,
ProcessStatus_Desc,
ProcessStatus_Ind,
ProcessStatusBy,
ProcessStatusBy_Name,
ProcessStatusAt,
ProcessStatusAt_Date,
ProcessStatusAt_Time,
ItemStatus,
ItemStatus_Desc,
ItemStatus_Ind,
ItemStatusBy,
ItemStatusBy_Name,
ItemStatusAt,
ItemStatusAt_Date,
ItemStatusAt_Time,
// Common properties.
Notes,
CreateOn_Date,
UpdateOn_Date,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public SysId InterfaceId { get; set; } = null;
public SaInterfaceProcessDirection Direction { get; set; } = SaInterfaceProcessDirection.Unknown;
public ItemId ItemId { get; set; } = new ItemId();
public String ExternalReference { get; set; } = String.Empty;
public SaStatus ProcessStatus { get; set; } = SaStatus.Unknown;
public SysId ProcessStatusBy { get; set; } = null;
public DateTime? ProcessStatusAt { get; set; } = DateTime.MinValue;
public SaStatus ItemStatus { get; set; } = SaStatus.Unknown;
public SysId ItemStatusBy { get; set; } = null;
public DateTime? ItemStatusAt { get; set; } = DateTime.MinValue;
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data()
{
ProcessStatus = DefaultProcessStatus;
ItemStatus = DefaultItemStatus;
}
// Properties.
public SysId InterfaceId
{
get { return data.InterfaceId; }
set { CheckChanged(data.InterfaceId, value); data.InterfaceId = value; }
}
public SaInterfaceProcessDirection Direction
{
get { return data.Direction; }
set { CheckChanged((int)data.Direction, (int)value); data.Direction = value; }
}
public ItemId ItemId
{
get { return data.ItemId; }
set { CheckChanged(data.ItemId, value); data.ItemId = value; }
}
public String ExternalReference
{
get { return data.ExternalReference; }
set { CheckChanged(data.ExternalReference, value); data.ExternalReference = value; }
}
public SaStatus ProcessStatus
{
get { return data.ProcessStatus; }
set { CheckChanged((int)data.ProcessStatus, (int)value); data.ProcessStatus = value; }
}
public SysId ProcessStatusBy
{
get { return data.ProcessStatusBy; }
set { CheckChanged(data.ProcessStatusBy, value); data.ProcessStatusBy = value; }
}
public DateTime? ProcessStatusAt
{
get { return data.ProcessStatusAt; }
set { CheckChangedNullable(data.ProcessStatusAt, value); data.ProcessStatusAt = value; }
}
public SaStatus ItemStatus
{
get { return data.ItemStatus; }
set { CheckChanged((int)data.ItemStatus, (int)value); data.ItemStatus = value; }
}
public SysId ItemStatusBy
{
get { return data.ItemStatusBy; }
set { CheckChanged(data.ItemStatusBy, value); data.ItemStatusBy = value; }
}
public DateTime? ItemStatusAt
{
get { return data.ItemStatusAt; }
set { CheckChangedNullable(data.ItemStatusAt, value); data.ItemStatusAt = value; }
}
// Population.
internal void PopulateFrom(Data data)
{
InterfaceId = data.InterfaceId;
Direction = data.Direction;
ItemId = data.ItemId;
ExternalReference = data.ExternalReference;
ProcessStatus = data.ProcessStatus;
ProcessStatusBy = data.ProcessStatusBy;
ProcessStatusAt = data.ProcessStatusAt;
ItemStatus = data.ItemStatus;
ItemStatusBy = data.ItemStatusBy;
ItemStatusAt = data.ItemStatusAt;
base.PopulateFrom(data);
}
public Data Clone()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
// Error field - identify properties with validation error.
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue InterfaceId { get; set; } = ValidValue.Valid;
public ValidValue Direction { get; set; } = ValidValue.Valid;
public ValidValue ItemType { get; set; } = ValidValue.Valid;
public ValidValue ItemId { get; set; } = ValidValue.Valid;
public ValidValue ExternalReference { get; set; } = ValidValue.Valid;
public ValidValue ProcessStatus { get; set; } = ValidValue.Valid;
public ValidValue ProcessStatusBy { get; set; } = ValidValue.Valid;
public ValidValue ProcessStatusAt { get; set; } = ValidValue.Valid;
public ValidValue ItemStatus { get; set; } = ValidValue.Valid;
public ValidValue ItemStatusBy { get; set; } = ValidValue.Valid;
public ValidValue ItemStatusAt { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
// Flags.
public static readonly Byte Flag_OnHold = 0x01;
//-------------------------------------------------------------------
// Construction.
public SaInterfaceDataItem(SysId id, SysId interfaceId, SaInterfaceProcessDirection direction, ItemId itemId, String externalReference) :
base(id)
{
base.SetData(data);
InterfaceId = interfaceId;
Direction = direction;
ItemId = itemId;
ExternalReference = externalReference;
ProcessStatus = DefaultProcessStatus;
ItemStatus = DefaultItemStatus;
}
//-------------------------------------------------------------------
// Process statuses.
private static readonly List<SaStatus> validProcessStatuses = new List<SaStatus>()
{
SaStatus.Awaiting,
SaStatus.Completed,
SaStatus.Cancelled,
SaStatus.Failed
};
public static SaStatus DefaultProcessStatus { get { return AwaitingProcessStatus; } }
public static SaStatus AwaitingProcessStatus { get { return SaStatus.Awaiting; } }
public static SaStatus CompletedProcessStatus { get { return SaStatus.Completed; } }
public static SaStatus CancelledProcessStatus { get { return SaStatus.Cancelled; } }
public static SaStatus FailedProcessStatus { get { return SaStatus.Failed; } }
public static List<SaStatus> ValidProcessStatuses { get { return new List<SaStatus>(validProcessStatuses); } }
public static DataValue.TriStateType GetProcessStatusTriState(SaStatus status)
{
switch (status)
{
case SaStatus.Completed:
return Core.DataValue.TriStateType.Green;
case SaStatus.Awaiting:
return Core.DataValue.TriStateType.Amber;
case SaStatus.Cancelled:
return Core.DataValue.TriStateType.Red;
case SaStatus.Failed:
return Core.DataValue.TriStateType.Yellow;
case SaStatus.Deleted:
return Core.DataValue.TriStateType.Purple;
}
return Core.DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Item Statuses.
private static readonly List<SaStatus> validItemStatuses = new List<SaStatus>()
{
SaStatus.InProgress,
SaStatus.Imported,
SaStatus.Exported,
SaStatus.Cancelled,
};
public static SaStatus DefaultItemStatus { get { return SaStatus.Unknown; } }
public static List<SaStatus> ValidItemStatuses { get { return new List<SaStatus>(validItemStatuses); } }
public static DataValue.TriStateType GetItemStatusTriState(SaStatus status)
{
switch (status)
{
case SaStatus.Imported:
case SaStatus.Exported:
return Core.DataValue.TriStateType.Green;
case SaStatus.InProgress:
return Core.DataValue.TriStateType.Amber;
case SaStatus.Cancelled:
return Core.DataValue.TriStateType.Red;
case SaStatus.Deleted:
return Core.DataValue.TriStateType.Purple;
}
return Core.DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Properties.
public Data GetData() { return data.Clone(); }
public void SetData(Data data)
{
// Properties that cannot be changed if previously specified.
if (SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id))
throw new NotSupportedException($"{SysUtil.Fn} Id cannot be changed");
if (SysId.IsValid(InterfaceId) && SysId.ToInt(InterfaceId) != SysId.ToInt(data.InterfaceId))
throw new NotSupportedException($"{SysUtil.Fn} Interface cannot be changed");
if ((int)Direction > 0 && (int)Direction != (int)data.Direction)
throw new NotSupportedException($"{SysUtil.Fn} Direction cannot be changed");
if (ItemId.Type >= 0 && ItemId.Type != data.ItemId.Type)
throw new NotSupportedException($"{SysUtil.Fn} Item type cannot be changed");
if (SysId.IsValid(ItemId.Id) && SysId.ToInt(ItemId.Id) != SysId.ToInt(data.ItemId.Id))
throw new NotSupportedException($"{SysUtil.Fn} Item Id cannot be changed");
if (!StringUtil.IsEmpty(ExternalReference) && !ExternalReference.Equals(data.ExternalReference))
throw new NotSupportedException($"{SysUtil.Fn} External reference cannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
public SysId InterfaceId
{
get { return data.InterfaceId; }
protected set { data.InterfaceId = value; }
}
public SaInterfaceProcessDirection Direction
{
get { return data.Direction; }
protected set { data.Direction = value; }
}
public ItemId ItemId
{
get { return data.ItemId; }
protected set { data.ItemId = value; }
}
public String ExternalReference
{
get { return data.ExternalReference; }
set { data.ExternalReference = value; }
}
public SaStatus ProcessStatus
{
get { return data.ProcessStatus; }
set { data.ProcessStatus = value; }
}
public SysId ProcessStatusBy
{
get { return data.ProcessStatusBy; }
set { data.ProcessStatusBy = value; }
}
public DateTime? ProcessStatusAt
{
get { return data.ProcessStatusAt; }
set { data.ProcessStatusAt = value; }
}
public SaStatus ItemStatus
{
get { return data.ItemStatus; }
set { data.ItemStatus = value; }
}
public SysId ItemStatusBy
{
get { return data.ItemStatusBy; }
set { data.ItemStatusBy = value; }
}
public DateTime? ItemStatusAt
{
get { return data.ItemStatusAt; }
set { data.ItemStatusAt = value; }
}
//-------------------------------------------------------------------
// Flags.
public bool OnHold
{
get { return GetFlag(Flag_OnHold); }
set { SetFlag(Flag_OnHold, value); }
}
//-------------------------------------------------------------------
// List parameters.
public enum ProcessStatusCat
{
Any,
AwaitingOnly,
CompletedOnly,
}
public enum ItemStatusCat
{
Any,
InProgressOnly,
ImportedOnly,
ExportedOnly,
CancelledOnly,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
public HashSet<SysId> IdsIncluded { get; } = new HashSet<SysId>();
public HashSet<SysId> IdsExcluded { get; } = new HashSet<SysId>();
public SysId InterfaceId { get; set; }
public SaInterfaceProcessDirection Direction { get; set; } = SaInterfaceProcessDirection.Unknown;
public short ItemType { get; set; }
public HashSet<ItemId> ItemIdsIncluded { get; } = new HashSet<ItemId>();
public String ExternalReference { get; set; }
public ProcessStatusCat ProcessStatusCat { get; set; } = ProcessStatusCat.Any;
public ItemStatusCat ItemStatusCat { get; set; } = ItemStatusCat.Any;
}
//-------------------------------------------------------------------
/// <summary>Mode for filtering associated data items.</summary>
public enum FilterMode
{
None,
Exists,
NotExists,
}
//-------------------------------------------------------------------
// L i s t
//-------------------------------------------------------------------
public class List : List<SaInterfaceDataItem>
{
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,487 @@
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
//---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Thu 30-Oct-2025 11:28:13
//---------------------------------------------------------------------------
namespace Sarand.Net.Standard.Base.Interfaces
{
public class SaInterfaceDbDfn
{
//-------------------------------------------------------------------
// Table identifiers.
public enum TableIdx
{
Unknown = 0,
SaInterface,
SaInterfaceDataItem,
SaInterfaceProcess,
SaInterfaceProcessDataItem,
SaInterfaceProcessMessage,
}
//-------------------------------------------------------------------
// Column identifiers.
public enum ColumnIdx
{
Unknown = 0,
SaInterface_Id,
SaInterface_Context,
SaInterface_Code,
SaInterface_Category,
SaInterface_Type,
SaInterface_Caption,
SaInterface_Notes,
SaInterface_Flags,
SaInterface_Status,
SaInterface_CreateOn,
SaInterface_CreateBy,
SaInterface_CreateHost,
SaInterface_UpdateOn,
SaInterface_UpdateBy,
SaInterface_UpdateHost,
SaInterfaceDataItem_Id,
SaInterfaceDataItem_InterfaceId,
SaInterfaceDataItem_Direction,
SaInterfaceDataItem_ExternalRef,
SaInterfaceDataItem_ItemType,
SaInterfaceDataItem_ItemId,
SaInterfaceDataItem_ProcessStatus,
SaInterfaceDataItem_ProcessStatusBy,
SaInterfaceDataItem_ProcessStatusAt,
SaInterfaceDataItem_ItemStatus,
SaInterfaceDataItem_ItemStatusBy,
SaInterfaceDataItem_ItemStatusAt,
SaInterfaceDataItem_Notes,
SaInterfaceDataItem_Flags,
SaInterfaceDataItem_CreateOn,
SaInterfaceDataItem_CreateBy,
SaInterfaceDataItem_CreateHost,
SaInterfaceDataItem_UpdateOn,
SaInterfaceDataItem_UpdateBy,
SaInterfaceDataItem_UpdateHost,
SaInterfaceProcess_Id,
SaInterfaceProcess_InterfaceId,
SaInterfaceProcess_Direction,
SaInterfaceProcess_ProcRef,
SaInterfaceProcess_ProcSeq,
SaInterfaceProcess_ProcessAt,
SaInterfaceProcess_BatchAt,
SaInterfaceProcess_ElapseSecs,
SaInterfaceProcess_ItemCount,
SaInterfaceProcess_Flags,
SaInterfaceProcess_Status,
SaInterfaceProcess_CreateOn,
SaInterfaceProcess_CreateBy,
SaInterfaceProcess_CreateHost,
SaInterfaceProcess_UpdateOn,
SaInterfaceProcess_UpdateBy,
SaInterfaceProcess_UpdateHost,
SaInterfaceProcessDataItem_ProcessId,
SaInterfaceProcessDataItem_InterfaceDataItemId,
SaInterfaceProcessDataItem_ItemData,
SaInterfaceProcessDataItem_Flags,
SaInterfaceProcessDataItem_Status,
SaInterfaceProcessDataItem_CreateOn,
SaInterfaceProcessDataItem_CreateBy,
SaInterfaceProcessDataItem_CreateHost,
SaInterfaceProcessDataItem_UpdateOn,
SaInterfaceProcessDataItem_UpdateBy,
SaInterfaceProcessDataItem_UpdateHost,
SaInterfaceProcessMessage_Id,
SaInterfaceProcessMessage_ProcessId,
SaInterfaceProcessMessage_MsgType,
SaInterfaceProcessMessage_Msg,
SaInterfaceProcessMessage_FileName,
SaInterfaceProcessMessage_LineNumber,
SaInterfaceProcessMessage_ItemType,
SaInterfaceProcessMessage_ItemId,
SaInterfaceProcessMessage_Flags,
SaInterfaceProcessMessage_Status,
SaInterfaceProcessMessage_CreateOn,
SaInterfaceProcessMessage_CreateBy,
SaInterfaceProcessMessage_CreateHost,
SaInterfaceProcessMessage_UpdateOn,
SaInterfaceProcessMessage_UpdateBy,
SaInterfaceProcessMessage_UpdateHost,
}
//-------------------------------------------------------------------
// Data members.
private static readonly int tableCount = 5;
private static readonly int columnCount = 79;
public static ulong MaxTextLen { get; private set; }
//-------------------------------------------------------------------
// Retrieve Table details.
public static int GetTableCount ()
{
return tableCount;
}
public static String GetSchemaName (TableIdx table, bool delimitReservedWords = true)
{
int tableIdx = (int)table - 1;
if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;
String schemaName = tables[(int)tableIdx].Schema;
if (delimitReservedWords) { schemaName = DelimitReservedWord(schemaName); }
return schemaName;
}
public static String GetTableName (TableIdx table, bool delimitReservedWords = true)
{
int tableIdx = (int)table - 1;
if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;
String tableName = tables[(int)tableIdx].Name;
if (delimitReservedWords) tableName = DelimitReservedWord(tableName);
return tableName;
}
public static String GetTableNameQual (TableIdx table, bool delimitReservedWords = true)
{
int tableIdx = (int)table - 1;
if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;
String schemaName = tables[(int)tableIdx].Schema;
String tableName = tables[(int)tableIdx].Name;
if (delimitReservedWords) { schemaName = DelimitReservedWord(schemaName); tableName = DelimitReservedWord(tableName); }
return (StringUtil.IsBlank(schemaName) ? "" : schemaName + ".") + tableName;
}
//-------------------------------------------------------------------
// Identify the table that corresponds with the specified column.
public static TableIdx GetTableForColumn (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return TableIdx.Unknown;
return columns[columnIdx].TableIdx;
}
//-------------------------------------------------------------------
// Retrieve the specified Column's name (Qualified include table name: '(<Table>.Column>)').
public static String GetColumnName (ColumnIdx column, bool delimitReservedWords = true)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return String.Empty;
String columnName = columns[columnIdx].Name;
if (delimitReservedWords) columnName = DelimitReservedWord(columnName);
return columnName;
}
public static String GetColumnNameQual (ColumnIdx column, String tableAlias = "", bool braces = false)
{
String columnName = GetColumnName(column);
if (!String.IsNullOrEmpty(columnName))
{
String tableName = StringUtil.EmptyOnNull(tableAlias);
if (tableName.IsEmpty()) tableName = GetTableName(GetTableForColumn(column));
columnName = tableName + (tableName.Length > 0 ? "." : "") + columnName;
if (braces) columnName = $"({columnName})";
}
return columnName;
}
//-------------------------------------------------------------------
// Reserved words.
private static DbReservedWordDelim reservedWordDelim = DbReservedWordDelim.SquareBrackets;
public static void SetReservedWordDelim (DbReservedWordDelim reservedWordDelim)
{
SaInterfaceDbDfn.reservedWordDelim = reservedWordDelim;
}
public static bool IsReservedWord (String word)
{
if (String.IsNullOrEmpty(word)) return false;
if (reservedWords.Contains(word, StringComparer.OrdinalIgnoreCase)) return true;
return false;
}
public static String DelimitReservedWord (String word)
{
return IsReservedWord(word) ? DelimitWord(word) : word;
}
public static String DelimitWord (String word)
{
return DelimitWord(word, reservedWordDelim);
}
public static String DelimitWord (String word, DbReservedWordDelim wordDelim)
{
switch (wordDelim)
{
case DbReservedWordDelim.None:
break;
case DbReservedWordDelim.DoubleQuotes:
word = $"\"{word}\"";
break;
case DbReservedWordDelim.SquareBrackets:
default:
word = $"[{word}]";
break;
}
return word;
}
//-------------------------------------------------------------------
// Retrieve information about the specified Column.
public static DbColumnDataType GetColDataType (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return DbColumnDataType.Unknown;
return columns[columnIdx].DataType;
}
public static short GetColNativeDataType (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return 0;
return columns[columnIdx].NativeDataType;
}
public static void SetMaxTextLen (ulong maxTextLen)
{
SaInterfaceDbDfn.MaxTextLen = maxTextLen;
}
public static bool IsColFmtText (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
return (columns[columnIdx].DataType == DbColumnDataType.VarChar);
}
public static ulong GetColTextLen (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return 0;
if (columns[columnIdx].DataType == DbColumnDataType.VarChar)
{
ulong textLen = columns[columnIdx].DataLen;
if (MaxTextLen > 0 && textLen > MaxTextLen) textLen = MaxTextLen;
return textLen;
}
return 0;
}
public static bool IsColFmtBool (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
return (columns[columnIdx].DataType == DbColumnDataType.Bit);
}
public static bool IsColFmtNumeric (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
switch (columns[columnIdx].DataType)
{
case DbColumnDataType.TinyInt:
case DbColumnDataType.SmallInt:
case DbColumnDataType.Int:
case DbColumnDataType.BigInt:
case DbColumnDataType.Single:
case DbColumnDataType.Double:
case DbColumnDataType.Decimal:
return true;
}
return false;
}
//-------------------------------------------------------------------
// Table definitions.
private class TableDfn
{
internal String Schema { get; set; }
internal String Name { get; set; }
internal TableDfn (String schema, String name)
{
this.Schema= schema;
this.Name = name;
}
}
private static readonly TableDfn[] tables =
{
new TableDfn("dbo","SaInterface"),
new TableDfn("dbo","SaInterfaceDataItem"),
new TableDfn("dbo","SaInterfaceProcess"),
new TableDfn("dbo","SaInterfaceProcessDataItem"),
new TableDfn("dbo","SaInterfaceProcessMessage"),
};
//-------------------------------------------------------------------
// Table column definitions.
private class ColumnDfn
{
internal TableIdx TableIdx { get; set; }
internal String Name { get; set; }
internal DbColumnDataType DataType { get; set; }
internal short NativeDataType { get; set; }
internal bool IsIdentity { get; set; }
internal ulong DataLen { get; set; }
internal ColumnDfn (int tableIdx, String name, int dataType, short nativeDataType, bool isIdentity, ulong dataLen)
{
this.TableIdx = (TableIdx)tableIdx;
this.Name = name;
this.DataType = (DbColumnDataType)dataType;
this.NativeDataType = nativeDataType;
this.IsIdentity = isIdentity;
this.DataLen = dataLen;
}
}
private static readonly ColumnDfn[] columns =
{
new ColumnDfn(1,"Id",4,4,false,10),
new ColumnDfn(1,"Context",0,-9,false,32),
new ColumnDfn(1,"Code",0,-9,false,32),
new ColumnDfn(1,"Category",3,5,false,5),
new ColumnDfn(1,"Type",3,5,false,5),
new ColumnDfn(1,"Caption",0,-9,false,100),
new ColumnDfn(1,"Notes",0,-9,false,255),
new ColumnDfn(1,"Flags",3,5,false,5),
new ColumnDfn(1,"Status",0,-9,false,3),
new ColumnDfn(1,"CreateOn",9,93,false,23),
new ColumnDfn(1,"CreateBy",4,4,false,10),
new ColumnDfn(1,"CreateHost",0,-9,false,64),
new ColumnDfn(1,"UpdateOn",9,93,false,23),
new ColumnDfn(1,"UpdateBy",4,4,false,10),
new ColumnDfn(1,"UpdateHost",0,-9,false,64),
new ColumnDfn(2,"Id",4,4,false,10),
new ColumnDfn(2,"InterfaceId",4,4,false,10),
new ColumnDfn(2,"Direction",3,5,false,5),
new ColumnDfn(2,"ExternalRef",0,-9,false,64),
new ColumnDfn(2,"ItemType",3,5,false,5),
new ColumnDfn(2,"ItemId",4,4,false,10),
new ColumnDfn(2,"ProcessStatus",0,-9,false,3),
new ColumnDfn(2,"ProcessStatusBy",4,4,false,10),
new ColumnDfn(2,"ProcessStatusAt",9,93,false,23),
new ColumnDfn(2,"ItemStatus",0,-9,false,3),
new ColumnDfn(2,"ItemStatusBy",4,4,false,10),
new ColumnDfn(2,"ItemStatusAt",9,93,false,23),
new ColumnDfn(2,"Notes",0,-9,false,255),
new ColumnDfn(2,"Flags",3,5,false,5),
new ColumnDfn(2,"CreateOn",9,93,false,23),
new ColumnDfn(2,"CreateBy",4,4,false,10),
new ColumnDfn(2,"CreateHost",0,-9,false,64),
new ColumnDfn(2,"UpdateOn",9,93,false,23),
new ColumnDfn(2,"UpdateBy",4,4,false,10),
new ColumnDfn(2,"UpdateHost",0,-9,false,64),
new ColumnDfn(3,"Id",4,4,false,10),
new ColumnDfn(3,"InterfaceId",4,4,false,10),
new ColumnDfn(3,"Direction",3,5,false,5),
new ColumnDfn(3,"ProcRef",0,-9,false,32),
new ColumnDfn(3,"ProcSeq",4,4,false,10),
new ColumnDfn(3,"ProcessAt",9,93,false,23),
new ColumnDfn(3,"BatchAt",9,93,false,23),
new ColumnDfn(3,"ElapseSecs",4,4,false,10),
new ColumnDfn(3,"ItemCount",4,4,false,10),
new ColumnDfn(3,"Flags",3,5,false,5),
new ColumnDfn(3,"Status",0,-9,false,3),
new ColumnDfn(3,"CreateOn",9,93,false,23),
new ColumnDfn(3,"CreateBy",4,4,false,10),
new ColumnDfn(3,"CreateHost",0,-9,false,64),
new ColumnDfn(3,"UpdateOn",9,93,false,23),
new ColumnDfn(3,"UpdateBy",4,4,false,10),
new ColumnDfn(3,"UpdateHost",0,-9,false,64),
new ColumnDfn(4,"ProcessId",4,4,false,10),
new ColumnDfn(4,"InterfaceDataItemId",4,4,false,10),
new ColumnDfn(4,"ItemData",0,-9,false,64),
new ColumnDfn(4,"Flags",3,5,false,5),
new ColumnDfn(4,"Status",0,-9,false,3),
new ColumnDfn(4,"CreateOn",9,93,false,23),
new ColumnDfn(4,"CreateBy",4,4,false,10),
new ColumnDfn(4,"CreateHost",0,-9,false,64),
new ColumnDfn(4,"UpdateOn",9,93,false,23),
new ColumnDfn(4,"UpdateBy",4,4,false,10),
new ColumnDfn(4,"UpdateHost",0,-9,false,64),
new ColumnDfn(5,"Id",4,4,false,10),
new ColumnDfn(5,"ProcessId",4,4,false,10),
new ColumnDfn(5,"MsgType",0,-9,false,3),
new ColumnDfn(5,"Msg",0,-9,false,4000),
new ColumnDfn(5,"FileName",0,-9,false,64),
new ColumnDfn(5,"LineNumber",4,4,false,10),
new ColumnDfn(5,"ItemType",3,5,false,5),
new ColumnDfn(5,"ItemId",4,4,false,10),
new ColumnDfn(5,"Flags",3,5,false,5),
new ColumnDfn(5,"Status",0,12,false,3),
new ColumnDfn(5,"CreateOn",9,93,false,23),
new ColumnDfn(5,"CreateBy",4,4,false,10),
new ColumnDfn(5,"CreateHost",0,12,false,64),
new ColumnDfn(5,"UpdateOn",9,93,false,23),
new ColumnDfn(5,"UpdateBy",4,4,false,10),
new ColumnDfn(5,"UpdateHost",0,12,false,64),
};
//-------------------------------------------------------------------
// Reserved words.
private static readonly HashSet<String> reservedWords = new HashSet<String>()
{
"ADD",
"ALL",
"ALTER",
"AND",
"ANY",
"AS",
"ASC",
"AVG",
"BEGIN",
"BETWEEN",
"BY",
"CASE",
"CAST",
"COLUMN",
"COMMIT",
"CONSTRAINT",
"CONVERT",
"COUNT",
"CREATE",
"CURRENCY",
"DEFAULT",
"DELETE",
"DESC",
"DISTINCT",
"DROP",
"ELSE",
"END",
"EXECUTE",
"EXISTS",
"FALSE",
"FROM",
"GRANT",
"GROUP",
"HAVING",
"IN",
"INDEX",
"INNER",
"INSERT",
"INTO",
"IS",
"JOIN",
"KEY",
"LEFT",
"LIKE",
"MAX",
"MIN",
"NOT",
"NULL",
"ON",
"OR",
"ORDER",
"OUTER",
"OUTPUT",
"PRIMARY",
"PROCEDURE",
"REVOKE",
"ROLLBACK",
"ROWCOUNT",
"SELECT",
"SET",
"SQL",
"SUM",
"TABLE",
"THEN",
"TRANSACTION",
"TRUE",
"UNION",
"UNIQUE",
"UPDATE",
"USER",
"VALUES",
"VIEW",
"WHEN",
"WHERE"
};
//-------------------------------------------------------------------
}
}
@@ -0,0 +1,204 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Base.Interfaces
{
//=======================================================================
public partial class SaInterfaceMgr
{
//*******************************************************************
// I n t e r f a c e D a t a I t e m s
//*******************************************************************
// Create Interface Data Item.
public abstract SaInterfaceDataItem CreateInterfaceDataItem (SysId interfaceId, SaInterfaceProcessDirection direction, ItemId itemId, String externalReference);
// Retrieve individual interface data items.
public abstract bool InterfaceDataItemExistsById (SysId id);
public abstract SaInterfaceDataItem GetInterfaceDataItemById (SysId id);
public abstract SaInterfaceDataItem GetInterfaceDataItem (SaInterfaceDataItem.Params prm);
//-------------------------------------------------------------------
// Validate Interface Data Item.
public bool IsValidInterfaceDataItem (SaInterfaceDataItem interfaceDataItem)
{
ClearErrorState();
if (interfaceDataItem == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidInterfaceDataItemData(interfaceDataItem.GetData(), new SaInterfaceDataItem.ErrField());
}
public virtual bool IsValidInterfaceDataItemData (SaInterfaceDataItem.Data data, SaInterfaceDataItem.ErrField errField)
{
ClearErrorState();
// Interface.
if (errField.InterfaceId != SacsHierarchyItem.ValidValue.Ignore && !SysId.IsValid(data.InterfaceId))
{
errField.InterfaceId = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Interface must be supplied");
}
if (errField.Direction != SacsHierarchyItem.ValidValue.Ignore && (int)data.Direction < 1)
{
errField.Direction = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Direction must be supplied");
}
// Data item.
if (errField.ItemType != SacsHierarchyItem.ValidValue.Ignore && (data.ItemId == null || data.ItemId.Type < 1))
{
errField.ItemType = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Invalid item type");
}
if (errField.ItemId != SacsHierarchyItem.ValidValue.Ignore && (data.ItemId == null || !SysId.IsValid(data.ItemId.Id)))
{
errField.ItemId = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Invalid item id");
}
if (errField.ExternalReference != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.ExternalReference, "reference", (long)SaInterfaceDbDfn.GetColTextLen(SaInterfaceDbDfn.ColumnIdx.SaInterfaceDataItem_ExternalRef)))
{
errField.ExternalReference = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
// Process status.
if (errField.ProcessStatus != SacsHierarchyItem.ValidValue.Ignore)
{
if (!IsValidValue(SacsSystem.GetStatusCode(data.ProcessStatus), "process status", (long)SaInterfaceDbDfn.GetColTextLen(SaInterfaceDbDfn.ColumnIdx.SaInterfaceDataItem_ProcessStatus), true))
{
errField.ProcessStatus = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!SaInterfaceDataItem.ValidProcessStatuses.Contains(data.ProcessStatus))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Invalid process status");
}
}
// Item status.
if (errField.ItemStatus != SacsHierarchyItem.ValidValue.Ignore)
{
if (!IsValidValue(SacsSystem.GetStatusCode(data.ItemStatus), "item status", (long)SaInterfaceDbDfn.GetColTextLen(SaInterfaceDbDfn.ColumnIdx.SaInterfaceDataItem_ItemStatus), true))
{
errField.ItemStatus = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!SaInterfaceDataItem.ValidItemStatuses.Contains(data.ItemStatus))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Invalid item status");
}
}
// Common properties.
if (errField.Notes != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Notes, "notes", (long)SaInterfaceDbDfn.GetColTextLen(SaInterfaceDbDfn.ColumnIdx.SaInterfaceDataItem_Notes)))
{
errField.Notes = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
// NB No Status on Interface Data Item.
return true;
}
//-------------------------------------------------------------------
// Interface Data Item database interface.
public abstract bool InsertInterfaceDataItem (SaInterfaceDataItem interfaceDataItem, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateInterfaceDataItem (SaInterfaceDataItem interfaceDataItem, DbUpdateInfo dbUpdateInfo);
public virtual bool InterfaceDataItemCanBeDeleted (SaInterfaceDataItem interfaceDataItem)
{
ClearErrorState();
return true;
}
public abstract bool DeleteInterfaceDataItem (SaInterfaceDataItem interfaceDataItem, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Interface Data Item list.
public abstract ColumnDfn GetInterfaceDataItemColumnDfn (SaInterfaceDataItem.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetInterfaceDataItemQueryFilter (SaInterfaceDataItem.Params prm);
public abstract long GetInterfaceDataItemCount (SaInterfaceDataItem.Params prm);
public abstract List<SaInterfaceDataItem> GetInterfaceDataItemList (SaInterfaceDataItem.Params prm);
public abstract DbResultSet ExecuteInterfaceDataItemQuery (List<ColumnDfn> columns, SaInterfaceDataItem.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public virtual DataValue GetInterfaceDataItemDataValue (ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
switch ((SaInterfaceDataItem.Column)column.Id)
{
//-----------------------------------------------------------
// Category.
case SaInterfaceDataItem.Column.Direction_Desc:
{
SaInterfaceProcessDirection direction = (SaInterfaceProcessDirection)StringUtil.ToInt(values.GetValue(column.DataName).ToString());
value = new DataValue(ProcessDirections.GetCodeForType(direction, direction.ToString()));
}
break;
//-----------------------------------------------------------
// Item Type.
case SaInterfaceDataItem.Column.ItemType_Desc:
{
short itemType = StringUtil.ToShort(values.GetValue(column.DataName).ToString());
String itemTypeDesc = InterfaceConsole.GetItemTypeDesc(itemType);
value = new DataValue(itemTypeDesc);
}
break;
//-----------------------------------------------------------
// Item Type.
case SaInterfaceDataItem.Column.Item_Caption:
{
short itemType = StringUtil.ToShort(values.GetValue(GetInterfaceProcessMessageColumnDfn(SaInterfaceProcessMessage.Column.ItemType).DataName).ToString());
SysId itemId = new SysId(StringUtil.ToInt(values.GetValue(column.DataName).ToString()));
String itemTypeDesc = InterfaceConsole.GetItemCaption(new ItemId(itemType,itemId));
value = new DataValue(itemTypeDesc);
}
break;
//-----------------------------------------------------------
// Process Status.
case SaInterfaceDataItem.Column.ProcessStatus_Desc:
case SaInterfaceDataItem.Column.ProcessStatus_Ind:
{
String statusCode = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusCode);
if (column.Id == (int)SaInterfaceDataItem.Column.ProcessStatus_Desc)
value = new DataValue(SacsSystem.GetStatusDescForCode(statusCode));
else if (column.Id == (int)SaInterfaceDataItem.Column.ProcessStatus_Ind)
value = new DataValue(SaInterfaceDataItem.GetProcessStatusTriState(status));
}
break;
//-----------------------------------------------------------
// Item Status.
case SaInterfaceDataItem.Column.ItemStatus_Desc:
case SaInterfaceDataItem.Column.ItemStatus_Ind:
{
String statusCode = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusCode);
if (column.Id == (int)SaInterfaceDataItem.Column.ItemStatus_Desc)
value = new DataValue(SacsSystem.GetStatusDescForCode(statusCode));
else if (column.Id == (int)SaInterfaceDataItem.Column.ItemStatus_Ind)
value = new DataValue(SaInterfaceDataItem.GetItemStatusTriState(status));
}
break;
//-----------------------------------------------------------
// Notes.
case SaInterfaceDataItem.Column.Notes:
{
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
}
break;
//-----------------------------------------------------------
}
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,15 @@
using System.Collections.Generic;
namespace Sarand.Net.Standard.Base.Interfaces
{
//=======================================================================
public partial class SaInterfaceMgr
{
//*******************************************************************
// I n t e r f a c e P r o c e s s D a t a I t e m s
//*******************************************************************
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,166 @@
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.Net.Standard.Base.Interfaces
{
//=======================================================================
public partial class SaInterfaceMgr
{
//*******************************************************************
// I n t e r f a c e P r o c e s s M e s s a g e s
//*******************************************************************
// Retrieve individual interface process messages.
public abstract bool InterfaceProcessMessageExistsById (SysId id);
public abstract SaInterfaceProcessMessage GetInterfaceProcessMessageById (SysId id);
public abstract SaInterfaceProcessMessage GetInterfaceProcessMessage (SaInterfaceProcessMessage.Params prm);
// Create Interface Process Message.
public abstract SaInterfaceProcessMessage CreateInterfaceProcessMessage (SysId interfaceProcessId);
//-------------------------------------------------------------------
// Validate Interface Process Message.
public bool IsValidInterfaceProcessMessage (SaInterfaceProcessMessage interfaceProcessMessage)
{
ClearErrorState();
if (interfaceProcessMessage == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidInterfaceProcessMessageData(interfaceProcessMessage.GetData(), new SaInterfaceProcessMessage.ErrField());
}
public virtual bool IsValidInterfaceProcessMessageData (SaInterfaceProcessMessage.Data data, SaInterfaceProcessMessage.ErrField errField)
{
ClearErrorState();
if (errField.InterfaceProcessId != SacsHierarchyItem.ValidValue.Ignore && !SysId.IsValid(data.InterfaceProcessId))
{
errField.InterfaceProcessId = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Process must be supplied");
}
if (errField.Level != SacsHierarchyItem.ValidValue.Ignore && (int)data.Level < 1)
{
errField.Level = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Level must be supplied");
}
if (errField.Level != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(messageLevels.GetCodeForType(data.Level), "level", (long)SaInterfaceDbDfn.GetColTextLen(SaInterfaceDbDfn.ColumnIdx.SaInterfaceProcessMessage_MsgType), true, true))
{
errField.Level = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Message != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Message, "message", (long)SaInterfaceDbDfn.GetColTextLen(SaInterfaceDbDfn.ColumnIdx.SaInterfaceProcessMessage_Msg), true))
{
errField.Message = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Filename != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Filename, "filename", (long)SaInterfaceDbDfn.GetColTextLen(SaInterfaceDbDfn.ColumnIdx.SaInterfaceProcessMessage_FileName)))
{
errField.Filename = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.LineNumber != SacsHierarchyItem.ValidValue.Ignore && data.LineNumber < 0)
{
errField.LineNumber = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Invalid line number");
}
// Common properties.
if (errField.Status != SacsHierarchyItem.ValidValue.Ignore && !SaInterfaceProcessMessage.ValidStatuses.Contains(data.Status))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.InvalidStatus);
}
return true;
}
//-------------------------------------------------------------------
// Interface Process Message database interface.
public abstract bool InsertInterfaceProcessMessage (SaInterfaceProcessMessage interfaceProcessMessage, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateInterfaceProcessMessage (SaInterfaceProcessMessage interfaceProcessMessage, DbUpdateInfo dbUpdateInfo);
public virtual bool InterfaceProcessMessageCanBeDeleted (SaInterfaceProcessMessage interfaceProcessMessage)
{
ClearErrorState();
return true;
}
public abstract bool DeleteInterfaceProcessMessage (SaInterfaceProcessMessage interfaceProcessMessage, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Interface Process Message list.
public abstract ColumnDfn GetInterfaceProcessMessageColumnDfn (SaInterfaceProcessMessage.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetInterfaceProcessMessageQueryFilter (SaInterfaceProcessMessage.Params prm);
public abstract long GetInterfaceProcessMessageCount (SaInterfaceProcessMessage.Params prm);
public abstract List<SaInterfaceProcessMessage> GetInterfaceProcessMessageList (SaInterfaceProcessMessage.Params prm);
public abstract DbResultSet ExecuteInterfaceProcessMessageQuery (List<ColumnDfn> columns, SaInterfaceProcessMessage.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public virtual DataValue GetInterfaceProcessMessageDataValue (ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
switch ((SaInterfaceProcessMessage.Column)column.Id)
{
//-----------------------------------------------------------
// Category.
case SaInterfaceProcessMessage.Column.Level_Desc:
{
String level = values.GetValue(column.DataName).ToString();
// Legacy 'Warning' code: 'WAR'.
if (level.EndsWithCI(MessageTypeWarningAlt)) level = messageLevels.GetCodeForType(SaMessageLevel.Warning);
value = new DataValue(messageLevels.GetDescForCode(level, level));
}
break;
//-----------------------------------------------------------
// Item Type.
case SaInterfaceProcessMessage.Column.ItemType_Desc:
{
short itemType = StringUtil.ToShort(values.GetValue(column.DataName).ToString());
String itemTypeDesc = InterfaceConsole.GetItemTypeDesc(itemType);
value = new DataValue(itemTypeDesc);
}
break;
//-----------------------------------------------------------
// Item Type.
case SaInterfaceProcessMessage.Column.Item_Caption:
{
short itemType = StringUtil.ToShort(values.GetValue(GetInterfaceProcessMessageColumnDfn(SaInterfaceProcessMessage.Column.ItemType).DataName).ToString());
SysId itemId = new SysId(StringUtil.ToInt(values.GetValue(column.DataName).ToString()));
String itemTypeDesc = InterfaceConsole.GetItemCaption(new ItemId(itemType,itemId));
value = new DataValue(itemTypeDesc);
}
break;
//-----------------------------------------------------------
// Notes.
case SaInterfaceProcessMessage.Column.Notes:
{
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
}
break;
//-----------------------------------------------------------
// Status.
case SaInterfaceProcessMessage.Column.Status_Desc:
case SaInterfaceProcessMessage.Column.Status_Ind:
{
String statusCode = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusCode);
if (column.Id == (int)SaInterfaceProcessMessage.Column.Status_Desc)
value = new DataValue(SacsSystem.GetStatusDescForCode(statusCode));
else if (column.Id == (int)SaInterfaceProcessMessage.Column.Status_Ind)
value = new DataValue(SaInterfaceProcessMessage.GetStatusTriState(status));
}
break;
//-----------------------------------------------------------
}
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,238 @@
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.Net.Standard.Base.Interfaces
{
//=======================================================================
public partial class SaInterfaceMgr
{
//*******************************************************************
// I n t e r f a c e P r o c e s s e s
//*******************************************************************
// Data members.
protected static readonly String colInterfaceProcess_MessageStatusErr = "IntPrcMessageStatusErr";
protected static readonly String colInterfaceProcess_MessageStatusWrn = "IntPrcMessageStatusWrn";
protected static readonly String colInterfaceProcess_MessageStatusInf = "IntPrcMessageStatusInf";
//-------------------------------------------------------------------
// Associated data.
public abstract int GetInterfaceProcessMessageCount (SysId id);
public abstract bool InterfaceProcessHasMessages (SysId id);
public abstract int GetInterfaceProcessDataItemCount (SysId id);
public abstract bool InterfaceProcessHasDataItems (SysId id);
//-------------------------------------------------------------------
// Retrieve individual interface processes.
public abstract bool InterfaceProcessExistsById (SysId id);
public abstract SaInterfaceProcess GetInterfaceProcessById (SysId id);
public abstract SaInterfaceProcess GetInterfaceProcess (SaInterfaceProcess.Params prm);
// Create Interface Process.
public abstract SaInterfaceProcess CreateInterfaceProcess (SysId interfaceId, SaInterfaceProcessDirection direction, String reference, int sequence);
//-------------------------------------------------------------------
// Validate Interface Process.
public bool IsValidInterfaceProcess (SaInterfaceProcess interfaceProcess)
{
ClearErrorState();
if (interfaceProcess == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidInterfaceProcessData(interfaceProcess.GetData(), new SaInterfaceProcess.ErrField());
}
public virtual bool IsValidInterfaceProcessData (SaInterfaceProcess.Data data, SaInterfaceProcess.ErrField errField)
{
ClearErrorState();
if (errField.InterfaceId != SacsHierarchyItem.ValidValue.Ignore && !SysId.IsValid(data.InterfaceId))
{
errField.InterfaceId = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Interface must be supplied");
}
if (errField.Direction != SacsHierarchyItem.ValidValue.Ignore && (int)data.Direction < 1)
{
errField.Direction = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Direction must be supplied");
}
if (errField.Reference != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Reference, "reference", (long)SaInterfaceDbDfn.GetColTextLen(SaInterfaceDbDfn.ColumnIdx.SaInterfaceProcess_ProcRef)))
{
errField.Reference = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Sequence != SacsHierarchyItem.ValidValue.Ignore && data.Sequence < 1)
{
errField.Sequence = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Sequence must be supplied");
}
// Common properties.
if (errField.Status != SacsHierarchyItem.ValidValue.Ignore && !SaInterfaceProcess.ValidStatuses.Contains(data.Status))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.InvalidStatus);
}
return true;
}
//-------------------------------------------------------------------
// Interface Process database interface.
public abstract bool InsertInterfaceProcess (SaInterfaceProcess interfaceProcess, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateInterfaceProcess (SaInterfaceProcess interfaceProcess, DbUpdateInfo dbUpdateInfo);
public virtual bool InterfaceProcessCanBeDeleted (SaInterfaceProcess interfaceProcess)
{
ClearErrorState();
if (InterfaceProcessHasMessages(interfaceProcess.Id)) return SetErrorState("Process has messages");
if (InterfaceProcessHasDataItems(interfaceProcess.Id)) return SetErrorState("Process has data items");
return true;
}
public abstract bool ClearInterfaceProcessMessages (List<SysId> interfaceProcessIds, DbUpdateInfo dbUpdateInfo);
public abstract bool ClearInterfaceProcessDataItems (List<SysId> interfaceProcessIds, DbUpdateInfo dbUpdateInfo);
public abstract bool DeleteInterfaceProcess (SaInterfaceProcess interfaceProcess, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Interface Process list.
public abstract ColumnDfn GetInterfaceProcessColumnDfn (SaInterfaceProcess.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetInterfaceProcessQueryFilter (SaInterfaceProcess.Params prm);
public abstract long GetInterfaceProcessCount (SaInterfaceProcess.Params prm);
public abstract List<SaInterfaceProcess> GetInterfaceProcessList (SaInterfaceProcess.Params prm);
public abstract DbResultSet ExecuteInterfaceProcessQuery (List<ColumnDfn> columns, SaInterfaceProcess.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public virtual DataValue GetInterfaceProcessDataValue (ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
switch ((SaInterfaceProcess.Column)column.Id)
{
//-----------------------------------------------------------
// Category.
case SaInterfaceProcess.Column.Interface_Category_Desc:
{
SaInterfaceCategory category = (SaInterfaceCategory)StringUtil.ToInt(values.GetValue(column.DataName).ToString());
value = new DataValue(interfaceCategories.GetCodeForType(category, category.ToString()));
break;
}
//-----------------------------------------------------------
// Type.
case SaInterfaceProcess.Column.Interface_Type_Desc:
{
String context = values.GetValue(GetInterfaceProcessColumnDfn(SaInterfaceProcess.Column.Interface_Context).DataName).ToString();
SaInterfaceCategory category = (SaInterfaceCategory)StringUtil.ToInt(values.GetValue(GetInterfaceProcessColumnDfn(SaInterfaceProcess.Column.Interface_Category).DataName).ToString());
short type = StringUtil.ToShort(values.GetValue(column.DataName).ToString());
String typeDesc = InterfaceConsole.GetInterfaceTypeDesc(context,category,type);
if (StringUtil.IsEmpty(typeDesc)) typeDesc = type.ToString();
value = new DataValue(typeDesc);
break;
}
//-----------------------------------------------------------
// Process Direction.
case SaInterfaceProcess.Column.ProcessDirection_Desc:
{
SaInterfaceProcessDirection direction = (SaInterfaceProcessDirection)StringUtil.ToInt(values.GetValue(column.DataName).ToString());
value = new DataValue(processDirections.GetCodeForType(direction, direction.ToString()));
break;
}
//-----------------------------------------------------------
// Processed & Batch DateTimes.
case SaInterfaceProcess.Column.ProcessAt:
case SaInterfaceProcess.Column.ProcessAt_Date:
case SaInterfaceProcess.Column.ProcessAt_Time:
{
// Skip if 'ProcessAt' db column exists.
if (ColumnExists(SaInterfaceDbDfn.ColumnIdx.SaInterfaceProcess_ProcessAt)) break;
int processDate = (int)values.GetValue(GetInterfaceProcessColumnDfn(SaInterfaceProcess.Column.ProcessAt_Date).DataName).AsLong();
int processTime = (int)values.GetValue(GetInterfaceProcessColumnDfn(SaInterfaceProcess.Column.ProcessAt_Time).DataName).AsLong();
DateTime processAt = DateUtil.Int32ToDate(processDate);
processAt = processAt.SetTime(DateUtil.Int32ToTime(processTime));
value = new DataValue(processAt);
break;
}
case SaInterfaceProcess.Column.BatchAt:
case SaInterfaceProcess.Column.BatchAt_Date:
case SaInterfaceProcess.Column.BatchAt_Time:
{
// Skip if 'BatchAt' db column exists.
if (ColumnExists(SaInterfaceDbDfn.ColumnIdx.SaInterfaceProcess_BatchAt)) break;
int batchDate = (int)values.GetValue(GetInterfaceProcessColumnDfn(SaInterfaceProcess.Column.BatchAt_Date).DataName).AsLong();
int batchTime = (int)values.GetValue(GetInterfaceProcessColumnDfn(SaInterfaceProcess.Column.BatchAt_Time).DataName).AsLong();
DateTime batchAt = DateUtil.Int32ToDate(batchDate);
batchAt = batchAt.SetTime(DateUtil.Int32ToTime(batchTime));
value = new DataValue(batchAt);
break;
}
//-----------------------------------------------------------
// Elapsed time.
case SaInterfaceProcess.Column.Elapsed_Fmt:
{
int elapsedSecs = StringUtil.ToInt(values.GetValue(column.DataName).ToString());
value = new DataValue(DateUtil.FormatNumberOfSeconds(elapsedSecs));
break;
}
//-----------------------------------------------------------
// Status.
case SaInterfaceProcess.Column.Message_Status_Desc:
case SaInterfaceProcess.Column.Message_Status_Ind:
{
long messageCountErr = values.GetValue(colInterfaceProcess_MessageStatusErr).AsLong();
long messageCountWrn = values.GetValue(colInterfaceProcess_MessageStatusWrn).AsLong();
long messageCountInf = values.GetValue(colInterfaceProcess_MessageStatusInf).AsLong();
if (column.Id == (int)SaInterfaceProcess.Column.Message_Status_Desc)
{
String statusDesc = "";
if (messageCountErr > 0) statusDesc = messageLevels.GetCodeForType(SaMessageLevel.Error, "Error");
else if (messageCountWrn > 0) statusDesc = messageLevels.GetCodeForType(SaMessageLevel.Warning, "Warning");
else if (messageCountInf > 0) statusDesc = messageLevels.GetCodeForType(SaMessageLevel.Info, "Info");
value = new DataValue(statusDesc);
}
else if (column.Id == (int)SaInterfaceProcess.Column.Message_Status_Ind)
{
DataValue.TriStateType triState = DataValue.TriStateType.Unknown;
if (messageCountErr > 0) triState = DataValue.TriStateType.Red;
else if (messageCountWrn > 0) triState = DataValue.TriStateType.Amber;
else if (messageCountInf > 0) triState = DataValue.TriStateType.Green;
value = new DataValue(triState);
}
break;
}
//-----------------------------------------------------------
// Notes.
case SaInterfaceProcess.Column.Notes:
{
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
break;
}
//-----------------------------------------------------------
// Status.
case SaInterfaceProcess.Column.Status_Desc:
case SaInterfaceProcess.Column.Status_Ind:
{
String statusCode = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusCode);
if (column.Id == (int)SaInterfaceProcess.Column.Status_Desc)
value = new DataValue(SacsSystem.GetStatusDescForCode(statusCode));
else if (column.Id == (int)SaInterfaceProcess.Column.Status_Ind)
value = new DataValue(SaInterfaceProcess.GetStatusTriState(status));
break;
}
//-----------------------------------------------------------
}
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,210 @@
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.Net.Standard.Base.Interfaces
{
//=======================================================================
public partial class SaInterfaceMgr
{
//*******************************************************************
// I n t e r f a c e s
//*******************************************************************
// Associated data.
public abstract bool InterfaceHasProcesses (SysId id);
public abstract bool InterfaceHasDataItems (SysId id);
// Process sequence.
public abstract int GetMaxProcessSequenceForInterface (SysId interfaceId, SaInterfaceProcessDirection processDirection);
//-------------------------------------------------------------------
// Retrieve individual interfaces.
public abstract bool InterfaceExistsById (SysId id);
public abstract bool InterfaceExistsByCode (String code);
public abstract SaInterface GetInterfaceById (SysId id);
public abstract SaInterface GetInterfaceByContextCode (String context, String code);
public abstract SaInterface GetInterface (SaInterface.Params prm);
// Create Interface.
public abstract SaInterface CreateInterface (String context, SaInterfaceCategory category, short type);
//-------------------------------------------------------------------
// Validate Interface.
public bool IsValidInterface (SaInterface interfaceObj)
{
ClearErrorState();
if (interfaceObj == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidInterfaceData(interfaceObj.GetData(), new SaInterface.ErrField());
}
public virtual bool IsValidInterfaceData (SaInterface.Data data, SaInterface.ErrField errField)
{
ClearErrorState();
if (errField.Context != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Context, "context", (long)SaInterfaceDbDfn.GetColTextLen(SaInterfaceDbDfn.ColumnIdx.SaInterface_Context)))
{
errField.Context = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Category != SacsHierarchyItem.ValidValue.Ignore && (int)data.Category < 1)
{
errField.Category = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Category must be supplied");
}
if (errField.Type != SacsHierarchyItem.ValidValue.Ignore && data.Type < 1)
{
errField.Type = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Type must be supplied");
}
if (errField.Code != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Code, "code", (long)SaInterfaceDbDfn.GetColTextLen(SaInterfaceDbDfn.ColumnIdx.SaInterface_Code), true))
{
errField.Code = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
// Code must be only alphanumeric with hyphens and underscores.
String codeTest = data.Code.Replace("-","").Replace("_","");
if (StringUtil.IsEmpty(codeTest) || !StringUtil.IsAlphaNumeric(codeTest))
{
SetErrorState("Code must only consts if letters, numbers, hyphens and underscores, and have at least one letter or number");
errField.Code = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
// Code must be unique.
SaInterface interfaceByCode = GetInterfaceByContextCode(data.Context, data.Code);
if (interfaceByCode != null && !data.Id.Equals(interfaceByCode.Id))
{
SetErrorState("Code is already in use by the '" + interfaceByCode.Caption + "' interface.");
errField.Code = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
// Caption.
if (errField.Caption != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Caption, "caption", (long)SaInterfaceDbDfn.GetColTextLen(SaInterfaceDbDfn.ColumnIdx.SaInterface_Caption), true))
{
errField.Caption = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
// Common properties.
if (errField.Notes != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Notes, "notes", (long)SaInterfaceDbDfn.GetColTextLen(SaInterfaceDbDfn.ColumnIdx.SaInterface_Notes)))
{
errField.Notes = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Status != SacsHierarchyItem.ValidValue.Ignore && !SaInterface.ValidStatuses.Contains(data.Status))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.InvalidStatus);
}
return true;
}
//-------------------------------------------------------------------
// Interface database interface.
public abstract bool InsertInterface (SaInterface interfaceObj, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateInterface (SaInterface interfaceObj, DbUpdateInfo dbUpdateInfo);
public virtual bool InterfaceCanBeDeleted (SaInterface interfaceObj)
{
ClearErrorState();
if (InterfaceHasProcesses(interfaceObj.Id)) return SetErrorState("Interface has processes");
if (InterfaceHasDataItems(interfaceObj.Id)) return SetErrorState("Interface has data items");
return true;
}
public abstract bool DeleteInterface (SaInterface interfaceObj, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Interface list.
public abstract ColumnDfn GetInterfaceColumnDfn (SaInterface.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetInterfaceQueryFilter (SaInterface.Params prm);
public abstract long GetInterfaceCount (SaInterface.Params prm);
public abstract List<SaInterface> GetInterfaceList (SaInterface.Params prm);
public abstract DbResultSet ExecuteInterfaceQuery (List<ColumnDfn> columns, SaInterface.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public virtual DataValue GetInterfaceDataValue (ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
switch ((SaInterface.Column)column.Id)
{
//-----------------------------------------------------------
// Category.
case SaInterface.Column.Category_Desc:
{
SaInterfaceCategory category = (SaInterfaceCategory)StringUtil.ToInt(values.GetValue(column.DataName).ToString());
value = new DataValue(interfaceCategories.GetCodeForType(category, category.ToString()));
}
break;
//-----------------------------------------------------------
// Type.
case SaInterface.Column.Type_Desc:
{
String context = values.GetValue(GetInterfaceColumnDfn(SaInterface.Column.Context).DataName).ToString();
SaInterfaceCategory category = (SaInterfaceCategory)StringUtil.ToInt(values.GetValue(GetInterfaceColumnDfn(SaInterface.Column.Category).DataName).ToString());
short type = StringUtil.ToShort(values.GetValue(column.DataName).ToString());
String typeDesc = InterfaceConsole.GetInterfaceTypeDesc(context, category, type);
if (StringUtil.IsEmpty(typeDesc)) typeDesc = type.ToString();
value = new DataValue(typeDesc);
}
break;
//-----------------------------------------------------------
// Item type.
case SaInterface.Column.Active_Y:
case SaInterface.Column.Active_TickCross:
case SaInterface.Column.Active_Ind:
{
ushort flags = (ushort)values.GetValue(column.DataName).AsLong();
bool activeInterface = SacsHierarchyItem.GetFlag(flags, SaInterface.Flag_Active);
if (column.Id == (int)SaInterface.Column.Active_Y)
value = new DataValue(activeInterface ? "Y" : "");
else if (column.Id == (int)SaInterface.Column.Active_Ind)
value = new DataValue(activeInterface ? DataValue.TriStateType.Green : DataValue.TriStateType.Red);
else
value = new DataValue(activeInterface);
}
break;
//-----------------------------------------------------------
// Notes.
case SaInterface.Column.Notes:
{
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
}
break;
//-----------------------------------------------------------
// Status.
case SaInterface.Column.Status_Desc:
case SaInterface.Column.Status_Ind:
{
String statusCode = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusCode);
if (column.Id == (int)SaInterface.Column.Status_Desc)
{
String statusDesc = SacsSystem.GetStatusDescForCode(statusCode);
value = new DataValue(statusDesc);
}
else if (column.Id == (int)SaInterface.Column.Status_Ind)
{
DataValue.TriStateType triState = DataValue.TriStateType.Unknown;
if (status == SaStatus.Current || status == SaStatus.Active)
triState = DataValue.TriStateType.Green;
value = new DataValue(triState);
}
}
break;
//-----------------------------------------------------------
}
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
namespace Sarand.Net.Standard.Base.Interfaces
{
//=======================================================================
public abstract partial class SaInterfaceMgr : SacsItemMgr
{
//-------------------------------------------------------------------
// Data members.
private static readonly List<TypeCodeDesc> interfaceCategories = SacsSystem.GetCodesOfType(SaSysCodeType.InterfaceCategory);
private static readonly List<TypeCodeDesc> processDirections = SacsSystem.GetCodesOfType(SaSysCodeType.InterfaceProcessDirection);
private static readonly List<TypeCodeDesc> messageLevels = SacsSystem.GetCodesOfType(SaSysCodeType.MessageLevel);
//-------------------------------------------------------------------
// Static initialisation.
static SaInterfaceMgr ()
{
}
//-------------------------------------------------------------------
// Construction.
protected SaInterfaceMgr (SaInterfaceConsole interfaceConsole)
{
InterfaceConsole = interfaceConsole;
}
//-------------------------------------------------------------------
// Properties.
protected SaInterfaceConsole InterfaceConsole { get; }
protected static List<TypeCodeDesc> InterfaceCategories { get { return new List<TypeCodeDesc>(interfaceCategories); } }
protected static List<TypeCodeDesc> ProcessDirections { get { return new List<TypeCodeDesc>(processDirections); } }
protected static List<TypeCodeDesc> MessageLevels { get { return new List<TypeCodeDesc>(messageLevels); } }
// Database.
public abstract bool DatabaseIsValid { get; }
public abstract bool CanUpdateDatabase { get; }
// Alternate 'Warning' message level code (pre 2014 Sapphire).
protected static String MessageTypeWarningAlt { get; } = "WAR";
//-------------------------------------------------------------------
// Utilities.
public abstract bool ColumnExists (SaInterfaceDbDfn.ColumnIdx columnIdx);
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,297 @@
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.Net.Standard.Base.Interfaces
{
//=======================================================================
public class SaInterfaceProcess : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Pos = 0,
Id,
// Interface.
InterfaceId,
Interface_Context,
Interface_Category,
Interface_Category_Desc,
Interface_Type,
Interface_Type_Desc,
Interface_Code,
Interface_Caption,
// Interface process.
ProcessDirection,
ProcessDirection_Desc,
ProcessReference,
ProcessSequence,
ProcessAt,
ProcessAt_Date,
ProcessAt_Time,
BatchAt,
BatchAt_Date,
BatchAt_Time,
Elapsed_Secs,
Elapsed_Fmt,
// Derived properties.
Message_Count,
Message_Status_Desc,
Message_Status_Ind,
DataItem_Count,
// Common properties.
Notes,
Status,
Status_Desc,
Status_Ind,
CreateOn_Date,
UpdateOn_Date,
UpdateHost,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public SysId InterfaceId { get; set; } = null;
public SaInterfaceProcessDirection Direction { get; set; } = SaInterfaceProcessDirection.Unknown;
public String Reference { get; set; } = String.Empty;
public int Sequence { get; set; } = 0;
public DateTime? ProcessAt { get; set; } = DateTime.MinValue;
public DateTime? BatchAt { get; set; } = DateTime.MinValue;
public int ElapseSecs { get; set; } = 0;
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data()
{
Status = DefaultStatus;
}
// Properties.
public SysId InterfaceId
{
get { return data.InterfaceId; }
set { CheckChanged(data.InterfaceId, value); data.InterfaceId = value; }
}
public SaInterfaceProcessDirection Direction
{
get { return data.Direction; }
set { CheckChanged((int)data.Direction, (int)value); data.Direction = value; }
}
public String Reference
{
get { return data.Reference; }
set { CheckChanged(data.Reference, value); data.Reference = value; }
}
public int Sequence
{
get { return data.Sequence; }
set { CheckChanged(data.Sequence, value); data.Sequence = value; }
}
public DateTime? ProcessAt
{
get { return data.ProcessAt; }
set { CheckChangedNullable(data.ProcessAt, value); data.ProcessAt = value; }
}
public DateTime? BatchAt
{
get { return data.BatchAt; }
set { CheckChangedNullable(data.BatchAt, value); data.BatchAt = value; }
}
public int ElapseSecs
{
get { return data.ElapseSecs; }
set { CheckChanged(data.ElapseSecs, value); data.ElapseSecs = value; }
}
// Population.
internal void PopulateFrom(Data data)
{
InterfaceId = data.InterfaceId;
Direction = data.Direction;
Reference = data.Reference;
Sequence = data.Sequence;
ProcessAt = data.ProcessAt;
BatchAt = data.BatchAt;
ElapseSecs = data.ElapseSecs;
base.PopulateFrom(data);
}
public Data Clone()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
// Error field - identify properties with validation error.
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue InterfaceId { get; set; } = ValidValue.Valid;
public ValidValue Direction { get; set; } = ValidValue.Valid;
public ValidValue Reference { get; set; } = ValidValue.Valid;
public ValidValue Sequence { get; set; } = ValidValue.Valid;
public ValidValue ProcessedAt { get; set; } = ValidValue.Valid;
public ValidValue BatchAt { get; set; } = ValidValue.Valid;
public ValidValue ElapseSecs { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
// Flags.
public static readonly Byte Flag_ = 0x01;
//-------------------------------------------------------------------
// Construction.
public SaInterfaceProcess(SysId id, SysId interfaceId, SaInterfaceProcessDirection direction, String reference, int sequence) :
base(id)
{
base.SetData(data);
InterfaceId = interfaceId;
Direction = direction;
Reference = reference;
Sequence = sequence;
Status = DefaultStatus;
}
//-------------------------------------------------------------------
// Statuses.
private static readonly List<SaStatus> validStatuses = new List<SaStatus>()
{
SaStatus.Awaiting,
SaStatus.InProgress,
SaStatus.Completed,
SaStatus.Cancelled
};
public static SaStatus DefaultStatus { get { return AwaitingStatus; } }
public static SaStatus AwaitingStatus { get { return SaStatus.Awaiting; } }
public static SaStatus InProgressStatus { get { return SaStatus.InProgress; } }
public static SaStatus CompletedStatus { get { return SaStatus.Completed; } }
public static SaStatus CancelledStatus { get { return SaStatus.Cancelled; } }
public static List<SaStatus> ValidStatuses { get { return new List<SaStatus>(validStatuses); } }
public static DataValue.TriStateType GetStatusTriState(SaStatus status)
{
switch (status)
{
case SaStatus.Awaiting:
return Core.DataValue.TriStateType.Amber;
case SaStatus.InProgress:
return Core.DataValue.TriStateType.Blue;
case SaStatus.Completed:
return Core.DataValue.TriStateType.Green;
case SaStatus.Cancelled:
return Core.DataValue.TriStateType.Red;
case SaStatus.Deleted:
return Core.DataValue.TriStateType.Purple;
}
return Core.DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Properties.
public Data GetData() { return data.Clone(); }
public void SetData(Data data)
{
// Properties that cannot be changed if previously specified.
if (SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id))
throw new NotSupportedException($"{SysUtil.Fn} Id cannot be changed");
if (SysId.IsValid(InterfaceId) && SysId.ToInt(InterfaceId) != SysId.ToInt(data.InterfaceId))
throw new NotSupportedException($"{SysUtil.Fn} Interface cannot be changed");
if ((int)Direction > 0 && (int)Direction != (int)data.Direction)
throw new NotSupportedException($"{SysUtil.Fn} Direction cannot be changed");
if (!StringUtil.IsEmpty(Reference) && !Reference.Equals(data.Reference))
throw new NotSupportedException($"{SysUtil.Fn} Reference cannot be changed");
if (Sequence > 0 && Sequence != data.Sequence)
throw new NotSupportedException($"{SysUtil.Fn} Sequence cannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
public SysId InterfaceId
{
get { return data.InterfaceId; }
protected set { data.InterfaceId = value; }
}
public SaInterfaceProcessDirection Direction
{
get { return data.Direction; }
protected set { data.Direction = value; }
}
public String Reference
{
get { return data.Reference; }
protected set { data.Reference = value; }
}
public int Sequence
{
get { return data.Sequence; }
protected set { data.Sequence = value; }
}
public DateTime? ProcessAt
{
get { return data.ProcessAt; }
set { data.ProcessAt = value; }
}
public DateTime? BatchAt
{
get { return data.BatchAt; }
set { data.BatchAt = value; }
}
public int ElapseSecs
{
get { return data.ElapseSecs; }
set { data.ElapseSecs = value; }
}
//-------------------------------------------------------------------
// Flags.
//-------------------------------------------------------------------
// List parameters.
public enum StatusCat
{
Any,
AwaitingOnly,
InProgressOnly,
CompletedOnly,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
public HashSet<SysId> IdsIncluded { get; } = new HashSet<SysId>();
public HashSet<SysId> IdsExcluded { get; } = new HashSet<SysId>();
public SysId InterfaceId { get; set; }
public SaInterfaceProcessDirection Direction { get; set; } = SaInterfaceProcessDirection.Unknown;
public String Reference { get; set; }
public String ReferencePartial { get; set; }
public DateTime ProcessedOn { get; set; } = DateTime.MinValue;
public DateTime ProcessedFrom { get; set; } = DateTime.MinValue;
public DateTime ProcessedTo { get; set; } = DateTime.MinValue;
public String MessageText { get; set; }
public String MessageTextPartial { get; set; }
public StatusCat StatusCat { get; set; } = StatusCat.Any;
}
//-------------------------------------------------------------------
// L i s t
//-------------------------------------------------------------------
public class List : List<SaInterfaceProcess>
{
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,201 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Base.Interfaces
{
//=======================================================================
public class SaInterfaceProcessDataItem : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Pos = 0,
Id,
// Process.
ProcessId,
// Data item.
ItemType,
ItemType_Desc,
ItemId,
Item_Caption,
// Common properties.
Notes,
Status,
Status_Desc,
Status_Ind,
CreateOn_Date,
UpdateOn_Date,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public SysId InterfaceProcessId { get; set; } = null;
public ItemId ItemId { get; set; } = new ItemId();
public String ItemData { get; set; } = String.Empty;
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data()
{
Status = DefaultStatus;
}
// Properties.
public SysId InterfaceProcessId
{
get { return data.InterfaceProcessId; }
set { CheckChanged(data.InterfaceProcessId, value); data.InterfaceProcessId = value; }
}
public ItemId ItemId
{
get { return data.ItemId; }
set { CheckChanged(data.ItemId, value); data.ItemId = value; }
}
public String ItemData
{
get { return data.ItemData; }
set { CheckChanged(data.ItemData, value); data.ItemData = value; }
}
//-------------------------------------------------------------------
// Population.
internal void PopulateFrom(Data data)
{
InterfaceProcessId = data.InterfaceProcessId;
ItemId = data.ItemId;
ItemData = data.ItemData;
base.PopulateFrom(data);
}
public Data Clone()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
// Error field - identify properties with validation error.
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue InterfaceProcessId { get; set; } = ValidValue.Valid;
public ValidValue ItemType { get; set; } = ValidValue.Valid;
public ValidValue ItemId { get; set; } = ValidValue.Valid;
public ValidValue ItemData { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
// Flags.
public static readonly Byte Flag_ = 0x01;
//-------------------------------------------------------------------
// Construction.
public SaInterfaceProcessDataItem(SysId id, SysId interfaceProcessId, ItemId itemId) :
base(id)
{
base.SetData(data);
InterfaceProcessId = interfaceProcessId;
ItemId = itemId;
Status = DefaultStatus;
}
//-------------------------------------------------------------------
// Statuses.
private static readonly List<SaStatus> validStatuses = new List<SaStatus>()
{
SaStatus.Completed
};
public static SaStatus DefaultStatus { get { return CompletedStatus; } }
public static SaStatus CompletedStatus { get { return SaStatus.Completed; } }
public static List<SaStatus> ValidStatuses { get { return new List<SaStatus>(validStatuses); } }
public static DataValue.TriStateType GetStatusTriState(SaStatus status)
{
switch (status)
{
case SaStatus.Completed:
return DataValue.TriStateType.Green;
case SaStatus.Deleted:
return DataValue.TriStateType.Purple;
}
return DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Properties.
public Data GetData() { return data.Clone(); }
public void SetData(Data data)
{
// Properties that cannot be changed if previously specified.
if (SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id))
throw new NotSupportedException($"{SysUtil.Fn} Id cannot be changed");
if (SysId.IsValid(InterfaceProcessId) && SysId.ToInt(InterfaceProcessId) != SysId.ToInt(data.InterfaceProcessId))
throw new NotSupportedException($"{SysUtil.Fn} Interface Process cannot be changed");
if (ItemId.Type >= 0 && ItemId.Type != data.ItemId.Type)
throw new NotSupportedException($"{SysUtil.Fn} Item type cannot be changed");
if (SysId.IsValid(ItemId.Id) && SysId.ToInt(ItemId.Id) != SysId.ToInt(data.ItemId.Id))
throw new NotSupportedException($"{SysUtil.Fn} Item Id cannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
public SysId InterfaceProcessId
{
get { return data.InterfaceProcessId; }
protected set { data.InterfaceProcessId = value; }
}
public ItemId ItemId
{
get { return data.ItemId; }
protected set { data.ItemId = value; }
}
public String ItemData
{
get { return data.ItemData; }
set { data.ItemData = value; }
}
//-------------------------------------------------------------------
// Flags.
//-------------------------------------------------------------------
// List parameters.
public enum StatusCat
{
Any,
CompletedOnly,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
public HashSet<SysId> IdsIncluded { get; } = new HashSet<SysId>();
public HashSet<SysId> IdsExcluded { get; } = new HashSet<SysId>();
public SysId InterfaceProcessId { get; } = null;
public HashSet<ItemId> ItemIdsIncluded { get; } = new HashSet<ItemId>();
public StatusCat StatusCat { get; set; } = StatusCat.Any;
}
//-------------------------------------------------------------------
// L i s t
//-------------------------------------------------------------------
public class List : List<SaInterfaceProcessDataItem>
{
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,238 @@
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.Net.Standard.Base.Interfaces
{
//=======================================================================
public class SaInterfaceProcessMessage : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Pos = 0,
Id,
// Process.
ProcessId,
// Message.
Level,
Level_Desc,
Message,
Filename,
LineNumber,
ItemType,
ItemType_Desc,
ItemId,
Item_Caption,
// Common properties.
Notes,
Status,
Status_Desc,
Status_Ind,
CreateOn_Date,
UpdateOn_Date,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public SysId InterfaceProcessId { get; set; } = null;
public SaMessageLevel Level { get; set; } = SaMessageLevel.Unknown;
public String Message { get; set; } = String.Empty;
public String Filename { get; set; } = String.Empty;
public int LineNumber { get; set; } = 0;
public ItemId ItemId { get; set; } = new ItemId();
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data()
{
Status = DefaultStatus;
}
// Properties.
public SysId InterfaceProcessId
{
get { return data.InterfaceProcessId; }
set { CheckChanged(data.InterfaceProcessId, value); data.InterfaceProcessId = value; }
}
public SaMessageLevel Level
{
get { return data.Level; }
set { CheckChanged((int)data.Level, (int)value); data.Level = value; }
}
public String Message
{
get { return data.Message; }
set { CheckChanged(data.Message, value); data.Message = value; }
}
public String Filename
{
get { return data.Filename; }
set { CheckChanged(data.Filename, value); data.Filename = value; }
}
public int LineNumber
{
get { return data.LineNumber; }
set { CheckChanged(data.LineNumber, value); data.LineNumber = value; }
}
public ItemId ItemId
{
get { return data.ItemId; }
set { if (value == null) value = new ItemId(); CheckChanged(data.ItemId, value); data.ItemId = value; }
}
// Population.
internal void PopulateFrom(Data data)
{
InterfaceProcessId = data.InterfaceProcessId;
Level = data.Level;
Message = data.Message;
Filename = data.Filename;
LineNumber = data.LineNumber;
ItemId = data.ItemId;
base.PopulateFrom(data);
}
public Data Clone()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
// Error field - identify properties with validation error.
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue InterfaceProcessId { get; set; } = ValidValue.Valid;
public ValidValue Level { get; set; } = ValidValue.Valid;
public ValidValue Message { get; set; } = ValidValue.Valid;
public ValidValue Filename { get; set; } = ValidValue.Valid;
public ValidValue LineNumber { get; set; } = ValidValue.Valid;
public ValidValue ItemId { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
// Flags.
public static readonly UInt16 Flag_ = 0x01;
//-------------------------------------------------------------------
// Construction.
public SaInterfaceProcessMessage(SysId id, SysId interfaceProcessId) :
base(id)
{
base.SetData(data);
InterfaceProcessId = interfaceProcessId;
Status = DefaultStatus;
}
//-------------------------------------------------------------------
// Statuses.
private static readonly List<SaStatus> validStatuses = new List<SaStatus>()
{
SaStatus.Completed
};
public static SaStatus DefaultStatus { get { return CompletedStatus; } }
public static SaStatus CompletedStatus { get { return SaStatus.Completed; } }
public static List<SaStatus> ValidStatuses { get { return new List<SaStatus>(validStatuses); } }
public static DataValue.TriStateType GetStatusTriState(SaStatus status)
{
switch (status)
{
case SaStatus.Completed:
return Core.DataValue.TriStateType.Green;
case SaStatus.Deleted:
return Core.DataValue.TriStateType.Purple;
}
return Core.DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Properties.
public Data GetData() { return data.Clone(); }
public void SetData(Data data)
{
// Properties that cannot be changed if previously specified.
if (SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id))
throw new NotSupportedException($"{SysUtil.Fn} Id cannot be changed");
if (SysId.IsValid(InterfaceProcessId) && SysId.ToInt(InterfaceProcessId) != SysId.ToInt(data.InterfaceProcessId))
throw new NotSupportedException($"{SysUtil.Fn} Id cannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
public SysId InterfaceProcessId
{
get { return data.InterfaceProcessId; }
protected set { data.InterfaceProcessId = value; }
}
public SaMessageLevel Level
{
get { return data.Level; }
set { data.Level = value; }
}
public String Message
{
get { return data.Message; }
set { data.Message = value; }
}
public String Filename
{
get { return data.Filename; }
set { data.Filename = value; }
}
public int LineNumber
{
get { return data.LineNumber; }
set { data.LineNumber = value; }
}
public ItemId ItemId
{
get { return data.ItemId; }
set { data.ItemId = value; }
}
//-------------------------------------------------------------------
// Flags.
//-------------------------------------------------------------------
// List parameters.
public enum StatusCat
{
Any,
CompletedOnly,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
public HashSet<SysId> IdsIncluded { get; } = new HashSet<SysId>();
public HashSet<SysId> IdsExcluded { get; } = new HashSet<SysId>();
public SysId InterfaceProcessId { get; set; } = new SysId();
public HashSet<ItemId> ItemIdsIncluded { get; } = new HashSet<ItemId>();
public StatusCat StatusCat { get; set; } = StatusCat.Any;
}
//-------------------------------------------------------------------
// L i s t
//-------------------------------------------------------------------
public class List : List<SaInterfaceProcessMessage>
{
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,221 @@
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Text;
namespace Sarand.Net.Standard.Base.ItemData
{
//=======================================================================
public class SaItemData : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Pos = 0,
Id,
// Item Option properties.
ItemType,
ItemType_Desc,
ItemId,
DataType,
ItemData,
// Common properties.
Notes,
Status,
Status_Desc,
Status_Ind,
CreateOn_Date,
UpdateOn_Date,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public ItemId ItemId { get; set; } = new ItemId();
public String DataType { get; set; } = String.Empty;
public String ItemData { get; set; } = String.Empty;
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data ()
{
Status = DefaultStatus;
}
// Properties.
public ItemId ItemId
{
get { return data.ItemId; }
set { CheckChanged(data.ItemId, value); data.ItemId = value; }
}
public String DataType
{
get { return data.DataType; }
set { CheckChanged(data.DataType, value); data.DataType = value; }
}
public String ItemData
{
get { return data.ItemData; }
set { CheckChanged(data.ItemData, value); data.ItemData = value; }
}
// Population.
internal void PopulateFrom (Data data)
{
ItemId = data.ItemId;
DataType = data.DataType;
ItemData = data.ItemData;
base.PopulateFrom(data);
}
public Data Clone ()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
// Error field - identify properties with validation error.
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue ItemType { get; set; } = ValidValue.Valid;
public ValidValue ItemId { get; set; } = ValidValue.Valid;
public ValidValue DataType { get; set; } = ValidValue.Valid;
public ValidValue ItemData { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
// Flags.
public static readonly Byte Flag_Encrypted = 0x01;
//-------------------------------------------------------------------
// Construction.
public SaItemData (SysId id, ItemId itemId) :
base(id)
{
base.SetData(data);
ItemId = itemId;
Status = DefaultStatus;
}
//-------------------------------------------------------------------
// Status.
private List<SaStatus> validStatuses = new List<SaStatus>()
{
SaStatus.Current,
SaStatus.Deleted,
};
public static SaStatus DefaultStatus { get { return StatusCurrent; } }
public static SaStatus StatusCurrent { get { return SaStatus.Current; } }
public static List<SaStatus> ValidStatuses { get { return new List<SaStatus>(ValidStatuses); } }
public static DataValue.TriStateType GetStatusTriState (SaStatus status)
{
if (status == SaStatus.Current) return DataValue.TriStateType.Green;
if (status == SaStatus.Deleted) return DataValue.TriStateType.Purple;
return DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Properties.
public Data GetData () { return data.Clone(); }
public void SetData (Data data)
{
// Properties that cannot be changed if previously specified.
if (ItemId.Type >= 0 && ItemId.Type != data.ItemId.Type)
throw new NotSupportedException($"{SysUtil.Fn} Item type cannot be changed");
if (SysId.IsValid(ItemId.Id) && SysId.ToInt(ItemId.Id) != SysId.ToInt(data.ItemId.Id))
throw new NotSupportedException($"{SysUtil.Fn} Item Id cannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
public ItemId ItemId
{
get { return data.ItemId; }
protected set { data.ItemId = value; }
}
public String DataType
{
get { return data.DataType; }
set { data.DataType = value; }
}
public String ItemData
{
get { return data.ItemData; }
set { data.ItemData = value; }
}
//-------------------------------------------------------------------
// Flags.
public bool Encrypted
{
get { return GetFlag(Flag_Encrypted); }
set { SetFlag(Flag_Encrypted, value); }
}
//-------------------------------------------------------------------
// Comparison.
public bool Matches (ItemId itemId)
{
if (ItemId.Type != itemId.Type) return false;
if (SysId.ToInt(ItemId.Id) != SysId.ToInt(itemId.Id)) return false;
return true;
}
public bool Matches (ItemId itemId, String dataType)
{
if (!Matches(itemId)) return false;
if (!DataType.EqualsCI(dataType)) return false;
return true;
}
//-------------------------------------------------------------------
// List parameters.
public enum StatusCat
{
Any,
NotDeleted,
CurrentOnly,
DeletedOnly,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
public HashSet<SysId> IdsIncluded { get; } = new HashSet<SysId>();
public HashSet<SysId> IdsExcluded { get; } = new HashSet<SysId>();
public HashSet<ItemId> ItemIdsIncluded { get; } = new HashSet<ItemId>();
public HashSet<String> DataTypesIncluded { get; } = new HashSet<String>();
public StatusCat StatusCat { get; set; } = StatusCat.NotDeleted;
}
//-------------------------------------------------------------------
}
//=======================================================================
/// <summary>List extension methods.</summary>
public static class SaItemDataList
{
public static List<SaItemData> FindByItem (this List<SaItemData> values, ItemId itemId)
{
return values.FindAll(item => item.Matches(itemId));
}
public static List<SaItemData> FindByItemDataType (this List<SaItemData> values, ItemId itemId, String dataType)
{
return values.FindAll(item => item.Matches(itemId, dataType));
}
}
//=======================================================================
}
@@ -0,0 +1,69 @@
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using System;
using System.Collections.Generic;
using System.Text;
namespace Sarand.Net.Standard.Base.ItemData
{
//=======================================================================
public abstract class SaItemDataConsole : SacsDisposableStateItem
{
//-------------------------------------------------------------------
// Definitions.
//-------------------------------------------------------------------
// Data members.
//-------------------------------------------------------------------
// Static initialisation.
static SaItemDataConsole()
{
}
//-------------------------------------------------------------------
// Construction.
protected SaItemDataConsole()
{
}
//-------------------------------------------------------------------
// Properties.
// Database.
public abstract bool DatabaseIsValid { get; }
public abstract bool CanUpdateDatabase { get; }
//-------------------------------------------------------------------
// I t e m D a t a
//-------------------------------------------------------------------
/// <summary>Type codes - specific for each type of item.</summary>
public abstract List<CodeDesc> GetDataTypeCodes(int itemType);
//-------------------------------------------------------------------
// Item data interface.
public abstract bool CanUpdateItemData(SaItemData itemData);
public abstract bool DoUpdateItemData(SaItemData itemData);
public abstract bool CanRemoveItemData(SaItemData itemData);
//-------------------------------------------------------------------
// Retrieve item data entries that match the specified params.
public abstract bool ItemDataExists(SaItemData.Params prmItemData);
public abstract long GetItemDataCount(SaItemData.Params prmItemData);
public abstract List<SaItemData> GetItemDataList(SaItemData.Params prmItemData);
//-------------------------------------------------------------------
// Create a new item data.
public abstract SaItemData CreateItemData(ItemId itemId);
//-------------------------------------------------------------------
// Store item data.
public abstract bool Store(SaItemData itemData, DbUpdateInfo dbUpdateInfo);
public abstract bool Remove(SaItemData itemData, DbUpdateInfo dbUpdateInfo);
public abstract bool ClearItemData(ItemId itemId, DbUpdateInfo dbUpdateInfo);
public abstract bool ClearItemData(ItemId itemId, String dataType, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,317 @@
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
//---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Thu 3-Oct-2019 15:10:50
//---------------------------------------------------------------------------
namespace Sarand.Net.Standard.Base.ItemData
{
public class SaItemDataDbDfn
{
//-------------------------------------------------------------------
// Table identifiers.
public enum TableIdx
{
Unknown = 0,
SaItemData,
}
//-------------------------------------------------------------------
// Column identifiers.
public enum ColumnIdx
{
Unknown = 0,
SaItemData_Id,
SaItemData_ItemType,
SaItemData_ItemId,
SaItemData_DataType,
SaItemData_ItemData,
SaItemData_Notes,
SaItemData_Flags,
SaItemData_Status,
SaItemData_CreateOn,
SaItemData_CreateBy,
SaItemData_CreateHost,
SaItemData_UpdateOn,
SaItemData_UpdateBy,
SaItemData_UpdateHost,
}
//-------------------------------------------------------------------
// Data members.
private static readonly int tableCount = 1;
private static readonly int columnCount = 14;
private static ulong maxTextLen = 0;
//-------------------------------------------------------------------
// Retrieve Table details (eg. name: 'Company').
public static int GetTableCount ()
{
return tableCount;
}
public static String GetTableName (TableIdx table, bool delimitReservedWords = true)
{
int tableIdx = (int)table - 1;
if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;
String tableName = tables[(int)tableIdx];
if (delimitReservedWords) tableName = DelimitReservedWord(tableName);
return tableName;
}
//-------------------------------------------------------------------
// Identify the table that corresponds with the specified column.
public static TableIdx GetTableForColumn (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return TableIdx.Unknown;
return columns[columnIdx].TableIdx;
}
//-------------------------------------------------------------------
// Retrieve the specified Column's name (Qualified include table name: '(<Table>.Column>)').
public static String GetColumnName (ColumnIdx column, bool delimitReservedWords = true)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return String.Empty;
String columnName = columns[columnIdx].Name;
if (delimitReservedWords) columnName = DelimitReservedWord(columnName);
return columnName;
}
public static String GetColumnNameQual (ColumnIdx column, String tableAlias = "", bool braces = false)
{
String columnName = GetColumnName(column);
if (!String.IsNullOrEmpty(columnName))
{
String tableName = StringUtil.EmptyOnNull(tableAlias);
if (tableName.IsEmpty()) tableName = GetTableName(GetTableForColumn(column));
columnName = tableName + (tableName.Length > 0 ? "." : "") + columnName;
if (braces)
columnName = "(" + columnName + ")";
}
return columnName;
}
//-------------------------------------------------------------------
// Reserved words.
private static DbReservedWordDelim reservedWordDelim = DbReservedWordDelim.SquareBrackets;
public static void SetReservedWordDelim (DbReservedWordDelim reservedWordDelim)
{
SaItemDataDbDfn.reservedWordDelim = reservedWordDelim;
}
public static bool IsReservedWord (String word)
{
if (String.IsNullOrEmpty(word)) return false;
if (reservedWords.Contains(word, StringComparer.OrdinalIgnoreCase)) return true;
return false;
}
public static String DelimitReservedWord (String word)
{
if (!IsReservedWord(word)) return word;
switch (reservedWordDelim)
{
case DbReservedWordDelim.None:
break;
case DbReservedWordDelim.DoubleQuotes:
word = "\"" + word + "\"";
break;
case DbReservedWordDelim.SquareBrackets:
default:
word = "[" + word + "]";
break;
}
return word;
}
//-------------------------------------------------------------------
// Retrieve information about the specified Column.
public static DbColumnDataType GetColDataType (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return DbColumnDataType.Unknown;
return columns[columnIdx].DataType;
}
public static short GetColNativeDataType (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return 0;
return columns[columnIdx].NativeDataType;
}
public static void SetMaxTextLen (ulong maxTextLen)
{
SaItemDataDbDfn.maxTextLen = maxTextLen;
}
public static bool IsColFmtText (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
return (columns[columnIdx].DataType == DbColumnDataType.VarChar);
}
public static ulong GetColTextLen (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return 0;
if (columns[columnIdx].DataType == DbColumnDataType.VarChar)
{
ulong textLen = columns[columnIdx].DataLen;
if (maxTextLen > 0 && textLen > maxTextLen) textLen = maxTextLen;
return textLen;
}
return 0;
}
public static bool IsColFmtBool (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
return (columns[columnIdx].DataType == DbColumnDataType.Bit);
}
public static bool IsColFmtNumeric (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
switch (columns[columnIdx].DataType)
{
case DbColumnDataType.TinyInt:
case DbColumnDataType.SmallInt:
case DbColumnDataType.Int:
case DbColumnDataType.BigInt:
case DbColumnDataType.Single:
case DbColumnDataType.Double:
case DbColumnDataType.Decimal:
return true;
}
return false;
}
//-------------------------------------------------------------------
// Table definitions.
private static readonly String[] tables =
{
"SaItemData",
};
//-------------------------------------------------------------------
// Table column definitions.
internal class ColumnDfn
{
internal TableIdx TableIdx { get; set; }
internal String Name { get; set; }
internal DbColumnDataType DataType { get; set; }
internal short NativeDataType { get; set; }
internal bool IsIdentity { get; set; }
internal ulong DataLen { get; set; }
internal ColumnDfn (int tableIdx, String name, int dataType, short nativeDataType, bool isIdentity, ulong dataLen)
{
this.TableIdx = (TableIdx)tableIdx;
this.Name = name;
this.DataType = (DbColumnDataType)dataType;
this.NativeDataType = nativeDataType;
this.IsIdentity = isIdentity;
this.DataLen = dataLen;
}
}
//-------------------------------------------------------------------
private static readonly ColumnDfn[] columns =
{
new ColumnDfn(1,"Id",4,4,false,10),
new ColumnDfn(1,"ItemType",3,5,false,5),
new ColumnDfn(1,"ItemId",4,4,false,10),
new ColumnDfn(1,"DataType",0,-9,false,50),
new ColumnDfn(1,"ItemData",0,-9,false,0),
new ColumnDfn(1,"Notes",0,-9,false,255),
new ColumnDfn(1,"Flags",3,5,false,5),
new ColumnDfn(1,"Status",0,-9,false,3),
new ColumnDfn(1,"CreateOn",9,93,false,23),
new ColumnDfn(1,"CreateBy",4,4,false,10),
new ColumnDfn(1,"CreateHost",0,-9,false,64),
new ColumnDfn(1,"UpdateOn",9,93,false,23),
new ColumnDfn(1,"UpdateBy",4,4,false,10),
new ColumnDfn(1,"UpdateHost",0,-9,false,64),
};
//-------------------------------------------------------------------
// Reserved words.
private static readonly HashSet<String> reservedWords = new HashSet<String>()
{
"ADD",
"ALL",
"ALTER",
"AND",
"ANY",
"AS",
"ASC",
"AVG",
"BEGIN",
"BETWEEN",
"BY",
"CASE",
"CAST",
"COLUMN",
"COMMIT",
"CONSTRAINT",
"CONVERT",
"COUNT",
"CREATE",
"CURRENCY",
"DEFAULT",
"DELETE",
"DESC",
"DISTINCT",
"DROP",
"ELSE",
"END",
"EXECUTE",
"EXISTS",
"FALSE",
"FROM",
"GRANT",
"GROUP",
"HAVING",
"IN",
"INDEX",
"INNER",
"INSERT",
"INTO",
"IS",
"JOIN",
"KEY",
"LEFT",
"LIKE",
"MAX",
"MIN",
"NOT",
"NULL",
"ON",
"OR",
"ORDER",
"OUTER",
"OUTPUT",
"PRIMARY",
"PROCEDURE",
"REVOKE",
"ROLLBACK",
"ROWCOUNT",
"SELECT",
"SET",
"SQL",
"SUM",
"TABLE",
"THEN",
"TRANSACTION",
"TRUE",
"UNION",
"UNIQUE",
"UPDATE",
"USER",
"VALUES",
"VIEW",
"WHEN",
"WHERE",
};
//-------------------------------------------------------------------
}
}
@@ -0,0 +1,171 @@
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using System;
using System.Collections.Generic;
using System.Text;
namespace Sarand.Net.Standard.Base.ItemData
{
//=======================================================================
public abstract class SaItemDataMgr : SacsItemMgr
{
//-------------------------------------------------------------------
// Definitions.
//-------------------------------------------------------------------
// Data members.
//-------------------------------------------------------------------
// Static initialisation.
static SaItemDataMgr ()
{
}
//-------------------------------------------------------------------
// Construction.
protected SaItemDataMgr ()
{
}
//-------------------------------------------------------------------
// Properties.
public abstract bool DatabaseIsValid { get; }
public abstract bool CanUpdateDatabase { get; }
//*******************************************************************
// I t e m D a t a
//*******************************************************************
// Utilities.
public abstract bool ItemHasData (ItemId itemId, bool ignoreDeleted = true);
public abstract bool ItemHasData (ItemId itemId, String dataType, bool ignoreDeleted = true);
//-------------------------------------------------------------------
// Retrieve individual item data entries.
public abstract bool ItemDataExists (SysId id);
public abstract bool ItemDataExists (ItemId itemId, String dataType, bool ignoreDeleted = true);
public abstract SaItemData GetItemData (SysId id);
public abstract SaItemData GetItemData (ItemId itemId, String dataType);
public abstract SaItemData GetItemData (SaItemData.Params prmItemData);
// Create Item Data.
public abstract SaItemData CreateItemData (ItemId itemId);
//-------------------------------------------------------------------
// Validate Item Data.
public bool IsValidItemData (SaItemData itemData)
{
ClearErrorState();
if (itemData == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidItemDataData(itemData.GetData(), new SaItemData.ErrField());
}
public virtual bool IsValidItemDataData (SaItemData.Data itemDataData, SaItemData.ErrField errField)
{
ClearErrorState();
if ((int)itemDataData.ItemId.Type < 1)
{
errField.ItemType = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.ItemTypeNotSpecified);
}
if (!SysId.IsValid(itemDataData.ItemId.Id))
{
errField.ItemId = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.ItemIdNotSpecified);
}
if (!IsValidValue(itemDataData.DataType, "Data type", (long)SaItemDataDbDfn.GetColTextLen(SaItemDataDbDfn.ColumnIdx.SaItemData_DataType), true))
{
errField.DataType = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!IsValidValue(itemDataData.ItemData, "Item data", (long)SaItemDataDbDfn.GetColTextLen(SaItemDataDbDfn.ColumnIdx.SaItemData_ItemData)))
{
errField.ItemData = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
// Common properties.
if (!IsValidValue(itemDataData.Notes, "notes", (long)SaItemDataDbDfn.GetColTextLen(SaItemDataDbDfn.ColumnIdx.SaItemData_Notes)))
{
errField.Notes = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!SaItemData.ValidStatuses.Contains(itemDataData.Status))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.InvalidStatus);
}
return true;
}
//-------------------------------------------------------------------
// Item Data database interface.
public abstract bool InsertItemData (SaItemData itemData, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateItemData (SaItemData itemData, DbUpdateInfo dbUpdateInfo);
public virtual bool ItemDataCanBeDeleted (SaItemData itemData)
{
ClearErrorState();
if (!SysId.IsValid(itemData.Id)) return SetErrorState(ErrorMessage.InvalidItemId);
return true;
}
public abstract bool DeleteItemData (SaItemData itemData, DbUpdateInfo dbUpdateInfo);
public abstract bool ClearItemData (ItemId itemId, DbUpdateInfo dbUpdateInfo);
public abstract bool ClearItemData (ItemId itemId, String dataType, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Item Data list.
public abstract ColumnDfn GetItemDataColumnDfn (SaItemData.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetItemDataQueryFilter (SaItemData.Params prm);
public abstract long GetItemDataCount (SaItemData.Params prm);
public abstract List<SaItemData> GetItemDataList (SaItemData.Params prm);
public abstract DbResultSet ExecuteItemDataQuery (List<ColumnDfn> columns, SaItemData.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public virtual DataValue GetItemDataDataValue (ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
switch ((SaItemData.Column)column.Id)
{
//-----------------------------------------------------------
// Item type.
case SaItemData.Column.ItemType_Desc:
{
short itemType = (short)values.GetValue(column.DataName).AsLong();
value = new DataValue(itemType.ToString());
}
break;
//-----------------------------------------------------------
// Notes.
case SaItemData.Column.Notes:
{
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
}
break;
//-----------------------------------------------------------
// Status.
case SaItemData.Column.Status_Desc:
case SaItemData.Column.Status_Ind:
{
String statusCode = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusCode);
if (column.Id == (int)SaItemData.Column.Status_Desc)
value = new DataValue(SacsSystem.GetStatusDescForCode(statusCode));
else if (column.Id == (int)SaItemData.Column.Status_Ind)
value = new DataValue(SaItemData.GetStatusTriState(status));
}
break;
//-----------------------------------------------------------
}
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
+312
View File
@@ -0,0 +1,312 @@
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Text;
namespace Sarand.Net.Standard.Base.ItemDocs
{
//=======================================================================
public class SaItemDoc : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Pos = 0,
Id,
// Item Id.
ItemType,
ItemType_Desc,
ItemId,
// Item Doc properties.
Category,
Category_Desc,
DocType,
DocType_Desc,
DescBrief,
Folder,
Filename,
MimeType,
// Common properties.
Notes,
Status,
Status_Desc,
Status_Ind,
CreateOn_Date,
UpdateOn_Date,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public ItemId ItemId { get; set; } = new ItemId();
public SaItemDocConsole.Category Category { get; set; }
public String DocType { get; set; } = String.Empty;
public String DescBrief { get; set; } = String.Empty;
public String Folder { get; set; } = String.Empty;
public String Filename { get; set; } = String.Empty;
public String MimeType { get; set; } = String.Empty;
public short ItemTypeAutoAssign { get; set; }
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data ()
{
Status = DefaultStatus;
}
// Properties.
public ItemId ItemId
{
get { return data.ItemId; }
set { CheckChanged(data.ItemId, value); data.ItemId = value; }
}
public SaItemDocConsole.Category Category
{
get { return data.Category; }
set { CheckChanged((int)data.Category, (int)value); data.Category = value; }
}
public String DocType
{
get { return data.DocType; }
set { CheckChanged(data.DocType, value); data.DocType = value; }
}
public String DescBrief
{
get { return data.DescBrief; }
set { CheckChanged(data.DescBrief, value); data.DescBrief = value; }
}
public String Folder
{
get { return data.Folder; }
set { CheckChanged(data.Folder, value); data.Folder = value; }
}
public String Filename
{
get { return data.Filename; }
set { CheckChanged(data.Filename, value); data.Filename = value; }
}
public String MimeType
{
get { return data.MimeType; }
set { CheckChanged(data.MimeType, value); data.MimeType = value; }
}
public short ItemTypeAutoAssign
{
get { return data.ItemTypeAutoAssign; }
set { CheckChanged(data.ItemTypeAutoAssign, value); data.ItemTypeAutoAssign = value; }
}
// Population.
internal void PopulateFrom (Data data)
{
ItemId = data.ItemId;
Category = data.Category;
DocType = data.DocType;
DescBrief = data.DescBrief;
Folder = data.Folder;
Filename = data.Filename;
MimeType = data.MimeType;
ItemTypeAutoAssign = data.ItemTypeAutoAssign;
base.PopulateFrom(data);
}
public Data Clone ()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
// Error field - identify properties with validation error.
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue ItemType { get; set; } = ValidValue.Valid;
public ValidValue ItemId { get; set; } = ValidValue.Valid;
public ValidValue Category { get; set; } = ValidValue.Valid;
public ValidValue DocType { get; set; } = ValidValue.Valid;
public ValidValue DescBrief { get; set; } = ValidValue.Valid;
public ValidValue Folder { get; set; } = ValidValue.Valid;
public ValidValue Filename { get; set; } = ValidValue.Valid;
public ValidValue MimeType { get; set; } = ValidValue.Valid;
public ValidValue ItemTypeAutoAssign { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
// Flags.
public static readonly Byte Flag_AutoAssigned = 0x01;
//-------------------------------------------------------------------
// Construction.
public SaItemDoc (SysId id, ItemId itemId, SaItemDocConsole.Category category) :
base(id)
{
base.SetData(data);
ItemId = itemId;
Category = category;
Status = DefaultStatus;
}
//-------------------------------------------------------------------
// Status.
private List<SaStatus> validStatuses = new List<SaStatus>()
{
SaStatus.Current,
SaStatus.Deleted,
};
public static SaStatus DefaultStatus { get { return StatusCurrent; } }
public static SaStatus StatusCurrent { get { return SaStatus.Current; } }
public static List<SaStatus> ValidStatuses { get { return new List<SaStatus>(ValidStatuses); } }
public static DataValue.TriStateType GetStatusTriState (SaStatus status)
{
if (status == SaStatus.Current) return DataValue.TriStateType.Green;
if (status == SaStatus.Deleted) return DataValue.TriStateType.Purple;
return DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Properties.
public Data GetData () { return data.Clone(); }
public void SetData (Data data)
{
// Properties that cannot be changed if previously specified.
if (ItemId.Type >= 0 && ItemId.Type != data.ItemId.Type)
throw new NotSupportedException($"{SysUtil.Fn} Item type cannot be changed");
if (SysId.IsValid(ItemId.Id) && SysId.ToInt(ItemId.Id) != SysId.ToInt(data.ItemId.Id))
throw new NotSupportedException($"{SysUtil.Fn} Item Id cannot be changed");
// Category.
if ((int)data.Category < 1)
data.Category = Category;
if ((int)Category != 0 && Category != data.Category)
throw new NotSupportedException($"{SysUtil.Fn} Category cannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
public ItemId ItemId
{
get { return data.ItemId; }
protected set { data.ItemId = value; }
}
public SaItemDocConsole.Category Category
{
get { return data.Category; }
protected set { data.Category = value; }
}
public String DocType
{
get { return data.DocType; }
set { data.DocType = value; }
}
public String DescBrief
{
get { return data.DescBrief; }
set { data.DescBrief = value; }
}
public String Folder
{
get { return data.Folder; }
set { data.Folder = value; }
}
public String Filename
{
get { return data.Filename; }
set { data.Filename = value; }
}
public String MimeType
{
get { return data.MimeType; }
set { data.MimeType = value; }
}
public short ItemTypeAutoAssign
{
get { return data.ItemTypeAutoAssign; }
set { data.ItemTypeAutoAssign = value; }
}
//-------------------------------------------------------------------
// Flags.
public bool AutoAssigned
{
get { return GetFlag(Flag_AutoAssigned); }
set { SetFlag(Flag_AutoAssigned, value); }
}
//-------------------------------------------------------------------
// Comparison.
public bool Matches (ItemId itemId)
{
if (ItemId.Type != itemId.Type) return false;
if (SysId.ToInt(ItemId.Id) != SysId.ToInt(itemId.Id)) return false;
return true;
}
public bool Matches (ItemId itemId, SaItemDocConsole.Category category)
{
if (!Matches(itemId)) return false;
if (Category != category) return false;
return true;
}
public bool Matches (ItemId itemId, SaItemDocConsole.Category category, String docType)
{
if (!Matches(itemId, category)) return false;
if (!DocType.EqualsCI(docType)) return false;
return true;
}
//-------------------------------------------------------------------
// List parameters.
public enum StatusCat
{
Any,
NotDeleted,
CurrentOnly,
DeletedOnly,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
public HashSet<SysId> IdsIncluded { get; } = new HashSet<SysId>();
public HashSet<SysId> IdsExcluded { get; } = new HashSet<SysId>();
public HashSet<ItemId> ItemIdsIncluded { get; } = new HashSet<ItemId>();
public SaItemDocConsole.Category Category { get; set; }
public String DocType { get; set; }
public String DescBriefPartial { get; set; }
public String MimeType { get; set; }
public String FolderFull { get; set; }
public String FolderPartial { get; set; }
public String FilenameFull { get; set; }
public short ItemTypeAutoAssign { get; set; }
public StatusCat StatusCat { get; set; } = StatusCat.NotDeleted;
}
//-------------------------------------------------------------------
}
//=======================================================================
/// <summary>List extension methods.</summary>
public static class SaItemDocList
{
public static List<SaItemDoc> FindByItem (this List<SaItemDoc> values, ItemId itemId)
{
return values.FindAll(item => item.Matches(itemId));
}
public static List<SaItemDoc> FindByItemDocCategory (this List<SaItemDoc> values, ItemId itemId, SaItemDocConsole.Category category)
{
return values.FindAll(item => item.Matches(itemId, category));
}
}
//=======================================================================
}
@@ -0,0 +1,86 @@
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using System;
using System.Collections.Generic;
using System.Text;
namespace Sarand.Net.Standard.Base.ItemDocs
{
//=======================================================================
public abstract class SaItemDocConsole : SacsDisposableStateItem
{
//-------------------------------------------------------------------
// Definitions.
/// <summary>Item document category.</summary>
public enum Category
{
// Do not change values - tied to database.
Unknown = 0,
Folder = 10,
Document = 20,
Pdf = 21,
Image = 30,
FileSpec = 90, /* Generic filename with wildcards */
}
//-------------------------------------------------------------------
// Data members.
//-------------------------------------------------------------------
// Static initialisation.
static SaItemDocConsole()
{
}
//-------------------------------------------------------------------
// Construction.
protected SaItemDocConsole()
{
}
//-------------------------------------------------------------------
// Properties.
// Database.
public abstract bool DatabaseIsValid { get; }
public abstract bool CanUpdateDatabase { get; }
//-------------------------------------------------------------------
// I t e m D o c s
//-------------------------------------------------------------------
// Category codes.
public abstract List<TypeCodeDesc> GetCategoryCodes();
/// <summary>eg. for 'Image' documents.</summary>
public abstract List<CodeDesc> GetCategoryTypeCodes(Category category);
//-------------------------------------------------------------------
// 'Recent' and 'Favourite' folders - to populate drop-down list when selecting folder:
/// <summary>How many recent foldes to retain? [default:5]</summary>
public abstract int GetMaxRecentFolderCount();
/// <summary>List of favourites to always include in dropdown.</summary>
public abstract void SetFavouriteFolders(List<String> folders);
/// <summary>Mix of recent and favourites.</summary>
public abstract List<String> GetSuggestedFolders();
//-------------------------------------------------------------------
// Retrieve list of docs that match the specified params:
public abstract bool ItemDocsExist(SaItemDoc.Params prmItemDoc);
public abstract List<SaItemDoc> GetItemDocs(SaItemDoc.Params prmItemDoc);
// Create a new document:
public abstract SaItemDoc CreateItemDoc(ItemId itemId, Category category);
// Store documents:
public abstract bool StoreItemDoc(SaItemDoc itemDoc, DbUpdateInfo dbUpdateInfo);
public abstract bool StoreItemDocs(List<SaItemDoc> itemDocs, DbUpdateInfo dbUpdateInfo);
public abstract bool RemoveItemDoc(SaItemDoc itemDoc, DbUpdateInfo dbUpdateInfo);
public abstract bool ClearItemDocs(ItemId itemId, DbUpdateInfo dbUpdateInfo);
public abstract bool ClearItemDocs(ItemId itemId, Category category, DbUpdateInfo dbUpdateInfo);
// Auto-assign documents.
// The master items define 'auto-assign' docs for the item's type.
// The 'File part' defines the filename excluding the extension.
// If the extension list is empty, any extension is matched.
public abstract bool AutoAssignDocs(ItemId itemId, List<ItemId> masterItemIds, String filePart, List<String> extension, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,207 @@
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using System;
using System.Collections.Generic;
using System.Text;
namespace Sarand.Net.Standard.Base.ItemDocs
{
//=======================================================================
public abstract class SaItemDocMgr : SacsItemMgr
{
//-------------------------------------------------------------------
// Definitions.
//-------------------------------------------------------------------
// Data members.
//-------------------------------------------------------------------
// Static initialisation.
static SaItemDocMgr ()
{
}
//-------------------------------------------------------------------
// Construction.
protected SaItemDocMgr ()
{
}
//-------------------------------------------------------------------
// Properties.
public abstract bool DatabaseIsValid { get; }
public abstract bool CanUpdateDatabase { get; }
//*******************************************************************
// I t e m D o c s
//*******************************************************************
// Utilities.
public abstract bool ItemHasDocs (ItemId itemId, bool ignoreDeleted = true);
public abstract bool ItemHasDocs (ItemId itemId, SaItemDocConsole.Category category, bool ignoreDeleted = true);
//-------------------------------------------------------------------
// Retrieve individual item data entries.
public abstract bool ItemDocExists (SysId id);
public abstract SaItemDoc GetItemDoc (SysId id);
public abstract SaItemDoc GetItemDoc (SaItemDoc.Params prmItemDoc);
// Create Item Data.
public abstract SaItemDoc CreateItemDoc (ItemId itemId, SaItemDocConsole.Category category);
//-------------------------------------------------------------------
// Validate Item Data.
public bool IsValidItemDoc (SaItemDoc itemDoc)
{
ClearErrorState();
if (itemDoc == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidItemDocData(itemDoc.GetData(), new SaItemDoc.ErrField());
}
public virtual bool IsValidItemDocData (SaItemDoc.Data itemDocData, SaItemDoc.ErrField errField)
{
ClearErrorState();
if ((int)itemDocData.ItemId.Type < 1)
{
errField.ItemType = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.ItemTypeNotSpecified);
}
if (!SysId.IsValid(itemDocData.ItemId.Id))
{
errField.ItemId = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.ItemIdNotSpecified);
}
if ((int)itemDocData.Category < 1)
{
errField.Category = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Category must be supplied");
}
if (!IsValidValue(itemDocData.DocType, "Doc type", (long)SaItemDocsDbDfn.GetColTextLen(SaItemDocsDbDfn.ColumnIdx.SaItemDoc_Type), true))
{
errField.DocType = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!IsValidValue(itemDocData.DescBrief, "Desciption", (long)SaItemDocsDbDfn.GetColTextLen(SaItemDocsDbDfn.ColumnIdx.SaItemDoc_DescBrief)))
{
errField.DescBrief = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!IsValidValue(itemDocData.Folder, "Folder", (long)SaItemDocsDbDfn.GetColTextLen(SaItemDocsDbDfn.ColumnIdx.SaItemDoc_Folder)))
{
errField.Folder = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!IsValidValue(itemDocData.Filename, "Filename", (long)SaItemDocsDbDfn.GetColTextLen(SaItemDocsDbDfn.ColumnIdx.SaItemDoc_Filename), true))
{
errField.Filename = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!IsValidValue(itemDocData.MimeType, "Mime", (long)SaItemDocsDbDfn.GetColTextLen(SaItemDocsDbDfn.ColumnIdx.SaItemDoc_MimeType)))
{
errField.MimeType = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
// Common properties.
if (!IsValidValue(itemDocData.Notes, "notes", (long)SaItemDocsDbDfn.GetColTextLen(SaItemDocsDbDfn.ColumnIdx.SaItemDoc_Notes)))
{
errField.Notes = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!SaItemDoc.ValidStatuses.Contains(itemDocData.Status))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.InvalidStatus);
}
return true;
}
//-------------------------------------------------------------------
// Item Data database interface.
public abstract bool InsertItemDoc (SaItemDoc itemDoc, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateItemDoc (SaItemDoc itemDoc, DbUpdateInfo dbUpdateInfo);
public virtual bool ItemDocCanBeDeleted (SaItemDoc itemDoc)
{
ClearErrorState();
if (!SysId.IsValid(itemDoc.Id)) return SetErrorState(ErrorMessage.InvalidItemId);
return true;
}
public abstract bool DeleteItemDoc (SaItemDoc itemDoc, DbUpdateInfo dbUpdateInfo);
public abstract bool ClearItemDocs (ItemId itemId, DbUpdateInfo dbUpdateInfo);
public abstract bool ClearItemDocs (ItemId itemId, SaItemDocConsole.Category category, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Item Data list.
public abstract ColumnDfn GetItemDocColumnDfn (SaItemDoc.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetItemDocQueryFilter (SaItemDoc.Params prm);
public abstract long GetItemDocCount (SaItemDoc.Params prm);
public abstract List<SaItemDoc> GetItemDocList (SaItemDoc.Params prm);
public abstract DbResultSet ExecuteItemDocQuery (List<ColumnDfn> columns, SaItemDoc.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public virtual DataValue GetItemDocDataValue (ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
switch ((SaItemDoc.Column)column.Id)
{
//-----------------------------------------------------------
// Item type.
case SaItemDoc.Column.ItemType_Desc:
{
short itemType = (short)values.GetValue(column.DataName).AsLong();
value = new DataValue(itemType.ToString());
}
break;
//-----------------------------------------------------------
// Category.
case SaItemDoc.Column.Category_Desc:
{
short category = (short)values.GetValue(column.DataName).AsLong();
value = new DataValue(category.ToString());
}
break;
//-----------------------------------------------------------
// Document type.
case SaItemDoc.Column.DocType_Desc:
{
short docType = (short)values.GetValue(column.DataName).AsLong();
value = new DataValue(docType.ToString());
}
break;
//-----------------------------------------------------------
// Notes.
case SaItemDoc.Column.Notes:
{
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
}
break;
//-----------------------------------------------------------
// Status.
case SaItemDoc.Column.Status_Desc:
case SaItemDoc.Column.Status_Ind:
{
String statusCode = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusCode);
if (column.Id == (int)SaItemDoc.Column.Status_Desc)
value = new DataValue(SacsSystem.GetStatusDescForCode(statusCode));
else if (column.Id == (int)SaItemDoc.Column.Status_Ind)
value = new DataValue(SaItemDoc.GetStatusTriState(status));
}
break;
//-----------------------------------------------------------
}
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,327 @@
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
//---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Thu 3-Oct-2019 15:10:54
//---------------------------------------------------------------------------
namespace Sarand.Net.Standard.Base.ItemDocs
{
public class SaItemDocsDbDfn
{
//-------------------------------------------------------------------
// Table identifiers.
public enum TableIdx
{
Unknown = 0,
SaItemDoc,
}
//-------------------------------------------------------------------
// Column identifiers.
public enum ColumnIdx
{
Unknown = 0,
SaItemDoc_Id,
SaItemDoc_ItemType,
SaItemDoc_ItemId,
SaItemDoc_Category,
SaItemDoc_Type,
SaItemDoc_DescBrief,
SaItemDoc_Folder,
SaItemDoc_Filename,
SaItemDoc_MimeType,
SaItemDoc_ItemTypeAutoAssign,
SaItemDoc_Notes,
SaItemDoc_Flags,
SaItemDoc_Status,
SaItemDoc_CreateOn,
SaItemDoc_CreateBy,
SaItemDoc_CreateHost,
SaItemDoc_UpdateOn,
SaItemDoc_UpdateBy,
SaItemDoc_UpdateHost,
}
//-------------------------------------------------------------------
// Data members.
private static readonly int tableCount = 1;
private static readonly int columnCount = 19;
private static ulong maxTextLen = 0;
//-------------------------------------------------------------------
// Retrieve Table details (eg. name: 'Company').
public static int GetTableCount ()
{
return tableCount;
}
public static String GetTableName (TableIdx table, bool delimitReservedWords = true)
{
int tableIdx = (int)table - 1;
if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;
String tableName = tables[(int)tableIdx];
if (delimitReservedWords) tableName = DelimitReservedWord(tableName);
return tableName;
}
//-------------------------------------------------------------------
// Identify the table that corresponds with the specified column.
public static TableIdx GetTableForColumn (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return TableIdx.Unknown;
return columns[columnIdx].TableIdx;
}
//-------------------------------------------------------------------
// Retrieve the specified Column's name (Qualified include table name: '(<Table>.Column>)').
public static String GetColumnName (ColumnIdx column, bool delimitReservedWords = true)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return String.Empty;
String columnName = columns[columnIdx].Name;
if (delimitReservedWords) columnName = DelimitReservedWord(columnName);
return columnName;
}
public static String GetColumnNameQual (ColumnIdx column, String tableAlias = "", bool braces = false)
{
String columnName = GetColumnName(column);
if (!String.IsNullOrEmpty(columnName))
{
String tableName = StringUtil.EmptyOnNull(tableAlias);
if (tableName.IsEmpty()) tableName = GetTableName(GetTableForColumn(column));
columnName = tableName + (tableName.Length > 0 ? "." : "") + columnName;
if (braces)
columnName = "(" + columnName + ")";
}
return columnName;
}
//-------------------------------------------------------------------
// Reserved words.
private static DbReservedWordDelim reservedWordDelim = DbReservedWordDelim.SquareBrackets;
public static void SetReservedWordDelim (DbReservedWordDelim reservedWordDelim)
{
SaItemDocsDbDfn.reservedWordDelim = reservedWordDelim;
}
public static bool IsReservedWord (String word)
{
if (String.IsNullOrEmpty(word)) return false;
if (reservedWords.Contains(word, StringComparer.OrdinalIgnoreCase)) return true;
return false;
}
public static String DelimitReservedWord (String word)
{
if (!IsReservedWord(word)) return word;
switch (reservedWordDelim)
{
case DbReservedWordDelim.None:
break;
case DbReservedWordDelim.DoubleQuotes:
word = "\"" + word + "\"";
break;
case DbReservedWordDelim.SquareBrackets:
default:
word = "[" + word + "]";
break;
}
return word;
}
//-------------------------------------------------------------------
// Retrieve information about the specified Column.
public static DbColumnDataType GetColDataType (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return DbColumnDataType.Unknown;
return columns[columnIdx].DataType;
}
public static short GetColNativeDataType (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return 0;
return columns[columnIdx].NativeDataType;
}
public static void SetMaxTextLen (ulong maxTextLen)
{
SaItemDocsDbDfn.maxTextLen = maxTextLen;
}
public static bool IsColFmtText (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
return (columns[columnIdx].DataType == DbColumnDataType.VarChar);
}
public static ulong GetColTextLen (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return 0;
if (columns[columnIdx].DataType == DbColumnDataType.VarChar)
{
ulong textLen = columns[columnIdx].DataLen;
if (maxTextLen > 0 && textLen > maxTextLen) textLen = maxTextLen;
return textLen;
}
return 0;
}
public static bool IsColFmtBool (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
return (columns[columnIdx].DataType == DbColumnDataType.Bit);
}
public static bool IsColFmtNumeric (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
switch (columns[columnIdx].DataType)
{
case DbColumnDataType.TinyInt:
case DbColumnDataType.SmallInt:
case DbColumnDataType.Int:
case DbColumnDataType.BigInt:
case DbColumnDataType.Single:
case DbColumnDataType.Double:
case DbColumnDataType.Decimal:
return true;
}
return false;
}
//-------------------------------------------------------------------
// Table definitions.
private static readonly String[] tables =
{
"SaItemDoc",
};
//-------------------------------------------------------------------
// Table column definitions.
internal class ColumnDfn
{
internal TableIdx TableIdx { get; set; }
internal String Name { get; set; }
internal DbColumnDataType DataType { get; set; }
internal short NativeDataType { get; set; }
internal bool IsIdentity { get; set; }
internal ulong DataLen { get; set; }
internal ColumnDfn (int tableIdx, String name, int dataType, short nativeDataType, bool isIdentity, ulong dataLen)
{
this.TableIdx = (TableIdx)tableIdx;
this.Name = name;
this.DataType = (DbColumnDataType)dataType;
this.NativeDataType = nativeDataType;
this.IsIdentity = isIdentity;
this.DataLen = dataLen;
}
}
//-------------------------------------------------------------------
private static readonly ColumnDfn[] columns =
{
new ColumnDfn(1,"Id",4,4,false,10),
new ColumnDfn(1,"ItemType",3,5,false,5),
new ColumnDfn(1,"ItemId",4,4,false,10),
new ColumnDfn(1,"Category",3,5,false,5),
new ColumnDfn(1,"Type",0,-9,false,16),
new ColumnDfn(1,"DescBrief",0,-9,false,64),
new ColumnDfn(1,"Folder",0,-9,false,255),
new ColumnDfn(1,"Filename",0,-9,false,255),
new ColumnDfn(1,"MimeType",0,-9,false,32),
new ColumnDfn(1,"ItemTypeAutoAssign",3,5,false,5),
new ColumnDfn(1,"Notes",0,-9,false,255),
new ColumnDfn(1,"Flags",3,5,false,5),
new ColumnDfn(1,"Status",0,-9,false,3),
new ColumnDfn(1,"CreateOn",9,93,false,23),
new ColumnDfn(1,"CreateBy",4,4,false,10),
new ColumnDfn(1,"CreateHost",0,-9,false,64),
new ColumnDfn(1,"UpdateOn",9,93,false,23),
new ColumnDfn(1,"UpdateBy",4,4,false,10),
new ColumnDfn(1,"UpdateHost",0,-9,false,64),
};
//-------------------------------------------------------------------
// Reserved words.
private static readonly HashSet<String> reservedWords = new HashSet<String>()
{
"ADD",
"ALL",
"ALTER",
"AND",
"ANY",
"AS",
"ASC",
"AVG",
"BEGIN",
"BETWEEN",
"BY",
"CASE",
"CAST",
"COLUMN",
"COMMIT",
"CONSTRAINT",
"CONVERT",
"COUNT",
"CREATE",
"CURRENCY",
"DEFAULT",
"DELETE",
"DESC",
"DISTINCT",
"DROP",
"ELSE",
"END",
"EXECUTE",
"EXISTS",
"FALSE",
"FROM",
"GRANT",
"GROUP",
"HAVING",
"IN",
"INDEX",
"INNER",
"INSERT",
"INTO",
"IS",
"JOIN",
"KEY",
"LEFT",
"LIKE",
"MAX",
"MIN",
"NOT",
"NULL",
"ON",
"OR",
"ORDER",
"OUTER",
"OUTPUT",
"PRIMARY",
"PROCEDURE",
"REVOKE",
"ROLLBACK",
"ROWCOUNT",
"SELECT",
"SET",
"SQL",
"SUM",
"TABLE",
"THEN",
"TRANSACTION",
"TRUE",
"UNION",
"UNIQUE",
"UPDATE",
"USER",
"VALUES",
"VIEW",
"WHEN",
"WHERE",
};
//-------------------------------------------------------------------
}
}
@@ -0,0 +1,278 @@
using Sarand.Net.Standard.Base.ItemOptions;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.Net.Standard.Base.ItemOptions
{
//=======================================================================
public class SaItemOption : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Pos = 0,
// Item Option properties.
ItemType,
ItemType_Desc,
ItemId,
Group,
Name,
Name_Display,
Context,
Context_Display,
Value,
Value_Display,
Password,
// Common properties.
Notes,
Status,
Status_Desc,
Status_Ind,
CreateOn_Date,
UpdateOn_Date,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public ItemId ItemId { get; set; } = new ItemId();
public String Name { get; set; } = String.Empty;
public String Context { get; set; } = String.Empty;
public String Value { get; set; } = String.Empty;
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data ()
{
Status = SaItemOptionMgr.ActiveItemOptionStatus;
}
// Properties.
public ItemId ItemId
{
get { return data.ItemId; }
set { CheckChanged(data.ItemId, value); data.ItemId = value; }
}
public String Name
{
get { return data.Name; }
set { CheckChanged(data.Name, value); data.Name = value; }
}
public String Context
{
get { return data.Context; }
set { CheckChanged(data.Context, value); data.Context = value; }
}
public String Value
{
get { return data.Value; }
set { CheckChanged(data.Value, value); data.Value = value; }
}
// Population.
internal void PopulateFrom (Data data)
{
ItemId = data.ItemId;
Name = data.Name;
Context = data.Context;
Value = data.Value;
base.PopulateFrom(data);
}
public Data Clone ()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
// Error field - identify properties with validation error.
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue ItemType { get; set; } = ValidValue.Valid;
public ValidValue ItemId { get; set; } = ValidValue.Valid;
public ValidValue Name { get; set; } = ValidValue.Valid;
public ValidValue Context { get; set; } = ValidValue.Valid;
public ValidValue Value { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
// Flags.
public static readonly Byte Flag_Encrypted = 0x01;
//-------------------------------------------------------------------
// Construction.
public SaItemOption (ItemId itemId, String name, String context) :
base()
{
base.SetData(data);
ItemId = itemId;
Name = name;
// Trim Context as legacy systems (Sapphire, StockMgr, PatientMgr) store a space instead of a blank value.
Context = context.TrimAll();
Status = SaItemOptionMgr.ActiveItemOptionStatus;
}
//-------------------------------------------------------------------
// Statuses.
private static readonly List<SaStatus> validStatuses = new List<SaStatus>()
{
SaStatus.Current,
SaStatus.Deleted
};
public static SaStatus DefaultStatus { get { return ActiveStatus; } }
public static SaStatus ActiveStatus { get { return SaStatus.Current; } }
public static List<SaStatus> ValidStatuses { get { return new List<SaStatus>(validStatuses); } }
public static DataValue.TriStateType GetStatusTriState (SaStatus status)
{
switch (status)
{
case SaStatus.Current:
return DataValue.TriStateType.Green;
case SaStatus.Deleted:
return DataValue.TriStateType.Purple;
}
return DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Properties.
public Data GetData () { return data.Clone(); }
public void SetData (Data data)
{
// Properties that cannot be changed if previously specified.
if (ItemId.Type >= 0 && ItemId.Type != data.ItemId.Type)
throw new NotSupportedException($"{SysUtil.Fn} Item type cannot be changed");
if (SysId.IsValid(ItemId.Id) && SysId.ToInt(ItemId.Id) != SysId.ToInt(data.ItemId.Id))
throw new NotSupportedException($"{SysUtil.Fn} Item Id cannot be changed");
if (!StringUtil.IsEmpty(Name) && !Name.Equals(data.Name))
throw new NotSupportedException($"{SysUtil.Fn} Name cannot be changed");
if (!StringUtil.IsEmpty(Context) && !Context.Equals(data.Context))
throw new NotSupportedException($"{SysUtil.Fn} Context cannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
public ItemId ItemId
{
get { return data.ItemId; }
protected set { data.ItemId = value; }
}
public String Name
{
get { return data.Name; }
protected set { data.Name = value; }
}
public String Context
{
get { return data.Context; }
protected set { data.Context = value; }
}
public String Value
{
get { return data.Value; }
set { data.Value = value; }
}
//-------------------------------------------------------------------
// Flags.
public bool Encrypted
{
get { return GetFlag(Flag_Encrypted); }
set { SetFlag(Flag_Encrypted, value); }
}
//-------------------------------------------------------------------
// List parameters.
public enum StatusCat
{
Any,
NotDeleted,
CurrentOnly,
DeletedOnly,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
public List<ItemId> IncludedItemIds { get; } = new List<ItemId>();
public List<StringPair> IncludedNameContexts { get; } = new List<StringPair>();
public StatusCat StatusCat { get; set; } = StatusCat.CurrentOnly;
}
//-------------------------------------------------------------------
/// <summary>
/// Item option cache - to allow op.
/// </summary>
public class Cache
{
public Cache ()
{
}
public ItemId ItemId { get; private set; } = new ItemId();
public ItemId ItemIdRef { get; private set; } = new ItemId();
public List<SaItemOption> ItemOptions { get; } = new List<SaItemOption>();
public void Reset (ItemId itemId, ItemId itemIdRef)
{
ItemId = itemId != null ? itemId : new ItemId();
ItemIdRef = itemIdRef != null ? itemIdRef : new ItemId();
ItemOptions.Clear();
}
public void Clear ()
{
ItemId = new ItemId();
ItemIdRef = new ItemId();
ItemOptions.Clear();
}
}
//-------------------------------------------------------------------
}
//=======================================================================
/// <summary>
/// Item Option list utilities.
/// </summary>
public static class SaItemOptionList
{
/// <summary>Does the list include an option for the specified name and context.</summary>
public static bool IsOptionDefined (this List<SaItemOption> options, String name, String context)
{
return options.Exists(item => item.Name.EqualsCI(name) && item.Context.EqualsCI(context) && !item.IsStatusDeleted);
}
/// <summary>Retrieve the list of contexts populated for the specified option name.</summary>
public static List<String> GetContextsForName (this List<SaItemOption> options, String name)
{
List<String> optionContexts = new List<string>();
foreach (SaItemOption itemOption in options.FindAll(item => item.Name.EqualsCI(name) && !item.IsStatusDeleted))
{
if (!StringUtil.IsEmpty(itemOption.Context) && !optionContexts.ContainsCI(itemOption.Context))
optionContexts.Add(itemOption.Context);
}
return optionContexts;
}
/// <summary>Retrieve the option value for the name and context.</summary>
public static String GetOptionValue (this List<SaItemOption> options, String name, String context, String defaultValue = "")
{
SaItemOption itemOption = options.Find(item => item.Name.EqualsCI(name) && item.Context.EqualsCI(context) && !item.IsStatusDeleted);
if (itemOption != null)
return itemOption.Value;
return defaultValue;
}
}
//=======================================================================
}
@@ -0,0 +1,93 @@
using Sarand.Net.Standard.Base.ItemOptions;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.UpdateLog;
namespace Sarand.Net.Standard.Base.ItemOptions
{
//=======================================================================
public abstract class SaItemOptionConsole : SacsDisposableStateItem
{
//-------------------------------------------------------------------
// Definitions.
//-------------------------------------------------------------------
// Data members.
private static readonly List<CodeDesc> yesNoValues = new List<CodeDesc>();
//-------------------------------------------------------------------
// Static initialisation.
static SaItemOptionConsole ()
{
yesNoValues.Add("Yes", "Yes");
yesNoValues.Add("No", "No");
}
//-------------------------------------------------------------------
// Construction.
protected SaItemOptionConsole ()
{
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
}
base.Dispose(disposing);
}
//-------------------------------------------------------------------
// Properties.
public abstract short ItemOptionDataType { get; }
public abstract SaUpdateLogConsole UpdateLogConsole { get; }
// Database.
public abstract bool DatabaseIsValid { get; }
public abstract bool CanUpdateDatabase { get; }
//-------------------------------------------------------------------
// Manage Item Options - returns true if changes made.
public abstract bool ShowItemOptionsDialog (ItemId itemId, DbUpdateInfo dbUpdateInfo);
public abstract bool MangageItemOptions (List<SaItemOption> itemOptions);
//-------------------------------------------------------------------
// Utilities.
public static List<CodeDesc> YesNoValues { get { return new List<CodeDesc>(yesNoValues); } }
//-------------------------------------------------------------------
// I t e m O p t i o n s
//-------------------------------------------------------------------
// Item Option definitions.
public abstract List<SaItemOptionDfn> GetItemOptionDfnsForItem (ItemId itemId);
// Retrieve specific option.
public abstract SaItemOption GetItemOption (ItemId itemId, String name, String context);
// Retrieve options.
public abstract List<SaItemOption> GetItemOptions (SaItemOption.Params prmItemOption);
public abstract List<SaItemOption> GetItemOptionsForItem (ItemId itemId);
// Retrieve specific option for range of items (all matching items if item id list is blank).
public abstract List<SaItemOption> GetItemOptions (List<ItemId> itemIds, String name, String context);
//-------------------------------------------------------------------
// Create an item option.
public abstract SaItemOption CreateItemOption (ItemId itemId, String name, String context);
// Item independent options, eg. for processes.
public abstract SaItemOption CreateItemOptionByNameContext (String name, String context);
//-------------------------------------------------------------------
// Store item option - create if not exsts, otherwise update.
public abstract bool StoreItemOption (SaItemOption itemOption, DbUpdateInfo dbUpdateInfo);
// Store a specific option against the specified item.
public abstract bool StoreItemOption (ItemId itemId, String name, String context, String sValue, DbUpdateInfo dbUpdateInfo);
// Store the list of options against the specified item. Options no longer in the list are deleted.
public abstract bool StoreItemOptions (ItemId itemId, List<SaItemOption> itemOptions, DbUpdateInfo dbUpdateInfo);
// Remove option(s) for the specified item.
public abstract bool ClearItemOption (SaItemOption itemOption, DbUpdateInfo dbUpdateInfo);
public abstract bool ClearItemOption (ItemId itemId, String name, String context, DbUpdateInfo dbUpdateInfo);
public abstract bool ClearItemOptions (ItemId itemId, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,349 @@
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
//---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Thu 30-Oct-2025 11:28:12
//---------------------------------------------------------------------------
namespace Sarand.Net.Standard.Base.ItemOptions
{
public class SaItemOptionDbDfn
{
//-------------------------------------------------------------------
// Table identifiers.
public enum TableIdx
{
Unknown = 0,
SaItemOption,
}
//-------------------------------------------------------------------
// Column identifiers.
public enum ColumnIdx
{
Unknown = 0,
SaItemOption_ItemType,
SaItemOption_ItemId,
SaItemOption_Name,
SaItemOption_Context,
SaItemOption_Value,
SaItemOption_Notes,
SaItemOption_Flags,
SaItemOption_Status,
SaItemOption_CreateOn,
SaItemOption_CreateBy,
SaItemOption_CreateHost,
SaItemOption_UpdateOn,
SaItemOption_UpdateBy,
SaItemOption_UpdateHost,
}
//-------------------------------------------------------------------
// Data members.
private static readonly int tableCount = 1;
private static readonly int columnCount = 14;
public static ulong MaxTextLen { get; private set; }
//-------------------------------------------------------------------
// Retrieve Table details.
public static int GetTableCount ()
{
return tableCount;
}
public static String GetSchemaName (TableIdx table, bool delimitReservedWords = true)
{
int tableIdx = (int)table - 1;
if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;
String schemaName = tables[(int)tableIdx].Schema;
if (delimitReservedWords) { schemaName = DelimitReservedWord(schemaName); }
return schemaName;
}
public static String GetTableName (TableIdx table, bool delimitReservedWords = true)
{
int tableIdx = (int)table - 1;
if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;
String tableName = tables[(int)tableIdx].Name;
if (delimitReservedWords) tableName = DelimitReservedWord(tableName);
return tableName;
}
public static String GetTableNameQual (TableIdx table, bool delimitReservedWords = true)
{
int tableIdx = (int)table - 1;
if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;
String schemaName = tables[(int)tableIdx].Schema;
String tableName = tables[(int)tableIdx].Name;
if (delimitReservedWords) { schemaName = DelimitReservedWord(schemaName); tableName = DelimitReservedWord(tableName); }
return (StringUtil.IsBlank(schemaName) ? "" : schemaName + ".") + tableName;
}
//-------------------------------------------------------------------
// Identify the table that corresponds with the specified column.
public static TableIdx GetTableForColumn (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return TableIdx.Unknown;
return columns[columnIdx].TableIdx;
}
//-------------------------------------------------------------------
// Retrieve the specified Column's name (Qualified include table name: '(<Table>.Column>)').
public static String GetColumnName (ColumnIdx column, bool delimitReservedWords = true)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return String.Empty;
String columnName = columns[columnIdx].Name;
if (delimitReservedWords) columnName = DelimitReservedWord(columnName);
return columnName;
}
public static String GetColumnNameQual (ColumnIdx column, String tableAlias = "", bool braces = false)
{
String columnName = GetColumnName(column);
if (!String.IsNullOrEmpty(columnName))
{
String tableName = StringUtil.EmptyOnNull(tableAlias);
if (tableName.IsEmpty()) tableName = GetTableName(GetTableForColumn(column));
columnName = tableName + (tableName.Length > 0 ? "." : "") + columnName;
if (braces) columnName = $"({columnName})";
}
return columnName;
}
//-------------------------------------------------------------------
// Reserved words.
private static DbReservedWordDelim reservedWordDelim = DbReservedWordDelim.SquareBrackets;
public static void SetReservedWordDelim (DbReservedWordDelim reservedWordDelim)
{
SaItemOptionDbDfn.reservedWordDelim = reservedWordDelim;
}
public static bool IsReservedWord (String word)
{
if (String.IsNullOrEmpty(word)) return false;
if (reservedWords.Contains(word, StringComparer.OrdinalIgnoreCase)) return true;
return false;
}
public static String DelimitReservedWord (String word)
{
return IsReservedWord(word) ? DelimitWord(word) : word;
}
public static String DelimitWord (String word)
{
return DelimitWord(word, reservedWordDelim);
}
public static String DelimitWord (String word, DbReservedWordDelim wordDelim)
{
switch (wordDelim)
{
case DbReservedWordDelim.None:
break;
case DbReservedWordDelim.DoubleQuotes:
word = $"\"{word}\"";
break;
case DbReservedWordDelim.SquareBrackets:
default:
word = $"[{word}]";
break;
}
return word;
}
//-------------------------------------------------------------------
// Retrieve information about the specified Column.
public static DbColumnDataType GetColDataType (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return DbColumnDataType.Unknown;
return columns[columnIdx].DataType;
}
public static short GetColNativeDataType (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return 0;
return columns[columnIdx].NativeDataType;
}
public static void SetMaxTextLen (ulong maxTextLen)
{
SaItemOptionDbDfn.MaxTextLen = maxTextLen;
}
public static bool IsColFmtText (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
return (columns[columnIdx].DataType == DbColumnDataType.VarChar);
}
public static ulong GetColTextLen (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return 0;
if (columns[columnIdx].DataType == DbColumnDataType.VarChar)
{
ulong textLen = columns[columnIdx].DataLen;
if (MaxTextLen > 0 && textLen > MaxTextLen) textLen = MaxTextLen;
return textLen;
}
return 0;
}
public static bool IsColFmtBool (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
return (columns[columnIdx].DataType == DbColumnDataType.Bit);
}
public static bool IsColFmtNumeric (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
switch (columns[columnIdx].DataType)
{
case DbColumnDataType.TinyInt:
case DbColumnDataType.SmallInt:
case DbColumnDataType.Int:
case DbColumnDataType.BigInt:
case DbColumnDataType.Single:
case DbColumnDataType.Double:
case DbColumnDataType.Decimal:
return true;
}
return false;
}
//-------------------------------------------------------------------
// Table definitions.
private class TableDfn
{
internal String Schema { get; set; }
internal String Name { get; set; }
internal TableDfn (String schema, String name)
{
this.Schema= schema;
this.Name = name;
}
}
private static readonly TableDfn[] tables =
{
new TableDfn("dbo","SaItemOption"),
};
//-------------------------------------------------------------------
// Table column definitions.
private class ColumnDfn
{
internal TableIdx TableIdx { get; set; }
internal String Name { get; set; }
internal DbColumnDataType DataType { get; set; }
internal short NativeDataType { get; set; }
internal bool IsIdentity { get; set; }
internal ulong DataLen { get; set; }
internal ColumnDfn (int tableIdx, String name, int dataType, short nativeDataType, bool isIdentity, ulong dataLen)
{
this.TableIdx = (TableIdx)tableIdx;
this.Name = name;
this.DataType = (DbColumnDataType)dataType;
this.NativeDataType = nativeDataType;
this.IsIdentity = isIdentity;
this.DataLen = dataLen;
}
}
private static readonly ColumnDfn[] columns =
{
new ColumnDfn(1,"ItemType",3,5,false,5),
new ColumnDfn(1,"ItemId",4,4,false,10),
new ColumnDfn(1,"Name",0,-9,false,64),
new ColumnDfn(1,"Context",0,-9,false,64),
new ColumnDfn(1,"Value",0,-9,false,255),
new ColumnDfn(1,"Notes",0,-9,false,255),
new ColumnDfn(1,"Flags",3,5,false,5),
new ColumnDfn(1,"Status",0,-9,false,3),
new ColumnDfn(1,"CreateOn",9,93,false,23),
new ColumnDfn(1,"CreateBy",4,4,false,10),
new ColumnDfn(1,"CreateHost",0,-9,false,64),
new ColumnDfn(1,"UpdateOn",9,93,false,23),
new ColumnDfn(1,"UpdateBy",4,4,false,10),
new ColumnDfn(1,"UpdateHost",0,-9,false,64),
};
//-------------------------------------------------------------------
// Reserved words.
private static readonly HashSet<String> reservedWords = new HashSet<String>()
{
"ADD",
"ALL",
"ALTER",
"AND",
"ANY",
"AS",
"ASC",
"AVG",
"BEGIN",
"BETWEEN",
"BY",
"CASE",
"CAST",
"COLUMN",
"COMMIT",
"CONSTRAINT",
"CONVERT",
"COUNT",
"CREATE",
"CURRENCY",
"DEFAULT",
"DELETE",
"DESC",
"DISTINCT",
"DROP",
"ELSE",
"END",
"EXECUTE",
"EXISTS",
"FALSE",
"FROM",
"GRANT",
"GROUP",
"HAVING",
"IN",
"INDEX",
"INNER",
"INSERT",
"INTO",
"IS",
"JOIN",
"KEY",
"LEFT",
"LIKE",
"MAX",
"MIN",
"NOT",
"NULL",
"ON",
"OR",
"ORDER",
"OUTER",
"OUTPUT",
"PRIMARY",
"PROCEDURE",
"REVOKE",
"ROLLBACK",
"ROWCOUNT",
"SELECT",
"SET",
"SQL",
"SUM",
"TABLE",
"THEN",
"TRANSACTION",
"TRUE",
"UNION",
"UNIQUE",
"UPDATE",
"USER",
"VALUES",
"VIEW",
"WHEN",
"WHERE"
};
//-------------------------------------------------------------------
}
}
@@ -0,0 +1,148 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Base.ItemOptions
{
//=======================================================================
public class SaItemOptionDfn
{
//-------------------------------------------------------------------
// Item Option Action.
public delegate bool ItemOptionActionFunction (SaItemOption itemOption, List<SaItemOption> itemOptions);
public class Action
{
public Action (String caption, ItemOptionActionFunction itemOptionActionFn)
{
Caption = caption;
ItemOptionActionFn = itemOptionActionFn;
}
public String Caption { get; set; } = "";
public ItemOptionActionFunction ItemOptionActionFn { get; set; } = null;
}
//-------------------------------------------------------------------
// Item Option display options.
public class Display
{
public String Group { get; set; } = "";
public String Caption { get; set; } = "";
/// <summary>Sort sequence for display.</summary>
public int Sequence { get; set; } = 0;
/// <summary>Allowed contexts ('Value' aganst each context defines default value).</summary>
public List<CodeDesc> Contexts { get; } = new List<CodeDesc>();
/// <summary>Allowed values.</summary>
public List<CodeDesc> Values { get; } = new List<CodeDesc>();
// Maximum value is defined by database.
public int MaxLength { get; set; } = 0;
// User must pick from the supplied list.
public bool ExclusiveValues { get; set; } = true;
public bool RightText { get; set; } = false;
public bool Uppercase { get; set; } = false;
public bool Lowercase { get; set; } = false;
public bool Numeric { get; set; } = false;
public bool Password { get; set; } = false;
public bool Encrypted { get; set; } = false;
public bool ReadOnly { get; set; } = false;
public decimal MinValue { get; set; } = 0.0m;
public decimal MaxValue { get; set; } = 0.0m;
public bool RequiresContext { get; set; } = false;
public bool PopulateWithContext { get; set; } = false;
/// <summary>Defines available contexts and other rules, but should not be shown in list.</summary>
public bool NonDisplayTemplate { get; set; } = false;
/// <summary>User can add additional options for other contexts.</summary>
public bool CanAddOption { get; set; } = false;
/// <summary>Use can remove the option from the list.</summary>
public bool CanRemoveOption { get; set; } = false;
/// <summary>Browse for filename/folder etc.</summary>
public Action BrowseAction { get; set; } = null;
}
//-------------------------------------------------------------------
// Properties.
/// <summary>Option Name - identifying code.</summary>
public String Name { get; set; } = "";
public String DisplayName { get { return StringUtil.OnEmpty(DisplayOptions.Caption,Name); } }
public String DefaultValue { get; set; } = "";
public String DefaultNotes { get; set; } = "";
public Display DisplayOptions { get; } = new Display();
//-------------------------------------------------------------------
// Utilities.
public String GetContextDesc (String context)
{
return DisplayOptions.Contexts.GetDescForCode(context, context);
}
//-------------------------------------------------------------------
}
//=======================================================================
public static class SaItemOptionDfnList
{
//-------------------------------------------------------------------
// List value properties.
public static List<String> GetNames (this List<SaItemOptionDfn> values)
{
List<String> names = new List<string>();
foreach (var itemOptionDfn in values)
{
if (!StringUtil.IsEmpty(itemOptionDfn.Name) && !names.ContainsCI(itemOptionDfn.Name))
names.Add(itemOptionDfn.Name);
}
return names;
}
//-------------------------------------------------------------------
// Retrieve available Item Option Definitions, ie. those that aren't fully defined in the list of item options.
public static List<SaItemOptionDfn> GetAvailableItemOptionDfns (this List<SaItemOptionDfn> values, List<SaItemOption> itemOptions)
{
List<SaItemOptionDfn> availableItemOptionDfns = new List<SaItemOptionDfn>();
foreach (SaItemOptionDfn itemOptionDfn in values)
{
if (itemOptionDfn.DisplayOptions.Contexts.Count == 0)
{
// Option has no context.
if (!itemOptions.IsOptionDefined(itemOptionDfn.Name, ""))
availableItemOptionDfns.Add(itemOptionDfn);
}
else
{
List<String> definedOptionContexts = itemOptions.GetContextsForName(itemOptionDfn.Name);
if (itemOptionDfn.DisplayOptions.Contexts.Exists(item => !definedOptionContexts.ContainsCI(item.Code)))
availableItemOptionDfns.Add(itemOptionDfn);
}
}
return availableItemOptionDfns;
}
//-------------------------------------------------------------------
// Retrieve Item Option Definition
public static SaItemOptionDfn GetDfnForItemOption (this List<SaItemOptionDfn> values, SaItemOption itemOption)
{
return values.GetItemOptionDfnByName(itemOption.Name);
}
public static SaItemOptionDfn GetItemOptionDfnByName (this List<SaItemOptionDfn> values, String name)
{
if (StringUtil.IsEmpty(name)) return null;
foreach (var itemOptionDfn in values)
{
if (itemOptionDfn.Name.EqualsCI(name))
return itemOptionDfn;
}
return null;
}
//-------------------------------------------------------------------
// Sorting
public enum SortBy
{
Name,
DisplayName,
}
public static void Sort (this List<SaItemOptionDfn> values)
{
}
}
//=======================================================================
}
@@ -0,0 +1,176 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
namespace Sarand.Net.Standard.Base.ItemOptions
{
//=======================================================================
public abstract class SaItemOptionMgr : SacsItemMgr
{
//-------------------------------------------------------------------
// Data members.
private static readonly List<SaStatus> itemOptionStatuses = new List<SaStatus>();
//-------------------------------------------------------------------
// Static initialisation.
static SaItemOptionMgr ()
{
// Item option statuses.
itemOptionStatuses.Add(SaStatus.Current);
itemOptionStatuses.Add(SaStatus.Deleted);
}
//-------------------------------------------------------------------
// Construction.
protected SaItemOptionMgr ()
{
}
//-------------------------------------------------------------------
// Properties.
public abstract bool DatabaseIsValid { get; }
public abstract bool CanUpdateDatabase { get; }
//*******************************************************************
// I t e m O p t i o n s
//*******************************************************************
// Statuses.
public static SaStatus ActiveItemOptionStatus { get { return SaStatus.Current; } }
public static List<SaStatus> ItemOptionStatuses { get { return itemOptionStatuses; } }
//-------------------------------------------------------------------
// Associated data.
//-------------------------------------------------------------------
// Retrieve individual item options.
public abstract bool ItemOptionExists (SaItemOption itemOption);
public abstract bool ItemOptionExists (ItemId itemId, String name, String context);
public abstract SaItemOption GetItemOption (SaItemOption itemOption);
public abstract SaItemOption GetItemOption (ItemId itemId, String name, String context);
// Create Item Option.
public abstract SaItemOption CreateItemOption (ItemId itemId, String name, String context);
//-------------------------------------------------------------------
// Validate Item Option.
public bool IsValidItemOption (SaItemOption itemOption)
{
ClearErrorState();
if (itemOption == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidItemOptionData(itemOption.GetData(), new SaItemOption.ErrField());
}
public virtual bool IsValidItemOptionData (SaItemOption.Data itemOptionData, SaItemOption.ErrField errField)
{
ClearErrorState();
if ((int)itemOptionData.ItemId.Type < 1)
{
errField.ItemType = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.ItemTypeNotSpecified);
}
if (!SysId.IsValid(itemOptionData.ItemId.Id))
{
errField.ItemId = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.ItemIdNotSpecified);
}
if (!IsValidValue(itemOptionData.Name, "name", (long)SaItemOptionDbDfn.GetColTextLen(SaItemOptionDbDfn.ColumnIdx.SaItemOption_Name), true))
{
errField.Name = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!IsValidValue(itemOptionData.Context, "context", (long)SaItemOptionDbDfn.GetColTextLen(SaItemOptionDbDfn.ColumnIdx.SaItemOption_Context)))
{
errField.Context = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!IsValidValue(itemOptionData.Value, "value", (long)SaItemOptionDbDfn.GetColTextLen(SaItemOptionDbDfn.ColumnIdx.SaItemOption_Value)))
{
errField.Value = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
// Common properties.
if (!IsValidValue(itemOptionData.Notes, "notes", (long)SaItemOptionDbDfn.GetColTextLen(SaItemOptionDbDfn.ColumnIdx.SaItemOption_Notes)))
{
errField.Notes = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!ItemOptionStatuses.Contains(itemOptionData.Status))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.InvalidStatus);
}
return true;
}
//-------------------------------------------------------------------
// Database interface.
public abstract bool InsertItemOption (SaItemOption itemOption, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateItemOption (SaItemOption itemOption, DbUpdateInfo dbUpdateInfo);
public virtual bool ItemOptionCanBeDeleted (SaItemOption itemOption)
{
ClearErrorState();
return true;
}
public abstract bool DeleteItemOption (SaItemOption itemOption, DbUpdateInfo dbUpdateInfo);
public abstract bool ClearItemOptionsForItem (ItemId itemId, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Item list.
public abstract ColumnDfn GetItemOptionColumnDfn (SaItemOption.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetItemOptionQueryFilter (SaItemOption.Params prm);
public abstract long GetItemOptionCount (SaItemOption.Params prm);
public abstract List<SaItemOption> GetItemOptionList (SaItemOption.Params prm);
public abstract DbResultSet ExecuteItemOptionQuery (List<ColumnDfn> columns, SaItemOption.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public DataValue GetItemOptionDataValue (ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
switch ((SaItemOption.Column)column.Id)
{
//-----------------------------------------------------------
// Item type.
case SaItemOption.Column.ItemType_Desc:
{
short itemType = (short)values.GetValue(column.DataName).AsLong();
value = new DataValue(itemType.ToString());
}
break;
//-----------------------------------------------------------
// Notes.
case SaItemOption.Column.Notes:
{
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
}
break;
//-----------------------------------------------------------
// Status.
case SaItemOption.Column.Status_Desc:
case SaItemOption.Column.Status_Ind:
{
String statusCode = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusCode);
if (column.Id == (int)SaItemOption.Column.Status_Desc)
value = new DataValue(SacsSystem.GetStatusDescForCode(statusCode));
else if (column.Id == (int)SaItemOption.Column.Status_Ind)
value = new DataValue(SaItemOption.GetStatusTriState(status));
}
break;
//-----------------------------------------------------------
}
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,301 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=======================================================================
public abstract class SaCurrency : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Hidden,
Pos,
Id,
// Currency.
Code,
Name,
PrimaryCurrencyId,
PrimaryCurrency_Code,
PrimaryCurrency_Name,
Division,
RegionId,
Region_Name,
Symbol,
SuffixSymbol_Y,
SuffixSymbol_Tick,
IncludeSpace_Y,
IncludeSpace_Tick,
Decimals,
// Common properties.
CreateOn_Date,
UpdateOn_Date,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public String Code { get; set; } = "";
public String Name { get; set; } = "";
public SysId CurrencyIdPrimary { get; set; } = new SysId();
public String Division { get; set; } = "";
public SysId RegionId { get; set; } = new SysId();
public String Symbol { get; set; } = "";
public bool SuffixSymbol { get; set; } = false;
public bool IncludeSpace { get; set; } = false;
public ushort Decimals { get; set; } = 0;
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data ()
{
// Currency has no status.
}
// Properties.
public String Code
{
get { return data.Code; }
set { CheckChanged(data.Code, value); data.Code = value; }
}
public String Name
{
get { return data.Name; }
set { CheckChanged(data.Name, value); data.Name = value; }
}
public SysId CurrencyIdPrimary
{
get { return data.CurrencyIdPrimary; }
set { CheckChanged(data.CurrencyIdPrimary, value); data.CurrencyIdPrimary = value; }
}
public String Division
{
get { return data.Division; }
set { CheckChanged(data.Division, value); data.Division = value; }
}
public SysId RegionId
{
get { return data.RegionId; }
set { CheckChanged(data.RegionId, value); data.RegionId = value; }
}
public String Symbol
{
get { return data.Symbol; }
set { CheckChanged(data.Symbol, value); data.Symbol = value; }
}
public bool SuffixSymbol
{
get { return data.SuffixSymbol; }
set { CheckChanged(data.SuffixSymbol, value); data.SuffixSymbol = value; }
}
public bool IncludeSpace
{
get { return data.IncludeSpace; }
set { CheckChanged(data.IncludeSpace, value); data.IncludeSpace = value; }
}
public ushort Decimals
{
get { return data.Decimals; }
set { CheckChanged(data.Decimals, value); data.Decimals = value; }
}
internal void PopulateFrom (Data data)
{
Code = data.Code;
Name = data.Name;
CurrencyIdPrimary = data.CurrencyIdPrimary;
Division = data.Division;
RegionId = data.RegionId;
Symbol = data.Symbol;
SuffixSymbol = data.SuffixSymbol;
IncludeSpace = data.IncludeSpace;
Decimals = data.Decimals;
base.PopulateFrom(data);
}
public Data Clone ()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue Code { get; set; } = ValidValue.Valid;
public ValidValue Name { get; set; } = ValidValue.Valid;
public ValidValue CurrencyIdPrimary { get; set; } = ValidValue.Valid;
public ValidValue Division { get; set; } = ValidValue.Valid;
public ValidValue RegionId { get; set; } = ValidValue.Valid;
public ValidValue Symbol { get; set; } = ValidValue.Valid;
public ValidValue SuffixSymbol { get; set; } = ValidValue.Valid;
public ValidValue IncludeSpace { get; set; } = ValidValue.Valid;
public ValidValue Decimals { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
//-------------------------------------------------------------------
// Static construction.
static SaCurrency ()
{
}
//-------------------------------------------------------------------
// Construction.
protected SaCurrency (SysId id) : base(id)
{
base.SetData(data);
// Currency has no status.
}
//-------------------------------------------------------------------
// Statuses - not applicable for currencies.
//-------------------------------------------------------------------
// Utilities.
public String FormatAmount (decimal amount)
{
return FormatAmount(Symbol, SuffixSymbol, IncludeSpace, amount, Decimals);
}
public static String FormatAmount (String symbol, bool suffix, bool includeSpace, decimal amount, ushort decimals)
{
String format = "N" + Math.Max(0, Math.Min(4, (int)decimals));
String amountFmt = amount.ToString(format);
if (suffix) amountFmt += (includeSpace ? " " : "") + symbol;
else amountFmt = symbol + (includeSpace ? " " : "") + amountFmt;
return amountFmt;
}
//-------------------------------------------------------------------
// Data.
public Data GetData () { return data.Clone(); }
public void SetData (Data data)
{
// Properties that cannot be changed if previously specified.
if (SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id))
throw new NotSupportedException($"{SysUtil.Fn} Id cannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
//-------------------------------------------------------------------
// Properties.
public String Code
{
get { return data.Code; }
set { data.Code = value; }
}
public String Name
{
get { return data.Name; }
set { data.Name = value; }
}
public SysId CurrencyIdPrimary
{
get { return data.CurrencyIdPrimary; }
set { data.CurrencyIdPrimary = value; }
}
public String Division
{
get { return data.Division; }
set { data.Division = value; }
}
public SysId RegionId
{
get { return data.RegionId; }
set { data.RegionId = value; }
}
public String Symbol
{
get { return data.Symbol; }
set { data.Symbol = value; }
}
public bool SuffixSymbol
{
get { return data.SuffixSymbol; }
set { data.SuffixSymbol = value; }
}
public bool IncludeSpace
{
get { return data.IncludeSpace; }
set { data.IncludeSpace = value; }
}
public ushort Decimals
{
get { return data.Decimals; }
set { data.Decimals = value; }
}
//-------------------------------------------------------------------
// A s s o c i a t e d D a t a E l e m e n t s
//-------------------------------------------------------------------
public abstract bool HasDependentCurrencies ();
//-------------------------------------------------------------------
// P a r a m s
//-------------------------------------------------------------------
/// <summary>
/// Parameters - used to define the filters that should be applied to a List of Currencies
/// </summary>
// List parameters.
public enum StatusCat
{
Any,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
// List filtering.
public HashSet<SysId> IdsIncluded { get; } = new HashSet<SysId>();
public HashSet<SysId> IdsExcluded { get; } = new HashSet<SysId>();
// Currency.
public String Code { get; set; }
public String CodePartial { get; set; }
public String Name { get; set; }
public String NamePartial { get; set; }
public SysId RegionId { get; set; }
public StatusCat StatusCat { get; set; } = StatusCat.Any;
}
//-------------------------------------------------------------------
}
//=======================================================================
// C u r r e n c y D a t a L i s t
//=======================================================================
public static class SaCurrencyList
{
public static SaCurrency FindById (this List<SaCurrency> values, SysId currencyId)
{
if (!SysId.IsValid(currencyId)) return null;
return values.Find(item => item.Id.Equals(currencyId));
}
public static SaCurrency FindByCode (this List<SaCurrency> values, String currencyCode)
{
if (StringUtil.IsEmpty(currencyCode)) return null;
return values.Find(item => item.Code.EqualsCI(currencyCode));
}
public static SaCurrency FindBySymbol (this List<SaCurrency> values, String currencySymbol)
{
if (StringUtil.IsEmpty(currencySymbol)) return null;
return values.Find(item => item.Symbol.EqualsCI(currencySymbol));
}
}
//=======================================================================
}
@@ -0,0 +1,214 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=======================================================================
public abstract class SaLanguage : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Hidden,
Pos,
Id,
// Language.
Code,
Name,
LanguageIdPrimary,
Unicode,
Translation,
// Common properties.
CreateOn_Date,
UpdateOn_Date,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public String Code { get; set; } = "";
public String Name { get; set; } = "";
public SysId LanguageIdPrimary { get; set; } = new SysId();
public bool Unicode { get; set; } = false;
public bool Translation { get; set; } = false;
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data ()
{
// Language has no status.
}
// Properties.
public String Code
{
get { return data.Code; }
set { CheckChanged(data.Code, value); data.Code = value; }
}
public String Name
{
get { return data.Name; }
set { CheckChanged(data.Name, value); data.Name = value; }
}
public SysId LanguageIdPrimary
{
get { return data.LanguageIdPrimary; }
set { CheckChanged(data.LanguageIdPrimary, value); data.LanguageIdPrimary = value; }
}
public bool Unicode
{
get { return data.Unicode; }
set { CheckChanged(data.Unicode, value); data.Unicode = value; }
}
public bool Translation
{
get { return data.Translation; }
set { CheckChanged(data.Translation, value); data.Translation = value; }
}
internal void PopulateFrom (Data data)
{
Code = data.Code;
Name = data.Name;
LanguageIdPrimary = data.LanguageIdPrimary;
Unicode = data.Unicode;
Translation = data.Translation;
base.PopulateFrom(data);
}
public Data Clone ()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue Code { get; set; } = ValidValue.Valid;
public ValidValue Name { get; set; } = ValidValue.Valid;
public ValidValue LanguageIdPrimary { get; set; } = ValidValue.Valid;
public ValidValue Unicode { get; set; } = ValidValue.Valid;
public ValidValue Translation { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
//-------------------------------------------------------------------
// Static construction.
static SaLanguage ()
{
}
//-------------------------------------------------------------------
// Construction.
protected SaLanguage (SysId id) : base(id)
{
base.SetData(data);
// Language has no status.
}
//-------------------------------------------------------------------
// Statuses - not applicable for languages.
//-------------------------------------------------------------------
// Utilities.
//-------------------------------------------------------------------
// Data.
public Data GetData () { return data.Clone(); }
public void SetData (Data data)
{
// Properties that cannot be changed if previously specified.
if (SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id))
throw new NotSupportedException($"{SysUtil.Fn} Id cannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
//-------------------------------------------------------------------
// Properties.
public String Code
{
get { return data.Code; }
set { data.Code = value; }
}
public String Name
{
get { return data.Name; }
set { data.Name = value; }
}
public SysId LanguageIdPrimary
{
get { return data.LanguageIdPrimary; }
set { data.LanguageIdPrimary = value; }
}
public bool Unicode
{
get { return data.Unicode; }
set { data.Unicode = value; }
}
public bool Translation
{
get { return data.Translation; }
set { data.Translation = value; }
}
//-------------------------------------------------------------------
// A s s o c i a t e d D a t a E l e m e n t s
//-------------------------------------------------------------------
public abstract bool HasDependentLanguages ();
//-------------------------------------------------------------------
// P a r a m s
//-------------------------------------------------------------------
// List parameters.
public enum StatusCat
{
Any,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
// List filtering.
public HashSet<SysId> IdsIncluded { get; } = new HashSet<SysId>();
public HashSet<SysId> IdsExcluded { get; } = new HashSet<SysId>();
// Item properties.
public String Code { get; set; }
public String CodePartial { get; set; }
public String Name { get; set; }
public String NamePartial { get; set; }
public SysId LanguageIdPrimary { get; set; }
public StatusCat StatusCat { get; set; } = StatusCat.Any;
}
//-------------------------------------------------------------------
}
//=======================================================================
// L a n g u a g e D a t a L i s t
//=======================================================================
public static class SaLanguageList
{
public static SaLanguage FindById (this List<SaLanguage> values, SysId languageId)
{
if (!SysId.IsValid(languageId)) return null;
return values.Find(item => item.Id.Equals(languageId));
}
}
//=======================================================================
}
@@ -0,0 +1,52 @@
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
using System;
using System.Collections.Generic;
using System.Text;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=======================================================================
// Reference Data Console - Currencies.
//=======================================================================
partial class SaReferenceDataConsole
{
//-------------------------------------------------------------------
// Utilities.
public static String GetDefaultCurrencyCode()
{
return GetCurrencyCode(SaCurrencyCode.Sterling);
}
public static String GetCurrencyCode(SaCurrencyCode currencyCode)
{
switch (currencyCode)
{
case SaCurrencyCode.Sterling: return "GBP";
case SaCurrencyCode.Euro: return "EUR";
}
return "";
}
//-------------------------------------------------------------------
// Properties.
public abstract short CurrencyItemType { get; }
public abstract String TableName_Currency { get; }
public abstract bool DatabaseIsValid_Currency { get; }
//-------------------------------------------------------------------
// Retrieve Currency.
public abstract SaCurrency GetCurrency(SaCurrency.Params prmCurrency);
// Currency list.
public abstract ColumnDfn GetCurrencyColumnDfn(SaCurrency.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetCurrencyQueryFilter(SaCurrency.Params prm);
public abstract long GetCurrencyCount(SaCurrency.Params prmCurrency);
public abstract List<SaCurrency> GetCurrencyList(SaCurrency.Params prmCurrency);
public abstract DbResultSet ExecuteCurrencyQuery(List<ColumnDfn> columns, SaCurrency.Params prm);
public abstract DataValue GetCurrencyDataValue(ColumnDfn column, NamedValue.Map values);
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,34 @@
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
using System;
using System.Collections.Generic;
using System.Text;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=======================================================================
// Reference Data Console - Languages.
//=======================================================================
partial class SaReferenceDataConsole
{
// Properties.
public abstract short LanguageItemType { get; }
public abstract String TableName_Language { get; }
public abstract bool DatabaseIsValid_Language { get; }
// Retrieve Language.
public abstract SaLanguage GetLanguage (SaLanguage.Params prmLanguage);
// Language list.
public abstract ColumnDfn GetLanguageColumnDfn (SaLanguage.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetLanguageQueryFilter (SaLanguage.Params prm);
public abstract long GetLanguageCount (SaLanguage.Params prmLanguage);
public abstract List<SaLanguage> GetLanguageList (SaLanguage.Params prmLanguage);
public abstract DbResultSet ExecuteLanguageQuery (List<ColumnDfn> columns, SaLanguage.Params prm);
public abstract DataValue GetLanguageDataValue (ColumnDfn column, NamedValue.Map values);
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,56 @@
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
using System;
using System.Collections.Generic;
using System.Text;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=======================================================================
// Reference Data Console - Regions.
//=======================================================================
partial class SaReferenceDataConsole
{
// Definitions.
public class RegionInitData
{
public SaRegionType Type { get; set; } = SaRegionType.Unknown;
public String Name { get; set; } = "";
public String CurrencyCode { get; set; } = "";
public SaRegionType ParentType { get; set; } = SaRegionType.Unknown;
public String ParentName { get; set; } = "";
}
// Utilities.
/// <summary>Return the valid parent type for the specified Region type.</summary>
public static SaRegionType ParentTypeFor(SaRegionType regionType)
{
return SaReferenceDataMgr.ParentTypeFor(regionType);
}
/// <summary>Return the valid subordinate Region type for the specified Region type.</summary>
public static SaRegionType SubordinateTypeFor(SaRegionType regionType)
{
return SaReferenceDataMgr.SubordinateTypeFor(regionType);
}
// Properties.
public abstract short RegionItemType { get; }
public abstract String TableName_Region { get; }
public abstract bool DatabaseIsValid_Region { get; }
// Retrieve Region.
public abstract SaRegion GetRegion(SaRegion.Params prmRegion);
// Region list.
public abstract ColumnDfn GetRegionColumnDfn(SaRegion.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetRegionQueryFilter(SaRegion.Params prm);
public abstract long GetRegionCount(SaRegion.Params prmRegion);
public abstract List<SaRegion> GetRegionList(SaRegion.Params prmRegion);
public abstract DbResultSet ExecuteRegionQuery(List<ColumnDfn> columns, SaRegion.Params prm);
public abstract DataValue GetRegionDataValue(ColumnDfn column, NamedValue.Map values);
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,63 @@
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
using System;
using System.Collections.Generic;
using System.Text;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=======================================================================
// Reference Data Console - Tax codes.
//=======================================================================
partial class SaReferenceDataConsole
{
//-------------------------------------------------------------------
// Utilities.
public static String GetStdTaxCode()
{
return GetTaxCode(SaTaxCodeType.Std);
}
public static String GetTaxCode(SaTaxCodeType taxCode)
{
switch (taxCode)
{
case SaTaxCodeType.Zero: return "ZERO";
case SaTaxCodeType.Std: return "STD";
case SaTaxCodeType.Exempt: return "EXEMPT";
}
return "";
}
public static String GetSageTaxCode(SaTaxCodeType taxCode)
{
switch (taxCode)
{
case SaTaxCodeType.Zero: return "T0";
case SaTaxCodeType.Std: return "T1";
case SaTaxCodeType.Exempt: return "T3";
}
return "";
}
//-------------------------------------------------------------------
// Properties.
public abstract short TaxCodeItemType { get; }
public abstract String TableName_TaxCode { get; }
public abstract bool DatabaseIsValid_TaxCode { get; }
//-------------------------------------------------------------------
// Retrieve Tax Code.
public abstract SaTaxCode GetTaxCode(SaTaxCode.Params prmTaxCode);
// Tax Code list.
public abstract ColumnDfn GetTaxCodeColumnDfn(SaTaxCode.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetTaxCodeQueryFilter(SaTaxCode.Params prm);
public abstract long GetTaxCodeCount(SaTaxCode.Params prmTaxCode);
public abstract List<SaTaxCode> GetTaxCodeList(SaTaxCode.Params prmTaxCode);
public abstract DbResultSet ExecuteTaxCodeQuery(List<ColumnDfn> columns, SaTaxCode.Params prm);
public abstract DataValue GetTaxCodeDataValue(ColumnDfn column, NamedValue.Map values);
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,34 @@
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
using System;
using System.Collections.Generic;
using System.Text;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=======================================================================
// Reference Data Console - Units of Measure.
//=======================================================================
partial class SaReferenceDataConsole
{
// Properties.
public abstract short UnitMeasureItemType { get; }
public abstract String TableName_UnitMeasure { get; }
public abstract bool DatabaseIsValid_UnitMeasure { get; }
// Retrieve Unit of Measure.
public abstract SaUnitMeasure GetUnitMeasure (SaUnitMeasure.Params prmUnitMeasure);
// Unit of Measure list.
public abstract ColumnDfn GetUnitMeasureColumnDfn (SaUnitMeasure.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetUnitMeasureQueryFilter (SaUnitMeasure.Params prm);
public abstract long GetUnitMeasureCount (SaUnitMeasure.Params prmUnitMeasure);
public abstract List<SaUnitMeasure> GetUnitMeasureList (SaUnitMeasure.Params prmUnitMeasure);
public abstract DbResultSet ExecuteUnitMeasureQuery (List<ColumnDfn> columns, SaUnitMeasure.Params prm);
public abstract DataValue GetUnitMeasureDataValue (ColumnDfn column, NamedValue.Map values);
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,272 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.UpdateLog;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=====================================================================
// R e f e r e n c e D a t a
//=====================================================================
// Reference data item types.
public enum ReferenceDataItemType
{
Unknown = 0,
Language,
Region,
Currency,
TaxCode,
UnitMeasure,
}
//-------------------------------------------------------------------
// Reference data code types.
public enum ReferenceDataSystemCode
{
RegionType,
CurrencyCode,
TaxCodeType,
TaxCodeColumn,
UnitMeasureCategory,
UnitMeasureType,
}
//-------------------------------------------------------------------
// Region types.
public enum SaRegionType
{
Unknown = 0,
Continent, // 'CON'
Country, // 'COU'
Province, // 'PRO'
Town, // 'TWN'
};
//-------------------------------------------------------------------
// Currency code.
public enum SaCurrencyCode
{
Unknown = 0,
Sterling,
Euro,
};
//-------------------------------------------------------------------
// Tax code - with Sage equivalent.
public enum SaTaxCodeType
{
Zero, // 'T0'
Std, // 'T1'
Exempt, // 'T2' or 'T3'
};
//-------------------------------------------------------------------
// Tax code column.
public enum SaTaxCodeColumn
{
Unknown = 0,
Code = 10,
CodeAlt1,
CodeAlt2,
};
//-------------------------------------------------------------------
// NB Do not change these values - they are tied to the database.
public enum SaUomCategory
{
/// <summary>Allows all UOM categories, eg. in combobox.</summary>
Any = -1,
/// <summary>UOM category is not defined. Allows any in filters, but none in combobox.</summary>
Unknown = 0,
Time = 1,
Pack = 2,
Weight = 3,
Length = 4,
Area = 5,
Volume = 6,
Density = 7,
/// <summary>'BOX' - types of container, eg. box, pallet.</summary>
Box = 8,
};
//-------------------------------------------------------------------
// NB Do not change these values - they are tied to the database.
public enum SaUomType
{
Any = -1,
Unknown = 0,
// Time units.
Time_Second = 100,
Time_Minute = 101,
Time_Hour = 102,
Time_Day = 110,
Time_WorkingDay = 111,
Time_Week = 120,
Time_WorkingWeek = 121,
Time_Fortnight = 122,
Time_Month = 140,
Time_Quarter = 141,
Time_Year = 142,
// Pack units.
Pack_Each = 200,
Pack_Set = 201,
// Weight units.
Weight_Gram = 300,
Weight_Kilogram = 301,
Weight_Tonne = 302,
// Length units.
Length_Metre = 400,
Length_Kilometre = 401,
// Area units.
Length_SquareMetre = 500,
Length_Hectare = 501,
Length_Acre = 590,
// Volume units.
Volume_Litre = 600,
Volume_CubicMetre = 601,
// Density units.
Density_KilogramsPerCubicMetre = 700,
Density_GramsPerCubicCentimeter = 701,
// Box units.
Box_Box = 800,
Box_Carton = 801,
Box_Pallet = 802,
};
//=======================================================================
public abstract partial class SaReferenceDataConsole : SacsDisposableStateItem
{
//-------------------------------------------------------------------
// Definitions.
//-------------------------------------------------------------------
// Data members.
private static List<TypeCodeDesc> regionTypes;
private static List<TypeCodeDesc> currencyCodes;
private static List<TypeCodeDesc> taxCodeTypes;
private static List<TypeCodeDesc> taxCodeColumns;
private static List<TypeCodeDesc> unitMeasureCategories;
private static List<TypeCodeDesc> unitMeasureTypes;
//-------------------------------------------------------------------
// Static initialisation.
static SaReferenceDataConsole()
{
}
//-------------------------------------------------------------------
// Construction.
protected SaReferenceDataConsole()
{
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
}
base.Dispose(disposing);
}
//-------------------------------------------------------------------
// Properties.
public abstract SaUpdateLogConsole UpdateLogConsole { get; }
// Database.
public abstract bool CanUpdateDatabase { get; }
//---------------------------------------------------------------
// Manage reference data - displays dialog.
public abstract bool ManageReferenceData(bool userCanManageReferenceData, DbUpdateInfo dbUpdateInfo);
//---------------------------------------------------------------
// Reference data codes.
public static List<TypeCodeDesc> GetReferenceDataCodes(ReferenceDataSystemCode systemCode)
{
switch (systemCode)
{
case ReferenceDataSystemCode.RegionType:
if (regionTypes == null)
{
regionTypes = new List<TypeCodeDesc>();
regionTypes.Add(SaRegionType.Continent, "CON", "Continent");
regionTypes.Add(SaRegionType.Country, "COU", "Country");
regionTypes.Add(SaRegionType.Province, "PRO", "Province");
regionTypes.Add(SaRegionType.Town, "TWN", "Town");
}
return new List<TypeCodeDesc>(regionTypes);
case ReferenceDataSystemCode.CurrencyCode:
if (currencyCodes == null)
{
currencyCodes = new List<TypeCodeDesc>();
currencyCodes.Add(SaCurrencyCode.Sterling, "GBP", "GBP");
currencyCodes.Add(SaCurrencyCode.Euro, "EUR", "EUR");
}
return new List<TypeCodeDesc>(currencyCodes);
case ReferenceDataSystemCode.TaxCodeType:
if (taxCodeTypes == null)
{
taxCodeTypes = new List<TypeCodeDesc>();
taxCodeTypes.Add(SaTaxCodeType.Zero, "ZERO", "Zero");
taxCodeTypes.Add(SaTaxCodeType.Std, "STD", "Standard");
taxCodeTypes.Add(SaTaxCodeType.Exempt, "EXEMPT", "Exempt");
}
return new List<TypeCodeDesc>(taxCodeTypes);
case ReferenceDataSystemCode.TaxCodeColumn:
if (taxCodeColumns == null)
{
taxCodeColumns = new List<TypeCodeDesc>();
taxCodeColumns.Add(SaTaxCodeColumn.Code, SaReferenceDataDbDfn.GetColumnName(SaReferenceDataDbDfn.ColumnIdx.TaxCode_Code, false), "Tax code");
taxCodeColumns.Add(SaTaxCodeColumn.CodeAlt1, SaReferenceDataDbDfn.GetColumnName(SaReferenceDataDbDfn.ColumnIdx.TaxCode_CodeAlt1, false), "Alt. tax code 1");
taxCodeColumns.Add(SaTaxCodeColumn.CodeAlt2, SaReferenceDataDbDfn.GetColumnName(SaReferenceDataDbDfn.ColumnIdx.TaxCode_CodeAlt2, false), "Alt. tax code 2");
}
return new List<TypeCodeDesc>(taxCodeColumns);
case ReferenceDataSystemCode.UnitMeasureCategory:
if (unitMeasureCategories == null)
{
unitMeasureCategories = new List<TypeCodeDesc>();
unitMeasureCategories.Add(SaUomCategory.Time, "TIM", "Time");
unitMeasureCategories.Add(SaUomCategory.Pack, "PCK", "Pack");
unitMeasureCategories.Add(SaUomCategory.Weight, "WEI", "Weight");
unitMeasureCategories.Add(SaUomCategory.Length, "LEN", "Length");
unitMeasureCategories.Add(SaUomCategory.Area, "ARE", "Area");
unitMeasureCategories.Add(SaUomCategory.Volume, "VOL", "Volume");
unitMeasureCategories.Add(SaUomCategory.Density, "DEN", "Density");
unitMeasureCategories.Add(SaUomCategory.Box, "BOX", "Box (container)");
}
return new List<TypeCodeDesc>(unitMeasureCategories);
case ReferenceDataSystemCode.UnitMeasureType:
if (unitMeasureTypes == null)
{
unitMeasureTypes = new List<TypeCodeDesc>();
unitMeasureTypes.Add(SaUomType.Time_Second, "SEC", "Second");
unitMeasureTypes.Add(SaUomType.Time_Minute, "MIN", "Minute");
unitMeasureTypes.Add(SaUomType.Time_Hour, "HR", "Hour");
unitMeasureTypes.Add(SaUomType.Time_Day, "DAY", "Day");
unitMeasureTypes.Add(SaUomType.Time_WorkingDay, "WDAY", "Working day");
unitMeasureTypes.Add(SaUomType.Time_Week, "WK", "Week");
unitMeasureTypes.Add(SaUomType.Time_WorkingWeek, "WWK", "Working week");
unitMeasureTypes.Add(SaUomType.Time_Fortnight, "FNT", "Fortnight");
unitMeasureTypes.Add(SaUomType.Time_Month, "MTH", "Month");
unitMeasureTypes.Add(SaUomType.Time_Quarter, "QTR", "Quarter");
unitMeasureTypes.Add(SaUomType.Time_Year, "YR", "Year");
unitMeasureTypes.Add(SaUomType.Pack_Each, "EACH", "Each");
unitMeasureTypes.Add(SaUomType.Pack_Set, "SET", "Set");
unitMeasureTypes.Add(SaUomType.Weight_Gram, "GRM", "Gram");
unitMeasureTypes.Add(SaUomType.Weight_Kilogram, "KG", "Kilogram");
unitMeasureTypes.Add(SaUomType.Weight_Tonne, "TON", "Tonne");
unitMeasureTypes.Add(SaUomType.Length_Metre, "METRE", "Metre");
unitMeasureTypes.Add(SaUomType.Length_Kilometre, "KMET", "Kilometre");
unitMeasureTypes.Add(SaUomType.Length_SquareMetre, "SQMET", "Square metre");
unitMeasureTypes.Add(SaUomType.Length_Hectare, "HECT", "Hectare");
unitMeasureTypes.Add(SaUomType.Length_Acre, "ACRE", "Acre");
unitMeasureTypes.Add(SaUomType.Volume_Litre, "LITRE", "Litre");
unitMeasureTypes.Add(SaUomType.Volume_CubicMetre, "CUBMET", "Cubic metre");
unitMeasureTypes.Add(SaUomType.Density_KilogramsPerCubicMetre, "KPCMET", "Kg/m3");
unitMeasureTypes.Add(SaUomType.Density_GramsPerCubicCentimeter, "GPCCMET", "g/cm3");
unitMeasureTypes.Add(SaUomType.Box_Box, "BOX", "Box");
unitMeasureTypes.Add(SaUomType.Box_Carton, "CARTON", "Carton");
unitMeasureTypes.Add(SaUomType.Box_Pallet, "PALLET", "Pallet");
}
return new List<TypeCodeDesc>(unitMeasureTypes);
}
throw new NotSupportedException(typeof(SaReferenceDataConsole).Name + ".GetReferenceDataCodes Invalid code type specified: " + systemCode.ToString());
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,466 @@
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
//---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Thu 3-Oct-2019 15:11:01
//---------------------------------------------------------------------------
namespace Sarand.Net.Standard.Base.ReferenceData
{
public class SaReferenceDataDbDfn
{
//-------------------------------------------------------------------
// Table identifiers.
public enum TableIdx
{
Unknown = 0,
Currency,
Language,
Region,
TaxCode,
UnitMeasure,
}
//-------------------------------------------------------------------
// Column identifiers.
public enum ColumnIdx
{
Unknown = 0,
Currency_Id,
Currency_Code,
Currency_Name,
Currency_Primary,
Currency_Division,
Currency_Region,
Currency_Symbol,
Currency_Suffix,
Currency_IncSpace,
Currency_Decimals,
Currency_CreateOn,
Currency_CreateBy,
Currency_CreateHost,
Currency_UpdateOn,
Currency_UpdateBy,
Currency_UpdateHost,
Language_Id,
Language_Code,
Language_Name,
Language_Primary,
Language_Unicode,
Language_Translation,
Language_CreateOn,
Language_CreateBy,
Language_CreateHost,
Language_UpdateOn,
Language_UpdateBy,
Language_UpdateHost,
Region_Id,
Region_Type,
Region_Name,
Region_Parent,
Region_Notes,
Region_Flags,
Region_Status,
Region_CreateOn,
Region_CreateBy,
Region_CreateHost,
Region_UpdateOn,
Region_UpdateBy,
Region_UpdateHost,
TaxCode_Id,
TaxCode_Code,
TaxCode_CodeAlt1,
TaxCode_CodeAlt2,
TaxCode_Description,
TaxCode_RegionId,
TaxCode_EffectFrom,
TaxCode_EffectTo,
TaxCode_TaxRate,
TaxCode_TaxRatePrev,
TaxCode_TaxCodeIdLink,
TaxCode_Notes,
TaxCode_Flags,
TaxCode_Status,
TaxCode_CreateOn,
TaxCode_CreateBy,
TaxCode_CreateHost,
TaxCode_UpdateOn,
TaxCode_UpdateBy,
TaxCode_UpdateHost,
UnitMeasure_Id,
UnitMeasure_Category,
UnitMeasure_Type,
UnitMeasure_UnitType,
UnitMeasure_Code,
UnitMeasure_Abbr,
UnitMeasure_Single,
UnitMeasure_Multiple,
UnitMeasure_EquValue,
UnitMeasure_UomIdEqu,
UnitMeasure_EquAlgorythm,
UnitMeasure_UomIdRef1,
UnitMeasure_UomIdRef2,
UnitMeasure_UomIdRef3,
UnitMeasure_Notes,
UnitMeasure_Flags,
UnitMeasure_Status,
UnitMeasure_CreateOn,
UnitMeasure_CreateBy,
UnitMeasure_CreateHost,
UnitMeasure_UpdateOn,
UnitMeasure_UpdateBy,
UnitMeasure_UpdateHost,
}
//-------------------------------------------------------------------
// Data members.
private static readonly int tableCount = 5;
private static readonly int columnCount = 84;
private static ulong maxTextLen = 0;
//-------------------------------------------------------------------
// Retrieve Table details (eg. name: 'Company').
public static int GetTableCount ()
{
return tableCount;
}
public static String GetTableName (TableIdx table, bool delimitReservedWords = true)
{
int tableIdx = (int)table - 1;
if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;
String tableName = tables[(int)tableIdx];
if (delimitReservedWords) tableName = DelimitReservedWord(tableName);
return tableName;
}
//-------------------------------------------------------------------
// Identify the table that corresponds with the specified column.
public static TableIdx GetTableForColumn (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return TableIdx.Unknown;
return columns[columnIdx].TableIdx;
}
//-------------------------------------------------------------------
// Retrieve the specified Column's name (Qualified include table name: '(<Table>.Column>)').
public static String GetColumnName (ColumnIdx column, bool delimitReservedWords = true)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return String.Empty;
String columnName = columns[columnIdx].Name;
if (delimitReservedWords) columnName = DelimitReservedWord(columnName);
return columnName;
}
public static String GetColumnNameQual (ColumnIdx column, String tableAlias = "", bool braces = false)
{
String columnName = GetColumnName(column);
if (!String.IsNullOrEmpty(columnName))
{
String tableName = StringUtil.EmptyOnNull(tableAlias);
if (tableName.IsEmpty()) tableName = GetTableName(GetTableForColumn(column));
columnName = tableName + (tableName.Length > 0 ? "." : "") + columnName;
if (braces)
columnName = "(" + columnName + ")";
}
return columnName;
}
//-------------------------------------------------------------------
// Reserved words.
private static DbReservedWordDelim reservedWordDelim = DbReservedWordDelim.SquareBrackets;
public static void SetReservedWordDelim (DbReservedWordDelim reservedWordDelim)
{
SaReferenceDataDbDfn.reservedWordDelim = reservedWordDelim;
}
public static bool IsReservedWord (String word)
{
if (String.IsNullOrEmpty(word)) return false;
if (reservedWords.Contains(word, StringComparer.OrdinalIgnoreCase)) return true;
return false;
}
public static String DelimitReservedWord (String word)
{
if (!IsReservedWord(word)) return word;
switch (reservedWordDelim)
{
case DbReservedWordDelim.None:
break;
case DbReservedWordDelim.DoubleQuotes:
word = "\"" + word + "\"";
break;
case DbReservedWordDelim.SquareBrackets:
default:
word = "[" + word + "]";
break;
}
return word;
}
//-------------------------------------------------------------------
// Retrieve information about the specified Column.
public static DbColumnDataType GetColDataType (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return DbColumnDataType.Unknown;
return columns[columnIdx].DataType;
}
public static short GetColNativeDataType (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return 0;
return columns[columnIdx].NativeDataType;
}
public static void SetMaxTextLen (ulong maxTextLen)
{
SaReferenceDataDbDfn.maxTextLen = maxTextLen;
}
public static bool IsColFmtText (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
return (columns[columnIdx].DataType == DbColumnDataType.VarChar);
}
public static ulong GetColTextLen (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return 0;
if (columns[columnIdx].DataType == DbColumnDataType.VarChar)
{
ulong textLen = columns[columnIdx].DataLen;
if (maxTextLen > 0 && textLen > maxTextLen) textLen = maxTextLen;
return textLen;
}
return 0;
}
public static bool IsColFmtBool (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
return (columns[columnIdx].DataType == DbColumnDataType.Bit);
}
public static bool IsColFmtNumeric (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
switch (columns[columnIdx].DataType)
{
case DbColumnDataType.TinyInt:
case DbColumnDataType.SmallInt:
case DbColumnDataType.Int:
case DbColumnDataType.BigInt:
case DbColumnDataType.Single:
case DbColumnDataType.Double:
case DbColumnDataType.Decimal:
return true;
}
return false;
}
//-------------------------------------------------------------------
// Table definitions.
private static readonly String[] tables =
{
"Currency",
"Language",
"Region",
"TaxCode",
"UnitMeasure",
};
//-------------------------------------------------------------------
// Table column definitions.
internal class ColumnDfn
{
internal TableIdx TableIdx { get; set; }
internal String Name { get; set; }
internal DbColumnDataType DataType { get; set; }
internal short NativeDataType { get; set; }
internal bool IsIdentity { get; set; }
internal ulong DataLen { get; set; }
internal ColumnDfn (int tableIdx, String name, int dataType, short nativeDataType, bool isIdentity, ulong dataLen)
{
this.TableIdx = (TableIdx)tableIdx;
this.Name = name;
this.DataType = (DbColumnDataType)dataType;
this.NativeDataType = nativeDataType;
this.IsIdentity = isIdentity;
this.DataLen = dataLen;
}
}
//-------------------------------------------------------------------
private static readonly ColumnDfn[] columns =
{
new ColumnDfn(1,"Id",4,4,false,10),
new ColumnDfn(1,"Code",0,-9,false,50),
new ColumnDfn(1,"Name",0,-9,false,50),
new ColumnDfn(1,"Primary",4,4,false,10),
new ColumnDfn(1,"Division",0,-9,false,50),
new ColumnDfn(1,"Region",4,4,false,10),
new ColumnDfn(1,"Symbol",0,-9,false,12),
new ColumnDfn(1,"Suffix",1,-7,false,1),
new ColumnDfn(1,"IncSpace",1,-7,false,1),
new ColumnDfn(1,"Decimals",3,5,false,5),
new ColumnDfn(1,"CreateOn",9,93,false,23),
new ColumnDfn(1,"CreateBy",4,4,false,10),
new ColumnDfn(1,"CreateHost",0,-9,false,64),
new ColumnDfn(1,"UpdateOn",9,93,false,23),
new ColumnDfn(1,"UpdateBy",4,4,false,10),
new ColumnDfn(1,"UpdateHost",0,-9,false,64),
new ColumnDfn(2,"Id",4,4,false,10),
new ColumnDfn(2,"Code",0,-9,false,4),
new ColumnDfn(2,"Name",0,-9,false,50),
new ColumnDfn(2,"Primary",4,4,false,10),
new ColumnDfn(2,"Unicode",1,-7,false,1),
new ColumnDfn(2,"Translation",1,-7,false,1),
new ColumnDfn(2,"CreateOn",9,93,false,23),
new ColumnDfn(2,"CreateBy",4,4,false,10),
new ColumnDfn(2,"CreateHost",0,-9,false,64),
new ColumnDfn(2,"UpdateOn",9,93,false,23),
new ColumnDfn(2,"UpdateBy",4,4,false,10),
new ColumnDfn(2,"UpdateHost",0,-9,false,64),
new ColumnDfn(3,"Id",4,4,false,10),
new ColumnDfn(3,"Type",0,-9,false,3),
new ColumnDfn(3,"Name",0,-9,false,50),
new ColumnDfn(3,"Parent",4,4,false,10),
new ColumnDfn(3,"Notes",0,-9,false,255),
new ColumnDfn(3,"Flags",3,5,false,5),
new ColumnDfn(3,"Status",0,-9,false,3),
new ColumnDfn(3,"CreateOn",9,93,false,23),
new ColumnDfn(3,"CreateBy",4,4,false,10),
new ColumnDfn(3,"CreateHost",0,-9,false,64),
new ColumnDfn(3,"UpdateOn",9,93,false,23),
new ColumnDfn(3,"UpdateBy",4,4,false,10),
new ColumnDfn(3,"UpdateHost",0,-9,false,64),
new ColumnDfn(4,"Id",4,4,false,10),
new ColumnDfn(4,"Code",0,-9,false,12),
new ColumnDfn(4,"CodeAlt1",0,-9,false,12),
new ColumnDfn(4,"CodeAlt2",0,-9,false,12),
new ColumnDfn(4,"Description",0,-9,false,50),
new ColumnDfn(4,"RegionId",4,4,false,10),
new ColumnDfn(4,"EffectFrom",9,93,false,23),
new ColumnDfn(4,"EffectTo",9,93,false,23),
new ColumnDfn(4,"TaxRate",7,6,false,53),
new ColumnDfn(4,"TaxRatePrev",7,6,false,53),
new ColumnDfn(4,"TaxCodeIdLink",4,4,false,10),
new ColumnDfn(4,"Notes",0,-9,false,255),
new ColumnDfn(4,"Flags",3,5,false,5),
new ColumnDfn(4,"Status",0,-9,false,3),
new ColumnDfn(4,"CreateOn",9,93,false,23),
new ColumnDfn(4,"CreateBy",4,4,false,10),
new ColumnDfn(4,"CreateHost",0,-9,false,64),
new ColumnDfn(4,"UpdateOn",9,93,false,23),
new ColumnDfn(4,"UpdateBy",4,4,false,10),
new ColumnDfn(4,"UpdateHost",0,-9,false,64),
new ColumnDfn(5,"Id",4,4,false,10),
new ColumnDfn(5,"Category",3,5,false,5),
new ColumnDfn(5,"Type",3,5,false,5),
new ColumnDfn(5,"UnitType",3,5,false,5),
new ColumnDfn(5,"Code",0,-9,false,12),
new ColumnDfn(5,"Abbr",0,-9,false,12),
new ColumnDfn(5,"Single",0,-9,false,50),
new ColumnDfn(5,"Multiple",0,-9,false,50),
new ColumnDfn(5,"EquValue",7,6,false,53),
new ColumnDfn(5,"UomIdEqu",4,4,false,10),
new ColumnDfn(5,"EquAlgorythm",4,4,false,10),
new ColumnDfn(5,"UomIdRef1",4,4,false,10),
new ColumnDfn(5,"UomIdRef2",4,4,false,10),
new ColumnDfn(5,"UomIdRef3",4,4,false,10),
new ColumnDfn(5,"Notes",0,-9,false,255),
new ColumnDfn(5,"Flags",3,5,false,5),
new ColumnDfn(5,"Status",0,-9,false,3),
new ColumnDfn(5,"CreateOn",9,93,false,23),
new ColumnDfn(5,"CreateBy",4,4,false,10),
new ColumnDfn(5,"CreateHost",0,-9,false,64),
new ColumnDfn(5,"UpdateOn",9,93,false,23),
new ColumnDfn(5,"UpdateBy",4,4,false,10),
new ColumnDfn(5,"UpdateHost",0,-9,false,64),
};
//-------------------------------------------------------------------
// Reserved words.
private static readonly HashSet<String> reservedWords = new HashSet<String>()
{
"ADD",
"ALL",
"ALTER",
"AND",
"ANY",
"AS",
"ASC",
"AVG",
"BEGIN",
"BETWEEN",
"BY",
"CASE",
"CAST",
"COLUMN",
"COMMIT",
"CONSTRAINT",
"CONVERT",
"COUNT",
"CREATE",
"CURRENCY",
"DEFAULT",
"DELETE",
"DESC",
"DISTINCT",
"DROP",
"ELSE",
"END",
"EXECUTE",
"EXISTS",
"FALSE",
"FROM",
"GRANT",
"GROUP",
"HAVING",
"IN",
"INDEX",
"INNER",
"INSERT",
"INTO",
"IS",
"JOIN",
"KEY",
"LEFT",
"LIKE",
"MAX",
"MIN",
"NOT",
"NULL",
"ON",
"OR",
"ORDER",
"OUTER",
"OUTPUT",
"PRIMARY",
"PROCEDURE",
"REVOKE",
"ROLLBACK",
"ROWCOUNT",
"SELECT",
"SET",
"SQL",
"SUM",
"TABLE",
"THEN",
"TRANSACTION",
"TRUE",
"UNION",
"UNIQUE",
"UPDATE",
"USER",
"VALUES",
"VIEW",
"WHEN",
"WHERE",
};
//-------------------------------------------------------------------
}
}
@@ -0,0 +1,38 @@
using Sarand.Net.Standard.Base.Bus;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=======================================================================
// Reference Data manager.
//=======================================================================
public abstract partial class SaReferenceDataMgr : SacsItemMgr
{
//-------------------------------------------------------------------
// Data members.
//-------------------------------------------------------------------
// Static initialisation.
static SaReferenceDataMgr()
{
}
//-------------------------------------------------------------------
// Construction.
protected SaReferenceDataMgr()
{
}
//-------------------------------------------------------------------
// Properties.
// Database.
public abstract bool DatabaseIsValid_Language { get; }
public abstract bool DatabaseIsValid_Region { get; }
public abstract bool DatabaseIsValid_Currency { get; }
public abstract bool DatabaseIsValid_TaxCode { get; }
public abstract bool DatabaseIsValid_UnitMeasure { get; }
public abstract bool CanUpdateDatabase { get; }
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,153 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=======================================================================
// Reference Data manager - Currencies.
//=======================================================================
public abstract partial class SaReferenceDataMgr : SacsItemMgr
{
//-------------------------------------------------------------------
// Create currency.
public abstract SaCurrency CreateCurrency();
// Retrieve individual currencies.
public abstract bool CurrencyExistsById(SysId id);
public abstract bool CurrencyExistsByCode(String code);
public abstract SaCurrency GetCurrencyById(SysId id);
public abstract SaCurrency GetCurrencyByCode(String code);
public abstract SaCurrency GetCurrency(SaCurrency.Params prm);
//-------------------------------------------------------------------
// Validate currency data.
public bool IsValidCurrency(SaCurrency currency)
{
ClearErrorState();
if (currency == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidCurrencyData(currency.GetData(), new SaCurrency.ErrField());
}
public virtual bool IsValidCurrencyData(SaCurrency.Data data, SaCurrency.ErrField errField)
{
ClearErrorState();
// Currency properties.
if (errField.Code != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Code, "code", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.Currency_Code), true))
{
errField.Code = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Name != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Name, "name", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.Currency_Name), true))
{
errField.Name = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Division != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Division, "division", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.Currency_Division)))
{
errField.Division = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Symbol != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Symbol, "symbol", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.Currency_Symbol), true))
{
errField.Symbol = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Decimals != SacsHierarchyItem.ValidValue.Ignore && (data.Decimals < 0 || data.Decimals > 4))
{
errField.Decimals = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Currency decimals must be between 0 and 4");
}
// Validate associated data.
if (errField.RegionId != SacsHierarchyItem.ValidValue.Ignore && SysId.IsValid(data.RegionId))
{
if (!RegionExistsById(data.RegionId))
{
errField.RegionId = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Currency's region not found");
}
}
if (errField.CurrencyIdPrimary != SacsHierarchyItem.ValidValue.Ignore && SysId.IsValid(data.CurrencyIdPrimary))
{
if (!CurrencyExistsById(data.CurrencyIdPrimary))
{
errField.CurrencyIdPrimary = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Currency's primary not found");
}
}
return true;
}
//-------------------------------------------------------------------
// Currency database interface.
public abstract bool InsertCurrency(SaCurrency currency, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateCurrency(SaCurrency currency, DbUpdateInfo dbUpdateInfo);
public virtual bool CurrencyCanBeDeleted(SaCurrency currency)
{
ClearErrorState();
if (currency == null) return SetErrorState(ErrorMessage.InvalidStatus);
if (currency.HasDependentCurrencies()) return SetErrorState("Has dependent currencies");
return true;
}
public abstract bool DeleteCurrency(SaCurrency currency, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Currency list.
public abstract ColumnDfn GetCurrencyColumnDfn(SaCurrency.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetCurrencyQueryFilter(SaCurrency.Params prm);
public abstract long GetCurrencyCount(SaCurrency.Params prm);
public abstract List<SaCurrency> GetCurrencyList(SaCurrency.Params prm);
public abstract DbResultSet ExecuteCurrencyQuery(List<ColumnDfn> columns, SaCurrency.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public virtual DataValue GetCurrencyDataValue(ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
/*
switch ((SaCurrency.Column)column.Id)
{
//-----------------------------------------------------------
// Notes.
case SaCurrency.Column.Notes:
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
break;
//-----------------------------------------------------------
// Status.
case SaCurrency.Column.Status_Desc:
case SaCurrency.Column.Status_Ind:
{
String statusCode = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusCode);
if (column.Id == (int)SaCurrency.Column.Status_Desc)
{
String statusDesc = SacsSystem.GetStatusDescForCode(statusCode);
value = new DataValue(statusDesc);
}
else if (column.Id == (int)SaCurrency.Column.Status_Ind)
{
DataValue.TriStateType triState = DataValue.TriStateType.Unknown;
if (status == SaStatus.Active)
triState = DataValue.TriStateType.Green;
else if (status == SaStatus.Inactive)
triState = DataValue.TriStateType.Red;
value = new DataValue(triState);
}
}
break;
//-----------------------------------------------------------
}
*/
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,115 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=======================================================================
// Reference Data manager - Languages.
//=======================================================================
public abstract partial class SaReferenceDataMgr : SacsItemMgr
{
//-------------------------------------------------------------------
// Retrieve individual languages.
public abstract bool LanguageExistsById(SysId id);
public abstract bool LanguageExistsByCode(String code);
public abstract SaLanguage GetLanguageById(SysId id);
public abstract SaLanguage GetLanguageByCode(String code);
public abstract SaLanguage GetLanguage(SaLanguage.Params prm);
// Create language.
public abstract SaLanguage CreateLanguage();
//-------------------------------------------------------------------
// Validate language data.
public bool IsValidLanguage(SaLanguage language)
{
ClearErrorState();
if (language == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidLanguageData(language.GetData(), new SaLanguage.ErrField());
}
public virtual bool IsValidLanguageData(SaLanguage.Data data, SaLanguage.ErrField errField)
{
ClearErrorState();
// Language properties.
if (errField.Code != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Code, "code", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.Language_Code), true))
{
errField.Code = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Name != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Name, "name", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.Language_Name), true))
{
errField.Name = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Unicode != SacsHierarchyItem.ValidValue.Ignore && data.Unicode)
{
errField.Unicode = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Translation != SacsHierarchyItem.ValidValue.Ignore && data.Translation)
{
errField.Translation = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
// Validate associated data.
if (errField.LanguageIdPrimary != SacsHierarchyItem.ValidValue.Ignore && SysId.IsValid(data.LanguageIdPrimary))
{
if (!LanguageExistsById(data.LanguageIdPrimary))
{
errField.LanguageIdPrimary = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Language's parent not found");
}
}
return true;
}
//-------------------------------------------------------------------
// Language database interface.
public abstract bool InsertLanguage(SaLanguage language, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateLanguage(SaLanguage language, DbUpdateInfo dbUpdateInfo);
public virtual bool LanguageCanBeDeleted(SaLanguage language)
{
ClearErrorState();
if (language == null) return SetErrorState(ErrorMessage.InvalidStatus);
if (language.HasDependentLanguages()) return SetErrorState("Has dependent languages");
return true;
}
public abstract bool DeleteLanguage(SaLanguage language, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Language list.
public abstract ColumnDfn GetLanguageColumnDfn(SaLanguage.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetLanguageQueryFilter(SaLanguage.Params prm);
public abstract long GetLanguageCount(SaLanguage.Params prm);
public abstract List<SaLanguage> GetLanguageList(SaLanguage.Params prm);
public abstract DbResultSet ExecuteLanguageQuery(List<ColumnDfn> columns, SaLanguage.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public virtual DataValue GetLanguageDataValue(ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
switch ((SaLanguage.Column)column.Id)
{
//-----------------------------------------------------------
// Default.
default:
break;
//-----------------------------------------------------------
}
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,155 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=======================================================================
// Reference Data manager - Regions.
//=======================================================================
public abstract partial class SaReferenceDataMgr : SacsItemMgr
{
//-------------------------------------------------------------------
// Utilities.
/// <summary>Return the valid parent type for the specified Region type.</summary>
public static SaRegionType ParentTypeFor(SaRegionType regionType)
{
if (regionType == SaRegionType.Country) return SaRegionType.Continent;
if (regionType == SaRegionType.Province) return SaRegionType.Country;
if (regionType == SaRegionType.Town) return SaRegionType.Province;
return SaRegionType.Unknown;
}
/// <summary>Return the valid subordinate Region type for the specified Region type.</summary>
public static SaRegionType SubordinateTypeFor(SaRegionType regionType)
{
if (regionType == SaRegionType.Continent) return SaRegionType.Country;
if (regionType == SaRegionType.Country) return SaRegionType.Province;
if (regionType == SaRegionType.Province) return SaRegionType.Town;
return SaRegionType.Unknown;
}
//-------------------------------------------------------------------
// Retrieve individual regions.
public abstract bool RegionExistsById(SysId id);
public abstract bool RegionExistsByType(String type);
public abstract SaRegion GetRegionById(SysId id);
public abstract SaRegion GetRegionByType(String type);
public abstract SaRegion GetRegion(SaRegion.Params prm);
// Create region.
public abstract SaRegion CreateRegion(SaRegionType regionType);
//-------------------------------------------------------------------
// Validate region data.
public bool IsValidRegion(SaRegion region)
{
ClearErrorState();
if (region == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidRegionData(region.GetData(), new SaRegion.ErrField());
}
public virtual bool IsValidRegionData(SaRegion.Data data, SaRegion.ErrField errField)
{
ClearErrorState();
// Region properties.
if (errField.RegionType != SacsHierarchyItem.ValidValue.Ignore)
{
if ((int)data.RegionType < 1)
{
errField.RegionType = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Region type must be supplied");
}
}
if (errField.Name != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Name, "name", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.Region_Name), true))
{
errField.Name = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
// Common properties.
if (errField.Notes != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Notes, "notes", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.Region_Notes)))
{
errField.Notes = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Status != SacsHierarchyItem.ValidValue.Ignore && !SaRegion.ValidStatuses.Contains(data.Status))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.InvalidStatus);
}
// Validate associated data.
if (errField.RegionIdParent != SacsHierarchyItem.ValidValue.Ignore && SysId.IsValid(data.RegionIdParent))
{
if (!RegionExistsById(data.RegionIdParent))
{
errField.RegionIdParent = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Region's parent not found");
}
}
return true;
}
//-------------------------------------------------------------------
// Region database interface.
public abstract bool InsertRegion(SaRegion region, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateRegion(SaRegion region, DbUpdateInfo dbUpdateInfo);
public virtual bool RegionCanBeDeleted(SaRegion region)
{
ClearErrorState();
if (region == null) return SetErrorState(ErrorMessage.InvalidStatus);
if (region.HasDependentRegions()) return SetErrorState("Has dependent regions");
if (region.HasDependentCurrencies()) return SetErrorState("Has dependent currencies");
if (region.HasDependentTaxCodes()) return SetErrorState("Has dependent tax codes");
return true;
}
public abstract bool DeleteRegion(SaRegion region, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Region list.
public abstract ColumnDfn GetRegionColumnDfn(SaRegion.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetRegionQueryFilter(SaRegion.Params prm);
public abstract long GetRegionCount(SaRegion.Params prm);
public abstract List<SaRegion> GetRegionList(SaRegion.Params prm);
public abstract DbResultSet ExecuteRegionQuery(List<ColumnDfn> columns, SaRegion.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public virtual DataValue GetRegionDataValue(ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
switch ((SaRegion.Column)column.Id)
{
//-----------------------------------------------------------
// Notes.
case SaRegion.Column.Notes:
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
break;
//-----------------------------------------------------------
// Status.
case SaRegion.Column.Status_Desc:
case SaRegion.Column.Status_Ind:
{
String statusCode = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusCode);
if (column.Id == (int)SaRegion.Column.Status_Desc)
value = new DataValue(SacsSystem.GetStatusDescForCode(statusCode));
else if (column.Id == (int)SaRegion.Column.Status_Ind)
value = new DataValue(SaRegion.GetStatusTriState(status));
}
break;
//-----------------------------------------------------------
}
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,179 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=======================================================================
// Reference Data manager - Tax Codes.
//=======================================================================
public abstract partial class SaReferenceDataMgr : SacsItemMgr
{
//-------------------------------------------------------------------
// Utilities.
public String GetTaxCode(SaTaxCodeType taxCode)
{
switch (taxCode)
{
case SaTaxCodeType.Zero: return "T0";
case SaTaxCodeType.Std: return "T1";
case SaTaxCodeType.Exempt: return "T3";
}
return "";
}
//-------------------------------------------------------------------
// Retrieve individual taxCodes.
public abstract bool TaxCodeExistsById(SysId id);
public abstract bool TaxCodeExistsByCode(String code);
public abstract SaTaxCode GetTaxCodeById(SysId id);
public abstract SaTaxCode GetTaxCodeByCode(String code);
public abstract SaTaxCode GetTaxCode(SaTaxCode.Params prm);
// Create taxCode.
public abstract SaTaxCode CreateTaxCode();
//-------------------------------------------------------------------
// Validate taxCode data.
public bool IsValidTaxCode(SaTaxCode taxCode)
{
ClearErrorState();
if (taxCode == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidTaxCodeData(taxCode.GetData(), new SaTaxCode.ErrField());
}
public virtual bool IsValidTaxCodeData(SaTaxCode.Data data, SaTaxCode.ErrField errField)
{
ClearErrorState();
// TaxCode properties.
if (errField.Code != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Code, "code", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.TaxCode_Code), true))
{
errField.Code = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.CodeAlt1 != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.CodeAlt1, "codeAlt1", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.TaxCode_CodeAlt1)))
{
errField.CodeAlt1 = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.CodeAlt2 != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.CodeAlt2, "codeAlt2", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.TaxCode_CodeAlt2)))
{
errField.CodeAlt2 = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Description != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Description, "description", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.TaxCode_Description), true))
{
errField.Description = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.EffectFrom != SacsHierarchyItem.ValidValue.Ignore && errField.EffectTo != SacsHierarchyItem.ValidValue.Ignore && DateUtil.IsValid(data.EffectFrom) && DateUtil.IsValid(data.EffectTo))
{
if (data.EffectFrom.CompareTo(data.EffectTo) > 0)
{
errField.EffectFrom = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Invalid effective date range");
}
}
if (errField.TaxRate != SacsHierarchyItem.ValidValue.Ignore && (short)data.TaxRate < 1)
{
errField.TaxRate = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Tax Rate must be supplied");
}
if (errField.TaxRatePrev != SacsHierarchyItem.ValidValue.Ignore && (short)data.TaxRatePrev < 1)
{
errField.TaxRatePrev = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("previous tax rate must be supplied");
}
// Common properties.
if (errField.Notes != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Notes, "notes", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.TaxCode_Notes)))
{
errField.Notes = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Status != SacsHierarchyItem.ValidValue.Ignore && !SaTaxCode.ValidStatuses.Contains(data.Status))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.InvalidStatus);
}
// Validate associated data.
if (errField.RegionId != SacsHierarchyItem.ValidValue.Ignore && SysId.IsValid(data.RegionId))
{
if (!RegionExistsById(data.RegionId))
{
errField.RegionId = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Tax code's region not found");
}
}
if (errField.TaxCodeIdLink != SacsHierarchyItem.ValidValue.Ignore && SysId.IsValid(data.TaxCodeIdLink))
{
if (!TaxCodeExistsById(data.TaxCodeIdLink))
{
errField.TaxCodeIdLink = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Tax code's parent not found");
}
}
return true;
}
//-------------------------------------------------------------------
// TaxCode database interface.
public abstract bool InsertTaxCode(SaTaxCode taxCode, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateTaxCode(SaTaxCode taxCode, DbUpdateInfo dbUpdateInfo);
public virtual bool TaxCodeCanBeDeleted(SaTaxCode taxCode)
{
ClearErrorState();
if (taxCode.HasDependentTaxCodes()) return SetErrorState("Has dependent tax codes");
return true;
}
public abstract bool DeleteTaxCode(SaTaxCode taxCode, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// TaxCode list.
public abstract ColumnDfn GetTaxCodeColumnDfn(SaTaxCode.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetTaxCodeQueryFilter(SaTaxCode.Params prm);
public abstract long GetTaxCodeCount(SaTaxCode.Params prm);
public abstract List<SaTaxCode> GetTaxCodeList(SaTaxCode.Params prm);
public abstract DbResultSet ExecuteTaxCodeQuery(List<ColumnDfn> columns, SaTaxCode.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public virtual DataValue GetTaxCodeDataValue(ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
switch ((SaTaxCode.Column)column.Id)
{
//-----------------------------------------------------------
// Notes.
case SaTaxCode.Column.Notes:
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
break;
//-----------------------------------------------------------
// Status.
case SaTaxCode.Column.Status_Desc:
case SaTaxCode.Column.Status_Ind:
{
String statusCode = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusCode);
if (column.Id == (int)SaTaxCode.Column.Status_Desc)
value = new DataValue(SacsSystem.GetStatusDescForCode(statusCode));
else if (column.Id == (int)SaTaxCode.Column.Status_Ind)
value = new DataValue(SaTaxCode.GetStatusTriState(status));
}
break;
//-----------------------------------------------------------
}
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,188 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=======================================================================
// Reference Data manager - Units of Measure.
//=======================================================================
public abstract partial class SaReferenceDataMgr : SacsItemMgr
{
//-------------------------------------------------------------------
// Utilities.
//-------------------------------------------------------------------
// Retrieve individual unitMeasures.
public abstract bool UnitMeasureExistsById(SysId id);
public abstract bool UnitMeasureExistsByCode(String code);
public abstract SaUnitMeasure GetUnitMeasureById(SysId id);
public abstract SaUnitMeasure GetUnitMeasureByCode(String code);
public abstract SaUnitMeasure GetUnitMeasure(SaUnitMeasure.Params prm);
// Create unitMeasure.
public abstract SaUnitMeasure CreateUnitMeasure();
//-------------------------------------------------------------------
// Validate unitMeasure data.
public bool IsValidUnitMeasure(SaUnitMeasure unitMeasure)
{
ClearErrorState();
if (unitMeasure == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidUnitMeasureData(unitMeasure.GetData(), new SaUnitMeasure.ErrField());
}
public virtual bool IsValidUnitMeasureData(SaUnitMeasure.Data data, SaUnitMeasure.ErrField errField)
{
ClearErrorState();
// UnitMeasure properties.
if (errField.Category != SacsHierarchyItem.ValidValue.Ignore && (short)data.Category < 1)
{
errField.Category = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.UnitType != SacsHierarchyItem.ValidValue.Ignore && (short)data.UnitType < 1)
{
if ((int)data.UnitType < 1)
{
errField.UnitType = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("UnitMeasure type must be supplied");
}
}
if (errField.Code != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Code, "code", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.UnitMeasure_Code), true))
{
errField.Code = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Abbr != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Abbr, "abbr", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.UnitMeasure_Abbr), true))
{
errField.Abbr = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Single != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Single, "single", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.UnitMeasure_Single), true))
{
errField.Single = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Multiple != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Multiple, "multiple", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.UnitMeasure_Multiple), true))
{
errField.Multiple = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.EquivalencyValue != SacsHierarchyItem.ValidValue.Ignore && data.EquivalencyValue < 1)
{
errField.EquivalencyValue = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("UnitMeasure equal value must be supplied");
}
if (errField.UomIdEquivalency != SacsHierarchyItem.ValidValue.Ignore && data.UomIdEquivalency < 1)
{
errField.UomIdEquivalency = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("UnitMeasure Id equal must be supplied");
}
if (errField.EquivalencyAlgorythm != SacsHierarchyItem.ValidValue.Ignore && data.EquivalencyAlgorythm < 1)
{
errField.EquivalencyAlgorythm = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("UnitMeasure equal algorythm must be supplied");
}
if (errField.UomIdRef1 != SacsHierarchyItem.ValidValue.Ignore && data.UomIdRef1 < 1)
{
errField.UomIdRef1 = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("UnitMeasure reference1 must be supplied");
}
if (errField.UomIdRef2 != SacsHierarchyItem.ValidValue.Ignore && data.UomIdRef2 < 1)
{
errField.UomIdRef2 = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("UnitMeasure reference2 must be supplied");
}
if (errField.UomIdRef3 != SacsHierarchyItem.ValidValue.Ignore && data.UomIdRef3 < 1)
{
errField.UomIdRef3 = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("UnitMeasure reference1 must be supplied");
}
// Common properties.
if (errField.Notes != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Notes, "notes", (long)SaReferenceDataDbDfn.GetColTextLen(SaReferenceDataDbDfn.ColumnIdx.UnitMeasure_Notes)))
{
errField.Notes = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Status != SacsHierarchyItem.ValidValue.Ignore && !SaUnitMeasure.ValidStatuses.Contains(data.Status))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.InvalidStatus);
}
// Validate associated data.
/*
if (errField. != SacsHierarchyItem.ValidValue.Ignore && SysId.IsValid(data.UnitMeasureIdParent))
{
if (!UnitMeasureExistsById(data.UnitMeasureIdParent))
{
errField.UnitMeasureIdParent = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("UnitMeasure's parent not found");
}
}
*/
return true;
}
//-------------------------------------------------------------------
// UnitMeasure database interface.
public abstract bool InsertUnitMeasure(SaUnitMeasure unitMeasure, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateUnitMeasure(SaUnitMeasure unitMeasure, DbUpdateInfo dbUpdateInfo);
public virtual bool UnitMeasureCanBeDeleted(SaUnitMeasure unitMeasure)
{
ClearErrorState();
if (unitMeasure.HasDependentUnitsOfMeasure()) return SetErrorState("Has dependent UOMs");
return true;
}
public abstract bool DeleteUnitMeasure(SaUnitMeasure unitMeasure, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// UnitMeasure list.
public abstract ColumnDfn GetUnitMeasureColumnDfn(SaUnitMeasure.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetUnitMeasureQueryFilter(SaUnitMeasure.Params prm);
public abstract long GetUnitMeasureCount(SaUnitMeasure.Params prm);
public abstract List<SaUnitMeasure> GetUnitMeasureList(SaUnitMeasure.Params prm);
public abstract DbResultSet ExecuteUnitMeasureQuery(List<ColumnDfn> columns, SaUnitMeasure.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public virtual DataValue GetUnitMeasureDataValue(ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
switch ((SaUnitMeasure.Column)column.Id)
{
//-----------------------------------------------------------
// Notes.
case SaUnitMeasure.Column.Notes:
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
break;
//-----------------------------------------------------------
// Status.
case SaUnitMeasure.Column.Status_Desc:
case SaUnitMeasure.Column.Status_Ind:
{
String statusCode = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusCode);
if (column.Id == (int)SaUnitMeasure.Column.Status_Desc)
value = new DataValue(SacsSystem.GetStatusDescForCode(statusCode));
else if (column.Id == (int)SaUnitMeasure.Column.Status_Ind)
value = new DataValue(SaUnitMeasure.GetStatusTriState(status));
}
break;
//-----------------------------------------------------------
}
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,207 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=======================================================================
public abstract class SaRegion : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Hidden,
Pos,
Id,
// Region.
Type,
Name,
Parent,
// Common properties.
Notes,
Status,
Status_Desc,
Status_Ind,
CreateOn_Date,
UpdateOn_Date,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public SaRegionType RegionType { get; set; } = SaRegionType.Unknown;
public String Name { get; set; } = "";
public SysId RegionIdParent { get; set; } = new SysId();
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data ()
{
Status = DefaultStatus;
}
// Properties.
public SaRegionType RegionType
{
get { return data.RegionType; }
set { CheckChanged((int)data.RegionType, (int)value); data.RegionType = value; }
}
public String Name
{
get { return data.Name; }
set { CheckChanged(data.Name, value); data.Name = value; }
}
public SysId RegionIdParent
{
get { return data.RegionIdParent; }
set { CheckChanged(data.RegionIdParent, value); data.RegionIdParent = value; }
}
internal void PopulateFrom(Data data)
{
RegionType = data.RegionType;
Name = data.Name;
RegionIdParent = data.RegionIdParent;
base.PopulateFrom(data);
}
public Data Clone()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue RegionType { get; set; } = ValidValue.Valid;
public ValidValue Name { get; set; } = ValidValue.Valid;
public ValidValue RegionIdParent { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
//-------------------------------------------------------------------
// Construction.
protected SaRegion (SysId id, SaRegionType regionType) : base(id)
{
RegionType = regionType;
Status = DefaultStatus;
base.SetData(data);
}
//-------------------------------------------------------------------
// Statuses.
private static readonly List<SaStatus> validStatuses = new List<SaStatus>()
{
SaStatus.Current
};
public static SaStatus DefaultStatus { get { return SaStatus.Current; } }
public static List<SaStatus> ValidStatuses { get { return new List<SaStatus>(validStatuses); } }
public static DataValue.TriStateType GetStatusTriState (SaStatus status)
{
switch (status)
{
case SaStatus.Current:
return DataValue.TriStateType.Green;
case SaStatus.Redundant:
return DataValue.TriStateType.Red;
case SaStatus.Deleted:
return DataValue.TriStateType.Purple;
}
return DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Utilities.
//-------------------------------------------------------------------
// Data.
public Data GetData() { return data.Clone(); }
public void SetData(Data data)
{
// Properties that cannot be changed if previously specified.
if (SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id))
throw new NotSupportedException($"{SysUtil.Fn} Id cannot be changed");
this.data.PopulateFrom(data);
}
//-------------------------------------------------------------------
// Properties.
public SaRegionType RegionType
{
get { return data.RegionType; }
protected set { data.RegionType = value; }
}
public String Name
{
get { return data.Name; }
set { data.Name = value; }
}
public SysId RegionIdParent
{
get { return data.RegionIdParent; }
set { data.RegionIdParent = value; }
}
//-------------------------------------------------------------------
// A s s o c i a t e d D a t a E l e m e n t s
//-------------------------------------------------------------------
public abstract bool HasDependentRegions ();
public abstract bool HasDependentCurrencies ();
public abstract bool HasDependentTaxCodes ();
//-------------------------------------------------------------------
// P a r a m s
//-------------------------------------------------------------------
// List parameters.
public enum StatusCat
{
Any,
ActiveOnly,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
// List filtering.
public HashSet<SysId> IdsIncluded { get; } = new HashSet<SysId>();
public HashSet<SysId> IdsExcluded { get; } = new HashSet<SysId>();
// Region.
public SaRegionType RegionType { get; set; } = SaRegionType.Unknown;
public String Name { get; set; }
public String NamePartial { get; set; }
public SysId RegionIdParent { get; set; }
public StatusCat StatusCat { get; set; } = StatusCat.Any;
}
//-------------------------------------------------------------------
}
//=======================================================================
// R e g i o n D a t a L i s t
//=======================================================================
public static class SaRegionList
{
/// <summary>Retrieve region with specified Id.</summary>
public static SaRegion FindById (this List<SaRegion> values, SysId measureId)
{
return values.Find(item => item.Id.Equals(measureId));
}
}
//=======================================================================
}
@@ -0,0 +1,347 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Utils;
using System.Text.RegularExpressions;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=======================================================================
public abstract class SaTaxCode : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Hidden,
Pos,
Id,
// TaxCode.
Code,
CodeAlt1,
CodeAlt2,
Description,
RegionId,
EffectFrom,
EffectTo,
TaxRate,
TaxRatePrev,
TaxCodeIdLink,
// Common properties.
Notes,
Status,
Status_Desc,
Status_Ind,
CreateOn_Date,
UpdateOn_Date,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public String Code { get; set; } = "";
public String CodeAlt1 { get; set; } = "";
public String CodeAlt2 { get; set; } = "";
public String Description { get; set; } = "";
public SysId RegionId { get; set; } = new SysId();
public DateTime EffectFrom { get; set; } = DateTime.MinValue;
public DateTime EffectTo { get; set; } = DateTime.MinValue;
public decimal TaxRate { get; set; } = 0.0m;
public decimal TaxRatePrev { get; set; } = 0.0m;
public SysId TaxCodeIdLink { get; set; } = new SysId();
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data()
{
Status = DefaultStatus;
}
// Properties.
public String Code
{
get { return data.Code; }
set { CheckChanged(data.Code, value); data.Code = value; }
}
public String CodeAlt1
{
get { return data.CodeAlt1; }
set { CheckChanged(data.CodeAlt1, value); data.CodeAlt1 = value; }
}
public String CodeAlt2
{
get { return data.CodeAlt2; }
set { CheckChanged(data.CodeAlt2, value); data.CodeAlt2 = value; }
}
public String Description
{
get { return data.Description; }
set { CheckChanged(data.Description, value); data.Description = value; }
}
public SysId RegionId
{
get { return data.RegionId; }
set { CheckChanged(data.RegionId, value); data.RegionId = value; }
}
public DateTime EffectFrom
{
get { return data.EffectFrom; }
set { CheckChanged(data.EffectFrom, value); data.EffectFrom = value; }
}
public DateTime EffectTo
{
get { return data.EffectTo; }
set { CheckChanged(data.EffectTo, value); data.EffectTo = value; }
}
public decimal TaxRate
{
get { return data.TaxRate; }
set { CheckChanged(data.TaxRate, value); data.TaxRate = value; }
}
public decimal TaxRatePrev
{
get { return data.TaxRatePrev; }
set { CheckChanged(data.TaxRatePrev, value); data.TaxRatePrev = value; }
}
public SysId TaxCodeIdLink
{
get { return data.TaxCodeIdLink; }
set { CheckChanged(data.TaxCodeIdLink, value); data.TaxCodeIdLink = value; }
}
internal void PopulateFrom(Data data)
{
Code = data.Code;
CodeAlt1 = data.CodeAlt1;
CodeAlt2 = data.CodeAlt2;
Description = data.Description;
RegionId = data.RegionId;
EffectFrom = data.EffectFrom;
EffectTo = data.EffectTo;
TaxRate = data.TaxRate;
TaxRatePrev = data.TaxRatePrev;
TaxCodeIdLink = data.TaxCodeIdLink;
base.PopulateFrom(data);
}
public Data Clone()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue Code { get; set; } = ValidValue.Valid;
public ValidValue CodeAlt1 { get; set; } = ValidValue.Valid;
public ValidValue CodeAlt2 { get; set; } = ValidValue.Valid;
public ValidValue Description { get; set; } = ValidValue.Valid;
public ValidValue RegionId { get; set; } = ValidValue.Valid;
public ValidValue EffectFrom { get; set; } = ValidValue.Valid;
public ValidValue EffectTo { get; set; } = ValidValue.Valid;
public ValidValue TaxRate { get; set; } = ValidValue.Valid;
public ValidValue TaxRatePrev { get; set; } = ValidValue.Valid;
public ValidValue TaxCodeIdLink { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
//-------------------------------------------------------------------
// Construction.
protected SaTaxCode(SysId id) : base(id)
{
base.SetData(data);
}
//-------------------------------------------------------------------
// Statuses.
private static readonly List<SaStatus> validStatuses = new List<SaStatus>()
{
SaStatus.Current
};
public static SaStatus DefaultStatus { get { return SaStatus.Current; } }
public static List<SaStatus> ValidStatuses { get { return new List<SaStatus>(validStatuses); } }
public static DataValue.TriStateType GetStatusTriState(SaStatus status)
{
switch (status)
{
case SaStatus.Current:
return DataValue.TriStateType.Green;
case SaStatus.Deleted:
return DataValue.TriStateType.Purple;
}
return DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Utilities.
public String GetCaption()
{
DateTime today = DateTime.Today;
String caption = $"{Code} (";
if (!StringUtil.IsBlank(CodeAlt1) && !CodeAlt1.EqualsCI(Code))
caption += $"{CodeAlt1}: ";
caption += $"{Regex.Replace(TaxRate.ToString("N2"), @"\.0+$", "")}%)";
if (DateUtil.IsValid(EffectFrom) || DateUtil.IsValid(EffectTo))
{
String effectiveFrom = (DateUtil.IsValid(EffectFrom) ? (EffectFrom.Year == today.Year ? EffectFrom.ToString("d-MMM") : EffectFrom.ToString("d-MMM-yy")) : "");
String effectiveTo = (DateUtil.IsValid(EffectTo) ? (EffectTo.Year == today.Year ? EffectTo.ToString("d-MMM") : EffectTo.ToString("d-MMM-yy")) : "");
caption += $" [{effectiveFrom}->{effectiveTo}]";
}
return caption;
}
public bool IsEffectiveOn(DateTime effectiveDate)
{
if (DateUtil.IsValid(EffectFrom) && EffectFrom.CompareTo(effectiveDate) > 0) return false;
if (DateUtil.IsValid(EffectTo) && EffectTo.CompareTo(effectiveDate) < 0) return false;
return true;
}
//-------------------------------------------------------------------
// Data.
public Data GetData() { return data.Clone(); }
public void SetData(Data data)
{
// Properties that cannot be changed if previously specified.
if (SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id))
throw new NotSupportedException($"{SysUtil.Fn} Id cannot be changed");
if (!StringUtil.IsEmpty(Code) && !Code.EqualsCI(data.Code))
throw new NotSupportedException($"{SysUtil.Fn} Code cannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
//-------------------------------------------------------------------
// Properties.
public String Code
{
get { return data.Code; }
set { data.Code = value; }
}
public String CodeAlt1
{
get { return data.CodeAlt1; }
set { data.CodeAlt1 = value; }
}
public String CodeAlt2
{
get { return data.CodeAlt2; }
set { data.CodeAlt2 = value; }
}
public String Description
{
get { return data.Description; }
set { data.Description = value; }
}
public SysId RegionId
{
get { return data.RegionId; }
set { data.RegionId = value; }
}
public DateTime EffectFrom
{
get { return data.EffectFrom; }
set { data.EffectFrom = value; }
}
public DateTime EffectTo
{
get { return data.EffectTo; }
set { data.EffectTo = value; }
}
public decimal TaxRate
{
get { return data.TaxRate; }
set { data.TaxRate = value; }
}
public decimal TaxRatePrev
{
get { return data.TaxRatePrev; }
set { data.TaxRatePrev = value; }
}
public SysId TaxCodeIdLink
{
get { return data.TaxCodeIdLink; }
set { data.TaxCodeIdLink = value; }
}
//-------------------------------------------------------------------
// A s s o c i a t e d D a t a E l e m e n t s
//-------------------------------------------------------------------
public abstract bool HasDependentTaxCodes();
//-------------------------------------------------------------------
// P a r a m s
//-------------------------------------------------------------------
// List parameters.
public enum StatusCat
{
Any,
ActiveOnly,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
// List filtering.
public HashSet<SysId> IdsIncluded { get; } = new HashSet<SysId>();
public HashSet<SysId> IdsExcluded { get; } = new HashSet<SysId>();
// Tax Code properties.
public String Code { get; set; }
public String CodePartial { get; set; }
public String CodeAlt1 { get; set; }
public String CodeAlt2 { get; set; }
public SysId RegionId { get; set; }
public DateTime EffectOn { get; set; } = DateTime.MinValue;
public String NotesPartial { get; set; }
public StatusCat StatusCat { get; set; } = StatusCat.Any;
}
//-------------------------------------------------------------------
}
//=======================================================================
// T a x C o d e D a t a L i s t
//=======================================================================
public static class SaTaxCodeList
{
/// <summary>Check whether taxcode exists/locate in list with specified Id.</summary>
public static bool ExistsById(this List<SaTaxCode> values, SysId taxId)
{
if (!SysId.IsValid(taxId)) return false;
return values.Exists(item => item.Id.Equals(taxId));
}
/// <summary>Retrieve tax code with specified Id.</summary>
public static SaTaxCode FindById(this List<SaTaxCode> values, SysId taxId)
{
if (!SysId.IsValid(taxId)) return null;
return values.Find(item => item.Id.Equals(taxId));
}
public static SaTaxCode FindByCode(this List<SaTaxCode> values, String taxCode)
{
if (StringUtil.IsEmpty(taxCode)) return null;
return values.Find(item => item.Code.Equals(taxCode));
}
public static SaTaxCode FindByCodeEffectiveOn(this List<SaTaxCode> values, String taxCode, DateTime effectiveOn)
{
if (StringUtil.IsEmpty(taxCode)) return null;
if (!DateUtil.IsValid(effectiveOn)) return null;
return values.Find(item => item.Code.Equals(taxCode) && item.IsEffectiveOn(effectiveOn));
}
}
//=======================================================================
}
@@ -0,0 +1,355 @@
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.Net.Standard.Base.ReferenceData
{
//=======================================================================
public abstract class SaUnitMeasure : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Hidden,
Pos,
Id,
// Unit of Measure.
Category,
UnitType,
Code,
Abbr,
Single,
Multiple,
EquivalencyValue,
UomIdEquivalency,
EquivalencyAlgorythm,
UomIdRef1,
UomIdRef2,
UomIdRef3,
// Common properties.
Notes,
Status,
Status_Desc,
Status_Ind,
CreateOn_Date,
UpdateOn_Date,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public SaUomCategory Category { get; set; } = SaUomCategory.Unknown;
public SaUomType UnitType { get; set; } = SaUomType.Unknown;
public String Code { get; set; } = "";
public String Abbr { get; set; } = "";
public String Single { get; set; } = "";
public String Multiple { get; set; } = "";
public decimal EquivalencyValue { get; set; } = 0.0m;
public int UomIdEquivalency { get; set; } = 0;
public int EquivalencyAlgorythm { get; set; } = 0;
public int UomIdRef1 { get; set; } = 0;
public int UomIdRef2 { get; set; } = 0;
public int UomIdRef3 { get; set; } = 0;
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data ()
{
Status = DefaultStatus;
}
// Properties.
public SaUomCategory Category
{
get { return data.Category; }
set { CheckChanged((short)data.Category, (short)value); data.Category = value; }
}
public SaUomType UnitType
{
get { return data.UnitType; }
set { CheckChanged((short)data.UnitType, (short)value); data.UnitType = value; }
}
public String Code
{
get { return data.Code; }
set { CheckChanged(data.Code, value); data.Code = value; }
}
public String Abbr
{
get { return data.Abbr; }
set { CheckChanged(data.Abbr, value); data.Abbr = value; }
}
public String Single
{
get { return data.Single; }
set { CheckChanged(data.Single, value); data.Single = value; }
}
public String Multiple
{
get { return data.Multiple; }
set { CheckChanged(data.Multiple, value); data.Multiple = value; }
}
public decimal EquivalencyValue
{
get { return data.EquivalencyValue; }
set { CheckChanged(data.EquivalencyValue, value); data.EquivalencyValue = value; }
}
public int UomIdEquivalency
{
get { return data.UomIdEquivalency; }
set { CheckChanged(data.UomIdEquivalency, value); data.UomIdEquivalency = value; }
}
public int EquivalencyAlgorythm
{
get { return data.EquivalencyAlgorythm; }
set { CheckChanged(data.EquivalencyAlgorythm, value); data.EquivalencyAlgorythm = value; }
}
public int UomIdRef1
{
get { return data.UomIdRef1; }
set { CheckChanged(data.UomIdRef1, value); data.UomIdRef1 = value; }
}
public int UomIdRef2
{
get { return data.UomIdRef2; }
set { CheckChanged(data.UomIdRef2, value); data.UomIdRef2 = value; }
}
public int UomIdRef3
{
get { return data.UomIdRef3; }
set { CheckChanged(data.UomIdRef3, value); data.UomIdRef3 = value; }
}
// Population.
internal void PopulateFrom (Data data)
{
Category = data.Category;
UnitType = data.UnitType;
Code = data.Code;
Abbr = data.Abbr;
Single = data.Single;
Multiple = data.Multiple;
EquivalencyValue = data.EquivalencyValue;
UomIdEquivalency = data.UomIdEquivalency;
EquivalencyAlgorythm = data.EquivalencyAlgorythm;
UomIdRef1 = data.UomIdRef1;
UomIdRef2 = data.UomIdRef2;
UomIdRef3 = data.UomIdRef3;
base.PopulateFrom(data);
}
public Data Clone ()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
// Error field - identify properties with validation error.
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue Category { get; set; } = ValidValue.Valid;
public ValidValue UnitType { get; set; } = ValidValue.Valid;
public ValidValue Code { get; set; } = ValidValue.Valid;
public ValidValue Abbr { get; set; } = ValidValue.Valid;
public ValidValue Single { get; set; } = ValidValue.Valid;
public ValidValue Multiple { get; set; } = ValidValue.Valid;
public ValidValue EquivalencyValue { get; set; } = ValidValue.Valid;
public ValidValue UomIdEquivalency { get; set; } = ValidValue.Valid;
public ValidValue EquivalencyAlgorythm { get; set; } = ValidValue.Valid;
public ValidValue UomIdRef1 { get; set; } = ValidValue.Valid;
public ValidValue UomIdRef2 { get; set; } = ValidValue.Valid;
public ValidValue UomIdRef3 { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
public static readonly Byte Flag_EquivalencyAccurate = 0x01;
public static readonly Byte Flag_CategoryDefault = 0x02;
//-------------------------------------------------------------------
// Construction.
protected SaUnitMeasure (SysId id) : base(id)
{
base.SetData(data);
Status = DefaultStatus;
}
//-------------------------------------------------------------------
// Statuses.
private static readonly List<SaStatus> validStatuses = new List<SaStatus>()
{
SaStatus.Current
};
public static SaStatus DefaultStatus { get { return SaStatus.Current; } }
public static List<SaStatus> ValidStatuses { get { return new List<SaStatus>(validStatuses); } }
public static DataValue.TriStateType GetStatusTriState (SaStatus status)
{
switch (status)
{
case SaStatus.Current:
return DataValue.TriStateType.Green;
case SaStatus.Deleted:
return DataValue.TriStateType.Purple;
}
return DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Utilities.
/// <summary>UOM caption - Multiple label is specified, otherwise Single label.</summary>
public String GetCaption()
{
return StringUtil.OnBlank(Single, Multiple, Abbr, Code);
}
//-------------------------------------------------------------------
// Data.
public Data GetData () { return data.Clone(); }
public void SetData (Data data)
{
// Properties that cannot be changed if previously specified.
if (SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id))
throw new NotSupportedException($"{SysUtil.Fn} Id cannot be changed");
if (!StringUtil.IsEmpty(Code) && !Code.EqualsCI(data.Code))
throw new NotSupportedException($"{SysUtil.Fn} Codecannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
//-------------------------------------------------------------------
// Properties.
public SaUomCategory Category
{
get { return data.Category; }
set { data.Category = value; }
}
public SaUomType UnitType
{
get { return data.UnitType; }
set { data.UnitType = value; }
}
public String Code
{
get { return data.Code; }
set { data.Code = value; }
}
public String Abbr
{
get { return data.Abbr; }
set { data.Abbr = value; }
}
public String Single
{
get { return data.Single; }
set { data.Single = value; }
}
public String Multiple
{
get { return data.Multiple; }
set { data.Multiple = value; }
}
public decimal EquivalencyValue
{
get { return data.EquivalencyValue; }
set { data.EquivalencyValue = value; }
}
public int UomIdEquivalency
{
get { return data.UomIdEquivalency; }
set { data.UomIdEquivalency = value; }
}
public int EquivalencyAlgorythm
{
get { return data.EquivalencyAlgorythm; }
set { data.EquivalencyAlgorythm = value; }
}
public int UomIdRef1
{
get { return data.UomIdRef1; }
set { data.UomIdRef1 = value; }
}
public int UomIdRef2
{
get { return data.UomIdRef2; }
set { data.UomIdRef2 = value; }
}
public int UomIdRef3
{
get { return data.UomIdRef3; }
set { data.UomIdRef3 = value; }
}
//-------------------------------------------------------------------
// Flags.
public bool EquivalencyAccurate
{
get { return GetFlag(Flag_EquivalencyAccurate); }
set { SetFlag(Flag_EquivalencyAccurate, value); }
}
public bool CategoryDefault
{
get { return GetFlag(Flag_CategoryDefault); }
set { SetFlag(Flag_CategoryDefault, value); }
}
//-------------------------------------------------------------------
// A s s o c i a t e d D a t a E l e m e n t s
//-------------------------------------------------------------------
public abstract bool HasDependentUnitsOfMeasure ();
//-------------------------------------------------------------------
// P a r a m s
//-------------------------------------------------------------------
// List parameters.
public enum StatusCat
{
Any,
ActiveOnly,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
// List filtering.
public HashSet<SysId> IdsIncluded { get; } = new HashSet<SysId>();
public HashSet<SysId> IdsExcluded { get; } = new HashSet<SysId>();
// UnitMeasure.
public SaUomCategory Category { get; set; }
public SaUomType UnitType { get; set; }
public String Code { get; set; }
public String CodePartial { get; set; }
public String NotesPartial { get; set; }
public StatusCat StatusCat { get; set; } = StatusCat.Any;
}
//-------------------------------------------------------------------
}
//=======================================================================
// U n i t M e a s u r e D a t a L i s t
//=======================================================================
public static class SaUnitMeasureList
{
/// <summary>Retrieve unit measure with specified Id.</summary>
public static SaUnitMeasure FindById (this List<SaUnitMeasure> values, SysId measureId)
{
return values.Find(item => item.Id.Equals(measureId));
}
}
//=======================================================================
}
@@ -0,0 +1,331 @@
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.UpdateLog;
using System;
using System.Collections.Generic;
namespace Sarand.Net.Standard.Base.Security
{
//=======================================================================
// Definitions.
public class SaSecurity
{
public enum ItemType
{
Any = -1,
Unknown = 0,
// Values are tied to the database - do not change.
User = 1,
Computer = 2,
Group = 3,
Right = 4,
}
// Password storage methods - must be kept up to date with legacy application.
public enum PasswordStorageMethod
{
Legacy = 0,
MsSql = 10,
}
public enum PasswordHashMethod { MsSql }
public enum FilterAttrType
{
Code, // Partial code.
Name, // Partial name.
Group_Include, // Item belongs to group.
Group_Exclude, // Item doesn't belong to group.
};
}
//=======================================================================
public abstract class SaSecurityConsole : SacsDisposableStateItem
{
//-------------------------------------------------------------------
// Definitions.
protected class DataItemDfn
{
public DataItemDfn(short dataItemType, String caption)
{
DataItemType = dataItemType;
Caption = caption;
}
public short DataItemType { get; set; } = -1;
public String Caption { get; set; } = String.Empty;
public List<SysIdString> ItemsAssign { get; } = new List<SysIdString>();
public List<SysIdString> ItemsFull { get; } = new List<SysIdString>();
}
//-------------------------------------------------------------------
// Data members.
public static String GroupCode_Super = "SUPER";
public static String UserCode_Admin = "admin";
private static List<TypeCodeDesc> securityItemTypes = new List<TypeCodeDesc>();
//-------------------------------------------------------------------
// Static initialisation
static SaSecurityConsole()
{
// Security item types.
securityItemTypes.Add(SaSecurity.ItemType.User, "USER", "User");
securityItemTypes.Add(SaSecurity.ItemType.Computer, "COMP", "Computer");
securityItemTypes.Add(SaSecurity.ItemType.Group, "SGRP", "Group");
securityItemTypes.Add(SaSecurity.ItemType.Right, "SRGT", "Right");
}
//-------------------------------------------------------------------
// Protected construction - use derived classes.
protected SaSecurityConsole()
{
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
}
base.Dispose(disposing);
}
//-------------------------------------------------------------------
// Properties.
public bool LogSecurityProfile { get; set; } = false;
public abstract short SecurityItemDataType { get; }
public abstract short SecurityLinkDataType { get; }
public abstract SaUpdateLogConsole UpdateLogConsole { get; }
public static List<TypeCodeDesc> SecurityItemTypes { get { return new List<TypeCodeDesc>(securityItemTypes); } }
#if DEBUG
// Login dialog has a 'Require debug login' option.
public bool RequireDebugLogin { get; protected set; } = true;
#endif
protected List<SaSecurityRight> RegisteredRights { get; } = new List<SaSecurityRight>();
protected Dictionary<short, DataItemDfn> DataItemDfns { get; } = new Dictionary<short, DataItemDfn>();
//-------------------------------------------------------------------
// Database properties.
public abstract bool DatabaseIsValid { get; }
public abstract bool CanUpdateDatabase { get; }
public abstract bool ColumnExists(SaSecurityDbDfn.ColumnIdx columnIdx);
//-------------------------------------------------------------------
// U t i l i t i e s
//-------------------------------------------------------------------
// Default user Id.
private SysId userIdDefault = new SysId();
public SysId GetUserIdDefault()
{
return userIdDefault;
}
protected void ClearRegisteredSecurityRights()
{
RegisteredRights.Clear();
DataItemDfns.Clear();
}
//-------------------------------------------------------------------
// L o g i n
//-------------------------------------------------------------------
/// <summary>User login.</summary>
public abstract bool LoginUser(SysId userId, bool recordLastLogin = true);
/// <summary>Using current windows user account.</summary>
public abstract bool LoginAuthenticatedUser();
protected abstract bool OnLogin(SysId userId);
/// <summary>Logout - Clear user and security details.</summary>
public abstract bool LogoutUser();
protected abstract void OnLogout();
//-------------------------------------------------------------------
// A p p l i c a t i o n I n t e r f a c e
//-------------------------------------------------------------------
/// <summary>Show Login form.</summary>
public abstract bool ManageSecurity(bool userCanManageSecurity, DbUpdateInfo dbUpdateInfo);
/// <summary>Show Security maintenance form.</summary>
public abstract bool ShowUserLoginForm(DbUpdateInfo dbUpdateInfo);
/// <summary>User modified event.</summary>
public abstract bool OnUserModified(SysId userId);
/// <summary>Security Group modified event.</summary>
public abstract bool OnSecurityGroupModified(SysId userId);
//-------------------------------------------------------------------
// Password utilities.
//-------------------------------------------------------------------
// Password configuration.
public class SaPasswordConfig
{
/// <summary>Minimum password length. < 1 = no limit.</summary>
public int MinimumLength { get; protected set; } = 6;
/// <summary>Maximum password length. < 1 = no limit.</summary>
public int MaximumLength { get; protected set; } = 6;
}
public SaPasswordConfig PasswordConfig { get; protected set; } = new SaPasswordConfig();
/// <summary>Store the password against against the user.</summary>
public abstract bool SetPassword(SaSecurityItem securityItemUser, String password);
/// <summary>Is the password currently defined against the user blank.</summary>
public abstract bool PasswordIsBlank(SaSecurityItem securityItemUser);
/// <summary>Does the password match that currently defined against the user.</summary>
public abstract bool PasswordMatches(SaSecurityItem securityItemUser, String password, DbUpdateInfo dbUpdateInfo);
/// <summary>Generate password hash using the specified method.</summary>
public abstract String EncodePassword_Hex(String password, SaSecurity.PasswordHashMethod method = SaSecurity.PasswordHashMethod.MsSql);
/// <summary>Compare password to hashed value using the specified method.</summary>
public abstract bool ComparePassword_Hex(String password, String passwordHashHex, SaSecurity.PasswordHashMethod method = SaSecurity.PasswordHashMethod.MsSql);
/// <summary>Show form to change password for currently logged in user.</summary>
/// <returns>Flag to indicate password changed</returns>
public abstract bool ShowChangePasswordForm(DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// A p p l i c a t i o n S e c u r i t y R i g h t s
//-------------------------------------------------------------------
// Register Security Rights.
public abstract void RegisterSecurityRights();
//-------------------------------------------------------------------
// Security rights are optionally associated with a specified data item type (>0),
// in which case they are always associated with a specific item Id of that type.
public bool RegisterSecurityRight(int type, String code, String desc, short dataItemType = 0)
{
RegisteredRights.Add(type, code, desc, dataItemType);
return true;
}
public List<SaSecurityRight> GetRegisteredRights()
{
return new List<SaSecurityRight>(RegisteredRights);
}
// Replace previous rights.
public bool RegisterSecurityRights(List<SaSecurityRight> securityRights)
{
RegisteredRights.Clear();
RegisteredRights.AddRange(securityRights);
return true;
}
// Determine whether any security items are present and allow them to be populated.
public abstract bool RequiresPopulation();
public abstract bool PopulateSecurityRights(DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// A p p l i c a t i o n D a t a I t e m s
//-------------------------------------------------------------------
// Application data items - as referenced by assigned security rights (where relevant).
// Items assign: Register the list of application data items of a particular type that can be associated with security rights.
// Items full: If specified, only data items in the 'assign' list can be associated with security items and existing security
// items that reference data items in the 'full' list but not in the 'assign' list cannot be modified.
public bool RegisterDataItemType(short dataItemType, String caption, List<SysIdString> itemsAssign = null, List<SysIdString> itemsFull = null)
{
DataItemDfn dataItemDfn = new DataItemDfn(dataItemType, caption);
if (itemsAssign != null)
dataItemDfn.ItemsAssign.AddRange(itemsAssign);
if (itemsFull != null)
dataItemDfn.ItemsFull.AddRange(itemsFull);
DataItemDfns.Add(dataItemType, dataItemDfn);
return true;
}
// Modify list of data item associated with specified type.
public bool RegisterDataItems(short dataItemType, List<SysIdString> itemsAssign, List<SysIdString> itemsFull = null)
{
if (!DataItemDfns.ContainsKey(dataItemType)) return false;
DataItemDfn dataItemDfn = DataItemDfns[dataItemType];
// Clear and repopulate assignable items.
dataItemDfn.ItemsAssign.Clear();
if (itemsAssign != null)
dataItemDfn.ItemsAssign.AddRange(itemsAssign);
// Clear and populate full list of items.
dataItemDfn.ItemsFull.Clear();
if (itemsFull != null)
dataItemDfn.ItemsFull.AddRange(itemsFull);
return true;
}
//-------------------------------------------------------------------
// U s e r S e c u r i t y P r o f i l e
//-------------------------------------------------------------------
/// <summary>Retrieve security profile for host computer</summary>
public abstract SaSecurityProfile GetHostSecurityProfile();
/// <summary>Retrieve security profile for specified user</summary>
public abstract SaSecurityProfile GetUserSecurityProfile(SysId userId);
/// <summary>Internal only - creat securitu profile.</summary>
protected SaSecurityProfile CreateSecurityProfile(SaSecurityItem secItem, List<SaSecurityProfile.GroupData> profileGroups, List<SaSecurityProfile.RightData> profileRights, bool systemAdmin)
{
return new SaSecurityProfile(secItem, profileGroups, profileRights, systemAdmin);
}
/*
// The security profile applies right by user and then host computer (if not defined by user).
public bool IsSecurityRightGranted (String rightCode, SysId dataItemId = null)
{
#if DEBUG
if (!RequireDebugLogin) return true;
#endif
if (UserSecurityProfile.IsSecurityRightGranted(rightCode, dataItemId)) return true;
if (HostSecurityProfile.IsSecurityRightGranted(rightCode, dataItemId)) return true;
return false;
}
public bool IsSecurityRightDenied (String rightCode, SysId dataItemId = null)
{
#if DEBUG
if (!RequireDebugLogin) return false;
#endif
if (UserSecurityProfile.IsSecurityRightDenied(rightCode, dataItemId)) return true;
if (HostSecurityProfile.IsSecurityRightDenied(rightCode, dataItemId)) return true;
return false;
}
// Retrieve the list of data items for which the user is explicitly granted the
// specified security right, or where the right is explicitly denied if the flag is false.
// NB If both lists are empty, assume that user is granted the right to all data items.
public List<SysId> GetDataItemsForRight (String rightCode, bool granted = true)
{
List<SysId> dataItemIds = UserSecurityProfile.GetDataItemsForRight (rightCode, granted);
dataItemIds.AddIds(HostSecurityProfile.GetDataItemsForRight(rightCode, granted));
return dataItemIds;
}
*/
//-------------------------------------------------------------------
// S e c u r i t y I t e m s
//-------------------------------------------------------------------
// Security items (user, computer, group or right).
public bool SecurityItemCodeExists(SaSecurity.ItemType securityItemType, String userCode)
{
return SysId.IsValid(GetIdForItemCode(securityItemType, userCode));
}
public SaSecurityItem GetUserByCode(String code)
{
return GetSecurityItemByCode(SaSecurity.ItemType.User, code);
}
public abstract SaSecurityItem GetUserByEmail(String emailAddress);
public abstract SaSecurityItem GetSecurityItemById(SaSecurity.ItemType securityItemType, SysId id);
public abstract SaSecurityItem GetSecurityItemByCode(SaSecurity.ItemType securityItemType, String code);
public abstract SaSecurityItem GetSecurityItem(SaSecurityItem.Params prm);
// Security item properties.
public abstract SysId GetIdForItemCode(SaSecurity.ItemType securityItemType, string code);
public abstract String GetCodeForItemId(SysId securityItemId);
public abstract String GetNameForItemId(SysId securityItemId);
public abstract Dictionary<SysId, String> GetSecurityItemDescriptions(List<SysId> securityItemIds);
// Security Item list.
public abstract ColumnDfn GetSecurityItemColumnDfn(SaSecurityItem.Column columnId, String caption = "", int width = 0);
public abstract long GetSecurityItemCount(SaSecurityItem.Params prm);
public abstract List<SaSecurityItem> GetSecurityItemList(SaSecurityItem.Params prm);
public abstract DbResultSet ExecuteSecurityItemQuery(List<ColumnDfn> columns, SaSecurityItem.Params prm);
public abstract DataValue GetSecurityItemDataValue(ColumnDfn column, NamedValue.Map values);
//-------------------------------------------------------------------
// Security item updates.
public abstract bool CreateUser(String code, String name, DbUpdateInfo dbUpdateInfo);
public abstract bool CreateGroup(String code, String name, DbUpdateInfo dbUpdateInfo);
public abstract bool AssignUserToGroup(String userCode, String groupCode, DbUpdateInfo dbUpdateInfo);
public abstract bool AssignRightToGroup(String rightCode, String groupCode, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateSecurityItem(SaSecurityItem securityItem, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// S e c u r i t y I t e m s L i n k s
//-------------------------------------------------------------------
// Security item links.
public abstract bool ItemsAreLinked(SysId securityItemId1, SysId securityItemId2);
//-------------------------------------------------------------------
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,401 @@
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
//---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Thu 30-Oct-2025 11:28:12
//---------------------------------------------------------------------------
namespace Sarand.Net.Standard.Base.Security
{
public class SaSecurityDbDfn
{
//-------------------------------------------------------------------
// Table identifiers.
public enum TableIdx
{
Unknown = 0,
SaSecItem,
SaSecLink,
}
//-------------------------------------------------------------------
// Column identifiers.
public enum ColumnIdx
{
Unknown = 0,
SaSecItem_Id,
SaSecItem_Code,
SaSecItem_Description,
SaSecItem_Type,
SaSecItem_EmailAddress,
SaSecItem_Location,
SaSecItem_DataItemType,
SaSecItem_EncPword,
SaSecItem_PwordSalt,
SaSecItem_PwordHash,
SaSecItem_PasswordToken,
SaSecItem_PasswordHistory,
SaSecItem_PasswordChangedAt,
SaSecItem_LastLogin,
SaSecItem_LastInvalidLoginAt,
SaSecItem_InvalidLoginCount,
SaSecItem_Notes,
SaSecItem_Flags,
SaSecItem_Status,
SaSecItem_CreateOn,
SaSecItem_CreateBy,
SaSecItem_CreateHost,
SaSecItem_UpdateOn,
SaSecItem_UpdateBy,
SaSecItem_UpdateHost,
SaSecLink_ItemOwner,
SaSecLink_ItemTarget,
SaSecLink_ItemContext,
SaSecLink_DayApplic,
SaSecLink_DateApplicFrom,
SaSecLink_DateApplicTo,
SaSecLink_Flags,
SaSecLink_Status,
SaSecLink_CreateOn,
SaSecLink_CreateBy,
SaSecLink_CreateHost,
SaSecLink_UpdateOn,
SaSecLink_UpdateBy,
SaSecLink_UpdateHost,
}
//-------------------------------------------------------------------
// Data members.
private static readonly int tableCount = 2;
private static readonly int columnCount = 39;
public static ulong MaxTextLen { get; private set; }
//-------------------------------------------------------------------
// Retrieve Table details.
public static int GetTableCount ()
{
return tableCount;
}
public static String GetSchemaName (TableIdx table, bool delimitReservedWords = true)
{
int tableIdx = (int)table - 1;
if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;
String schemaName = tables[(int)tableIdx].Schema;
if (delimitReservedWords) { schemaName = DelimitReservedWord(schemaName); }
return schemaName;
}
public static String GetTableName (TableIdx table, bool delimitReservedWords = true)
{
int tableIdx = (int)table - 1;
if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;
String tableName = tables[(int)tableIdx].Name;
if (delimitReservedWords) tableName = DelimitReservedWord(tableName);
return tableName;
}
public static String GetTableNameQual (TableIdx table, bool delimitReservedWords = true)
{
int tableIdx = (int)table - 1;
if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;
String schemaName = tables[(int)tableIdx].Schema;
String tableName = tables[(int)tableIdx].Name;
if (delimitReservedWords) { schemaName = DelimitReservedWord(schemaName); tableName = DelimitReservedWord(tableName); }
return (StringUtil.IsBlank(schemaName) ? "" : schemaName + ".") + tableName;
}
//-------------------------------------------------------------------
// Identify the table that corresponds with the specified column.
public static TableIdx GetTableForColumn (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return TableIdx.Unknown;
return columns[columnIdx].TableIdx;
}
//-------------------------------------------------------------------
// Retrieve the specified Column's name (Qualified include table name: '(<Table>.Column>)').
public static String GetColumnName (ColumnIdx column, bool delimitReservedWords = true)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return String.Empty;
String columnName = columns[columnIdx].Name;
if (delimitReservedWords) columnName = DelimitReservedWord(columnName);
return columnName;
}
public static String GetColumnNameQual (ColumnIdx column, String tableAlias = "", bool braces = false)
{
String columnName = GetColumnName(column);
if (!String.IsNullOrEmpty(columnName))
{
String tableName = StringUtil.EmptyOnNull(tableAlias);
if (tableName.IsEmpty()) tableName = GetTableName(GetTableForColumn(column));
columnName = tableName + (tableName.Length > 0 ? "." : "") + columnName;
if (braces) columnName = $"({columnName})";
}
return columnName;
}
//-------------------------------------------------------------------
// Reserved words.
private static DbReservedWordDelim reservedWordDelim = DbReservedWordDelim.SquareBrackets;
public static void SetReservedWordDelim (DbReservedWordDelim reservedWordDelim)
{
SaSecurityDbDfn.reservedWordDelim = reservedWordDelim;
}
public static bool IsReservedWord (String word)
{
if (String.IsNullOrEmpty(word)) return false;
if (reservedWords.Contains(word, StringComparer.OrdinalIgnoreCase)) return true;
return false;
}
public static String DelimitReservedWord (String word)
{
return IsReservedWord(word) ? DelimitWord(word) : word;
}
public static String DelimitWord (String word)
{
return DelimitWord(word, reservedWordDelim);
}
public static String DelimitWord (String word, DbReservedWordDelim wordDelim)
{
switch (wordDelim)
{
case DbReservedWordDelim.None:
break;
case DbReservedWordDelim.DoubleQuotes:
word = $"\"{word}\"";
break;
case DbReservedWordDelim.SquareBrackets:
default:
word = $"[{word}]";
break;
}
return word;
}
//-------------------------------------------------------------------
// Retrieve information about the specified Column.
public static DbColumnDataType GetColDataType (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return DbColumnDataType.Unknown;
return columns[columnIdx].DataType;
}
public static short GetColNativeDataType (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return 0;
return columns[columnIdx].NativeDataType;
}
public static void SetMaxTextLen (ulong maxTextLen)
{
SaSecurityDbDfn.MaxTextLen = maxTextLen;
}
public static bool IsColFmtText (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
return (columns[columnIdx].DataType == DbColumnDataType.VarChar);
}
public static ulong GetColTextLen (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return 0;
if (columns[columnIdx].DataType == DbColumnDataType.VarChar)
{
ulong textLen = columns[columnIdx].DataLen;
if (MaxTextLen > 0 && textLen > MaxTextLen) textLen = MaxTextLen;
return textLen;
}
return 0;
}
public static bool IsColFmtBool (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
return (columns[columnIdx].DataType == DbColumnDataType.Bit);
}
public static bool IsColFmtNumeric (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
switch (columns[columnIdx].DataType)
{
case DbColumnDataType.TinyInt:
case DbColumnDataType.SmallInt:
case DbColumnDataType.Int:
case DbColumnDataType.BigInt:
case DbColumnDataType.Single:
case DbColumnDataType.Double:
case DbColumnDataType.Decimal:
return true;
}
return false;
}
//-------------------------------------------------------------------
// Table definitions.
private class TableDfn
{
internal String Schema { get; set; }
internal String Name { get; set; }
internal TableDfn (String schema, String name)
{
this.Schema= schema;
this.Name = name;
}
}
private static readonly TableDfn[] tables =
{
new TableDfn("dbo","SaSecItem"),
new TableDfn("dbo","SaSecLink"),
};
//-------------------------------------------------------------------
// Table column definitions.
private class ColumnDfn
{
internal TableIdx TableIdx { get; set; }
internal String Name { get; set; }
internal DbColumnDataType DataType { get; set; }
internal short NativeDataType { get; set; }
internal bool IsIdentity { get; set; }
internal ulong DataLen { get; set; }
internal ColumnDfn (int tableIdx, String name, int dataType, short nativeDataType, bool isIdentity, ulong dataLen)
{
this.TableIdx = (TableIdx)tableIdx;
this.Name = name;
this.DataType = (DbColumnDataType)dataType;
this.NativeDataType = nativeDataType;
this.IsIdentity = isIdentity;
this.DataLen = dataLen;
}
}
private static readonly ColumnDfn[] columns =
{
new ColumnDfn(1,"Id",4,4,false,10),
new ColumnDfn(1,"Code",0,-9,false,128),
new ColumnDfn(1,"Description",0,-9,false,100),
new ColumnDfn(1,"Type",2,-6,false,3),
new ColumnDfn(1,"EmailAddress",0,-9,false,128),
new ColumnDfn(1,"Location",0,-9,false,50),
new ColumnDfn(1,"DataItemType",3,5,false,5),
new ColumnDfn(1,"EncPword",0,-9,false,128),
new ColumnDfn(1,"PwordSalt",0,-9,false,16),
new ColumnDfn(1,"PwordHash",0,-9,false,200),
new ColumnDfn(1,"PasswordToken",0,12,false,32),
new ColumnDfn(1,"PasswordHistory",0,-9,false,0),
new ColumnDfn(1,"PasswordChangedAt",9,93,false,16),
new ColumnDfn(1,"LastLogin",9,93,false,23),
new ColumnDfn(1,"LastInvalidLoginAt",9,93,false,16),
new ColumnDfn(1,"InvalidLoginCount",3,5,false,5),
new ColumnDfn(1,"Notes",0,-9,false,255),
new ColumnDfn(1,"Flags",3,5,false,5),
new ColumnDfn(1,"Status",0,12,false,3),
new ColumnDfn(1,"CreateOn",9,93,false,23),
new ColumnDfn(1,"CreateBy",4,4,false,10),
new ColumnDfn(1,"CreateHost",0,12,false,64),
new ColumnDfn(1,"UpdateOn",9,93,false,23),
new ColumnDfn(1,"UpdateBy",4,4,false,10),
new ColumnDfn(1,"UpdateHost",0,12,false,64),
new ColumnDfn(2,"ItemOwner",4,4,false,10),
new ColumnDfn(2,"ItemTarget",4,4,false,10),
new ColumnDfn(2,"ItemContext",4,4,false,10),
new ColumnDfn(2,"DayApplic",0,-9,false,50),
new ColumnDfn(2,"DateApplicFrom",4,4,false,10),
new ColumnDfn(2,"DateApplicTo",4,4,false,10),
new ColumnDfn(2,"Flags",3,5,false,5),
new ColumnDfn(2,"Status",0,-9,false,3),
new ColumnDfn(2,"CreateOn",9,93,false,23),
new ColumnDfn(2,"CreateBy",4,4,false,10),
new ColumnDfn(2,"CreateHost",0,-9,false,64),
new ColumnDfn(2,"UpdateOn",9,93,false,23),
new ColumnDfn(2,"UpdateBy",4,4,false,10),
new ColumnDfn(2,"UpdateHost",0,-9,false,64),
};
//-------------------------------------------------------------------
// Reserved words.
private static readonly HashSet<String> reservedWords = new HashSet<String>()
{
"ADD",
"ALL",
"ALTER",
"AND",
"ANY",
"AS",
"ASC",
"AVG",
"BEGIN",
"BETWEEN",
"BY",
"CASE",
"CAST",
"COLUMN",
"COMMIT",
"CONSTRAINT",
"CONVERT",
"COUNT",
"CREATE",
"CURRENCY",
"DEFAULT",
"DELETE",
"DESC",
"DISTINCT",
"DROP",
"ELSE",
"END",
"EXECUTE",
"EXISTS",
"FALSE",
"FROM",
"GRANT",
"GROUP",
"HAVING",
"IN",
"INDEX",
"INNER",
"INSERT",
"INTO",
"IS",
"JOIN",
"KEY",
"LEFT",
"LIKE",
"MAX",
"MIN",
"NOT",
"NULL",
"ON",
"OR",
"ORDER",
"OUTER",
"OUTPUT",
"PRIMARY",
"PROCEDURE",
"REVOKE",
"ROLLBACK",
"ROWCOUNT",
"SELECT",
"SET",
"SQL",
"SUM",
"TABLE",
"THEN",
"TRANSACTION",
"TRUE",
"UNION",
"UNIQUE",
"UPDATE",
"USER",
"VALUES",
"VIEW",
"WHEN",
"WHERE"
};
//-------------------------------------------------------------------
}
}
@@ -0,0 +1,441 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Base.Security
{
//=======================================================================
public abstract class SaSecurityItem : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Definitions.
// Password Salt constants - must be kept up to date with legacy application.
private static String PasswordSalt_MsSql = "MsSql";
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Pos = 0,
Id,
ItemType,
ItemType_Desc,
Code,
EmailAddress,
Description,
Location,
LastLogin_Date,
OwnerLinkCount,
TargetLinkCount,
TargetLinkCount_Groups,
OwnerLinkCount_Rights,
Notes,
Status,
Status_Desc,
Status_Ind,
CreateOn_Date,
UpdateOn_Date,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public SaSecurity.ItemType ItemType { get; set; } = SaSecurity.ItemType.Unknown;
public String Code { get; set; } = String.Empty;
public String EmailAddress { get; set; } = String.Empty;
public String Description { get; set; } = String.Empty;
public String Location { get; set; } = String.Empty;
public int DataItemType { get; set; } = -1;
// Security.
public String PasswordEncrypted { get; set; } = String.Empty;
public String PasswordSalt { get; set; } = String.Empty;
public String PasswordHash { get; set; } = String.Empty;
public List<String> PasswordHistory { get; } = new List<string>();
public String PasswordToken { get; set; } = String.Empty;
public DateTime? PasswordChangedAt { get; set; } = DateTime.MinValue;
// Login.
public DateTime? LastLogin { get; set; } = DateTime.MinValue;
public DateTime? LastInvalidLoginAt { get; set; } = DateTime.MinValue;
public short InvalidLoginCount { get; set; }
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data()
{
Status = DefaultStatus;
}
// Properties.
public SaSecurity.ItemType ItemType
{
get { return data.ItemType; }
set { CheckChanged((int)data.ItemType, (int)value); data.ItemType = value; }
}
public String Code
{
get { return data.Code; }
set { CheckChanged(data.Code, value); data.Code = value; }
}
public String EmailAddress
{
get { return data.EmailAddress; }
set { CheckChanged(data.EmailAddress, value); data.EmailAddress = value; }
}
public String Description
{
get { return data.Description; }
set { CheckChanged(data.Description, value); data.Description = value; }
}
public String Location
{
get { return data.Location; }
set { CheckChanged(data.Location, value); data.Location = value; }
}
public int DataItemType
{
get { return data.DataItemType; }
set { CheckChanged(data.DataItemType, value); data.DataItemType = value; }
}
// Security.
public String PasswordEncrypted
{
get { return data.PasswordEncrypted; }
set { CheckChanged(data.PasswordEncrypted, value); data.PasswordEncrypted = value; }
}
public String PasswordSalt
{
get { return data.PasswordSalt; }
set { CheckChanged(data.PasswordSalt, value); data.PasswordSalt = value; }
}
public String PasswordHash
{
get { return data.PasswordHash; }
set { CheckChanged(data.PasswordHash, value); data.PasswordHash = value; }
}
public List<String> PasswordHistory
{
get { return data.PasswordHistory; }
set
{
CheckChanged(data.PasswordHistory, value);
data.PasswordHistory.Clear();
data.PasswordHistory.AddRange((value ?? new List<String>()).FindAll(item => !StringUtil.IsEmpty(StringUtil.TrimAll(item))));
}
}
public String PasswordToken
{
get { return data.PasswordToken; }
set { CheckChanged(data.PasswordToken, value); data.PasswordToken = value; }
}
public DateTime? PasswordChangedAt
{
get { return data.PasswordChangedAt; }
set { CheckChangedNullable(data.PasswordChangedAt, value); data.PasswordChangedAt = value; }
}
// Login.
public DateTime? LastLogin
{
get { return data.LastLogin; }
set { CheckChangedNullable(data.LastLogin, value); data.LastLogin = value; }
}
public DateTime? LastInvalidLoginAt
{
get { return data.LastInvalidLoginAt; }
set { CheckChangedNullable(data.LastInvalidLoginAt, value); data.LastInvalidLoginAt = value; }
}
public short InvalidLoginCount
{
get { return data.InvalidLoginCount; }
set { CheckChanged(data.InvalidLoginCount, value); data.InvalidLoginCount = value; }
}
// Flags.
public bool AuthenticatedUser
{
get { return GetFlag(Flag_AuthenticatedUser); }
set { SetFlag(Flag_AuthenticatedUser, value); }
}
// Population.
internal void PopulateFrom(Data data)
{
ItemType = data.ItemType;
Code = data.Code;
EmailAddress = data.EmailAddress;
Description = data.Description;
Location = data.Location;
DataItemType = data.DataItemType;
// Security.
PasswordEncrypted = data.PasswordEncrypted;
PasswordSalt = data.PasswordSalt;
PasswordHash = data.PasswordHash;
PasswordHistory = data.PasswordHistory;
PasswordToken = data.PasswordToken;
PasswordChangedAt = data.PasswordChangedAt;
// Login.
LastLogin = data.LastLogin;
LastInvalidLoginAt = data.LastInvalidLoginAt;
InvalidLoginCount = data.InvalidLoginCount;
base.PopulateFrom(data);
}
public Data Clone()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
// Error field - identify properties with validation error.
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue ItemType { get; set; } = ValidValue.Valid;
public ValidValue Code { get; set; } = ValidValue.Valid;
public ValidValue EmailAddress { get; set; } = ValidValue.Valid;
public ValidValue Description { get; set; } = ValidValue.Valid;
public ValidValue Location { get; set; } = ValidValue.Valid;
// Security.
public ValidValue Password { get; set; } = ValidValue.Valid;
public ValidValue PasswordHistory { get; set; } = ValidValue.Valid;
public ValidValue PasswordToken { get; set; } = ValidValue.Valid;
public ValidValue PasswordChanged { get; set; } = ValidValue.Valid;
// Login.
public ValidValue LastLogin { get; set; } = ValidValue.Valid;
public ValidValue LastInvalidLogin { get; set; } = ValidValue.Valid;
public ValidValue InvalidLoginCount { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
// Flags.
public static readonly Byte Flag_AuthenticatedUser = 0x01;
//-------------------------------------------------------------------
// Construction.
public SaSecurityItem(SysId id, SaSecurity.ItemType securityItemType) :
base(id)
{
base.SetData(data);
ItemType = securityItemType;
Status = DefaultStatus;
}
//-------------------------------------------------------------------
// Status.
private static readonly List<SaStatus> securityItemStatuses = new List<SaStatus>()
{
SaStatus.Enabled,
SaStatus.Disabled,
};
public static SaStatus DefaultStatus { get { return EnabledStatus; } }
public static SaStatus EnabledStatus { get { return SaStatus.Enabled; } }
public static SaStatus DisabledStatus { get { return SaStatus.Disabled; } }
public static List<SaStatus> ValidStatuses { get { return new List<SaStatus>(securityItemStatuses); } }
public static DataValue.TriStateType GetStatusTriState(SaStatus status)
{
switch (status)
{
case SaStatus.Enabled:
return DataValue.TriStateType.Green;
case SaStatus.Disabled:
return DataValue.TriStateType.Red;
case SaStatus.Deleted:
return DataValue.TriStateType.Purple;
}
return DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Data properties.
public Data GetData() { return data.Clone(); }
public void SetData(Data data)
{
// Properties that cannot be changed if previously specified.
if (SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id))
throw new NotSupportedException($"{SysUtil.Fn} Id cannot be changed");
if ((int)data.ItemType > 0 && data.ItemType != ItemType)
throw new NotSupportedException($"{SysUtil.Fn} Item Type cannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
//-------------------------------------------------------------------
// Properties.
public SaSecurity.ItemType ItemType
{
get { return data.ItemType; }
protected set { data.ItemType = value; }
}
public String Code
{
get { return data.Code; }
set { data.Code = value; }
}
public String EmailAddress
{
get { return data.EmailAddress; }
set { data.EmailAddress = value; }
}
public String Description
{
get { return data.Description; }
set { data.Description = value; }
}
public String Location
{
get { return data.Location; }
set { data.Location = value; }
}
public int DataItemType
{
get { return data.DataItemType; }
set { data.DataItemType = value; }
}
// Security.
public String PasswordSalt
{
get { return data.PasswordSalt; }
protected set { data.PasswordSalt = value; }
}
public String PasswordHash
{
get { return data.PasswordHash; }
protected set { data.PasswordHash = value; }
}
[Obsolete("Avoid using the original C++ password encryption - switch to hashed password instead.")]
public String PasswordEncrypted
{
get { return data.PasswordEncrypted; }
protected set { data.PasswordEncrypted = value; }
}
public String PasswordToken
{
get { return data.PasswordToken; }
set { data.PasswordToken = value; }
}
public List<String> PasswordHistory
{
get { return data.PasswordHistory; }
set { data.PasswordHistory = value; }
}
public DateTime? PasswordChangedAt
{
get { return data.PasswordChangedAt; }
set { data.PasswordChangedAt = value; }
}
// Login.
public DateTime? LastLogin
{
get { return data.LastLogin; }
set { data.LastLogin = value; }
}
public DateTime? LastInvalidLoginAt
{
get { return data.LastInvalidLoginAt; }
set { data.LastInvalidLoginAt = value; }
}
public short InvalidLoginCount
{
get { return data.InvalidLoginCount; }
set { data.InvalidLoginCount = value; }
}
//-------------------------------------------------------------------
// Flags.
public bool AuthenticatedUser
{
get { return GetFlag(Flag_AuthenticatedUser); }
set { SetFlag(Flag_AuthenticatedUser, value); }
}
//-------------------------------------------------------------------
// Password utilities.
/// <summary>Extract password storage method from data.</summary>
public SaSecurity.PasswordStorageMethod GetPasswordMethod()
{
if (PasswordSalt == PasswordSalt_MsSql && !StringUtil.IsBlank(PasswordHash))
return SaSecurity.PasswordStorageMethod.MsSql;
return SaSecurity.PasswordStorageMethod.Legacy;
}
public void SetEncodedPassword(SaSecurity.PasswordStorageMethod method, String encodedPassword)
{
if (method == SaSecurity.PasswordStorageMethod.MsSql)
{
#pragma warning disable CS0618 // Deprecated property
PasswordEncrypted = "";
#pragma warning restore CS0618 // Deprecated property
PasswordSalt = PasswordSalt_MsSql;
PasswordHash = encodedPassword;
}
else
{
#pragma warning disable CS0618 // Deprecated property
PasswordEncrypted = encodedPassword;
#pragma warning restore CS0618 // Deprecated property
PasswordSalt = "";
PasswordHash = "";
}
}
//-------------------------------------------------------------------
// List parameters.
public enum StatusCat
{
Any,
EnabledOnly,
DisabledOnly,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
public HashSet<SysId> IdsIncluded { get; } = new HashSet<SysId>();
public HashSet<SysId> IdsExcluded { get; } = new HashSet<SysId>();
public SaSecurity.ItemType SecurityItemType { get; set; } = SaSecurity.ItemType.Any;
public String Code { get; set; }
public String CodePartial { get; set; }
public String EmailAddress { get; set; }
public String EmailAddressPartial { get; set; }
public String Description { get; set; }
public String DescriptionPartial { get; set; }
public HashSet<SysId> GroupIdsIncluded { get; } = new HashSet<SysId>();
public StatusCat StatusCat { get; set; } = StatusCat.EnabledOnly;
}
//-------------------------------------------------------------------
}
//=======================================================================
public static class SaSecurityItemList
{
public static SaSecurityItem GetSecItemById(this List<SaSecurityItem> secItems, SysId secItemId)
{
if (!SysId.IsValid(secItemId)) return null;
foreach (SaSecurityItem secItem in secItems)
{
if (secItem.Id.Equals(secItemId))
return secItem;
}
return null;
}
}
//=======================================================================
}
@@ -0,0 +1,286 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Base.Security
{
//=======================================================================
public abstract class SaSecurityLink : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Pos = 0,
ItemIdOwner,
ItemOwner_Code,
ItemOwner_Desc,
ItemIdTarget,
ItemTarget_Code,
ItemTarget_Desc,
ItemIdContext,
ItemContext_Desc,
DaysApplicable,
DateApplicableFrom,
DateApplicableTo,
Granted_Y,
Denied_X,
Status,
Status_Ind,
Status_Desc,
CreateOn_Date,
UpdateOn_Date,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public SysId ItemIdOwner { get; set; } = new SysId();
public SysId ItemIdTarget { get; set; } = new SysId();
public SysId ItemIdContext { get; set; } = new SysId();
public String DayApplicability { get; set; } = String.Empty;
public DateTime? ApplicableFrom { get; set; } = DateTime.MinValue;
public DateTime? ApplicableTo { get; set; } = DateTime.MinValue;
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data()
{
Status = DefaultStatus;
}
// Properties.
public SysId ItemIdOwner
{
get { return data.ItemIdOwner; }
set { CheckChanged(data.ItemIdOwner, value); data.ItemIdOwner = value; }
}
public SysId ItemIdTarget
{
get { return data.ItemIdTarget; }
set { CheckChanged(data.ItemIdTarget, value); data.ItemIdTarget = value; }
}
public SysId ItemIdContext
{
get { return data.ItemIdContext; }
set { CheckChanged(data.ItemIdContext, value); data.ItemIdContext = value; }
}
public String DayApplicability
{
get { return data.DayApplicability; }
set { CheckChanged(data.DayApplicability, value); data.DayApplicability = value; }
}
public DateTime? ApplicableFrom
{
get { return data.ApplicableFrom; }
set { CheckChangedNullable(data.ApplicableFrom, value); data.ApplicableFrom = value; }
}
public DateTime? ApplicableTo
{
get { return data.ApplicableTo; }
set { CheckChangedNullable(data.ApplicableTo, value); data.ApplicableTo = value; }
}
// Population.
internal void PopulateFrom(Data data)
{
ItemIdOwner = data.ItemIdOwner;
ItemIdTarget = data.ItemIdTarget;
ItemIdContext = data.ItemIdContext;
DayApplicability = data.DayApplicability;
ApplicableFrom = data.ApplicableFrom;
ApplicableTo = data.ApplicableTo;
base.PopulateFrom(data);
}
public Data Clone()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
// Error field - identify properties with validation error.
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue ItemIdOwner { get; set; } = ValidValue.Valid;
public ValidValue ItemIdTarget { get; set; } = ValidValue.Valid;
public ValidValue ItemIdContext { get; set; } = ValidValue.Valid;
public ValidValue DayApplicability { get; set; } = ValidValue.Valid;
public ValidValue ApplicableFrom { get; set; } = ValidValue.Valid;
public ValidValue ApplicableTo { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
//-------------------------------------------------------------------
// Construction.
public SaSecurityLink(SysId itemIdOwner, SysId itemIdTarget, SysId itemIdContext) :
base()
{
base.SetData(data);
ItemIdOwner = itemIdOwner;
ItemIdTarget = itemIdTarget;
ItemIdContext = itemIdContext;
Status = DefaultStatus;
}
//-------------------------------------------------------------------
// Status.
private static readonly List<SaStatus> securityLinkStatuses = new List<SaStatus>()
{
SaStatus.Granted,
SaStatus.Denied,
};
public static SaStatus DefaultStatus { get { return GrantedStatus; } }
public static SaStatus GrantedStatus { get { return SaStatus.Granted; } }
public static SaStatus DeniedStatus { get { return SaStatus.Denied; } }
public static List<SaStatus> ValidStatuses { get { return new List<SaStatus>(securityLinkStatuses); } }
public static DataValue.TriStateType GetStatusTriState(SaStatus status)
{
switch (status)
{
case SaStatus.Granted:
return DataValue.TriStateType.Green;
case SaStatus.Denied:
return DataValue.TriStateType.Red;
case SaStatus.Deleted:
return DataValue.TriStateType.Purple;
}
return DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Properties.
public Data GetData() { return data.Clone(); }
public void SetData(Data data)
{
// Properties that cannot be changed if previously specified.
if (SysId.IsValid(data.Id))
throw new NotSupportedException($"{SysUtil.Fn} Id is not applicable for security links");
if (SysId.IsValid(data.ItemIdOwner) && SysId.ToInt(data.ItemIdOwner) != SysId.ToInt(ItemIdOwner))
throw new NotSupportedException($"{SysUtil.Fn} Owner Item cannot be changed");
if (SysId.IsValid(data.ItemIdTarget) && SysId.ToInt(data.ItemIdTarget) != SysId.ToInt(ItemIdTarget))
throw new NotSupportedException($"{SysUtil.Fn} Target Item cannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
//-------------------------------------------------------------------
// Properties.
public override bool ItemHasId() { return false; }
public SysId ItemIdOwner
{
get { return data.ItemIdOwner; }
protected set { data.ItemIdOwner = value; }
}
public SysId ItemIdTarget
{
get { return data.ItemIdTarget; }
protected set { data.ItemIdTarget = value; }
}
public SysId ItemIdContext
{
get { return data.ItemIdContext; }
protected set { data.ItemIdContext = value; }
}
public String DayApplicability
{
get { return data.DayApplicability; }
set { data.DayApplicability = value; }
}
public DateTime? ApplicableFrom
{
get { return data.ApplicableFrom; }
set { data.ApplicableFrom = value; }
}
public DateTime? ApplicableTo
{
get { return data.ApplicableTo; }
set { data.ApplicableTo = value; }
}
//-------------------------------------------------------------------
// List parameters.
public enum StatusCat
{
Any,
GrantedOnly,
DeniedOnly,
}
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
public readonly HashSet<SysId> ItemIdsOwnerIncluded = new HashSet<SysId>();
public SaSecurity.ItemType OwnerItemType { get; set; } = SaSecurity.ItemType.Unknown;
public readonly HashSet<SysId> ItemIdsTargetIncluded = new HashSet<SysId>();
public SaSecurity.ItemType TargetItemType { get; set; } = SaSecurity.ItemType.Unknown;
public readonly HashSet<SysId> ItemIdsContextIncluded = new HashSet<SysId>();
public StatusCat StatusCat { get; set; } = StatusCat.Any;
}
//-------------------------------------------------------------------
}
//=======================================================================
public static class SaSecurityLinkList
{
//-------------------------------------------------------------------
// Link owner.
public static bool ContaineOwnerItemId(this List<SaSecurityLink> links, SysId itemIdOwner)
{
if (!SysId.IsValid(itemIdOwner)) return false;
SaSecurityLink secLink = links.Find(link => SysId.IsValid(link.ItemIdOwner) && link.ItemIdOwner.Equals(itemIdOwner));
return (secLink != null);
}
public static List<SysId> GetOwnerItemIds(this List<SaSecurityLink> links)
{
List<SysId> ownerItemIds = new List<SysId>();
foreach (SaSecurityLink secLink in links)
{
if (SysId.IsValid(secLink.ItemIdOwner) && !ownerItemIds.Contains(secLink.ItemIdOwner))
ownerItemIds.Add(secLink.ItemIdOwner);
}
return ownerItemIds;
}
//-------------------------------------------------------------------
// Link target.
public static bool ContainsTargetItemId(this List<SaSecurityLink> links, SysId itemIdTarget)
{
if (!SysId.IsValid(itemIdTarget)) return false;
SaSecurityLink secLink = links.Find(link => SysId.IsValid(link.ItemIdTarget) && link.ItemIdTarget.Equals(itemIdTarget));
return (secLink != null);
}
public static List<SysId> GetTargetItemIds(this List<SaSecurityLink> links)
{
List<SysId> targetItemIds = new List<SysId>();
foreach (SaSecurityLink secLink in links)
{
if (SysId.IsValid(secLink.ItemIdTarget) && !targetItemIds.Contains(secLink.ItemIdTarget))
targetItemIds.Add(secLink.ItemIdTarget);
}
return targetItemIds;
}
public static SaStatus GetStatusByTargetItemId(this List<SaSecurityLink> links, SysId itemIdTarget)
{
if (!SysId.IsValid(itemIdTarget)) return SaStatus.Unknown;
SaSecurityLink secLink = links.Find(link => SysId.IsValid(link.ItemIdTarget) && link.ItemIdTarget.Equals(itemIdTarget));
return (secLink != null ? secLink.Status : SaStatus.Unknown);
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,168 @@
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
using System;
using System.Collections.Generic;
using System.Text;
namespace Sarand.Net.Standard.Base.Security
{
//=======================================================================
partial class SaSecurityMgr
{
//*******************************************************************
// S e c u r i t y I t e m s
//*******************************************************************
// Associated data.
public bool SecurityItemHasLinks(SysId securityItemId)
{
return (SecurityItemIsSourceOfLinks(securityItemId) || SecurityItemIsTargetOfLinks(securityItemId));
}
public abstract bool SecurityItemIsSourceOfLinks(SysId securityItemId);
public abstract bool SecurityItemIsTargetOfLinks(SysId securityItemId);
public abstract bool SecurityItemHasLinksWith(SysId securityItemIdOwner, SysId securityItemIdTarget);
//-------------------------------------------------------------------
// Retrieve individual security items.
public abstract bool SecurityItemExistsById(SysId id);
public abstract bool SecurityItemExistsByTypeCode(SaSecurity.ItemType securityItemType, String code);
public abstract SaSecurityItem GetSecurityItemById(SysId id);
public abstract SaSecurityItem GetSecurityItemByTypeId(SaSecurity.ItemType securityItemType, SysId id);
public abstract SaSecurityItem GetSecurityItemByTypeEmail(SaSecurity.ItemType securityItemType, String emailAddress);
public abstract SaSecurityItem GetSecurityItemByTypeCode(SaSecurity.ItemType securityItemType, String code);
public abstract SaSecurityItem GetSecurityItem(SaSecurityItem.Params prmSecItem);
// Create Security Item.
public abstract SaSecurityItem CreateSecurityItem(SaSecurity.ItemType securityItemType);
//-------------------------------------------------------------------
// Validate Security Item.
public bool IsValidSecurityItem(SaSecurityItem securityItem)
{
ClearErrorState();
if (securityItem == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidSecurityItemData(securityItem.GetData(), new SaSecurityItem.ErrField());
}
public virtual bool IsValidSecurityItemData(SaSecurityItem.Data data, SaSecurityItem.ErrField errField)
{
ClearErrorState();
if (errField.ItemType != SacsHierarchyItem.ValidValue.Ignore && (int)data.ItemType < 1)
{
SetErrorState("security item type must be supplied");
errField.ItemType = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Code != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Code, "code", (long)SaSecurityDbDfn.GetColTextLen(SaSecurityDbDfn.ColumnIdx.SaSecItem_Code), true))
{
errField.Code = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.EmailAddress != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.EmailAddress, "email address", (long)SaSecurityDbDfn.GetColTextLen(SaSecurityDbDfn.ColumnIdx.SaSecItem_EmailAddress)))
{
errField.EmailAddress = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Description != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Description, "description", (long)SaSecurityDbDfn.GetColTextLen(SaSecurityDbDfn.ColumnIdx.SaSecItem_Description), true))
{
errField.Description = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Location != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Location, "location", (long)SaSecurityDbDfn.GetColTextLen(SaSecurityDbDfn.ColumnIdx.SaSecItem_Location)))
{
errField.Location = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Password != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.PasswordEncrypted, "password", (long)SaSecurityDbDfn.GetColTextLen(SaSecurityDbDfn.ColumnIdx.SaSecItem_EncPword)))
{
errField.Password = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
// Common properties.
if (errField.Notes != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Notes, "notes", (long)SaSecurityDbDfn.GetColTextLen(SaSecurityDbDfn.ColumnIdx.SaSecItem_Notes)))
{
errField.Notes = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (errField.Status != SacsHierarchyItem.ValidValue.Ignore)
{
if (!IsValidValue(data.StatusCode, "status", (long)SaSecurityDbDfn.GetColTextLen(SaSecurityDbDfn.ColumnIdx.SaSecItem_Status), true, true))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!SaSecurityItem.ValidStatuses.Contains(data.Status))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.InvalidStatus);
}
}
return true;
}
//-------------------------------------------------------------------
// SecurityItem database interface.
public abstract bool InsertSecurityItem(SaSecurityItem securityItem, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateSecurityItem(SaSecurityItem securityItem, DbUpdateInfo dbUpdateInfo);
public virtual bool SecurityItemCanBeDeleted(SaSecurityItem securityItem)
{
ClearErrorState();
if (SecurityItemHasLinks(securityItem.Id)) return SetErrorState("security item has links");
return true;
}
public abstract bool DeleteSecurityItem(SaSecurityItem securityItem, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Item list.
public abstract ColumnDfn GetSecurityItemColumnDfn(SaSecurityItem.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetSecurityItemQueryFilter(SaSecurityItem.Params prm);
public abstract long GetSecurityItemCount(SaSecurityItem.Params prm);
public abstract List<SaSecurityItem> GetSecurityItemList(SaSecurityItem.Params prm);
public abstract DbResultSet ExecuteSecurityItemQuery(List<ColumnDfn> columns, SaSecurityItem.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public DataValue GetSecurityItemDataValue(ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
switch ((SaSecurityItem.Column)column.Id)
{
//-----------------------------------------------------------
// Item type.
case SaSecurityItem.Column.ItemType_Desc:
SaSecurity.ItemType securityItemType = (SaSecurity.ItemType)values.GetValue(column.DataName).AsLong();
value = new DataValue(securityItemTypes.GetCodeForType(securityItemType, securityItemType.ToString()));
break;
//-----------------------------------------------------------
// Notes.
case SaSecurityItem.Column.Notes:
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
break;
//-----------------------------------------------------------
// Status.
case SaSecurityItem.Column.Status_Desc:
case SaSecurityItem.Column.Status_Ind:
{
String statusCode = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusCode);
if (column.Id == (int)SaSecurityItem.Column.Status_Desc)
value = new DataValue(SacsSystem.GetStatusDescForCode(statusCode));
else if (column.Id == (int)SaSecurityItem.Column.Status_Ind)
value = new DataValue(SaSecurityItem.GetStatusTriState(status));
}
break;
//-----------------------------------------------------------
}
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,126 @@
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
using System;
using System.Collections.Generic;
using System.Text;
namespace Sarand.Net.Standard.Base.Security
{
//=======================================================================
partial class SaSecurityMgr
{
//*******************************************************************
// S e c u r i t y L i n k s
//*******************************************************************
// Retrieve individual securityLinks.
public abstract bool SecurityLinkExistsByItemsIds (SysId itemIdOwner, SysId itemIdTarget, SysId itemIdContext);
public abstract SaSecurityLink GetSecurityLinkByItemsIds (SysId itemIdOwner, SysId itemIdTarget, SysId itemIdContext);
// Create securityLink.
public abstract SaSecurityLink CreateSecurityLink (SysId itemIdOwner, SysId itemIdTarget, SysId itemIdContext);
//-------------------------------------------------------------------
// Validate securityLink data.
public bool IsValidSecurityLink (SaSecurityLink securityLink)
{
ClearErrorState();
if (securityLink == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidSecurityLinkData(securityLink.GetData(), new SaSecurityLink.ErrField());
}
public virtual bool IsValidSecurityLinkData (SaSecurityLink.Data securityLinkData, SaSecurityLink.ErrField errField)
{
ClearErrorState();
if (!SysId.IsValid(securityLinkData.ItemIdOwner))
{
errField.ItemIdOwner = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("owner must be specified");
}
if (!SysId.IsValid(securityLinkData.ItemIdOwner))
{
errField.ItemIdOwner = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("owner must be specified");
}
if (!SysId.IsValid(securityLinkData.ItemIdOwner))
{
errField.ItemIdOwner = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("owner must be specified");
}
// Common properties.
if (!SaSecurityLink.ValidStatuses.Contains(securityLinkData.Status))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.InvalidStatus);
}
return true;
}
//-------------------------------------------------------------------
// SecurityLink database interface.
public abstract bool InsertSecurityLink (SaSecurityLink securityLink, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateSecurityLink (SaSecurityLink securityLink, DbUpdateInfo dbUpdateInfo);
public virtual bool SecurityLinkCanBeDeleted (SaSecurityLink securityLink)
{
ClearErrorState();
return true;
}
public abstract bool DeleteSecurityLink (SaSecurityLink securityLink, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Security Link list:
public abstract ColumnDfn GetSecurityLinkColumnDfn (SaSecurityLink.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetSecurityLinkQueryFilter (SaSecurityLink.Params prm);
public abstract long GetSecurityLinkCount (SaSecurityLink.Params prm);
public abstract List<SaSecurityLink> GetSecurityLinkList (SaSecurityLink.Params prm);
public abstract DbResultSet ExecuteSecurityLinkQuery (List<ColumnDfn> columns, SaSecurityLink.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public DataValue GetSecurityLinkDataValue (ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
SaSecurityLink.Column colId = (SaSecurityLink.Column)column.Id;
switch (colId)
{
//-----------------------------------------------------------
// Context Item description.
case SaSecurityLink.Column.ItemContext_Desc:
{
SysId contextItemId = new SysId((int)values.GetValue(GetSecurityLinkColumnDfn(SaSecurityLink.Column.ItemIdContext).DataName).AsLong());
value = new DataValue("Item #" + SysId.ToString(contextItemId));
}
break;
//-----------------------------------------------------------
// Status.
case SaSecurityLink.Column.Granted_Y:
case SaSecurityLink.Column.Denied_X:
case SaSecurityLink.Column.Status_Desc:
case SaSecurityLink.Column.Status_Ind:
{
String statusValue = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusValue);
if (column.Id == (int)SaSecurityLink.Column.Granted_Y)
value = new DataValue(status == SaStatus.Granted ? "Y" : "");
else if (column.Id == (int)SaSecurityLink.Column.Denied_X)
value = new DataValue(status == SaStatus.Denied ? "X" : "");
else if (column.Id == (int)SaSecurityLink.Column.Status_Desc)
value = new DataValue(SacsSystem.GetStatusDescForCode(statusValue));
else if (column.Id == (int)SaSecurityLink.Column.Status_Ind)
value = new DataValue(SaSecurityLink.GetStatusTriState(status));
}
break;
//-----------------------------------------------------------
}
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
namespace Sarand.Net.Standard.Base.Security
{
//=======================================================================
public abstract partial class SaSecurityMgr : SacsItemMgr
{
//-------------------------------------------------------------------
// Data members.
private List<TypeCodeDesc> securityItemTypes;
//-------------------------------------------------------------------
// Static initialisation.
static SaSecurityMgr ()
{
}
//-------------------------------------------------------------------
// Construction.
protected SaSecurityMgr ()
{
securityItemTypes = SaSecurityConsole.SecurityItemTypes;
}
//-------------------------------------------------------------------
// Database properties.
public abstract bool DatabaseIsValid { get; }
public abstract bool CanUpdateDatabase { get; }
public abstract bool ColumnExists (SaSecurityDbDfn.ColumnIdx columnIdx);
//-------------------------------------------------------------------
// Password utilities.
/// <summary>Store the password against against the user.</summary>
public abstract bool SetPassword(SaSecurityItem securityItemUser, String password);
/// <summary>Does the password match that currently defined against the user.</summary>
public abstract bool PasswordMatches(SaSecurityItem securityItemUser, String password, DbUpdateInfo dbUpdateInfo);
/// <summary>Is the password currently defined against the user blank.</summary>
public abstract bool PasswordIsBlank(SaSecurityItem securityItemUser);
/// <summary>Generate password hash using the specified method.</summary>
public abstract String EncodePassword_Hex(String password, SaSecurity.PasswordHashMethod method = SaSecurity.PasswordHashMethod.MsSql);
/// <summary>Compare password to hashed value using the specified method.</summary>
public abstract bool ComparePassword_Hex(String password, String passwordHashHex, SaSecurity.PasswordHashMethod method = SaSecurity.PasswordHashMethod.MsSql);
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,227 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Base.Security
{
//=======================================================================
public class SaSecurityProfile
{
//-------------------------------------------------------------------
/// <summary>Security Group definition.</summary>
public class GroupData
{
private readonly List<SaSecurityProfile.RightData> rights = new List<RightData>();
public GroupData(SaSecurityItem secGroup, List<SaSecurityProfile.RightData> groupRights)
{
if (secGroup.ItemType != SaSecurity.ItemType.Group) throw new NotSupportedException("SaSecurityProfile.GroupData - Invalid security item type: " + secGroup.ItemType.ToString());
Id = secGroup.Id;
Code = secGroup.Code;
Desc = secGroup.Description;
rights.AddRange(groupRights);
}
protected GroupData() { }
public SysId Id { get; }
public String Code { get; }
public String Desc { get; }
// Security rights.
public List<SaSecurityProfile.RightData> Rights { get { return new List<RightData>(rights); } }
/// <summary>
/// Retrieve the list of data items for which the user is explicitly granted the
/// specified security right, or where the right is explicitly denied if the flag is false.
/// </summary>
public List<SysId> GetDataItemsForRight(String rightCode, bool granted = true) { return rights.GetDataItemsForRight(rightCode, granted); }
/// <summary>Is the Security Right code granted access for the Data item (if specified).</summary>
public bool IsSecurityRightGranted(String rightCode, SysId dataItemId = null) { return rights.IsSecurityRightGranted(rightCode, dataItemId); }
/// <summary>Is the Security Right code denined access for the Data item (if specified).</summary>
public bool IsSecurityRightDenied(String rightCode, SysId dataItemId = null) { return rights.IsSecurityRightDenied(rightCode, dataItemId); }
}
/// <summary>Security Right definition.</summary>
public class RightData
{
public RightData(SaSecurityItem secRight, SaSecurityLink secRightLink)
{
if (secRight.ItemType != SaSecurity.ItemType.Right) throw new NotSupportedException("SaSecurityProfile.RightData - Invalid security item type: " + secRight.ItemType.ToString());
Id = secRight.Id;
Code = secRight.Code;
Desc = secRight.Description;
DataItemId = secRightLink.ItemIdContext;
Granted = (secRightLink.Status == SaStatus.Granted);
}
protected RightData() { }
public SysId Id { get; }
public String Code { get; }
public String Desc { get; }
public SysId DataItemId { get; }
public bool Granted { get; }
}
//-------------------------------------------------------------------
// Data members.
protected readonly List<SaSecurityProfile.GroupData> securityGroups = new List<GroupData>();
protected readonly List<SaSecurityProfile.RightData> securityRights = new List<RightData>();
//-------------------------------------------------------------------
// Construction.
internal SaSecurityProfile(SaSecurityItem secItem, List<SaSecurityProfile.GroupData> profileGroups, List<SaSecurityProfile.RightData> profileRights, bool systemAdmin)
{
Clear();
if (secItem != null)
{
// Security item properties.
Id = secItem.Id;
SecurityItemType = secItem.ItemType;
Code = secItem.Code;
EmailAddress = secItem.EmailAddress;
Description = secItem.Description;
Location = secItem.Location;
LastLogin = secItem.LastLogin ?? DateTime.MinValue;
}
if (profileGroups != null)
securityGroups.AddRange(profileGroups);
if (profileRights != null)
securityRights.AddRange(profileRights);
SystemAdmin = systemAdmin;
}
/// <summary>
/// Protected construction - for derived classes.
/// <para>Ref. Mobile Security Profile.</para>
/// </summary>
protected SaSecurityProfile()
{
Clear();
}
//-------------------------------------------------------------------
// Properties.
public SysId Id { get; protected set; }
public SaSecurity.ItemType SecurityItemType { get; protected set; } = SaSecurity.ItemType.Unknown;
public String Code { get; protected set; }
public String EmailAddress { get; protected set; }
public String Description { get; protected set; }
public String Location { get; protected set; }
public DateTime LastLogin { get; protected set; } = DateTime.MinValue;
public List<SaSecurityProfile.GroupData> Groups { get { return new List<GroupData>(securityGroups); } }
public List<SaSecurityProfile.RightData> Rights { get { return new List<RightData>(securityRights); } }
public bool SystemAdmin { get; protected set; } = false;
//-------------------------------------------------------------------
// Population.
//-------------------------------------------------------------------
// Clear profile.
public void Clear()
{
Id = new SysId();
SecurityItemType = SaSecurity.ItemType.Unknown;
Code = String.Empty;
Description = String.Empty;
Location = String.Empty;
LastLogin = DateTime.MinValue;
securityGroups.Clear();
securityRights.Clear();
SystemAdmin = false;
}
//-------------------------------------------------------------------
// Utilities.
public bool IsMemberOfSecurityGroup(SysId secGroupId)
{
return securityGroups.Exists(item => item.Id.Equals(secGroupId));
}
//-------------------------------------------------------------------
/// <summary>
/// Retrieve the list of data items for which the user is explicitly granted the
/// specified security right, or where the right is explicitly denied if the flag is false.
/// </summary>
public List<SysId> GetDataItemsForRight(String rightCode, bool granted = true)
{
return securityGroups.GetDataItemsForRight(rightCode, granted);
}
//-------------------------------------------------------------------
/// <summary>Is the Security Right code granted access for the Data item (if specified).</summary>
public bool IsSecurityRightGranted(String rightCode, SysId dataItemId = null)
{
if (SystemAdmin) return true;
return (securityGroups.IsSecurityRightGranted(rightCode, dataItemId) || securityRights.IsSecurityRightGranted(rightCode, dataItemId));
}
//-------------------------------------------------------------------
/// <summary>Is the Security Right code denined access for the Data item (if specified).</summary>
public bool IsSecurityRightDenied(String rightCode, SysId dataItemId = null)
{
if (SystemAdmin) return false;
return (securityGroups.IsSecurityRightDenied(rightCode, dataItemId) || securityRights.IsSecurityRightDenied(rightCode, dataItemId));
}
//-------------------------------------------------------------------
}
//=======================================================================
public static class SaSecurityProfileGroupDataList
{
/// <summary>
/// Retrieve the list of data items for which the user is explicitly granted the
/// specified security right, or where the right is explicitly denied if the flag is false.
/// </summary>
public static List<SysId> GetDataItemsForRight(this List<SaSecurityProfile.GroupData> groups, String rightCode, bool granted = true)
{
HashSet<SysId> dataItemIds = new HashSet<SysId>();
foreach (var securityGroup in groups)
dataItemIds.AddIds(securityGroup.GetDataItemsForRight(rightCode, granted));
return new List<SysId>(dataItemIds);
}
/// <summary>Is the Security Right code granted access for the Data item (if specified).</summary>
public static bool IsSecurityRightGranted(this List<SaSecurityProfile.GroupData> groups, String rightCode, SysId dataItemId = null)
{
return groups.Exists(group => group.IsSecurityRightGranted(rightCode, dataItemId));
}
/// <summary>Is the Security Right code denined access for the Data item (if specified).</summary>
public static bool IsSecurityRightDenied(this List<SaSecurityProfile.GroupData> groups, String rightCode, SysId dataItemId = null)
{
return groups.Exists(group => group.IsSecurityRightDenied(rightCode, dataItemId));
}
}
//=======================================================================
public static class SaSecurityProfileRightDataList
{
/// <summary>
/// Retrieve the list of data items for which the user is explicitly granted the
/// specified security right, or where the right is explicitly denied if the flag is false.
/// </summary>
public static List<SysId> GetDataItemsForRight(this List<SaSecurityProfile.RightData> rights, String rightCode, bool granted = true)
{
HashSet<SysId> dataItemIds = new HashSet<SysId>();
foreach (var securityRight in rights.FindAll(x => x.Code.EqualsCI(rightCode) && x.Granted == granted))
dataItemIds.AddId(securityRight.DataItemId);
return new List<SysId>(dataItemIds);
}
/// <summary>Is the Security Right code granted access for the Data item (if specified).</summary>
public static bool IsSecurityRightGranted(this List<SaSecurityProfile.RightData> rights, String rightCode, SysId dataItemId = null)
{
foreach (var userSecurityRight in rights.FindAll(item => item.Code.EqualsCI(rightCode)))
{
if (SysId.ToInt(dataItemId) != SysId.ToInt(userSecurityRight.DataItemId)) continue;
return userSecurityRight.Granted;
}
return false;
}
/// <summary>Is the Security Right code denined access for the Data item (if specified).</summary>
public static bool IsSecurityRightDenied(this List<SaSecurityProfile.RightData> rights, String rightCode, SysId dataItemId = null)
{
foreach (var userSecurityRight in rights.FindAll(item => item.Code.EqualsCI(rightCode)))
{
if (SysId.ToInt(dataItemId) != SysId.ToInt(userSecurityRight.DataItemId)) continue;
return !userSecurityRight.Granted;
}
return false;
}
}
//=======================================================================
}
@@ -0,0 +1,75 @@
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Sarand.Net.Standard.Base.Security
{
//=======================================================================
/// <summary>Definition of security right as required by application</summary>
public class SaSecurityRight
{
//-------------------------------------------------------------------
// Construction.
public SaSecurityRight(int type, String code, String desc, int dataItemType = 0)
{
Type = type;
Code = code;
Desc = desc;
DataItemType = dataItemType;
}
//-------------------------------------------------------------------
// Properties.
public int Type { get; }
public String Code { get; }
public String Desc { get; }
public int DataItemType { get; }
//-------------------------------------------------------------------
}
//=======================================================================
public static class SaSecurityRightList
{
// Conversion by type.
public static String GetCodeForType(this List<SaSecurityRight> securityRights, int type, String defaultValue = "")
{
return securityRights.FirstOrDefault(item => item.Type == type)?.Code ?? defaultValue;
}
public static String GetCodeForType<T>(this List<SaSecurityRight> values, T type, String defaultValue = "") where T : struct, IConvertible
{
if (!(type is Enum))
throw new ArgumentException("SaSecurityRightList.GetCodeForType parameter must be an enumerated type. Type supplied: " + type.GetType().Name);
return values.GetCodeForType((int)(type as IConvertible), defaultValue);
}
public static String GetDescForType(this List<SaSecurityRight> securityRights, int type)
{
return securityRights.FirstOrDefault(item => item.Type == type)?.Desc ?? "";
}
public static String GetDescForType<T>(this List<SaSecurityRight> values, T type, String defaultValue = "") where T : struct, IConvertible
{
if (!(type is Enum))
throw new ArgumentException("SaSecurityRightList.GetDescForType parameter must be an enumerated type. Type supplied: " + type.GetType().Name);
return values.GetDescForType((int)(type as IConvertible), defaultValue);
}
// Conversion by code.
public static int GetTypeForCode(this List<SaSecurityRight> securityRights, String code)
{
return securityRights.FirstOrDefault(item => item.Code.EqualsCI(code))?.Type ?? 0;
}
public static String GetDescForCode(this List<SaSecurityRight> securityRights, String code)
{
return securityRights.FirstOrDefault(item => item.Code.EqualsCI(code))?.Desc ?? "";
}
// Population.
public static void Add(this List<SaSecurityRight> securityRights, int type, String code, String desc, int dataItemType = 0)
{
securityRights.Add(new SaSecurityRight(type, code, desc, dataItemType));
}
}
//=======================================================================
}
@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
namespace Sarand.Net.Standard.Base.UpdateLog
{
//=======================================================================
// Definitions.
//=======================================================================
public abstract class SaUpdateLogConsole : SacsDisposableStateItem
{
//-------------------------------------------------------------------
// Definitions.
//-------------------------------------------------------------------
// Data members.
//-------------------------------------------------------------------
// Static initialisation
static SaUpdateLogConsole ()
{
}
//-------------------------------------------------------------------
// Protected construction - use derived classes.
protected SaUpdateLogConsole ()
{
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
}
base.Dispose(disposing);
}
//-------------------------------------------------------------------
// Properties.
public abstract bool DatabaseIsValid { get; }
public abstract bool CanUpdateDatabase { get; }
//-------------------------------------------------------------------
// Utilities - retrieve application data.
public abstract Dictionary<SysId, String> GetNameForUserIds (List<SysId> userIds);
//-------------------------------------------------------------------
// Update Log Form.
public class ShowUpdateLogConfig
{
public ShowUpdateLogConfig(ItemId itemId, String itemCaption, DbUpdateInfo dbUpdateInfo)
{
ItemId = itemId;
ItemCaption = itemCaption;
DbUpdateInfo = dbUpdateInfo;
}
public ItemId ItemId { get; }
public String ItemCaption { get; }
public DbUpdateInfo DbUpdateInfo { get; }
}
public abstract bool ShowUpdateLogDialog (ShowUpdateLogConfig config);
//*******************************************************************
// U p d a t e L o g E n t r i e s
//*******************************************************************
// Log updates.
public abstract bool LogUpdates (SaUpdateLogItemMonitor updateLogItemMonitor);
//-------------------------------------------------------------------
// Retrieve list of updates that match the specified params:
public abstract bool ItemHasLogEntries (ItemId itemId);
public abstract bool LogEntriesExist (SaUpdateLogEntry.Params prmUpdateLog);
public abstract SaUpdateLogEntry GetLogEntry (ItemId itemId, String attrName, DateTime loggedAt);
public abstract long GetLogEntryCount (SaUpdateLogEntry.Params prmUpdateLog);
public abstract List<SaUpdateLogEntry> GetLogEntries (SaUpdateLogEntry.Params prmUpdateLog);
//-------------------------------------------------------------------
// Create a new item data.
public abstract SaUpdateLogEntry CreateLogEntry (ItemId itemId, String attrName);
//-------------------------------------------------------------------
// Store item data.
public abstract bool StoreLogEntry (SaUpdateLogEntry logEntry, DbUpdateInfo dbUpdateInfo);
public abstract bool RemoveLogEntry (SaUpdateLogEntry logEntry, DbUpdateInfo dbUpdateInfo);
public abstract bool ClearLogEntriesForItem (ItemId itemId, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,320 @@
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
//---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Thu 3-Oct-2019 15:11:05
//---------------------------------------------------------------------------
namespace Sarand.Net.Standard.Base.UpdateLog
{
public class SaUpdateLogDbDfn
{
//-------------------------------------------------------------------
// Table identifiers.
public enum TableIdx
{
Unknown = 0,
SaAttrUpdate,
}
//-------------------------------------------------------------------
// Column identifiers.
public enum ColumnIdx
{
Unknown = 0,
SaAttrUpdate_ItemType,
SaAttrUpdate_ItemId,
SaAttrUpdate_Logged,
SaAttrUpdate_Attribute,
SaAttrUpdate_DataBefore,
SaAttrUpdate_DataAfter,
SaAttrUpdate_Notes,
SaAttrUpdate_Flags,
SaAttrUpdate_Status,
SaAttrUpdate_CreateOn,
SaAttrUpdate_CreateBy,
SaAttrUpdate_CreateHost,
SaAttrUpdate_UpdateOn,
SaAttrUpdate_UpdateBy,
SaAttrUpdate_UpdateHost,
}
//-------------------------------------------------------------------
// Data members.
private static readonly int tableCount = 1;
private static readonly int columnCount = 15;
private static ulong maxTextLen = 0;
//-------------------------------------------------------------------
// Retrieve Table details (eg. name: 'Company').
public static int GetTableCount ()
{
return tableCount;
}
public static String GetTableName (TableIdx table, bool delimitReservedWords = true)
{
int tableIdx = (int)table - 1;
if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;
String tableName = tables[(int)tableIdx];
if (delimitReservedWords) tableName = DelimitReservedWord(tableName);
return tableName;
}
//-------------------------------------------------------------------
// Identify the table that corresponds with the specified column.
public static TableIdx GetTableForColumn (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return TableIdx.Unknown;
return columns[columnIdx].TableIdx;
}
//-------------------------------------------------------------------
// Retrieve the specified Column's name (Qualified include table name: '(<Table>.Column>)').
public static String GetColumnName (ColumnIdx column, bool delimitReservedWords = true)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return String.Empty;
String columnName = columns[columnIdx].Name;
if (delimitReservedWords) columnName = DelimitReservedWord(columnName);
return columnName;
}
public static String GetColumnNameQual (ColumnIdx column, String tableAlias = "", bool braces = false)
{
String columnName = GetColumnName(column);
if (!String.IsNullOrEmpty(columnName))
{
String tableName = StringUtil.EmptyOnNull(tableAlias);
if (tableName.IsEmpty()) tableName = GetTableName(GetTableForColumn(column));
columnName = tableName + (tableName.Length > 0 ? "." : "") + columnName;
if (braces)
columnName = "(" + columnName + ")";
}
return columnName;
}
//-------------------------------------------------------------------
// Reserved words.
private static DbReservedWordDelim reservedWordDelim = DbReservedWordDelim.SquareBrackets;
public static void SetReservedWordDelim (DbReservedWordDelim reservedWordDelim)
{
SaUpdateLogDbDfn.reservedWordDelim = reservedWordDelim;
}
public static bool IsReservedWord (String word)
{
if (String.IsNullOrEmpty(word)) return false;
if (reservedWords.Contains(word, StringComparer.OrdinalIgnoreCase)) return true;
return false;
}
public static String DelimitReservedWord (String word)
{
if (!IsReservedWord(word)) return word;
switch (reservedWordDelim)
{
case DbReservedWordDelim.None:
break;
case DbReservedWordDelim.DoubleQuotes:
word = "\"" + word + "\"";
break;
case DbReservedWordDelim.SquareBrackets:
default:
word = "[" + word + "]";
break;
}
return word;
}
//-------------------------------------------------------------------
// Retrieve information about the specified Column.
public static DbColumnDataType GetColDataType (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return DbColumnDataType.Unknown;
return columns[columnIdx].DataType;
}
public static short GetColNativeDataType (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return 0;
return columns[columnIdx].NativeDataType;
}
public static void SetMaxTextLen (ulong maxTextLen)
{
SaUpdateLogDbDfn.maxTextLen = maxTextLen;
}
public static bool IsColFmtText (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
return (columns[columnIdx].DataType == DbColumnDataType.VarChar);
}
public static ulong GetColTextLen (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return 0;
if (columns[columnIdx].DataType == DbColumnDataType.VarChar)
{
ulong textLen = columns[columnIdx].DataLen;
if (maxTextLen > 0 && textLen > maxTextLen) textLen = maxTextLen;
return textLen;
}
return 0;
}
public static bool IsColFmtBool (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
return (columns[columnIdx].DataType == DbColumnDataType.Bit);
}
public static bool IsColFmtNumeric (ColumnIdx column)
{
int columnIdx = (int)column - 1;
if (columnIdx < 0 || columnIdx >= columnCount) return false;
switch (columns[columnIdx].DataType)
{
case DbColumnDataType.TinyInt:
case DbColumnDataType.SmallInt:
case DbColumnDataType.Int:
case DbColumnDataType.BigInt:
case DbColumnDataType.Single:
case DbColumnDataType.Double:
case DbColumnDataType.Decimal:
return true;
}
return false;
}
//-------------------------------------------------------------------
// Table definitions.
private static readonly String[] tables =
{
"SaAttrUpdate",
};
//-------------------------------------------------------------------
// Table column definitions.
internal class ColumnDfn
{
internal TableIdx TableIdx { get; set; }
internal String Name { get; set; }
internal DbColumnDataType DataType { get; set; }
internal short NativeDataType { get; set; }
internal bool IsIdentity { get; set; }
internal ulong DataLen { get; set; }
internal ColumnDfn (int tableIdx, String name, int dataType, short nativeDataType, bool isIdentity, ulong dataLen)
{
this.TableIdx = (TableIdx)tableIdx;
this.Name = name;
this.DataType = (DbColumnDataType)dataType;
this.NativeDataType = nativeDataType;
this.IsIdentity = isIdentity;
this.DataLen = dataLen;
}
}
//-------------------------------------------------------------------
private static readonly ColumnDfn[] columns =
{
new ColumnDfn(1,"ItemType",3,5,false,5),
new ColumnDfn(1,"ItemId",4,4,false,10),
new ColumnDfn(1,"Logged",9,93,false,23),
new ColumnDfn(1,"Attribute",0,12,false,32),
new ColumnDfn(1,"DataBefore",0,-9,false,1024),
new ColumnDfn(1,"DataAfter",0,-9,false,1024),
new ColumnDfn(1,"Notes",0,-9,false,255),
new ColumnDfn(1,"Flags",3,5,false,5),
new ColumnDfn(1,"Status",0,12,false,3),
new ColumnDfn(1,"CreateOn",9,93,false,23),
new ColumnDfn(1,"CreateBy",4,4,false,10),
new ColumnDfn(1,"CreateHost",0,12,false,64),
new ColumnDfn(1,"UpdateOn",9,93,false,23),
new ColumnDfn(1,"UpdateBy",4,4,false,10),
new ColumnDfn(1,"UpdateHost",0,12,false,64),
};
//-------------------------------------------------------------------
// Reserved words.
private static readonly HashSet<String> reservedWords = new HashSet<String>()
{
"ADD",
"ALL",
"ALTER",
"AND",
"ANY",
"AS",
"ASC",
"AVG",
"BEGIN",
"BETWEEN",
"BY",
"CASE",
"CAST",
"COLUMN",
"COMMIT",
"CONSTRAINT",
"CONVERT",
"COUNT",
"CREATE",
"CURRENCY",
"DEFAULT",
"DELETE",
"DESC",
"DISTINCT",
"DROP",
"ELSE",
"END",
"EXECUTE",
"EXISTS",
"FALSE",
"FROM",
"GRANT",
"GROUP",
"HAVING",
"IN",
"INDEX",
"INNER",
"INSERT",
"INTO",
"IS",
"JOIN",
"KEY",
"LEFT",
"LIKE",
"MAX",
"MIN",
"NOT",
"NULL",
"ON",
"OR",
"ORDER",
"OUTER",
"OUTPUT",
"PRIMARY",
"PROCEDURE",
"REVOKE",
"ROLLBACK",
"ROWCOUNT",
"SELECT",
"SET",
"SQL",
"SUM",
"TABLE",
"THEN",
"TRANSACTION",
"TRUE",
"UNION",
"UNIQUE",
"UPDATE",
"USER",
"VALUES",
"VIEW",
"WHEN",
"WHERE",
};
//-------------------------------------------------------------------
}
}
@@ -0,0 +1,225 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Base.UpdateLog
{
//=======================================================================
public abstract class SaUpdateLogEntry : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Columns.
public enum Column
{
Pos = 0,
// Log Entry properties.
ItemType,
ItemType_Desc,
ItemId,
Attribute,
Location,
Logged,
Logged_Date,
Logged_Time,
DataBefore,
DataAfter,
// Common properties.
Notes,
Status,
Status_Desc,
Status_Ind,
CreateOn_Date,
CreateBy,
CreateBy_Name,
UpdateOn_Date,
Hidden,
}
//-------------------------------------------------------------------
/// <summary>Properties other than common.</summary>
public class DataProperties
{
public ItemId ItemId { get; set; } = new ItemId();
public String Attribute { get; set; } = String.Empty;
public DateTime Logged { get; set; } = DateTime.MinValue;
public String DataBefore { get; set; } = String.Empty;
public String DataAfter { get; set; } = String.Empty;
}
//-------------------------------------------------------------------
// Data.
public new class Data : SacsHierarchyItem.Data
{
// Data members.
private readonly DataProperties data = new DataProperties();
// Construction.
public Data ()
{
Status = DefaultStatus;
}
// Properties.
public ItemId ItemId
{
get { return data.ItemId; }
set { CheckChanged(data.ItemId, value); data.ItemId = value; }
}
public String Attribute
{
get { return data.Attribute; }
set { CheckChanged(data.Attribute, value); data.Attribute = value; }
}
public DateTime Logged
{
get { return data.Logged; }
set { CheckChanged(data.Logged, value); data.Logged = value; }
}
public String DataBefore
{
get { return data.DataBefore; }
set { CheckChanged(data.DataBefore, value); data.DataBefore = value; }
}
public String DataAfter
{
get { return data.DataAfter; }
set { CheckChanged(data.DataAfter, value); data.DataAfter = value; }
}
// Population.
internal void PopulateFrom (Data data)
{
ItemId = data.ItemId;
Attribute = data.Attribute;
Logged = data.Logged;
DataBefore = data.DataBefore;
DataAfter = data.DataAfter;
base.PopulateFrom(data);
}
public Data Clone ()
{
Data data = new Data();
data.PopulateFrom(this);
return data;
}
}
//-------------------------------------------------------------------
// Error field - identify properties with validation error.
public new class ErrField : SacsHierarchyItem.ErrField
{
// Identifies the field that has invalid data.
public ValidValue ItemType { get; set; } = ValidValue.Valid;
public ValidValue ItemId { get; set; } = ValidValue.Valid;
public ValidValue Attribute { get; set; } = ValidValue.Valid;
public ValidValue Logged { get; set; } = ValidValue.Valid;
public ValidValue DataBefore { get; set; } = ValidValue.Valid;
public ValidValue DataAfter { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
private readonly Data data = new Data();
//-------------------------------------------------------------------
// Construction.
public SaUpdateLogEntry (ItemId itemId, String attribute, DateTime logged) :
base()
{
base.SetData(data);
ItemId = itemId;
Attribute = attribute;
Logged = logged;
Status = DefaultStatus;
}
//-------------------------------------------------------------------
// Statuses.
private static readonly List<SaStatus> validStatuses = new List<SaStatus>()
{
SaStatus.Logged,
SaStatus.Deleted
};
public static SaStatus DefaultStatus { get { return LoggedStatus; } }
public static SaStatus LoggedStatus { get { return SaStatus.Logged; } }
public static List<SaStatus> ValidStatuses { get { return new List<SaStatus>(validStatuses); } }
public static DataValue.TriStateType GetStatusTriState (SaStatus status)
{
switch (status)
{
case SaStatus.Logged:
return DataValue.TriStateType.Green;
case SaStatus.Deleted:
return DataValue.TriStateType.Purple;
}
return DataValue.TriStateType.Unknown;
}
//-------------------------------------------------------------------
// Properties.
public Data GetData () { return data.Clone(); }
public void SetData (Data data)
{
// Properties that cannot be changed if previously specified.
if (ItemId.Type >= 0 && ItemId.Type != data.ItemId.Type)
throw new NotSupportedException($"{SysUtil.Fn} Item type cannot be changed");
if (SysId.IsValid(ItemId.Id) && SysId.ToInt(ItemId.Id) != SysId.ToInt(data.ItemId.Id))
throw new NotSupportedException($"{SysUtil.Fn} Item Id cannot be changed");
if (!StringUtil.IsEmpty(Attribute) && !Attribute.Equals(data.Attribute))
throw new NotSupportedException($"{SysUtil.Fn} Attribute cannot be changed");
if (Logged != DateTime.MinValue && !Logged.Equals(data.Logged))
throw new NotSupportedException($"{SysUtil.Fn} Logged date/time cannot be changed");
// Populate individual properties to ensure that 'Changed' indicator is kept up to date.
this.data.PopulateFrom(data);
}
public ItemId ItemId
{
get { return data.ItemId; }
protected set { data.ItemId = value; }
}
public String Attribute
{
get { return data.Attribute; }
protected set { data.Attribute = value; }
}
public DateTime Logged
{
get { return data.Logged; }
protected set { data.Logged = value; }
}
public String DataBefore
{
get { return data.DataBefore; }
set { data.DataBefore = value; }
}
public String DataAfter
{
get { return data.DataAfter; }
set { data.DataAfter = value; }
}
//-------------------------------------------------------------------
// List parameters.
/// <summary>
/// Item list parameters.
/// </summary>
public new class Params : SacsHierarchyItem.Params
{
public List<ItemId> IncludedItemIds { get; } = new List<ItemId>();
public List<String> IncludedAttributes { get; } = new List<String>();
public DateTime Logged { get; set; } = DateTime.MinValue;
public DateTime LoggedFrom { get; set; } = DateTime.MinValue;
public DateTime LoggedTo { get; set; } = DateTime.MinValue;
}
//-------------------------------------------------------------------
// L i s t
//-------------------------------------------------------------------
public class List : List<SaUpdateLogEntry>
{
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,163 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Base.UpdateLog
{
//=======================================================================
public class SaUpdateLogItemMonitor : SacsStateItem
{
//-------------------------------------------------------------------
// Configuration.
public class Config
{
public Config (SaUpdateLogConsole updateLogConsole, DbUpdateInfo dbUpdateInfo)
{
UpdateLogConsole = updateLogConsole;
DbUpdateInfo = dbUpdateInfo;
}
public SaUpdateLogConsole UpdateLogConsole { get; }
public short ItemType { get; set; }
public SysId ItemId { get; set; }
public DbUpdateInfo DbUpdateInfo { get; }
}
//-------------------------------------------------------------------
// Definitions.
public class AttrData
{
public AttrData (String name)
{
Name = name;
}
public String Name { get; private set; }
public DataValue ValueBefore { get; internal set; } = new DataValue();
public DataValue ValueAfter { get; internal set; } = new DataValue();
}
//-------------------------------------------------------------------
// Data members.
private Config config = null;
private readonly Dictionary<String,AttrData> attrUpdateMap = new Dictionary<String,AttrData>();
//-------------------------------------------------------------------
// Static initialisation
static SaUpdateLogItemMonitor ()
{
}
//-------------------------------------------------------------------
// Protected construction - use derived classes.
protected SaUpdateLogItemMonitor (Config config)
{
this.config = config;
}
//-------------------------------------------------------------------
// Properties.
public short ItemType { get { return config.ItemType; } }
public SysId ItemId { get { return config.ItemId; } }
public List<AttrData> AttrUpdates
{
get
{
// Compile list of attributes whose value has changed.
List<AttrData> attrUpdates = new List<AttrData>();
foreach (AttrData attrData in attrUpdateMap.Values)
{
if (!FormatDataValue(attrData.ValueBefore).Equals(FormatDataValue(attrData.ValueAfter)))
{
// Data values are ppre-formatted as Strings for database storage.
attrUpdates.Add(new AttrData(attrData.Name) { ValueBefore=new DataValue(FormatDataValue(attrData.ValueBefore)), ValueAfter= new DataValue(FormatDataValue(attrData.ValueAfter)) });
}
}
return attrUpdates;
}
}
public DbUpdateInfo DbUpdateInfo { get { return config.DbUpdateInfo; } }
//-------------------------------------------------------------------
// Log updates.
public bool LogUpdates ()
{
ClearErrorState();
if (!config.UpdateLogConsole.LogUpdates(this))
SetErrorState(config.UpdateLogConsole.ErrorStateMessage);
return OK;
}
protected virtual bool IsColumnChangeLogged (String attrName)
{
if (!config.UpdateLogConsole.CanUpdateDatabase) return false;
return true;
}
//-------------------------------------------------------------------
// Populate attribute values.
protected bool RecordAttrValue (String attrName, String value, bool newValue)
{
return RecordAttrValue(attrName, new DataValue(value), newValue);
}
protected bool RecordAttrValue (String attrName, int value, bool newValue, bool blankZeroValue = true)
{
return RecordAttrValue(attrName, new DataValue(value == 0 && blankZeroValue ? "" : value.ToString()), newValue);
}
protected bool RecordAttrValue (String attrName, decimal value, bool newValue, bool blankZeroValue = true, ushort decimals = 2)
{
return RecordAttrValue(attrName, new DataValue(value == 0.0m && blankZeroValue ? "" : value.ToString("N" + decimals.ToString())), newValue);
}
protected bool RecordAttrValue (String attrName, DateTime value, bool newValue, bool includeTime = true)
{
return RecordAttrValue(attrName, new DataValue(DateUtil.Format(value, (includeTime ? "d-MMM-yyyy HH:mm" : "d-MMM-yyyy"))), newValue);
}
protected bool RecordAttrValue (String attrName, DataValue value, bool newValue)
{
ClearErrorState();
if (attrName.IsEmpty()) return SetErrorState("Blank attribute name ["+GetType().Name+"]");
if (!IsColumnChangeLogged(attrName)) return true;
if (newValue)
SetAttrValueAfter(attrName, value);
else
SetAttrValueBefore(attrName, value);
return OK;
}
public void SetAttrValueBefore (String attrName, DataValue value)
{
AttrData attrData = (attrUpdateMap.ContainsKey(attrName) ? attrUpdateMap[attrName] : null);
if (attrData == null)
{
attrData = new AttrData(attrName);
attrUpdateMap[attrName] = attrData;
}
attrData.ValueBefore = new DataValue(value);
}
public void SetAttrValueAfter (String attrName, DataValue value)
{
AttrData attrData = (attrUpdateMap.ContainsKey(attrName) ? attrUpdateMap[attrName] : null);
if (attrData == null)
{
attrData = new AttrData(attrName);
attrUpdateMap[attrName] = attrData;
}
attrData.ValueAfter = new DataValue(value);
}
//-------------------------------------------------------------------
// Format data value for database storage.
private static String FormatDataValue (DataValue dataValue)
{
String value = (dataValue != null ? dataValue.ToString() : "");
StringUtil.ReplaceAll(value, "\t", " ");
StringUtil.ReplaceAll(value, "\n\r", "\n");
StringUtil.ReplaceAll(value, "\r\n", "\n");
StringUtil.ReplaceAll(value, "\r", " ");
StringUtil.ReplaceAll(value, "\n", " ");
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,205 @@
using System;
using System.Collections.Generic;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Base.UpdateLog
{
//=======================================================================
public abstract class SaUpdateLogMgr : SacsItemMgr
{
//-------------------------------------------------------------------
// Data members.
private readonly Dictionary<SysId,String> userNames = new Dictionary<SysId, string>();
//-------------------------------------------------------------------
// Static initialisation.
static SaUpdateLogMgr ()
{
}
//-------------------------------------------------------------------
// Construction.
protected SaUpdateLogMgr (SaUpdateLogConsole updateLogConsole)
{
UpdateLogConsole = updateLogConsole;
}
//-------------------------------------------------------------------
// Properties.
protected SaUpdateLogConsole UpdateLogConsole { get; }
public abstract bool DatabaseIsValid { get; }
public abstract bool CanUpdateDatabase { get; }
//*******************************************************************
// U p d a t e L o g E n t r i e s
//*******************************************************************
// Retrieve individual update log entries.
public abstract bool LogEntryExists (SaUpdateLogEntry logEntry);
public abstract bool LogEntryExists (ItemId itemId, String attribute, DateTime logged);
public abstract SaUpdateLogEntry GetLogEntry (ItemId itemId, String attribute, DateTime logged);
// Create Update Log Entry.
public abstract SaUpdateLogEntry CreateLogEntry (ItemId itemId, String attribute);
//-------------------------------------------------------------------
// Validate Update Log Entry.
public bool IsValidLogEntry (SaUpdateLogEntry logEntry)
{
ClearErrorState();
if (logEntry == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidLogEntryData(logEntry.GetData(), new SaUpdateLogEntry.ErrField());
}
public virtual bool IsValidLogEntryData (SaUpdateLogEntry.Data logEntryData, SaUpdateLogEntry.ErrField errField)
{
ClearErrorState();
if ((int)logEntryData.ItemId.Type < 1)
{
errField.ItemType = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.ItemTypeNotSpecified);
}
if (!SysId.IsValid(logEntryData.ItemId.Id))
{
errField.ItemId = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.ItemIdNotSpecified);
}
if (!IsValidValue(logEntryData.Attribute, "attribute", (long)SaUpdateLogDbDfn.GetColTextLen(SaUpdateLogDbDfn.ColumnIdx.SaAttrUpdate_Attribute), true))
{
errField.Attribute = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!IsValidValue(logEntryData.DataBefore, "data before", (long)SaUpdateLogDbDfn.GetColTextLen(SaUpdateLogDbDfn.ColumnIdx.SaAttrUpdate_DataBefore)))
{
errField.DataBefore = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!IsValidValue(logEntryData.DataAfter, "data after", (long)SaUpdateLogDbDfn.GetColTextLen(SaUpdateLogDbDfn.ColumnIdx.SaAttrUpdate_DataAfter)))
{
errField.DataAfter = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
// Common properties.
if (!IsValidValue(logEntryData.Notes, "notes", (long)SaUpdateLogDbDfn.GetColTextLen(SaUpdateLogDbDfn.ColumnIdx.SaAttrUpdate_Notes)))
{
errField.Notes = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!SaUpdateLogEntry.ValidStatuses.Contains(logEntryData.Status))
{
errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.InvalidStatus);
}
return true;
}
//-------------------------------------------------------------------
// Update Log Entry database interface.
public abstract bool LogUpdates (SaUpdateLogItemMonitor updateLogItemMonitor, DbUpdateInfo dbUpdateInfo);
public abstract bool InsertLogEntry (SaUpdateLogEntry logEntry, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateLogEntry (SaUpdateLogEntry logEntry, DbUpdateInfo dbUpdateInfo);
public virtual bool LogEntryCanBeDeleted (SaUpdateLogEntry logEntry)
{
ClearErrorState();
return true;
}
public abstract bool DeleteLogEntry (SaUpdateLogEntry logEntry, DbUpdateInfo dbUpdateInfo);
public abstract bool ClearLogEntriesForItem (ItemId itemId, DbUpdateInfo dbUpdateInfo);
//-------------------------------------------------------------------
// Update Log Entry list.
public abstract ColumnDfn GetLogEntryColumnDfn (SaUpdateLogEntry.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetLogEntryQueryFilter (SaUpdateLogEntry.Params prm);
public abstract long GetLogEntryCount (SaUpdateLogEntry.Params prm);
public abstract List<SaUpdateLogEntry> GetLogEntryList (SaUpdateLogEntry.Params prm);
public abstract DbResultSet ExecuteLogEntryQuery (List<ColumnDfn> columns, SaUpdateLogEntry.Params prm);
//-------------------------------------------------------------------
/// <summary>
/// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary>
public virtual DataValue GetLogEntryDataValue (ColumnDfn column, NamedValue.Map values)
{
DataValue value = new DataValue();
switch ((SaUpdateLogEntry.Column)column.Id)
{
//-----------------------------------------------------------
// Item type.
case SaUpdateLogEntry.Column.ItemType_Desc:
{
short itemType = (short)values.GetValue(column.DataName).AsLong();
value = new DataValue(itemType.ToString());
}
break;
//-----------------------------------------------------------
// Data values.
case SaUpdateLogEntry.Column.DataBefore:
case SaUpdateLogEntry.Column.DataAfter:
{
value = new DataValue(values.GetValue(column.DataName).ToString());
String attribute = values.GetValue(GetLogEntryColumnDfn(SaUpdateLogEntry.Column.Attribute).DataName).ToString();
if (attribute.EqualsCI("Status"))
value = new DataValue(SacsSystem.GetStatusDescForCode(value.ToString()));
}
break;
//-----------------------------------------------------------
// Notes.
case SaUpdateLogEntry.Column.Notes:
{
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
}
break;
//-----------------------------------------------------------
// Status.
case SaUpdateLogEntry.Column.Status_Desc:
case SaUpdateLogEntry.Column.Status_Ind:
{
String statusCode = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusCode);
if (column.Id == (int)SaUpdateLogEntry.Column.Status_Desc)
{
String statusDesc = SacsSystem.GetStatusDescForCode(statusCode);
value = new DataValue(statusDesc);
}
else if (column.Id == (int)SaUpdateLogEntry.Column.Status_Ind)
{
DataValue.TriStateType triState = DataValue.TriStateType.Unknown;
if (status == SaStatus.Logged)
triState = DataValue.TriStateType.Green;
value = new DataValue(triState);
}
}
break;
//-----------------------------------------------------------
// Notes.
case SaUpdateLogEntry.Column.CreateBy_Name:
{
SysId userId = new SysId(StringUtil.ToInt(values.GetValue(GetLogEntryColumnDfn(SaUpdateLogEntry.Column.CreateBy).DataName).ToString()));
String userName = SysId.ToString(userId);
if (SysId.IsValid(userId) && !userNames.ContainsKey(userId))
{
foreach (var userNameKV in UpdateLogConsole.GetNameForUserIds(new List<SysId> { userId }))
userNames.Add(userNameKV.Key, userNameKV.Value);
}
if (userNames.ContainsKey(userId))
userName = userNames[userId];
value = new DataValue(userName);
}
break;
//-----------------------------------------------------------
}
return value;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
+12
View File
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<RootNamespace>Sarand.Net.Standard</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\SacsStandardBase\SacsStandardBase.csproj" />
</ItemGroup>
</Project>