chore: deploy initial linqpad queries
This commit is contained in:
@@ -0,0 +1,305 @@
|
||||
<Query Kind="Program">
|
||||
<Reference><ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll</Reference>
|
||||
<Reference><RuntimeDirectory>\System.Data.Entity.Design.dll</Reference>
|
||||
<Reference><RuntimeDirectory>\System.Data.Entity.dll</Reference>
|
||||
<NuGetReference>LINQtoCSV</NuGetReference>
|
||||
<Namespace>LINQtoCSV</Namespace>
|
||||
<Namespace>Newtonsoft.Json</Namespace>
|
||||
<Namespace>Newtonsoft.Json.Converters</Namespace>
|
||||
<Namespace>Newtonsoft.Json.Linq</Namespace>
|
||||
<Namespace>Newtonsoft.Json.Schema</Namespace>
|
||||
<Namespace>Newtonsoft.Json.Serialization</Namespace>
|
||||
<Namespace>System</Namespace>
|
||||
<Namespace>System.Diagnostics</Namespace>
|
||||
<Namespace>System.Diagnostics.Tracing</Namespace>
|
||||
<Namespace>System.Dynamic</Namespace>
|
||||
<Namespace>System.Globalization</Namespace>
|
||||
<Namespace>System.IO.Compression</Namespace>
|
||||
<Namespace>System.Data.Entity.Design.PluralizationServices</Namespace>
|
||||
</Query>
|
||||
|
||||
private PluralizationService ps => PluralizationService.CreateService(new CultureInfo("en-US"));
|
||||
|
||||
void Main()
|
||||
{
|
||||
var testExpando = new List<object>();
|
||||
var meds = new List<Inventory>();
|
||||
var inputFileDescription = new CsvFileDescription
|
||||
{
|
||||
SeparatorChar = '\t', // tab delimited
|
||||
FirstLineHasColumnNames = false, // no column names in first record
|
||||
FileCultureName = "en-US" // use formats used in The Netherlands
|
||||
};
|
||||
var cc = new CsvContext();
|
||||
var path = @"C:\Users\tlamb\Downloads\";
|
||||
var files = new[] {
|
||||
@"Outreach - Monthly Inventory Records - Inventory - March.tsv",
|
||||
@"Outreach - Monthly Inventory Records - Inventory - April.tsv",
|
||||
@"Outreach - Monthly Inventory Records - Inventory - May.tsv",
|
||||
@"Outreach - Monthly Inventory Records - Inventory - June.tsv"
|
||||
}.ToList();
|
||||
var nextmonth = new DateTime(2019, 2, 1);
|
||||
files.ForEach(inventory =>
|
||||
{
|
||||
nextmonth = nextmonth.AddMonths(1);
|
||||
var monthData = cc.Read<MyDataRow>(Path.Combine(path, inventory), inputFileDescription);
|
||||
var data = ConvertToDataRow(ConvertMyDataRow(monthData, nextmonth).ToList()).ToList();
|
||||
meds.AddRange(data);
|
||||
});
|
||||
|
||||
var medBrands = meds
|
||||
.Select(m => new PropDef(m))
|
||||
.Distinct(new NameBrandComparer())
|
||||
.OrderBy(m => m.name).ThenBy(m => m.type)
|
||||
.Select((m, i) => new
|
||||
{
|
||||
Id = i + 1,
|
||||
Medication = m.name,
|
||||
Brand = m.type,
|
||||
Minimum = Math.Max(m.inventory.StartQty, 10),
|
||||
m.inventory.Dosage,
|
||||
Unit = m.inventory.container, //ps.Singularize(m.inventory.container.Trim("() ".ToCharArray())),
|
||||
Package = Regex.Replace(m.inventory.PerBox, @"[^\d]*", ""),
|
||||
Per = m.inventory.Per, //ps.Singularize(m.inventory.Unit.Trim("() ".ToCharArray())),
|
||||
Purchased = m.inventory.Purchased
|
||||
})
|
||||
.ToList();
|
||||
|
||||
medBrands.Dump();
|
||||
foreach (var m in meds)
|
||||
{
|
||||
var mbx = medBrands.FirstOrDefault(mb => m.Medicine.Trim() == mb.Medication && m.MedicineBrand.Trim() == mb.Brand);
|
||||
if (mbx != null)
|
||||
{
|
||||
m.MedicineID = mbx.Id;
|
||||
}
|
||||
else
|
||||
{
|
||||
m.Dump();
|
||||
}
|
||||
};
|
||||
meds.GroupBy(m => m.MedicineID)
|
||||
.Select(grp => grp.Last())
|
||||
.OrderBy(m => m.MedicineID)
|
||||
.ThenBy(m => m.Expiry)
|
||||
.ThenBy(m => m.InvDate)
|
||||
.Dump();
|
||||
}
|
||||
|
||||
// Define other methods and classes here
|
||||
internal IEnumerable<object> ConvertMyDataRow(IEnumerable<MyDataRow> data, DateTime month)
|
||||
{
|
||||
var groupData = data.SelectMany(dr => dr.ToList())
|
||||
.GroupBy(t => t.LineNbr)
|
||||
.Select(t => new { Key = t.Key - 2, Values = t.ToList().Select(v => v.Value).ToArray() });
|
||||
//groupData.Dump("groupData");
|
||||
var properties = groupData.Where(d => d.Key < 0)
|
||||
.SelectMany(d => d.Values.Select(v => Regex.Replace(v, @"[\s()]", "")
|
||||
//.Replace("LastMonthsFinalQuantity", "Start_Quantity")
|
||||
.Replace("StartingQuantityBeginningofMonth", "StartQuantity")
|
||||
.Replace("StartingQuantityBeginningofCurrentMonth", "StartQuantity")
|
||||
.Replace("FinalQuantityEndofMonth", "FinalQuantity")
|
||||
.Replace("FinalQuantityEndofCurrentMonth", "FinalQuantity")
|
||||
.Replace("MedicationTotalStartQuantity", "MedicationTotal")).ToList()).ToArray();
|
||||
//properties.Dump("properties");
|
||||
var medication = string.Empty;
|
||||
var expandoData = groupData.Where(d => d.Key >= 0)
|
||||
.Select((t, j) =>
|
||||
{
|
||||
dynamic expando = new ExpandoObject();
|
||||
AddProperty(expando, "MedicineID", j);
|
||||
AddProperty(expando, "InvDate", month);
|
||||
int i = 0;
|
||||
t.Values.ToList().ForEach(d =>
|
||||
{
|
||||
var property = properties[i]
|
||||
.Replace("Medication", "Medicine");
|
||||
if (property == "Medicine")
|
||||
{
|
||||
if (string.IsNullOrEmpty(d))
|
||||
{
|
||||
d = medication;
|
||||
}
|
||||
medication = d;
|
||||
}
|
||||
AddProperty(expando, property, d ?? string.Empty);
|
||||
i++;
|
||||
});
|
||||
return expando;
|
||||
});
|
||||
return expandoData;
|
||||
}
|
||||
|
||||
internal IEnumerable<Inventory> ConvertToDataRow(List<object> data)
|
||||
{
|
||||
var newData =
|
||||
data.Select(d => (d as IDictionary<string, object>))
|
||||
.Select(d =>
|
||||
{
|
||||
var dr = new Inventory();
|
||||
d.Keys.ToList().ForEach(k =>
|
||||
{
|
||||
var value = d[k];
|
||||
var name = Regex.Replace(k, "[^A-Za-z]", "");
|
||||
PropertyInfo prop = dr.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
if (null != prop && prop.CanWrite)
|
||||
{
|
||||
prop.SetValue(dr, value, null);
|
||||
}
|
||||
});
|
||||
return dr;
|
||||
});
|
||||
return newData;
|
||||
}
|
||||
|
||||
// Define other methods and classes here
|
||||
internal class MyDataRow : List<DataRowItem>, IDataRow
|
||||
{
|
||||
}
|
||||
|
||||
public static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue)
|
||||
{
|
||||
// ExpandoObject supports IDictionary so we can extend it like this
|
||||
var expandoDict = expando as IDictionary<string, object>;
|
||||
if (expandoDict.ContainsKey(propertyName))
|
||||
expandoDict[propertyName] = propertyValue;
|
||||
else
|
||||
expandoDict.Add(propertyName, propertyValue);
|
||||
}
|
||||
|
||||
public class Inventory
|
||||
{
|
||||
internal Regex regex = new Regex(@"\(?(Tube|Bottle|Tablet|Capsule|Lancet|Vial|Kit)[ s]?\)?", RegexOptions.IgnoreCase);
|
||||
internal string PerBox { get; set; }
|
||||
internal string container => ps.Singularize(regex.Match(PerBox).Value.Trim("() ".ToCharArray()));
|
||||
internal string StartQuantity { get; set; }
|
||||
internal string Received { get; set; }
|
||||
internal string Output { get; set; }
|
||||
internal string FinalQuantity { get; set; }
|
||||
internal string Notes { get; set; }
|
||||
internal string ExpirationDate { get; set; }
|
||||
internal string LastMonthsFinalQuantity { get; set; }
|
||||
|
||||
internal PluralizationService ps => PluralizationService.CreateService(new CultureInfo("en-US"));
|
||||
|
||||
public int MedicineID { get; set; }
|
||||
public DateTime InvDate { get; set; }
|
||||
public string Medicine { get; set; }
|
||||
public string MedicineBrand { get; set; }
|
||||
public string Dosage { get; set; }
|
||||
public string Unit { get; set; }
|
||||
public string Pkg => container != string.Empty ? PerBox.Replace(container, "").TrimEnd() : PerBox;
|
||||
public string Per => ps.Singularize((string.IsNullOrEmpty(container) ? regex.Match(Unit).Value : container).Trim());
|
||||
public int StartQty => ParseStartQuantity(StartQuantity, LastMonthsFinalQuantity);
|
||||
public int FinalQty => ParseFinalQuantity(FinalQuantity);
|
||||
public DateTime Purchased => !Notes.StartsWith("Purchased") ? new DateTime(2018,1,1).Date
|
||||
: DateTime.Parse(Regex.Replace(Notes, @"[^\d/]*", ""));
|
||||
public DateTime Expiry => ParseExpiry();
|
||||
public string Note => !Notes.StartsWith("Purchased") ? Notes : string.Empty;
|
||||
// public string Medication { get; set; }
|
||||
internal string BrandTotal { get; set; }
|
||||
internal string MedicationTotal { get; set; }
|
||||
|
||||
public Inventory()
|
||||
{
|
||||
Medicine = string.Empty;
|
||||
Dosage = string.Empty;
|
||||
PerBox = string.Empty;
|
||||
StartQuantity = string.Empty;
|
||||
Received = string.Empty;
|
||||
Output = string.Empty;
|
||||
FinalQuantity = string.Empty;
|
||||
ExpirationDate = string.Empty;
|
||||
Notes = string.Empty;
|
||||
//Medication = string.Empty;
|
||||
MedicineBrand = string.Empty;
|
||||
BrandTotal = string.Empty;
|
||||
MedicationTotal = string.Empty;
|
||||
Unit = string.Empty;
|
||||
LastMonthsFinalQuantity = string.Empty;
|
||||
}
|
||||
|
||||
internal DateTime ParseExpiry()
|
||||
{
|
||||
if (string.IsNullOrEmpty(ExpirationDate)) return DateTime.MaxValue.Date;
|
||||
DateTime dt;
|
||||
if (!DateTime.TryParseExact(ExpirationDate, @"M/yy", null, DateTimeStyles.None, out dt)) return DateTime.MaxValue.Date;
|
||||
return dt;
|
||||
}
|
||||
|
||||
internal Int32 ParseFinalQuantity(string FinalQuantity)
|
||||
{
|
||||
var result = 0;
|
||||
var regex = new Regex(@"[^\d]+", RegexOptions.IgnoreCase);
|
||||
try
|
||||
{
|
||||
result = Convert.ToInt32("0" + (string.IsNullOrEmpty(FinalQuantity) || string.IsNullOrEmpty(regex.Replace(FinalQuantity, ""))
|
||||
? "" : regex.Replace(FinalQuantity, "")));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.Message.Dump();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Int32 ParseStartQuantity(string StartQuantity, string LastMonthsFinalQuantity)
|
||||
{
|
||||
var result = 0;
|
||||
var regex = new Regex(@"[^\d]+", RegexOptions.IgnoreCase);
|
||||
try
|
||||
{
|
||||
result = Convert.ToInt32("0" + (!string.IsNullOrEmpty(regex.Replace(StartQuantity, ""))
|
||||
? regex.Replace(StartQuantity, "")
|
||||
: !string.IsNullOrEmpty(regex.Replace(LastMonthsFinalQuantity, ""))
|
||||
? regex.Replace(LastMonthsFinalQuantity, "") : ""));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.Message.Dump();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public class PropDef
|
||||
{
|
||||
public string name { get; set; }
|
||||
public string type { get; set; }
|
||||
public Inventory inventory { get; set; }
|
||||
|
||||
public PropDef(string a, System.Type b)
|
||||
{
|
||||
name = a;
|
||||
type = b.Name;
|
||||
}
|
||||
public PropDef(Inventory inv)
|
||||
{
|
||||
name = inv.Medicine == string.Empty ? inv.MedicineBrand.Trim() : inv.Medicine.Trim();
|
||||
type = inv.Medicine == string.Empty ? string.Empty : inv.MedicineBrand.Trim();
|
||||
inventory = inv;
|
||||
}
|
||||
}
|
||||
|
||||
public class NameBrandComparer : IEqualityComparer<PropDef>
|
||||
{
|
||||
public bool Equals(PropDef med1, PropDef med2)
|
||||
{
|
||||
if (med1 == null && med2 == null) return true;
|
||||
else if (med1 == null || med2 == null) return false;
|
||||
else if (med1.inventory != null && med2.inventory != null)
|
||||
{
|
||||
if (med1.name == med2.name && med1.type == med2.type && med1.inventory.Purchased == med2.inventory.Purchased) return true;
|
||||
else return false;
|
||||
}
|
||||
else if (med1.name == med2.name && med1.type == med2.type) return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public int GetHashCode(PropDef med)
|
||||
{
|
||||
return $"{med.name}{med.type}".GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
<Query Kind="Program">
|
||||
<Reference><ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll</Reference>
|
||||
<NuGetReference>AutoMapper</NuGetReference>
|
||||
<Namespace>AutoMapper</Namespace>
|
||||
<Namespace>Newtonsoft.Json</Namespace>
|
||||
<Namespace>Newtonsoft.Json.Converters</Namespace>
|
||||
<Namespace>Newtonsoft.Json.Linq</Namespace>
|
||||
<Namespace>Newtonsoft.Json.Schema</Namespace>
|
||||
<Namespace>Newtonsoft.Json.Serialization</Namespace>
|
||||
<Namespace>System</Namespace>
|
||||
<Namespace>System.Diagnostics</Namespace>
|
||||
<Namespace>System.Diagnostics.Tracing</Namespace>
|
||||
<Namespace>System.IO.Compression</Namespace>
|
||||
<Namespace>AutoMapper.Configuration.Annotations</Namespace>
|
||||
<Namespace>static UserQuery</Namespace>
|
||||
</Query>
|
||||
|
||||
private IDResolver idResolver = new IDResolver();
|
||||
|
||||
protected MapperConfiguration config { get; } = new MapperConfiguration(cfg =>
|
||||
{
|
||||
cfg.AddMaps(Assembly.GetExecutingAssembly());
|
||||
cfg.Advanced.AllowAdditiveTypeMapCreation = true;
|
||||
cfg.ValidateInlineMaps = false;
|
||||
});
|
||||
|
||||
void Main()
|
||||
{
|
||||
|
||||
NameBrandExpiryComparer nameBrandExpiryEqC = new NameBrandExpiryComparer();
|
||||
NameBrandComparer nameBrandEqC = new NameBrandComparer();
|
||||
|
||||
Mapper.Reset();
|
||||
IMapper mapper = new Mapper(config);
|
||||
mapper.ConfigurationProvider.CompileMappings();
|
||||
mapper.ConfigurationProvider.AssertConfigurationIsValid();
|
||||
|
||||
var path = @"C:\Users\Tlamb\Downloads";
|
||||
var json = "medications.json";
|
||||
var data = LoadFile(Path.Combine(path, json));
|
||||
|
||||
var meds = mapper.Map<List<Medication>>(data.records);
|
||||
var medBrandList = meds.Distinct(nameBrandEqC)
|
||||
.OrderBy(m => m.Name).ThenBy(m => m.Brand)
|
||||
.Select((m, i) => mapper.Map<MedBrand>(m, opt => opt.Items["id"] = i))
|
||||
.ToList();
|
||||
medBrandList.Dump("MedBrands");
|
||||
|
||||
var withLabels = medBrandList.Select(m => mapper.Map<MedBrandLabel>(m, opt => opt.Items["id"] = m.MedicineID)); //new MedBrandLabel(m));
|
||||
withLabels.Dump("MedBrands with Labels");
|
||||
|
||||
var medList = meds.Distinct(nameBrandExpiryEqC)
|
||||
.Join(medBrandList
|
||||
, exp => new { exp.Name, exp.Brand }
|
||||
, key => new { key.Name, key.Brand },
|
||||
(exp, key) => new MedInventory
|
||||
{
|
||||
MedicineID = key.MedicineID,
|
||||
Start = exp.Start,
|
||||
Expiry = exp.Expiry,
|
||||
})
|
||||
.OrderBy(m => m.MedicineID).ThenBy(m => m.Expiry)
|
||||
.ToList();
|
||||
medList.Dump("Med List");
|
||||
var medInv = medList.Select(ml => mapper.Map<MedInvLabel>(ml, opt => opt.Items["medBrands"] = withLabels.ToDictionary(key => key.MedicineID, label => label.Label)));
|
||||
medInv.Dump("Med Inventory");
|
||||
|
||||
meds.OrderBy(m => m.Name).ThenBy(m => m.Brand).ThenBy(m => m.Expiry).Dump();
|
||||
|
||||
}
|
||||
|
||||
public RootObject LoadFile(string fileName)
|
||||
{
|
||||
var jsonFile = File.ReadAllText(fileName);
|
||||
return JsonConvert.DeserializeObject<RootObject>(jsonFile);
|
||||
}
|
||||
|
||||
// Define other methods and classes here
|
||||
|
||||
public class NameBrandExpiryComparer : IEqualityComparer<Medication>
|
||||
{
|
||||
public bool Equals(Medication med1, Medication med2)
|
||||
{
|
||||
if (med1 == null && med2 == null) return true;
|
||||
else if (med1 == null || med2 == null) return false;
|
||||
else if (med1.Name == med2.Name && med1.Brand == med2.Brand && med1.Expiry == med2.Expiry) return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public int GetHashCode(Medication med)
|
||||
{
|
||||
return $"{med.Name}{med.Brand}{med.Expiry:MMddyyyy}".GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public class NameBrandComparer : IEqualityComparer<Medication>
|
||||
{
|
||||
public bool Equals(Medication med1, Medication med2)
|
||||
{
|
||||
if (med1 == null && med2 == null) return true;
|
||||
else if (med1 == null || med2 == null) return false;
|
||||
else if (med1.Name == med2.Name && med1.Brand == med2.Brand) return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public int GetHashCode(Medication med)
|
||||
{
|
||||
return $"{med.Name}{med.Brand}".GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
[AutoMap(typeof(Record))]
|
||||
public class Medication
|
||||
{
|
||||
[SourceMember(nameof(Record.field_48_raw))]
|
||||
public int MedicineID { get; set; }
|
||||
[SourceMember(nameof(Record.field_49_raw))]
|
||||
public string Name { get; set; }
|
||||
[SourceMember(nameof(Record.field_50_raw))]
|
||||
public string Brand { get; set; }
|
||||
[SourceMember(nameof(Record.field_51_raw))]
|
||||
public int Start { get; set; }
|
||||
[SourceMember(nameof(Record.field_55_raw))]
|
||||
public int Minimum { get; set; }
|
||||
[SourceMember(nameof(Record.field_57_raw))]
|
||||
public Field57Raw field57 { get; set; }
|
||||
public DateTime Expiry => field57?.iso_timestamp ?? DateTime.MaxValue;
|
||||
[Ignore]
|
||||
public bool NeedsReorder => (Start < Minimum) || (Expiry <= DateTime.Now);
|
||||
}
|
||||
|
||||
[AutoMap(typeof(Medication))]
|
||||
public class MedBrand
|
||||
{
|
||||
[ValueResolver(typeof(IDResolver))]
|
||||
public int MedicineID { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Brand { get; set; }
|
||||
public int Minimum { get; set; }
|
||||
[Ignore]
|
||||
public string Dosage { get; set; }
|
||||
[Ignore]
|
||||
public int Package { get; set; }
|
||||
[Ignore]
|
||||
public string Per { get; set; }
|
||||
[Ignore]
|
||||
public string Unit { get; set; }
|
||||
|
||||
public MedBrand()
|
||||
{
|
||||
Minimum = 10;
|
||||
Dosage = "50mg";
|
||||
Unit = "Tablet";
|
||||
Package = 250;
|
||||
Per = "Bottle";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[AutoMap(typeof(MedBrand))]
|
||||
public class MedBrandLabel : MedBrand
|
||||
{
|
||||
[Ignore]
|
||||
public string Label => $"{Name} {Brand} {Dosage} {Package} {Per} / {Unit}";
|
||||
}
|
||||
|
||||
public class MedInventory
|
||||
{
|
||||
public int MedicineID { get; set; }
|
||||
public int Start { get; set; }
|
||||
public DateTime Expiry { get; set; }
|
||||
public bool NeedsReorder => Expiry <= DateTime.Now;
|
||||
}
|
||||
|
||||
[AutoMap(typeof(MedInventory))]
|
||||
public class MedInvLabel : MedInventory
|
||||
{
|
||||
[ValueResolver(typeof(BrandResolver))]
|
||||
public string MedicationBrand { get; set; }
|
||||
[Ignore]
|
||||
public string Label => $"{MedicationBrand} {Expiry:MM/dd/yyyy}";
|
||||
}
|
||||
|
||||
public class Field57Raw
|
||||
{
|
||||
public string date { get; set; }
|
||||
public string date_formatted { get; set; }
|
||||
public string hours { get; set; }
|
||||
public string minutes { get; set; }
|
||||
public string am_pm { get; set; }
|
||||
public object unix_timestamp { get; set; }
|
||||
public DateTime iso_timestamp { get; set; }
|
||||
public string timestamp { get; set; }
|
||||
public int time { get; set; }
|
||||
}
|
||||
|
||||
public class Record
|
||||
{
|
||||
public string id { get; set; }
|
||||
public int field_48_raw { get; set; }
|
||||
public string field_49_raw { get; set; }
|
||||
public string field_50_raw { get; set; }
|
||||
public int field_51_raw { get; set; }
|
||||
public int field_52_raw { get; set; }
|
||||
public int field_53_raw { get; set; }
|
||||
public int field_54_raw { get; set; }
|
||||
public int field_55_raw { get; set; }
|
||||
public bool field_56_raw { get; set; }
|
||||
public Field57Raw field_57_raw { get; set; }
|
||||
public string field_58_raw { get; set; }
|
||||
public string field_63_raw { get; set; }
|
||||
}
|
||||
|
||||
public class RootObject
|
||||
{
|
||||
public List<Record> records { get; set; }
|
||||
}
|
||||
|
||||
public class IDResolver : IValueResolver<object, object, int>
|
||||
{
|
||||
public int Resolve(object source, object destination, int id, ResolutionContext context)
|
||||
{
|
||||
id = (int)context.Items["id"];
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
public class BrandResolver : IValueResolver<MedInventory, object, string>
|
||||
{
|
||||
public string Resolve(MedInventory source, object destination, string label, ResolutionContext context)
|
||||
{
|
||||
label = ((Dictionary<int, string>)context.Items["medBrands"])[source.MedicineID];
|
||||
return label;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
<Query Kind="Program">
|
||||
<Reference><ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll</Reference>
|
||||
<Reference><RuntimeDirectory>\System.Data.Entity.Design.dll</Reference>
|
||||
<NuGetReference>Amazon.Lambda.S3Events</NuGetReference>
|
||||
<NuGetReference>AWSSDK.Core</NuGetReference>
|
||||
<NuGetReference>AWSSDK.S3</NuGetReference>
|
||||
<NuGetReference>LINQtoCSV</NuGetReference>
|
||||
<Namespace>Amazon</Namespace>
|
||||
<Namespace>Amazon.Auth.AccessControlPolicy</Namespace>
|
||||
<Namespace>Amazon.Auth.AccessControlPolicy.ActionIdentifiers</Namespace>
|
||||
<Namespace>Amazon.Internal</Namespace>
|
||||
<Namespace>Amazon.Lambda.S3Events</Namespace>
|
||||
<Namespace>Amazon.MissingTypes</Namespace>
|
||||
<Namespace>Amazon.Runtime</Namespace>
|
||||
<Namespace>Amazon.Runtime.CredentialManagement</Namespace>
|
||||
<Namespace>Amazon.Runtime.CredentialManagement.Internal</Namespace>
|
||||
<Namespace>Amazon.Runtime.EventStreams</Namespace>
|
||||
<Namespace>Amazon.Runtime.EventStreams.Internal</Namespace>
|
||||
<Namespace>Amazon.Runtime.Internal</Namespace>
|
||||
<Namespace>Amazon.Runtime.Internal.Auth</Namespace>
|
||||
<Namespace>Amazon.Runtime.Internal.Settings</Namespace>
|
||||
<Namespace>Amazon.Runtime.Internal.Transform</Namespace>
|
||||
<Namespace>Amazon.Runtime.Internal.Util</Namespace>
|
||||
<Namespace>Amazon.Runtime.SharedInterfaces</Namespace>
|
||||
<Namespace>Amazon.Runtime.SharedInterfaces.Internal</Namespace>
|
||||
<Namespace>Amazon.S3</Namespace>
|
||||
<Namespace>Amazon.S3.Encryption</Namespace>
|
||||
<Namespace>Amazon.S3.Encryption.Internal</Namespace>
|
||||
<Namespace>Amazon.S3.Internal</Namespace>
|
||||
<Namespace>Amazon.S3.IO</Namespace>
|
||||
<Namespace>Amazon.S3.Model</Namespace>
|
||||
<Namespace>Amazon.S3.Model.Internal.MarshallTransformations</Namespace>
|
||||
<Namespace>Amazon.S3.Transfer</Namespace>
|
||||
<Namespace>Amazon.S3.Util</Namespace>
|
||||
<Namespace>Amazon.Util</Namespace>
|
||||
<Namespace>Amazon.Util.Internal</Namespace>
|
||||
<Namespace>Amazon.Util.Internal.PlatformServices</Namespace>
|
||||
<Namespace>LINQPad.Extensibility.DataContext.DbSchema</Namespace>
|
||||
<Namespace>LINQtoCSV</Namespace>
|
||||
<Namespace>Newtonsoft.Json</Namespace>
|
||||
<Namespace>Newtonsoft.Json.Converters</Namespace>
|
||||
<Namespace>Newtonsoft.Json.Linq</Namespace>
|
||||
<Namespace>Newtonsoft.Json.Schema</Namespace>
|
||||
<Namespace>Newtonsoft.Json.Serialization</Namespace>
|
||||
<Namespace>System</Namespace>
|
||||
<Namespace>System.Diagnostics</Namespace>
|
||||
<Namespace>System.Diagnostics.Tracing</Namespace>
|
||||
<Namespace>System.Globalization</Namespace>
|
||||
<Namespace>System.IO.Compression</Namespace>
|
||||
<Namespace>ThirdParty.BouncyCastle.Asn1</Namespace>
|
||||
<Namespace>ThirdParty.BouncyCastle.Asn1.Utilities</Namespace>
|
||||
<Namespace>ThirdParty.BouncyCastle.Math</Namespace>
|
||||
<Namespace>ThirdParty.BouncyCastle.OpenSsl</Namespace>
|
||||
<Namespace>ThirdParty.BouncyCastle.Utilities.IO.Pem</Namespace>
|
||||
<Namespace>ThirdParty.Ionic.Zlib</Namespace>
|
||||
<Namespace>ThirdParty.Json.LitJson</Namespace>
|
||||
<Namespace>ThirdParty.MD5</Namespace>
|
||||
<Namespace>System.Data.Entity.Design.PluralizationServices</Namespace>
|
||||
</Query>
|
||||
|
||||
private static PluralizationService ps => PluralizationService.CreateService(new CultureInfo("en-US"));
|
||||
|
||||
void Main()
|
||||
{
|
||||
var path = @"C:\Users\tlamb\downloads";
|
||||
var newPath = @"C:\Users\tlamb\downloads\Solehope 190705";
|
||||
var file = "medical inventory July 5 2019.2.csv";
|
||||
var filepath = Path.Combine(path, file);
|
||||
|
||||
CsvFileDescription inputFileDescription = new CsvFileDescription
|
||||
{
|
||||
SeparatorChar = ',',
|
||||
FirstLineHasColumnNames = true,
|
||||
IgnoreUnknownColumns = true
|
||||
};
|
||||
|
||||
CsvFileDescription outputFileDescription = new CsvFileDescription
|
||||
{
|
||||
SeparatorChar = ',',
|
||||
FirstLineHasColumnNames = true
|
||||
};
|
||||
|
||||
CsvContext cc = new CsvContext();
|
||||
IEnumerable<MedicationOut> medications;
|
||||
IEnumerable<Inventory> inventory;
|
||||
IEnumerable<Intake> intake;
|
||||
|
||||
var meds = cc.Read<Med>(filepath, inputFileDescription).ToList();
|
||||
meds.Dump(file);
|
||||
|
||||
medications = meds.ConvertAll(med => (MedicationOut)med);
|
||||
inventory = meds.ConvertAll(med => (Inventory)med);
|
||||
inventory = inventory.OrderBy(i => i.Medication)
|
||||
.Select((i, idx) => { i.InventoryId = idx.ToString(); return i; });
|
||||
intake = meds.ConvertAll(med => (Intake)med);
|
||||
intake = intake
|
||||
.Join(inventory, x => x.MedicationId, inv => inv.MedicationId, (x, inv) => new { intake = x, inv }).ToList()
|
||||
.ConvertAll(u => { u.intake.InventoryId = u.inv.InventoryId; return u.intake; });
|
||||
|
||||
var updates = cc.Read<Intake>(Path.Combine(@"C:\Users\tlamb\downloads\Solehope 190819", "intake2.csv"), inputFileDescription).ToList()
|
||||
.Join(inventory, x => x.InventoryId, inv => inv.InventoryId, (x, inv) => new { intake = x, inv }).ToList()
|
||||
.ConvertAll(u => { u.intake.MedicationId = u.inv.MedicationId; return u.intake; });
|
||||
|
||||
newPath.Dump("New Path");
|
||||
medications.Dump("Medications");
|
||||
inventory.Dump("Inventory");
|
||||
intake.Dump("Intake - from Medications");
|
||||
updates.Dump("Updates");
|
||||
|
||||
file = "medication.csv";
|
||||
filepath = Path.Combine(newPath, file);
|
||||
cc.Write(medications, filepath, outputFileDescription);
|
||||
file = "inventory.csv";
|
||||
filepath = Path.Combine(newPath, file);
|
||||
cc.Write(inventory, filepath, outputFileDescription);
|
||||
file = "intake.csv";
|
||||
filepath = Path.Combine(newPath, file);
|
||||
cc.Write(intake, filepath, outputFileDescription);
|
||||
file = "updates.csv";
|
||||
filepath = Path.Combine(newPath, file);
|
||||
cc.Write(updates, filepath, outputFileDescription);
|
||||
}
|
||||
|
||||
// Define other methods and classes here
|
||||
|
||||
public class Med
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
public string Type { get; set; }
|
||||
|
||||
[CsvColumn(Name = "Medication")]
|
||||
public string MedicationStr { get; set; }
|
||||
internal string Medications => box.Match(MedicationStr.Trim()).Success ? box.Replace(MedicationStr.Trim(), "$1").Trim() : MedicationStr.Trim();
|
||||
|
||||
public string Strength { get; set; }
|
||||
|
||||
[CsvColumn(Name = "Quantity")]
|
||||
public string Start { get; set; }
|
||||
internal int StartCnt => Convert.ToInt32(regex.Replace(string.IsNullOrEmpty(Start) ? "0" : Start, ""));
|
||||
|
||||
[CsvColumn(Name = "Minimum")]
|
||||
public string MinimumStr { get; set; }
|
||||
internal int MinimumCnt => Convert.ToInt32(regex.Replace(string.IsNullOrEmpty(MinimumStr) ? "0" : MinimumStr, ""));
|
||||
|
||||
public string Unit { get; set; }
|
||||
|
||||
public string Package { get; set; }
|
||||
|
||||
[CsvColumn(Name = "Number")]
|
||||
public string NumberStr { get; set; }
|
||||
internal int NumberCnt => box.Match(MedicationStr.Trim()).Success ? Convert.ToInt32(box.Replace(MedicationStr.Trim(), "$2"))
|
||||
: Convert.ToInt32(regex.Replace(string.IsNullOrEmpty(NumberStr) ? "0" : NumberStr, ""));
|
||||
|
||||
[CsvColumn(Name = "Expiration Date")]
|
||||
public string Expiry { get; set; }
|
||||
internal DateTime ExpiryDate => GetDateFromString(Expiry);
|
||||
|
||||
internal string Form => string.IsNullOrEmpty(Package) ? ""
|
||||
: Package.Trim() == "Tube/Cream" ? "Cream" : ps.Singularize(Package.Trim());
|
||||
internal string UnitOut => !string.IsNullOrEmpty(UnitNoBox)
|
||||
? ps.Singularize(UnitNoBox)
|
||||
: string.IsNullOrEmpty(Package)
|
||||
? string.Empty
|
||||
: Package.Trim() == "Tube/Cream"
|
||||
? "Tube"
|
||||
: string.Empty;
|
||||
|
||||
public string Label => $"{Medications} {Strength} {Form} {NumberCnt} / {UnitOut}";
|
||||
|
||||
internal string UnitNoBox => box.Match(MedicationStr.Trim()).Success ? "Box" : Unit?.Trim() ?? "";
|
||||
|
||||
internal Regex regex = new Regex(@"[^\d]");
|
||||
internal Regex date = new Regex(@"([\d]{1,2})/([\d]{1,2})/([\d]{1,4})");
|
||||
internal Regex shortDate = new Regex(@"([\d]{1,2})/([\d]{1,2})");
|
||||
internal Regex box = new Regex(@"^(\D*)([\d]*)/Box$");
|
||||
|
||||
internal DateTime GetDateFromString(string theDate)
|
||||
{
|
||||
DateTime result = DateTime.MaxValue;
|
||||
DateTime work;
|
||||
if (string.IsNullOrEmpty(theDate) || theDate == "0/0")
|
||||
work = result;
|
||||
else if (date.IsMatch(theDate))
|
||||
work = Convert.ToDateTime(theDate);
|
||||
else if (shortDate.IsMatch(theDate))
|
||||
work = Convert.ToDateTime(shortDate.Replace(theDate, "$1/5/$2"));
|
||||
else
|
||||
work = result;
|
||||
work = new DateTime(work.Year, work.Month, DateTime.DaysInMonth(work.Year, work.Month));
|
||||
return work;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class MedicationOut
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Medication { get; set; }
|
||||
public int Minimum { get; set; }
|
||||
public string Strength { get; set; }
|
||||
public string Form { get; set; }
|
||||
public int Number { get; set; }
|
||||
public string Unit { get; set; }
|
||||
public string Label { get; internal set; }
|
||||
|
||||
public static explicit operator MedicationOut(Med med)
|
||||
{
|
||||
return new MedicationOut
|
||||
{
|
||||
Id = med.Id,
|
||||
Type = med.Type,
|
||||
Medication = med.Medications,
|
||||
Minimum = med.MinimumCnt,
|
||||
Strength = med.Strength ?? "",
|
||||
Form = med.Form,
|
||||
Number = med.NumberCnt,
|
||||
Unit = !string.IsNullOrEmpty(med.UnitNoBox)
|
||||
? ps.Singularize(med.UnitNoBox)
|
||||
: string.IsNullOrEmpty(med.Package)
|
||||
? string.Empty
|
||||
: med.Package.Trim() == "Tube/Cream"
|
||||
? "Tube"
|
||||
: string.Empty,
|
||||
Label = med.Label
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class Inventory
|
||||
{
|
||||
public string MedicationId { get; set; }
|
||||
public string InventoryId { get; set; }
|
||||
public string Medication { get; set; }
|
||||
public int Start => 0;
|
||||
public string Label { get; internal set; }
|
||||
public string Note { get; set; }
|
||||
|
||||
public static explicit operator Inventory(Med med)
|
||||
{
|
||||
return new Inventory
|
||||
{
|
||||
MedicationId = med.Id,
|
||||
Medication = med.Medications,
|
||||
Label = med.Label,
|
||||
Note = string.Empty
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class Intake
|
||||
{
|
||||
public string MedicationId { get; set; }
|
||||
public string InventoryId { get; set; }
|
||||
public string Medication { get; set; }
|
||||
public int Received { get; set; }
|
||||
public DateTime Date { get; set; }
|
||||
public DateTime Expiry { get; set; }
|
||||
internal string MedLabel { get; set; }
|
||||
public string Label => $"({Received}) {MedLabel}";
|
||||
|
||||
public static explicit operator Intake(Med med)
|
||||
{
|
||||
return new Intake
|
||||
{
|
||||
MedicationId = med.Id,
|
||||
Medication = med.Medications,
|
||||
Received = med.StartCnt,
|
||||
Date = new DateTime(2019, 7, 5),
|
||||
Expiry = med.ExpiryDate,
|
||||
MedLabel = med.Label
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,536 @@
|
||||
<Query Kind="Program">
|
||||
<Reference><ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll</Reference>
|
||||
<Reference><RuntimeDirectory>\System.Data.Entity.Design.dll</Reference>
|
||||
<NuGetReference>Amazon.Lambda.S3Events</NuGetReference>
|
||||
<NuGetReference>AWSSDK.Core</NuGetReference>
|
||||
<NuGetReference>AWSSDK.S3</NuGetReference>
|
||||
<NuGetReference>LINQtoCSV</NuGetReference>
|
||||
<Namespace>Amazon</Namespace>
|
||||
<Namespace>Amazon.Auth.AccessControlPolicy</Namespace>
|
||||
<Namespace>Amazon.Auth.AccessControlPolicy.ActionIdentifiers</Namespace>
|
||||
<Namespace>Amazon.Internal</Namespace>
|
||||
<Namespace>Amazon.Lambda.S3Events</Namespace>
|
||||
<Namespace>Amazon.MissingTypes</Namespace>
|
||||
<Namespace>Amazon.Runtime</Namespace>
|
||||
<Namespace>Amazon.Runtime.CredentialManagement</Namespace>
|
||||
<Namespace>Amazon.Runtime.CredentialManagement.Internal</Namespace>
|
||||
<Namespace>Amazon.Runtime.EventStreams</Namespace>
|
||||
<Namespace>Amazon.Runtime.EventStreams.Internal</Namespace>
|
||||
<Namespace>Amazon.Runtime.Internal</Namespace>
|
||||
<Namespace>Amazon.Runtime.Internal.Auth</Namespace>
|
||||
<Namespace>Amazon.Runtime.Internal.Settings</Namespace>
|
||||
<Namespace>Amazon.Runtime.Internal.Transform</Namespace>
|
||||
<Namespace>Amazon.Runtime.Internal.Util</Namespace>
|
||||
<Namespace>Amazon.Runtime.SharedInterfaces</Namespace>
|
||||
<Namespace>Amazon.Runtime.SharedInterfaces.Internal</Namespace>
|
||||
<Namespace>Amazon.S3</Namespace>
|
||||
<Namespace>Amazon.S3.Encryption</Namespace>
|
||||
<Namespace>Amazon.S3.Encryption.Internal</Namespace>
|
||||
<Namespace>Amazon.S3.Internal</Namespace>
|
||||
<Namespace>Amazon.S3.IO</Namespace>
|
||||
<Namespace>Amazon.S3.Model</Namespace>
|
||||
<Namespace>Amazon.S3.Model.Internal.MarshallTransformations</Namespace>
|
||||
<Namespace>Amazon.S3.Transfer</Namespace>
|
||||
<Namespace>Amazon.S3.Util</Namespace>
|
||||
<Namespace>Amazon.Util</Namespace>
|
||||
<Namespace>Amazon.Util.Internal</Namespace>
|
||||
<Namespace>Amazon.Util.Internal.PlatformServices</Namespace>
|
||||
<Namespace>LINQtoCSV</Namespace>
|
||||
<Namespace>Newtonsoft.Json</Namespace>
|
||||
<Namespace>Newtonsoft.Json.Converters</Namespace>
|
||||
<Namespace>Newtonsoft.Json.Linq</Namespace>
|
||||
<Namespace>Newtonsoft.Json.Schema</Namespace>
|
||||
<Namespace>Newtonsoft.Json.Serialization</Namespace>
|
||||
<Namespace>System</Namespace>
|
||||
<Namespace>System.ComponentModel.Composition</Namespace>
|
||||
<Namespace>System.ComponentModel.Composition.Hosting</Namespace>
|
||||
<Namespace>System.ComponentModel.Composition.Primitives</Namespace>
|
||||
<Namespace>System.ComponentModel.Composition.ReflectionModel</Namespace>
|
||||
<Namespace>System.Diagnostics</Namespace>
|
||||
<Namespace>System.Diagnostics.Tracing</Namespace>
|
||||
<Namespace>System.Dynamic</Namespace>
|
||||
<Namespace>System.IO.Compression</Namespace>
|
||||
<Namespace>System.Net.Http</Namespace>
|
||||
<Namespace>System.Net.Http.Headers</Namespace>
|
||||
<Namespace>System.Numerics</Namespace>
|
||||
<Namespace>ThirdParty.BouncyCastle.Asn1</Namespace>
|
||||
<Namespace>ThirdParty.BouncyCastle.Asn1.Utilities</Namespace>
|
||||
<Namespace>ThirdParty.BouncyCastle.Math</Namespace>
|
||||
<Namespace>ThirdParty.BouncyCastle.OpenSsl</Namespace>
|
||||
<Namespace>ThirdParty.BouncyCastle.Utilities.IO.Pem</Namespace>
|
||||
<Namespace>ThirdParty.Ionic.Zlib</Namespace>
|
||||
<Namespace>ThirdParty.Json.LitJson</Namespace>
|
||||
<Namespace>ThirdParty.MD5</Namespace>
|
||||
<Namespace>System.Data.Entity.Design.PluralizationServices</Namespace>
|
||||
<Namespace>System.Globalization</Namespace>
|
||||
</Query>
|
||||
|
||||
void Main()
|
||||
{
|
||||
IEnumerable<object> testExpando;
|
||||
var inputFileDescription = new CsvFileDescription
|
||||
{
|
||||
SeparatorChar = '\t', // tab delimited
|
||||
FirstLineHasColumnNames = false, // no column names in first record
|
||||
FileCultureName = "en-US" // use formats used in The Netherlands
|
||||
};
|
||||
var outputFileDescription = new CsvFileDescription
|
||||
{
|
||||
SeparatorChar = ',', // tab delimited
|
||||
FirstLineHasColumnNames = true, // no column names in first record
|
||||
EnforceCsvColumnAttribute = true,
|
||||
FileCultureName = "en-US" // use formats used in The Netherlands
|
||||
};
|
||||
var cc = new CsvContext();
|
||||
var path = @"C:\Users\tlamb\Downloads\";
|
||||
var files = new[] {
|
||||
@"Outreach - Monthly Inventory Records - Inventory March.tsv",
|
||||
@"Outreach - Monthly Inventory Records - Inventory - April.tsv",
|
||||
@"Outreach - Monthly Inventory Records - Inventory - May.tsv",
|
||||
@"Outreach - Monthly Inventory Records - Inventory - June.tsv"
|
||||
}.ToList();
|
||||
var nextmonth = new DateTime(2019, 2, 1);
|
||||
var productList = new List<Product>();
|
||||
var purchaseSummary = new List<Purchase>();
|
||||
var orderSummary = new List<Order>();
|
||||
files.ForEach(inventory =>
|
||||
{
|
||||
nextmonth = nextmonth.AddMonths(1);
|
||||
var monthData = cc.Read<MyDataRow>(Path.Combine(path, inventory), inputFileDescription);
|
||||
testExpando = ConvertMyDataRow(monthData);
|
||||
var products = testExpando.Select(o => new Product(o as ExpandoObject, nextmonth)).ToList();
|
||||
var purchases = testExpando.Select(o => new Purchase(o as ExpandoObject, nextmonth)).Where(p => p.Rcvd != 0).ToList();
|
||||
var orders = testExpando.Select(o => new Order(o as ExpandoObject, nextmonth)).Where(o => o.Out != 0).ToList();
|
||||
productList.AddRange(products);
|
||||
purchaseSummary.AddRange(purchases);
|
||||
orderSummary.AddRange(orders);
|
||||
});
|
||||
var medicationBrandList = productList.GroupBy(l => new { l.Medicine, l.Brand }).Select(grp => grp.First()).ToList()
|
||||
.Select(mb => new MedicationBrand { Medicine = mb.Medicine, Brand = mb.Brand, Reorder = mb.MinimumRequired });
|
||||
productList.GroupBy(p => p.Medicine).OrderBy(p => p.Key).Dump("Products");
|
||||
purchaseSummary.Dump("Purchases");
|
||||
orderSummary.Dump("Orders");
|
||||
medicationBrandList.Dump("Medications");
|
||||
var docsFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "SoleHope");
|
||||
if (!Directory.Exists(docsFolder))
|
||||
Directory.CreateDirectory(docsFolder);
|
||||
cc.Write(medicationBrandList, Path.Combine(docsFolder, "MedicationBrand.csv"), outputFileDescription);
|
||||
cc.Write(productList, Path.Combine(docsFolder, "Medications.csv"), outputFileDescription);
|
||||
cc.Write(purchaseSummary, Path.Combine(docsFolder, "Intake.csv"), outputFileDescription);
|
||||
cc.Write(orderSummary, Path.Combine(docsFolder, "Outtake.csv"), outputFileDescription);
|
||||
|
||||
}
|
||||
|
||||
internal IEnumerable<object> ConvertMyDataRow(IEnumerable<MyDataRow> data)
|
||||
{
|
||||
var groupData = data.SelectMany(dr => dr.ToList())
|
||||
.GroupBy(t => t.LineNbr)
|
||||
.Select(t => new { Key = t.Key - 2, Values = t.ToList().Select(v => v.Value).ToArray() });
|
||||
var properties = groupData.Where(d => d.Key < 0)
|
||||
.SelectMany(d => d.Values.Select(v => Regex.Replace(v, @"[\s()]", "")
|
||||
.Replace("StartingQuantityBeginningofCurrentMonth", "StartQuantity")
|
||||
.Replace("FinalQuantityEndofCurrentMonth", "FinalQuantity")
|
||||
.Replace("MedicationTotalStartQuantity", "StartQuantity")).ToList()).ToArray();
|
||||
var medication = string.Empty;
|
||||
var expandoData = groupData.Where(d => d.Key >= 0)
|
||||
.Select((t, j) =>
|
||||
{
|
||||
dynamic expando = new ExpandoObject();
|
||||
AddProperty(expando, "MedicineID", j);
|
||||
int i = 0;
|
||||
t.Values.ToList().ForEach(d =>
|
||||
{
|
||||
if (properties[i] == "Medication")
|
||||
{
|
||||
if (string.IsNullOrEmpty(d))
|
||||
{
|
||||
d = medication;
|
||||
}
|
||||
medication = d;
|
||||
}
|
||||
AddProperty(expando, properties[i], d ?? string.Empty);
|
||||
i++;
|
||||
});
|
||||
return expando;
|
||||
});
|
||||
return expandoData;
|
||||
}
|
||||
|
||||
// Define other methods and classes here
|
||||
internal class MyDataRow : List<DataRowItem>, IDataRow
|
||||
{
|
||||
}
|
||||
|
||||
public class MedicationBrand
|
||||
{
|
||||
[CsvColumn(Name = "Medication", FieldIndex = 1)]
|
||||
public string Medicine { get; set; }
|
||||
[CsvColumn(Name = "Brand", FieldIndex = 2)]
|
||||
public string Brand { get; set; }
|
||||
[CsvColumn(FieldIndex = 3)]
|
||||
public int Reorder {get;set;}
|
||||
}
|
||||
|
||||
public class Product
|
||||
{
|
||||
internal string[] Row { get; set; }
|
||||
[CsvColumn(Name = "MedicineID", FieldIndex = 1)]
|
||||
public int index { get; set; }
|
||||
internal string InvDateStr { get; set; }
|
||||
public DateTime InvDate => !string.IsNullOrEmpty(InvDateStr)
|
||||
? DateTime.ParseExact(InvDateStr, "M/yy", System.Globalization.CultureInfo.InvariantCulture)
|
||||
: new DateTime(2999, 12, 31);
|
||||
[CsvColumn(Name = "Medication", FieldIndex = 2)]
|
||||
public string Medicine { get; set; }
|
||||
[CsvColumn(Name = "Brand", FieldIndex = 3)]
|
||||
public string Brand { get; set; }
|
||||
[CsvColumn(FieldIndex = 4)]
|
||||
public string Label => string.IsNullOrEmpty(Brand) ? $"{Medicine} ({index})" : $"{Medicine} {Brand} ({index})";
|
||||
public string Dosage { get; set; }
|
||||
public string Per { get; set; }
|
||||
public string Unit { get; set; }
|
||||
internal string StartStr { get; set; }
|
||||
internal string RcvdStr { get; set; }
|
||||
internal string OutStr { get; set; }
|
||||
internal string FinalStr { get; set; }
|
||||
[CsvColumn(Name = "StartingInventory", FieldIndex = 5)]
|
||||
public int Start => Convert.ToInt32(regex.Replace(string.IsNullOrEmpty(StartStr) ? "0" : StartStr, ""));
|
||||
public int Rcvd => Convert.ToInt32(regex.Replace(string.IsNullOrEmpty(RcvdStr) ? "0" : RcvdStr, ""));
|
||||
public int Out => Convert.ToInt32(regex.Replace(string.IsNullOrEmpty(OutStr) ? "0" : OutStr, ""));
|
||||
public int Final => Convert.ToInt32(regex.Replace(string.IsNullOrEmpty(FinalStr) ? "0" : FinalStr, ""));
|
||||
[CsvColumn(FieldIndex = 6)]
|
||||
public int InventoryReceived => Rcvd;
|
||||
[CsvColumn(FieldIndex = 7)]
|
||||
public int InventoryShipped => Out;
|
||||
[CsvColumn(FieldIndex = 8)]
|
||||
public int InventoryOnHand => Final;
|
||||
[CsvColumn(FieldIndex = 9)]
|
||||
public int MinimumRequired => Start;
|
||||
[CsvColumn(FieldIndex = 10)]
|
||||
public string NeedsReorder => Start == 0 ? "Yes" : "No";
|
||||
internal string ExpiryStr { get; set; }
|
||||
[CsvColumn(FieldIndex = 11)]
|
||||
public DateTime Expiry { get; set; }
|
||||
public DateTime Purchased { get; set; }
|
||||
public DateTime OrderDate => InvDate.AddMonths(1).AddDays(-1);
|
||||
public string Notes { get; set; }
|
||||
|
||||
internal PluralizationService ps => PluralizationService.CreateService(new CultureInfo("en-US"));
|
||||
internal Regex regex = new Regex(@"[^\d]");
|
||||
|
||||
internal Product()
|
||||
{
|
||||
index = 0;
|
||||
InvDateStr = DateTime.Today.ToString("M/yy");
|
||||
Medicine = string.Empty;
|
||||
Brand = string.Empty;
|
||||
Dosage = string.Empty;
|
||||
Per = string.Empty;
|
||||
Unit = string.Empty;
|
||||
StartStr = "0";
|
||||
RcvdStr = "0";
|
||||
OutStr = "0";
|
||||
FinalStr = "0";
|
||||
Expiry = new DateTime(2018, 1, 1);
|
||||
ExpiryStr = Expiry.ToString("M/yy");
|
||||
Purchased = new DateTime(2999, 12, 31);
|
||||
Notes = string.Empty;
|
||||
}
|
||||
|
||||
public Product(int i, string[] row)
|
||||
: this()
|
||||
{
|
||||
Row = row;
|
||||
index = i + 1;
|
||||
InvDateStr = row[0];
|
||||
Medicine = row[1];
|
||||
Dosage = row[2] ?? string.Empty;
|
||||
Per = row[3] ?? string.Empty;
|
||||
Unit = row[3] ?? string.Empty;
|
||||
Unit = Unit.ToUpper().Contains("TUBE") ? "Tube"
|
||||
: Unit.ToUpper().Contains("BOTTLE") ? "Bottle"
|
||||
: Unit.ToUpper().Contains("VIAL") ? "Vial"
|
||||
: Unit.ToUpper().Contains("TABLET") ? "Tablet"
|
||||
: Unit.ToUpper().Contains("CAPSULE") ? "Capsule"
|
||||
: Unit.ToUpper().Contains("LANCET") ? "Lancet" : Unit;
|
||||
Per = !string.IsNullOrEmpty(Per) ? Per.Replace(Unit, "").TrimEnd("(s) ".ToCharArray()) : string.Empty;
|
||||
StartStr = string.IsNullOrEmpty(row[4]) ? "0" : row[4];
|
||||
RcvdStr = string.IsNullOrEmpty(row[5]) ? "0" : row[5];
|
||||
OutStr = string.IsNullOrEmpty(row[6]) ? "0" : row[6];
|
||||
FinalStr = string.IsNullOrEmpty(row[7]) ? "0" : row[7];
|
||||
ExpiryStr = row[8];
|
||||
Notes = string.IsNullOrEmpty(row[9]) ? string.Empty : row[9];
|
||||
Expiry = !string.IsNullOrEmpty(ExpiryStr)
|
||||
? DateTime.ParseExact(ExpiryStr, "M/yy", System.Globalization.CultureInfo.InvariantCulture)
|
||||
: new DateTime(2999, 12, 31);
|
||||
Purchased = !string.IsNullOrEmpty(Notes) && Notes.StartsWith("Purchased")
|
||||
? DateTime.ParseExact(Notes.Substring(10), "M/d/yy", System.Globalization.CultureInfo.InvariantCulture)
|
||||
: DateTime.Compare(Expiry, new DateTime(2018, 1, 1)) < 0
|
||||
? Expiry.AddMonths(-6) : new DateTime(2018, 1, 1);
|
||||
Notes = Notes.Replace($"Purchased {Purchased:M/d/yy}", "");
|
||||
}
|
||||
|
||||
public Product(ExpandoObject expando, DateTime invDate)
|
||||
: this()
|
||||
{
|
||||
InvDateStr = invDate.ToString("M/yy");
|
||||
var dictionary = expando as IDictionary<string, object>;
|
||||
dictionary.Keys.ToList()
|
||||
.ForEach(k =>
|
||||
{
|
||||
var value = Convert.ToString(dictionary[k]);
|
||||
switch (k)
|
||||
{
|
||||
case "MedicineID":
|
||||
index = Convert.ToInt32(value);
|
||||
break;
|
||||
case "Medicine":
|
||||
case "Medication":
|
||||
Medicine = value;
|
||||
break;
|
||||
case "MedicineBrand":
|
||||
Brand = value;
|
||||
break;
|
||||
case "Dosage":
|
||||
Dosage = value;
|
||||
break;
|
||||
case "PerBox":
|
||||
Per = value;
|
||||
break;
|
||||
case "Unit":
|
||||
Unit = ps.IsPlural(value) ? ps.Singularize(value) : value;
|
||||
break;
|
||||
case "Start":
|
||||
case "StartQuantity":
|
||||
StartStr = value;
|
||||
break;
|
||||
case "Received":
|
||||
RcvdStr = value;
|
||||
break;
|
||||
case "Output":
|
||||
OutStr = value;
|
||||
break;
|
||||
case "Final":
|
||||
FinalStr = value;
|
||||
break;
|
||||
case "ExpirationDate":
|
||||
ExpiryStr = Regex.Replace(value, @"[^\d/]", "");
|
||||
Expiry = !string.IsNullOrEmpty(ExpiryStr)
|
||||
? DateTime.ParseExact(ExpiryStr, "M/yy", System.Globalization.CultureInfo.InvariantCulture)
|
||||
: new DateTime(2999, 12, 31);
|
||||
break;
|
||||
}
|
||||
});
|
||||
if (string.IsNullOrEmpty(Unit))
|
||||
{
|
||||
Unit = FindUnits(Per);
|
||||
if (string.IsNullOrEmpty(Unit))
|
||||
Unit = FindUnits(Dosage);
|
||||
}
|
||||
}
|
||||
|
||||
public string FindUnits(string unit)
|
||||
{
|
||||
return unit.ToUpper().Contains("TUBE") ? "Tube"
|
||||
: unit.ToUpper().Contains("BOTTLE") ? "Bottle"
|
||||
: unit.ToUpper().Contains("VIAL") ? "Vial"
|
||||
: unit.ToUpper().Contains("TABLET") ? "Tablet"
|
||||
: unit.ToUpper().Contains("CAPSULE") ? "Capsule"
|
||||
: unit.ToUpper().Contains("LANCET") ? "Lancet"
|
||||
: string.Empty;
|
||||
}
|
||||
|
||||
object ToDump() => new
|
||||
{
|
||||
MedicineID = index,
|
||||
Medication = Medicine,
|
||||
Brand,
|
||||
Label,
|
||||
Unit,
|
||||
StartingInventory = Start,
|
||||
InventoryReceived,
|
||||
InventoryShipped,
|
||||
InventoryOnHand,
|
||||
MinimumRequired,
|
||||
NeedsReorder,
|
||||
Expiry = $"{Expiry.AddMonths(1).AddDays(-1):MM/dd/yy}"
|
||||
};
|
||||
}
|
||||
|
||||
public class Order
|
||||
{
|
||||
internal string[] Row { get; set; }
|
||||
[CsvColumn(Name = "MedicineID", FieldIndex = 1)]
|
||||
public int index { get; set; }
|
||||
internal string InvDateStr { get; set; }
|
||||
public DateTime InvDate => !string.IsNullOrEmpty(InvDateStr)
|
||||
? DateTime.ParseExact(InvDateStr, "M/yy", System.Globalization.CultureInfo.InvariantCulture)
|
||||
: new DateTime(2999, 12, 31);
|
||||
[CsvColumn(Name = "Medication", FieldIndex = 2)]
|
||||
public string Medicine { get; set; }
|
||||
internal string Brand { get; set; }
|
||||
[CsvColumn(FieldIndex = 3)]
|
||||
public string Label => $"{Medicine} {Brand}";
|
||||
[CsvColumn(FieldIndex = 4)]
|
||||
public string Customer => string.Empty;
|
||||
internal string OutStr { get; set; }
|
||||
[CsvColumn(Name = "Shipped", FieldIndex = 5)]
|
||||
public int Out => Convert.ToInt32(regex.Replace(string.IsNullOrEmpty(OutStr) ? "0" : OutStr, ""));
|
||||
[CsvColumn(Name = "Date", FieldIndex = 6)]
|
||||
public DateTime OrderDate => InvDate.AddMonths(1).AddDays(-1);
|
||||
|
||||
internal PluralizationService ps => PluralizationService.CreateService(new CultureInfo("en-US"));
|
||||
internal Regex regex = new Regex(@"[^\d]");
|
||||
|
||||
internal Order()
|
||||
{
|
||||
index = 0;
|
||||
InvDateStr = DateTime.Today.ToString("M/yy");
|
||||
Medicine = string.Empty;
|
||||
Brand = string.Empty;
|
||||
OutStr = "0";
|
||||
}
|
||||
|
||||
public Order(ExpandoObject expando, DateTime invDate)
|
||||
: this()
|
||||
{
|
||||
InvDateStr = invDate.ToString("M/yy");
|
||||
var dictionary = expando as IDictionary<string, object>;
|
||||
dictionary.Keys.ToList()
|
||||
.ForEach(k =>
|
||||
{
|
||||
var value = Convert.ToString(dictionary[k]);
|
||||
switch (k)
|
||||
{
|
||||
case "MedicineID":
|
||||
index = Convert.ToInt32(value);
|
||||
break;
|
||||
case "Medicine":
|
||||
case "Medication":
|
||||
Medicine = value;
|
||||
break;
|
||||
case "MedicineBrand":
|
||||
Brand = value;
|
||||
break;
|
||||
case "Output":
|
||||
OutStr = value;
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
object ToDump() => new
|
||||
{
|
||||
MedicineID = index,
|
||||
Medication = Medicine,
|
||||
Brand,
|
||||
Label,
|
||||
Customer = "",
|
||||
Shipped = Out,
|
||||
Date = InvDate.AddMonths(1).AddDays(-1)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public class Purchase
|
||||
{
|
||||
internal string[] Row { get; set; }
|
||||
[CsvColumn(Name = "MedicineID", FieldIndex = 1)]
|
||||
public int index { get; set; }
|
||||
internal string InvDateStr { get; set; }
|
||||
public DateTime InvDate => !string.IsNullOrEmpty(InvDateStr)
|
||||
? DateTime.ParseExact(InvDateStr, "M/yy", System.Globalization.CultureInfo.InvariantCulture)
|
||||
: new DateTime(2999, 12, 31);
|
||||
[CsvColumn(Name = "Medication", FieldIndex = 2)]
|
||||
public string Medicine { get; set; }
|
||||
internal string Brand { get; set; }
|
||||
[CsvColumn(FieldIndex = 3)]
|
||||
public string Label => $"{Medicine} {Brand}";
|
||||
[CsvColumn(FieldIndex = 4)]
|
||||
public string Supplier => string.Empty;
|
||||
internal string RcvdStr { get; set; }
|
||||
[CsvColumn(Name = "Received", FieldIndex = 5)]
|
||||
public int Rcvd => Convert.ToInt32(regex.Replace(string.IsNullOrEmpty(RcvdStr) ? "0" : RcvdStr, ""));
|
||||
internal string Notes { get; set; }
|
||||
internal string ExpiryStr = "";
|
||||
internal DateTime Expiry => !string.IsNullOrEmpty(ExpiryStr)
|
||||
? DateTime.ParseExact(ExpiryStr, "M/yy", System.Globalization.CultureInfo.InvariantCulture)
|
||||
: new DateTime(2999, 12, 31);
|
||||
[CsvColumn(Name = "Date", FieldIndex = 6)]
|
||||
public DateTime Purchased { get; set; }
|
||||
|
||||
internal PluralizationService ps => PluralizationService.CreateService(new CultureInfo("en-US"));
|
||||
internal Regex regex = new Regex(@"[^\d]");
|
||||
|
||||
internal Purchase()
|
||||
{
|
||||
index = 0;
|
||||
InvDateStr = DateTime.Today.ToString("M/yy");
|
||||
Medicine = string.Empty;
|
||||
Brand = string.Empty;
|
||||
RcvdStr = "0";
|
||||
Purchased = new DateTime(2999, 12, 31);
|
||||
}
|
||||
|
||||
public Purchase(ExpandoObject expando, DateTime invDate)
|
||||
: this()
|
||||
{
|
||||
InvDateStr = invDate.ToString("M/yy");
|
||||
Purchased = InvDate;
|
||||
var dictionary = expando as IDictionary<string, object>;
|
||||
dictionary.Keys.ToList()
|
||||
.ForEach(k =>
|
||||
{
|
||||
var value = Convert.ToString(dictionary[k]);
|
||||
switch (k)
|
||||
{
|
||||
case "MedicineID":
|
||||
index = Convert.ToInt32(value);
|
||||
break;
|
||||
case "Medicine":
|
||||
case "Medication":
|
||||
Medicine = value;
|
||||
break;
|
||||
case "MedicineBrand":
|
||||
Brand = value;
|
||||
break;
|
||||
case "Received":
|
||||
RcvdStr = value;
|
||||
break;
|
||||
case "ExpirationDate":
|
||||
ExpiryStr = Regex.Replace(value, @"[^\d/]", "");
|
||||
break;
|
||||
case "Notes:":
|
||||
var purchaseStr = !string.IsNullOrEmpty(value) && value.StartsWith("Purchased")
|
||||
? Regex.Replace(value, @"[^\d/]", "")
|
||||
: string.Empty;
|
||||
Purchased = !string.IsNullOrEmpty(purchaseStr)
|
||||
? DateTime.ParseExact(purchaseStr, "M/d/yy", System.Globalization.CultureInfo.InvariantCulture)
|
||||
: DateTime.Compare(Expiry, new DateTime(2018, 1, 1)) < 0
|
||||
? Expiry.AddMonths(-6) : new DateTime(2018, 1, 1); ;
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
object ToDump() => new
|
||||
{
|
||||
MedicineID = index,
|
||||
Medication = Medicine,
|
||||
Brand,
|
||||
Label,
|
||||
Supplier = "",
|
||||
Received = Rcvd,
|
||||
Date = Purchased
|
||||
};
|
||||
}
|
||||
|
||||
public static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue)
|
||||
{
|
||||
// ExpandoObject supports IDictionary so we can extend it like this
|
||||
var expandoDict = expando as IDictionary<string, object>;
|
||||
if (expandoDict.ContainsKey(propertyName))
|
||||
expandoDict[propertyName] = propertyValue;
|
||||
else
|
||||
expandoDict.Add(propertyName, propertyValue);
|
||||
}
|
||||
Reference in New Issue
Block a user