Initial commit: JDE Scoping Tool migration project
Set up repository with legacy .NET Framework 4.8 source (OLD/), new .NET 10 Blazor solution (NEW/), OpenSpec specifications, documentation, and project configuration.
This commit is contained in:
Executable
+80
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
|
||||
namespace DataModel.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// JDE date/time conversion helpers
|
||||
/// </summary>
|
||||
public static class DateTimeHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Strips time component from datetime
|
||||
/// </summary>
|
||||
/// <param name="source">Datetime to strip time component from</param>
|
||||
/// <returns>Date component of source datetime</returns>
|
||||
public static int ToJDEDate(this DateTime source)
|
||||
{
|
||||
return (source.Year < 2000 ? 0 : 100000) + (source.Year % 100) * 1000 + source.DayOfYear;
|
||||
}
|
||||
|
||||
public static DateTime FromJDEDate(this int sourceDate)
|
||||
{
|
||||
if (sourceDate == 0) { return new DateTime(1900, 1, 1); }
|
||||
|
||||
DateTime baseDate = new DateTime(1900, 1, 1);
|
||||
try
|
||||
{
|
||||
string strSource = sourceDate.ToString();
|
||||
|
||||
if (strSource.Length < 5 || strSource.Length > 6) { throw new Exception($"invalid source date length ({strSource.Length})"); }
|
||||
|
||||
if (strSource.StartsWith("1"))
|
||||
{
|
||||
baseDate = new DateTime(2000, 1, 1);
|
||||
}
|
||||
|
||||
baseDate = baseDate.AddYears(int.Parse(strSource.Substring(1, 2)));
|
||||
baseDate = baseDate.AddDays(int.Parse(strSource.Substring(3)) - 1);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
return baseDate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Strips date component from datetime
|
||||
/// </summary>
|
||||
/// <param name="source">Datetime to strip date component from</param>
|
||||
/// <returns>Time component of source datetime</returns>
|
||||
public static int ToJDETime(this DateTime source)
|
||||
{
|
||||
return source.Hour * 10000 + source.Minute * 100 + source.Second;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the JDE date + time components into a datetime
|
||||
/// </summary>
|
||||
/// <param name="sourceDate">JDE date component</param>
|
||||
/// <param name="sourceTime">JDE time component</param>
|
||||
/// <returns>Combined datetime from source JDE date/time components</returns>
|
||||
public static DateTime FromJDEDateTime(this DateTime sourceDate, int sourceTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
int hours = sourceTime / 10000;
|
||||
int minutes = (sourceTime % 10000) / 100;
|
||||
int seconds = sourceTime % 100;
|
||||
|
||||
return sourceDate.Date.AddHours(hours).AddMinutes(minutes).AddSeconds(seconds);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return sourceDate;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+141
@@ -0,0 +1,141 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace DataModel.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper methods for encryption / decryption
|
||||
/// </summary>
|
||||
public class EncryptionHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Default salt value
|
||||
/// </summary>
|
||||
private const string DEFAULT_SALT = ")kjdnl3k1jh234a9";
|
||||
|
||||
/// <summary>
|
||||
/// Default hashing algorithm to use
|
||||
/// </summary>
|
||||
private const string DEFAULT_HASH_ALGORITHM = "SHA1";
|
||||
|
||||
/// <summary>
|
||||
/// Default number of iterations to do
|
||||
/// </summary>
|
||||
private const int DEFAULT_PASSWORD_ITERATION = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Default initialization vector
|
||||
/// </summary>
|
||||
private const string DEFAULT_INITIAL_VECTOR = "X8pgVu239uOjdKH1";
|
||||
|
||||
/// <summary>
|
||||
/// Default encryption keysize
|
||||
/// </summary>
|
||||
private const int DEFAULT_KEYSIZE = 256;
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a string
|
||||
/// </summary>
|
||||
/// <param name="plainText">Text to be encrypted</param>
|
||||
/// <param name="password">Password to encrypt with</param>
|
||||
/// <param name="salt">Salt to encrypt with</param>
|
||||
/// <param name="hashAlgorithm">Can be either SHA1 or MD5</param>
|
||||
/// <param name="passwordIterations">Number of iterations to do</param>
|
||||
/// <param name="initialVector">Needs to be 16 ASCII characters long</param>
|
||||
/// <param name="keySize">Can be 128, 192, or 256</param>
|
||||
/// <returns>An encrypted string</returns>
|
||||
public static string Encrypt(string plainText, string password, string salt = DEFAULT_SALT, string hashAlgorithm = DEFAULT_HASH_ALGORITHM, int passwordIterations = DEFAULT_PASSWORD_ITERATION, string initialVector = DEFAULT_INITIAL_VECTOR, int keySize = DEFAULT_KEYSIZE)
|
||||
{
|
||||
if (string.IsNullOrEmpty(plainText))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
byte[] initialVectorBytes = Encoding.ASCII.GetBytes(initialVector);
|
||||
byte[] saltValueBytes = Encoding.ASCII.GetBytes(salt);
|
||||
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
|
||||
|
||||
PasswordDeriveBytes derivedPassword = new PasswordDeriveBytes(password, saltValueBytes, hashAlgorithm, passwordIterations);
|
||||
byte[] keyBytes = derivedPassword.GetBytes(keySize / 8);
|
||||
|
||||
RijndaelManaged symmetricKey = new RijndaelManaged
|
||||
{
|
||||
Mode = CipherMode.CBC
|
||||
};
|
||||
byte[] cipherTextBytes = null;
|
||||
|
||||
using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initialVectorBytes))
|
||||
{
|
||||
using (MemoryStream memStream = new MemoryStream())
|
||||
{
|
||||
using (CryptoStream cryptoStream = new CryptoStream(memStream, encryptor, CryptoStreamMode.Write))
|
||||
{
|
||||
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
|
||||
cryptoStream.FlushFinalBlock();
|
||||
cipherTextBytes = memStream.ToArray();
|
||||
memStream.Close();
|
||||
cryptoStream.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
symmetricKey.Clear();
|
||||
|
||||
return Convert.ToBase64String(cipherTextBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a string
|
||||
/// </summary>
|
||||
/// <param name="encrypted">Text to be decrypted</param>
|
||||
/// <param name="password">Password to decrypt with</param>
|
||||
/// <param name="salt">Salt to decrypt with</param>
|
||||
/// <param name="hashAlgorithm">Can be either SHA1 or MD5</param>
|
||||
/// <param name="passwordIterations">Number of iterations to do</param>
|
||||
/// <param name="initialVector">Needs to be 16 ASCII characters long</param>
|
||||
/// <param name="keySize">Can be 128, 192, or 256</param>
|
||||
/// <returns>A decrypted string</returns>
|
||||
public static string Decrypt(string encrypted, string password, string salt = DEFAULT_SALT, string hashAlgorithm = DEFAULT_HASH_ALGORITHM, int passwordIterations = DEFAULT_PASSWORD_ITERATION, string initialVector = DEFAULT_INITIAL_VECTOR, int keySize = DEFAULT_KEYSIZE)
|
||||
{
|
||||
if (string.IsNullOrEmpty(encrypted))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
byte[] initialVectorBytes = Encoding.ASCII.GetBytes(initialVector);
|
||||
byte[] saltValueBytes = Encoding.ASCII.GetBytes(salt);
|
||||
byte[] cipherTextBytes = Convert.FromBase64String(encrypted);
|
||||
|
||||
PasswordDeriveBytes derivedPassword = new PasswordDeriveBytes(password, saltValueBytes, hashAlgorithm, passwordIterations);
|
||||
byte[] keyBytes = derivedPassword.GetBytes(keySize / 8);
|
||||
|
||||
RijndaelManaged symmetricKey = new RijndaelManaged
|
||||
{
|
||||
Mode = CipherMode.CBC
|
||||
};
|
||||
|
||||
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
|
||||
int byteCount = 0;
|
||||
|
||||
using (ICryptoTransform decrypt = symmetricKey.CreateDecryptor(keyBytes, initialVectorBytes))
|
||||
{
|
||||
using (MemoryStream memStream = new MemoryStream(cipherTextBytes))
|
||||
{
|
||||
using (CryptoStream cryptoStream = new CryptoStream(memStream, decrypt, CryptoStreamMode.Read))
|
||||
{
|
||||
|
||||
byteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
|
||||
memStream.Close();
|
||||
cryptoStream.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
symmetricKey.Clear();
|
||||
|
||||
return Encoding.UTF8.GetString(plainTextBytes, 0, byteCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Reflection;
|
||||
using Fasterflect;
|
||||
|
||||
namespace DataModel.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// IEnumerable extension helpers
|
||||
/// </summary>
|
||||
public static class GenericListDataReaderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates generic data reader for bulk copies from list
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Element data type</typeparam>
|
||||
/// <param name="list">Source list</param>
|
||||
/// <returns>Data reader to parse list contents</returns>
|
||||
public static GenericListDataReader<T> GetDataReader<T>(this IEnumerable<T> list) where T : class
|
||||
{
|
||||
return new GenericListDataReader<T>(list);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Data reader that parses list of generic elements
|
||||
/// </summary>
|
||||
public class GenericListDataReader : IDataReader
|
||||
{
|
||||
public int Count { get; set; }
|
||||
private readonly IEnumerator<object> list = null;
|
||||
private readonly List<PropertyInfo> properties = new List<PropertyInfo>();
|
||||
private readonly Dictionary<string, int> nameLookup = new Dictionary<string, int>();
|
||||
private readonly string[] propertyNames;
|
||||
|
||||
public GenericListDataReader(IEnumerable<object> list, Type type)
|
||||
{
|
||||
this.list = list.GetEnumerator();
|
||||
|
||||
properties.AddRange(type.GetProperties(BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly));
|
||||
propertyNames = new string[properties.Count];
|
||||
|
||||
for (int i = 0; i < properties.Count; i++)
|
||||
{
|
||||
nameLookup[properties[i].Name] = i;
|
||||
propertyNames[i] = properties[i].Name;
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
list.Dispose();
|
||||
}
|
||||
|
||||
public int Depth => throw new NotImplementedException();
|
||||
|
||||
public DataTable GetSchemaTable()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsClosed => false;
|
||||
|
||||
public bool NextResult()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Read()
|
||||
{
|
||||
bool readResult = list.MoveNext();
|
||||
|
||||
//Update counter
|
||||
if (readResult)
|
||||
{
|
||||
Count++;
|
||||
}
|
||||
|
||||
return readResult;
|
||||
}
|
||||
|
||||
public int RecordsAffected => throw new NotImplementedException();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
public int FieldCount => properties.Count;
|
||||
|
||||
public bool GetBoolean(int i)
|
||||
{
|
||||
return (bool)GetValue(i);
|
||||
}
|
||||
|
||||
public byte GetByte(int i)
|
||||
{
|
||||
return (byte)GetValue(i);
|
||||
}
|
||||
|
||||
public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public char GetChar(int i)
|
||||
{
|
||||
return (char)GetValue(i);
|
||||
}
|
||||
|
||||
public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IDataReader GetData(int i)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetDataTypeName(int i)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public DateTime GetDateTime(int i)
|
||||
{
|
||||
return (DateTime)GetValue(i);
|
||||
}
|
||||
|
||||
public decimal GetDecimal(int i)
|
||||
{
|
||||
return (decimal)GetValue(i);
|
||||
}
|
||||
|
||||
public double GetDouble(int i)
|
||||
{
|
||||
return (double)GetValue(i);
|
||||
}
|
||||
|
||||
public Type GetFieldType(int i)
|
||||
{
|
||||
return properties[i].PropertyType;
|
||||
}
|
||||
|
||||
public float GetFloat(int i)
|
||||
{
|
||||
return (float)GetValue(i);
|
||||
}
|
||||
|
||||
public Guid GetGuid(int i)
|
||||
{
|
||||
return (Guid)GetValue(i);
|
||||
}
|
||||
|
||||
public short GetInt16(int i)
|
||||
{
|
||||
return (short)GetValue(i);
|
||||
}
|
||||
|
||||
public int GetInt32(int i)
|
||||
{
|
||||
return (int)GetValue(i);
|
||||
}
|
||||
|
||||
public long GetInt64(int i)
|
||||
{
|
||||
return (long)GetValue(i);
|
||||
}
|
||||
|
||||
public string GetName(int i)
|
||||
{
|
||||
return properties[i].Name;
|
||||
}
|
||||
|
||||
public int GetOrdinal(string name)
|
||||
{
|
||||
if (nameLookup.ContainsKey(name))
|
||||
{
|
||||
return nameLookup[name];
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetString(int i)
|
||||
{
|
||||
return (string)GetValue(i);
|
||||
}
|
||||
|
||||
public object GetValue(int i)
|
||||
{
|
||||
string name = propertyNames[i];
|
||||
return list.Current.GetPropertyValue(name);
|
||||
}
|
||||
|
||||
public int GetValues(object[] values)
|
||||
{
|
||||
int getValues = Math.Max(FieldCount, values.Length);
|
||||
|
||||
for (int i = 0; i < getValues; i++)
|
||||
{
|
||||
values[i] = GetValue(i);
|
||||
}
|
||||
|
||||
return getValues;
|
||||
}
|
||||
|
||||
public bool IsDBNull(int i)
|
||||
{
|
||||
return GetValue(i) == null;
|
||||
}
|
||||
|
||||
public object this[string name] => list.Current.GetPropertyValue(name);
|
||||
|
||||
public object this[int i] => GetValue(i);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Data reader that parses list of generic elements
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Element data type</typeparam>
|
||||
public class GenericListDataReader<T> : GenericListDataReader where T : class
|
||||
{
|
||||
public GenericListDataReader(IEnumerable<T> list)
|
||||
: base(list, typeof(T))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace DataModel.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// JSON serialization helpers
|
||||
/// </summary>
|
||||
public static class JsonHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts parameter to JSON
|
||||
/// </summary>
|
||||
/// <param name="value">Value to serialize</param>
|
||||
/// <returns>Parameter value serialized in JSON format</returns>
|
||||
public static string ToJSON<T>(this T value)
|
||||
{
|
||||
return value == null ?
|
||||
"{}" :
|
||||
JsonConvert.SerializeObject(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses value from JSON
|
||||
/// </summary>
|
||||
/// <param name="json">JSON to parse</param>
|
||||
/// <returns>Parsed value</returns>
|
||||
public static T FromJSON<T>(string json)
|
||||
{
|
||||
T value = default;
|
||||
try
|
||||
{
|
||||
value = JsonConvert.DeserializeObject<T>(json);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+59
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DataModel.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// LINQ helper methods
|
||||
/// </summary>
|
||||
public static class LinqHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Filters for distinct elements by given key
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">Source data type</typeparam>
|
||||
/// <typeparam name="TKey">Key data type</typeparam>
|
||||
/// <param name="source">Source data</param>
|
||||
/// <param name="keySelector">Key value function</param>
|
||||
/// <returns>Distinct elements from source</returns>
|
||||
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
|
||||
{
|
||||
HashSet<TKey> keys = new HashSet<TKey>();
|
||||
foreach (TSource element in source)
|
||||
{
|
||||
if (keys.Add(keySelector(element)))
|
||||
{
|
||||
yield return element;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Groups the data into batches of give size
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Data type of data</typeparam>
|
||||
/// <param name="allData">Data to break into batches</param>
|
||||
/// <param name="batchSize">Size of batches to create</param>
|
||||
/// <returns>Enumerable collection of batches to process</returns>
|
||||
public static IEnumerable<List<T>> BatchGroup<T>(this IEnumerable<T> allData, int batchSize)
|
||||
{
|
||||
List<T> batchGroup = new List<T>();
|
||||
|
||||
//Loop through data and group into batches
|
||||
foreach (T data in allData)
|
||||
{
|
||||
batchGroup.Add(data);
|
||||
|
||||
if (batchGroup.Count == batchSize)
|
||||
{
|
||||
//Return batch of data
|
||||
yield return batchGroup;
|
||||
batchGroup = new List<T>();
|
||||
}
|
||||
}
|
||||
|
||||
//Return remaining data
|
||||
yield return batchGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
namespace DataModel.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// SQL server ADO helpers
|
||||
/// </summary>
|
||||
public static class SqlHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Binds the parameter to the command
|
||||
/// </summary>
|
||||
/// <param name="command">Command to bind parameter to</param>
|
||||
/// <param name="parameterName">Name of parameter</param>
|
||||
/// <param name="parameterValue">Value of parameter</param>
|
||||
/// <returns>Bound parameter</returns>
|
||||
public static SqlParameter Bind(this SqlCommand command, string parameterName, object parameterValue)
|
||||
{
|
||||
return parameterValue != null
|
||||
? command.Parameters.AddWithValue(parameterName, parameterValue)
|
||||
: command.Parameters.AddWithValue(parameterName, DBNull.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Binds the parameter to the command
|
||||
/// </summary>
|
||||
/// <param name="command">Command to bind parameter to</param>
|
||||
/// <param name="parameterName">Name of parameter</param>
|
||||
/// <param name="parameterValue">Value of parameter</param>
|
||||
/// <returns>Bound parameter</returns>
|
||||
public static SqlParameter Bind(this SqlCommand command, string parameterName, string parameterValue)
|
||||
{
|
||||
return !string.IsNullOrEmpty(parameterValue) ?
|
||||
command.Parameters.AddWithValue(parameterName, parameterValue) :
|
||||
command.Parameters.AddWithValue(parameterName, DBNull.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Binds the parameter to the command
|
||||
/// </summary>
|
||||
/// <param name="command">Command to bind parameter to</param>
|
||||
/// <param name="parameterName">Name of parameter</param>
|
||||
/// <param name="parameterValue">Value of parameter</param>
|
||||
/// <returns>Bound parameter</returns>
|
||||
public static SqlParameter Bind(this SqlCommand command, string parameterName, byte[] parameterValue)
|
||||
{
|
||||
return parameterValue != null ?
|
||||
command.Parameters.AddWithValue(parameterName, parameterValue) :
|
||||
command.Parameters.AddWithValue(parameterName, DBNull.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user