diff --git a/server/AyaNova/biz/CustomerBiz.cs b/server/AyaNova/biz/CustomerBiz.cs index e2edb5a1..47c0a2af 100644 --- a/server/AyaNova/biz/CustomerBiz.cs +++ b/server/AyaNova/biz/CustomerBiz.cs @@ -430,26 +430,64 @@ namespace AyaNova.Biz List ImportResult = new List(); string ImportTag = $"imported-{FileUtil.GetSafeDateFileName()}"; + //ignore these fields var jsset = JsonSerializer.CreateDefault(new JsonSerializerSettings { ContractResolver = new AyaNova.Util.JsonUtil.ShouldSerializeContractResolver(new string[] { "Concurrency", "Id", "CustomFields" }) }); + foreach (JObject j in importData.Data) { + long? existingId = await ct.Customer.AsNoTracking().Where(z => z.Name == (string)j["Name"]).Select(x => x.Id).FirstOrDefaultAsync(); - - - var w = j.ToObject(jsset); - if (j["CustomFields"] != null) - w.CustomFields = j["CustomFields"].ToString(); - w.Tags.Add(ImportTag);//so user can find them all and revert later if necessary - var res = await CreateAsync(w); - if (res == null) + if (existingId == null) { - ImportResult.Add($"* {w.Name} - {this.GetErrorsAsString()}"); - this.ClearErrors(); + if (importData.DoImport) + { + //import this record + var o = j.ToObject(jsset); + o.Tags.Add(ImportTag); + var res = await CreateAsync(o); + if (res == null) + { + ImportResult.Add($"❌ {o.Name} - {this.GetErrorsAsString()}"); + this.ClearErrors(); + } + else + { + ImportResult.Add($"✔️ {o.Name}"); + } + } + } else { - ImportResult.Add($"{w.Name} - ok"); + if (importData.DoUpdate) + { + //update this record with any data provided + //load existing record + var target = await GetAsync((long)existingId); + var source = j.ToObject(jsset); + var propertiesToUpdate = j.Properties().Select(p => p.Name).ToList(); + propertiesToUpdate.Remove("Name"); + ImportUpdateObject.Update(source, target, propertiesToUpdate); + var res = await PutAsync(target); + + if (res == null) + { + ImportResult.Add($"❌ {target.Name} - {this.GetErrorsAsString()}"); + this.ClearErrors(); + } + else + { + ImportResult.Add($"✔️ {target.Name}"); + } + // bool copyTags=false; + // if(propertiesToUpdate.Contains("Tags")) + // copyTags=true; + + } } + + + } return ImportResult; } diff --git a/server/AyaNova/util/ImportUpdateObject.cs b/server/AyaNova/util/ImportUpdateObject.cs new file mode 100644 index 00000000..236e59a1 --- /dev/null +++ b/server/AyaNova/util/ImportUpdateObject.cs @@ -0,0 +1,60 @@ +using System; +using System.Reflection; +using System.Linq; +using System.Collections.Generic; + +namespace AyaNova.Util +{ + + internal static class ImportUpdateObject + { + /// + /// Copies the data of one object to another. The target object 'pulls' properties of the first. + /// Any matching properties are written to the target. + /// + /// The object copy is a shallow copy only. Any nested types will be copied as + /// whole values rather than individual property assignments (ie. via assignment) + /// + /// The source object to copy from + /// The object to copy to + /// A list of properties that should be copied + public static void Update(object source, object target, List propertiesToUpdate) + { + + MemberInfo[] miT = target.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance); + foreach (MemberInfo Field in miT) + { + string name = Field.Name; + // Skip over any property exceptions + if (!propertiesToUpdate.Contains(name)) + continue; + + if (Field.MemberType == MemberTypes.Field) + { + FieldInfo SourceField = source.GetType().GetField(name); + if (SourceField == null) + continue; + + object SourceValue = SourceField.GetValue(source); + ((FieldInfo)Field).SetValue(target, SourceValue); + } + else if (Field.MemberType == MemberTypes.Property) + { + PropertyInfo piTarget = Field as PropertyInfo; + PropertyInfo SourceField = source.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.Instance); + if (SourceField == null) + continue; + + if (piTarget.CanWrite && SourceField.CanRead) + { + object SourceValue = SourceField.GetValue(source, null); + piTarget.SetValue(target, SourceValue, null); + } + } + } + } + + + }//eoc + +}//eons \ No newline at end of file