diff --git a/WebAPI/Calculators/BaseCalc.cs b/WebAPI/Calculators/BaseCalc.cs index 25dba7c..b7b1f32 100644 --- a/WebAPI/Calculators/BaseCalc.cs +++ b/WebAPI/Calculators/BaseCalc.cs @@ -25,6 +25,7 @@ public class BaseCalc { return false; } + if (!ResultCode.Substring(1, ResultCode.Length - 2).All(char.IsDigit)) { return false; @@ -57,12 +58,15 @@ public class BaseCalc { throw new Exception($"Record for code {code} not found."); } + ingredients.Add(ingredient); } - + for (var i = 1; i <= 32; i++) { - var formula = ingredients.Aggregate(Formula, (current, ingredient) => current.Replace($"[{ingredient.Code}]", ProcessHelper.GetValue(ingredient, i)?.ToString(CultureInfo.InvariantCulture))); + var formula = ingredients.Aggregate(Formula, + (current, ingredient) => current.Replace($"[{ingredient.Code}]", + ProcessHelper.GetValue(ingredient, i)?.ToString(CultureInfo.InvariantCulture))); if (formula.Contains('[')) { throw new Exception($"Not all placeholders were replaced. Value{i} [{formula}]"); @@ -71,6 +75,47 @@ public class BaseCalc Entity expr = formula; ProcessHelper.SetValue(result, i, (double)expr.EvalNumerical()); } + + return result; + } + } + + public Record CalculateT1(List records) + { + var resultCode = ResultCode; + { + var result = new Record + { + Id = Guid.NewGuid(), + Code = resultCode, + CreatedAt = DateTime.UtcNow, + ModifiedAt = DateTime.UtcNow + }; + var codes = GetCodes(); + var ingredients = new List(); + foreach (var code in codes) + { + var ingredient = records.FirstOrDefault(r => r.Code == code); + if (ingredient == null) + { + throw new Exception($"Record for code {code} not found."); + } + + ingredients.Add(ingredient); + } + + + var formula = ingredients.Aggregate(Formula, + (current, ingredient) => current.Replace($"[{ingredient.Code}]", + ProcessHelper.GetValue(ingredient, 32)?.ToString(CultureInfo.InvariantCulture))); + if (formula.Contains('[')) + { + throw new Exception($"Not all placeholders were replaced. Value{1} [{formula}]"); + } + + Entity expr = formula; + ProcessHelper.SetValue(result, 32, (double)expr.EvalNumerical()); + return result; } } @@ -93,6 +138,7 @@ public class BaseCalc var valueCode = Formula.Substring(startIndex + 1, endIndex - startIndex - 1); codes.Add(valueCode); } + return codes; } } \ No newline at end of file diff --git a/WebAPI/Controllers/LayersController.cs b/WebAPI/Controllers/LayersController.cs index fcbdcdb..65b10dc 100644 --- a/WebAPI/Controllers/LayersController.cs +++ b/WebAPI/Controllers/LayersController.cs @@ -353,7 +353,8 @@ public class LayersController : Controller "T3-MultiSourceYearSummary", // AA/13 "T4-SingleSource", "T1-R1", - "T4-R2" + "T4-R2", + "T1-R1_V2" ]; foreach (var type in processTypes) @@ -505,6 +506,21 @@ public class LayersController : Controller }); return; } + case "T1-R1_V2": + { + var processor = new T1R1V2Processor(_db, _googleSheetValues, this, _logsController); + processor.Process(processWorker); + + _logsController.AddEntry(new LogEntry + { + Title = $"{processWorker.Name}, {processWorker.Id}", + Type = LogEntryType.Info, + LogType = LogType.Process, + Message = "Success", + CreatedAt = DateTime.UtcNow + }); + return; + } case "T4-R2": { var processor = new T4R2Processor(_db, this, _logsController, _googleSheetValues); diff --git a/WebAPI/dataProcessors/t1.r1_v2.processor.cs b/WebAPI/dataProcessors/t1.r1_v2.processor.cs new file mode 100644 index 0000000..ebbdbe7 --- /dev/null +++ b/WebAPI/dataProcessors/t1.r1_v2.processor.cs @@ -0,0 +1,180 @@ +using System.Globalization; +using DiunaBIWebAPI.dataProcessors; +using Google.Apis.Sheets.v4; +using Google.Apis.Sheets.v4.Data; +using Microsoft.EntityFrameworkCore; +using WebAPI.Calculator; +using WebAPI.Controllers; +using WebAPI.Models; + +namespace WebAPI.dataProcessors; + +public class T1R1V2Processor( + AppDbContext db, + SpreadsheetsResource.ValuesResource googleSheetValues, + LayersController controller, + LogsController logsController) +{ + private readonly SpreadsheetsResource.ValuesResource _googleSheetValues = googleSheetValues; + private readonly LogsController _logsController = logsController; + + public void Process(Layer processWorker) + { + var year = int.Parse(processWorker.Records?.SingleOrDefault(x => x.Code == "Year")?.Desc1!); + var sources = processWorker.Records?.Where(x => x.Code == "Source").ToList(); + if (sources!.Count == 0) + { + throw new Exception("Source record not found"); + } + + var processedLayer = db.Layers + .Where(x => x.ParentId == processWorker.Id + && !x.IsDeleted) + .OrderByDescending(x => x.CreatedAt) + .FirstOrDefault(); + + var isNew = false; + if (processedLayer == null) + { + isNew = true; + processedLayer = new Layer + { + Id = Guid.NewGuid(), + Type = LayerType.Processed, + ParentId = processWorker.Id, + Number = db.Layers.Count() + 1 + }; + processedLayer.Name = $"L{processedLayer.Number}-P-{year}-R1_V2-T1"; + processedLayer.CreatedById = Guid.Parse("F392209E-123E-4651-A5A4-0B1D6CF9FF9D"); + processedLayer.ModifiedById = Guid.Parse("F392209E-123E-4651-A5A4-0B1D6CF9FF9D"); + processedLayer.CreatedAt = DateTime.UtcNow; + processedLayer.ModifiedAt = DateTime.UtcNow; + } + + processedLayer.ModifiedById = Guid.Parse("F392209E-123E-4651-A5A4-0B1D6CF9FF9D"); + processedLayer.ModifiedAt = DateTime.UtcNow; + + var dynamicCodes = processWorker.Records?.Where(x => x.Code!.Contains("DynamicCode-")) + .OrderBy(x => int.Parse(x.Code!.Split('-')[1])) + .ToList(); + + var newRecords = new List(); + + for (var month = 1; month <= DateTime.UtcNow.Month; month++) + { + var records = new List(); + foreach (var source in sources) + { + var monthCopy = month; + var dataSource = db.Layers.Where(x => + x.Type == LayerType.Processed && + !x.IsDeleted && + x.Name != null && x.Name.Contains($"{year}/{monthCopy}-{source.Desc1}-T3") + ).Include(x => x.Records) + .FirstOrDefault(); + + if (dataSource == null) + { + throw new Exception($"Source layer {year}/{monthCopy}-{source.Desc1}-T3 not found."); + } + + var codesRecord = processWorker.Records?.Where(x => x.Code == $"Codes-{source.Desc1}").FirstOrDefault(); + if (codesRecord != null) + { + var codes = ProcessHelper.ParseCodes(codesRecord.Desc1!); + records.AddRange(dataSource.Records!.Where(x => codes.Contains(int.Parse(x.Code!)))); + } + else + { + records.AddRange(dataSource.Records!); + } + } + + if (dynamicCodes != null) + { + foreach (var dynamicCode in dynamicCodes) + { + try + { + if (dynamicCode.Desc1 == null) + { + _logsController.AddEntry(new LogEntry + { + Title = $"{processWorker.Name}, {processWorker.Id}", + Type = LogEntryType.Warning, + LogType = LogType.Process, + Message = $"Formula in Record {dynamicCode.Id} is missing.", + CreatedAt = DateTime.UtcNow + }); + continue; + } + + var calc = new BaseCalc(dynamicCode.Desc1); + if (!calc.IsFormulaCorrect()) + { + _logsController.AddEntry(new LogEntry + { + Title = $"{processWorker.Name}, {processWorker.Id}", + Type = LogEntryType.Warning, + LogType = LogType.Process, + Message = $"Formula {calc.Expression} in Record {dynamicCode.Id} is not correct", + CreatedAt = DateTime.UtcNow + }); + continue; + } + + try + { + records.Add(calc.CalculateT1(records)); + } + catch (Exception e) + { + _logsController.AddEntry(new LogEntry + { + Title = $"{processWorker.Name}, {processWorker.Id}", + Type = LogEntryType.Warning, + LogType = LogType.Process, + Message = + $"Formula {calc.Expression} in Record {dynamicCode.Id} error: {e.Message}", + CreatedAt = DateTime.UtcNow + }); + } + } + catch (Exception e) + { + _logsController.AddEntry(new LogEntry + { + Title = $"{processWorker.Name}, {processWorker.Id}", + Type = LogEntryType.Warning, + LogType = LogType.Process, + Message = $"Calculation error {dynamicCode.Id}: {e.Message} ", + CreatedAt = DateTime.UtcNow + }); + } + } + } + + newRecords.AddRange(records.Select(x => new Record + { + Id = Guid.NewGuid(), + Code = x.Code + month.ToString("D2"), + CreatedAt = DateTime.UtcNow, + ModifiedAt = DateTime.UtcNow, + Value1 = x.Value32 + } + )); + } + + if (isNew) + { + db.Layers.Add(processedLayer); + } + else + { + db.Layers.Update(processedLayer); + } + + controller.SaveRecords(processedLayer.Id, newRecords, Guid.Parse("F392209E-123E-4651-A5A4-0B1D6CF9FF9D")); + db.SaveChanges(); + } +} \ No newline at end of file