This commit is contained in:
2022-03-28 23:11:09 +00:00
parent 4c6e8102c4
commit 83a3ad689c
3 changed files with 197 additions and 15 deletions

View File

@@ -0,0 +1,109 @@
# Task group import / update specifications
Names of fields listed here are the exact case and spelling required to be recognized by AyaNova for [importing / updating](adm-import.md).
Any field in the import file that is not listed on this page will be removed before sending to the server for import.
## Required fields
- Name
## Key field used to match to existing records
- Name
## Fields directly importable / updateable
- Name (import only)
- Active
- Notes
- Items
## JSON file format
The .json file must contain an array of one or more Task group objects.
```JSON
[
{
"Name": "Aerostat monitor standard refurb",
"Active": true,
"Notes": "Alias maxime deserunt corrupti voluptatem a voluptatem eligendi.",
"Items": [
{
"Sequence": 1,
"Task": "Power down unit"
},
{
"Sequence": 2,
"Task": "Open seals"
},
{
"Sequence": 3,
"Task": "Replace central core"
},
{
"Sequence": 4,
"Task": "Test point B and verify +.25"
},
{
"Sequence": 5,
"Task": "Replace seals"
},
{
"Sequence": 6,
"Task": "Confirm power up"
}
]
},
{
"Name": "Clean and inspect Class 7C",
"Active": true,
"Notes": "Facilis omnis dolor tempora dolores suscipit maxime ut et eum aperiam dolor.",
"Items": [
{
"Sequence": 1,
"Task": "Open unit"
},
{
"Sequence": 2,
"Task": "Test tinclavic seals"
},
{
"Task": "Inspect triple-bonded polysium for cracks"
},
{
"Sequence": 4,
"Task": "Verify thickness of zybanium shield"
},
{
"Sequence": 5,
"Task": "Close unit"
},
{
"Sequence": 6,
"Task": "Clean unit and confirm power up"
}
]
}
]
```
## CSV file format
The first row of the .csv file must contain column headers that match the field names listed above.
CSV doesn't cleanly map on to structured elements with sub collections well so the Items column here which contains the Tasks for this Task group has a special format we've adopted:
The Items column **must** be:
- surrounded in double "quotes"
- contain the Tasks separated by commas
- each Task text must _not_ have a comma or a quotation mark in it or the csv will not be valid
- Sequence numbers are not importable from csv but will be automatically assigned in the order presented so the first item will be sequence 1, second sequence 2 etc
```
Name,Active,Notes,Items
Aerostat monitor standard refurb,true,Alias maxime deserunt corrupti voluptatem a voluptatem eligendi.,"Power down unit, Open seals, Replace central core, Test point B and verify +.25"
Clean and inspect Class 7C,true,Facilis omnis dolor tempora dolores suscipit maxime ut et eum aperiam dolor.,"Open unit, Test tinclavic seals, Inspect triple-bonded polysium for cracks, Verify thickness of zybanium shield,Close unit, Clean unit and confirm power up"
```

View File

@@ -175,6 +175,7 @@ Each object type listed below links to a page showing the specific format requir
- ##### [Part warhouses](adm-import-part-warehouse.md) - ##### [Part warhouses](adm-import-part-warehouse.md)
- ##### [Projects](adm-import-projects.md) - ##### [Projects](adm-import-projects.md)
- ##### [Service rates](adm-import-service-rate.md) - ##### [Service rates](adm-import-service-rate.md)
- ##### [Task group](adm-import-task-group.md)
- ##### [Travel rates](adm-import-travel-rate.md) - ##### [Travel rates](adm-import-travel-rate.md)
## Import form ## Import form

View File

@@ -325,32 +325,104 @@ namespace AyaNova.Biz
return await GetReportData(dataListSelectedRequest, jobId); return await GetReportData(dataListSelectedRequest, jobId);
} }
public async Task<List<string>> ImportData(AyImportData importData) public async Task<List<string>> ImportData(AyImportData importData)
{ {
List<string> ImportResult = new List<string>();
string ImportTag = $"imported-{FileUtil.GetSafeDateFileName()}";
List<string> ImportResult = new List<string>();
string ImportTag = ImportUtil.GetImportTag();
//ignore these fields
var jsset = JsonSerializer.CreateDefault(new JsonSerializerSettings { ContractResolver = new AyaNova.Util.JsonUtil.ShouldSerializeContractResolver(new string[] { "Concurrency", "Id", "CustomFields" }) }); var jsset = JsonSerializer.CreateDefault(new JsonSerializerSettings { ContractResolver = new AyaNova.Util.JsonUtil.ShouldSerializeContractResolver(new string[] { "Concurrency", "Id", "CustomFields" }) });
foreach (JObject j in importData.Data) foreach (JObject j in importData.Data)
{ {
var w = j.ToObject<TaskGroup>(jsset); try
// if (j["CustomFields"] != null) {
// w.CustomFields = j["CustomFields"].ToString(); //Compile Items collection if specified
// w.Tags.Add(ImportTag);//so user can find them all and revert later if necessary var ImportTaskGroupItems = new List<TaskGroupItem>();
var res = await CreateAsync(w); if (j["Items"] != null)
{
//hydrate from collection
foreach (JToken t in j["Items"])
{
ImportTaskGroupItems.Add(new TaskGroupItem() { TaskGroupId = 0, Sequence = (int)t["Sequence"], Task = (string)t["Task"] });
}
j["Items"] = null;//strip it out so it doesn't get automatically converted into parsed object later
}
long existingId = await ct.TaskGroup.AsNoTracking().Where(z => z.Name == (string)j["Name"]).Select(x => x.Id).FirstOrDefaultAsync();
if (existingId == 0)
{
if (importData.DoImport)
{
//import this record
var Target = j.ToObject<TaskGroup>(jsset);
if (Target.Items == null)
Target.Items = new List<TaskGroupItem>();
if (j["Items"] != null)
foreach (TaskGroupItem tgi in ImportTaskGroupItems)
Target.Items.Add(tgi);
var res = await CreateAsync(Target);
if (res == null) if (res == null)
{ {
ImportResult.Add($"* {w.Name} - {this.GetErrorsAsString()}"); ImportResult.Add($" {Target.Name}\r\n{this.GetErrorsAsString()}");
this.ClearErrors(); this.ClearErrors();
} }
else else
{ {
ImportResult.Add($"{w.Name} - ok"); ImportResult.Add($"✔️ {Target.Name}");
} }
} }
return ImportResult; }
else
{
if (importData.DoUpdate)
{
//update this record with any data provided
//load existing record
var Target = await GetAsync((long)existingId);
var Source = j.ToObject<TaskGroup>(jsset);
var propertiesToUpdate = j.Properties().Select(p => p.Name).ToList();
propertiesToUpdate.Remove("Name");
propertiesToUpdate.Remove("Items");
ImportUtil.Update(Source, Target, propertiesToUpdate);
if (j["Items"] != null)
{
Target.Items.Clear();
foreach (TaskGroupItem tgi in ImportTaskGroupItems)
Target.Items.Add(tgi);
} }
var res = await PutAsync(Target);
if (res == null)
{
ImportResult.Add($"❌ {Target.Name} - {this.GetErrorsAsString()}");
this.ClearErrors();
}
else
{
ImportResult.Add($"✔️ {Target.Name}");
}
}
}
}
catch (Exception ex)
{
ImportResult.Add($"❌ Exception processing import\n record:{j.ToString()}\nError:{ex.Message}\nSource:{ex.Source}\nStack:{ex.StackTrace.ToString()}");
}
}
return ImportResult;
}