using System.Globalization; using System.Xml.Serialization; using Google.Apis.Sheets.v4; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using WebAPI.dataParsers; using WebAPI.dataProcessors; using WebAPI.Exports; using WebAPI.Models; namespace WebAPI.Controllers { [ApiController] [Route("api/[controller]")] public class LayersController : Controller { private readonly AppDbContext db; private SpreadsheetsResource.ValuesResource googleSheetValues; private GoogleDriveHelper googleDriveHelper; private GoogleSheetsHelper googleSheetsHelper; private readonly IConfiguration configuration; private readonly LogsController logsController; public LayersController( AppDbContext _db, GoogleSheetsHelper _googleSheetsHelper, GoogleDriveHelper _googleDriveHelper, IConfiguration _configuration) { db = _db; googleSheetValues = _googleSheetsHelper.Service.Spreadsheets.Values; googleSheetsHelper = _googleSheetsHelper; googleDriveHelper = _googleDriveHelper; configuration = _configuration; logsController = new LogsController(googleSheetsHelper, googleDriveHelper, configuration); } [HttpGet] public IActionResult GetAll(int start, int limit, string? name, LayerType? type) { try { IQueryable response = db.Layers.Where(x => !x.IsDeleted); if (name != null) { response = response.Where(x => x.Name.Contains(name)); } if (type != null) { response = response.Where(x => x.Type == type); } return Ok(response .OrderByDescending(x => x.Number) .Skip(start).Take(limit).ToList()); } catch (Exception e) { return BadRequest(e.ToString()); } } [HttpPost] public IActionResult Save(Layer input) { try { Request.Headers.TryGetValue("userId", out var value); Guid currentUserId = new Guid(value!); return Ok(AddLayer(input, currentUserId).Id); } catch (Exception e) { return BadRequest(e.ToString()); } } [HttpGet] [Route("{id}")] public IActionResult Get(Guid id) { try { return Ok(db.Layers .Include(x => x.CreatedBy) .Include(x => x.Records) .Where(x => x.Id == id && !x.IsDeleted).First()); } catch (Exception e) { return BadRequest(e.ToString()); } } [HttpGet] [Route("parseGoogleSheet/{sheetId}")] public IActionResult ParseGoogleSheet(string sheetId) { string sheetName = "KOSZTY"; Layer layer = new Layer(); layer.Source = "GoogleSheet"; layer.Number = db.Layers.Count() + 1; var parser = new googleSheetParser(googleSheetValues); dynamic parsedSheet = parser.parse(sheetId); layer.Records = parsedSheet.records; layer.Name = $"W{layer.Number}-I-{sheetName}-{parsedSheet.date}-{DateTime.Now.ToString("yyyyMMddHHmm")}"; return Ok(layer); } [HttpPost] [DisableRequestSizeLimit] [Route("parseFile")] public IActionResult ParseFile() { var parser = new csvParser(); return Ok(parser.parse(Request.Form.Files[0])); } [HttpGet] [Route("exportToGoogleSheet/{id}")] public IActionResult ExportToGoogleSheet(Guid id) { Layer layer = db.Layers .Include(x => x.Records!.OrderByDescending(x => x.Code)) .Where(x => x.Id == id && !x.IsDeleted).First(); var export = new googleSheetExport(googleDriveHelper, googleSheetValues, configuration); export.export(layer); return Ok(true); } [HttpGet] [Route("AutoImport/{apiKey}")] [AllowAnonymous] public IActionResult AutoImport(string apiKey) { if (Request.Host.Value != configuration["apiLocalUrl"] || apiKey != configuration["apiKey"]) { return Unauthorized(); } List importWorkerLayers; List layersToImport; ; try { importWorkerLayers = db.Layers .Include(x => x.Records) .Where(x => x.Records!.Any(x => x.Code == "Type" && x.Desc1 == "ImportWorker")) .ToList(); layersToImport = new List(); foreach (Layer layer in importWorkerLayers) { string startDate = layer.Records!.Where(x => x.Code == "StartDate").First().Desc1!; string endDate = layer.Records!.Where(x => x.Code == "EndDate").First().Desc1!; var startDateParsed = DateTime.ParseExact(startDate, "yyyy.MM.dd", null); var endDateParsed = DateTime.ParseExact(endDate, "yyyy.MM.dd", null); if (startDateParsed.Date <= DateTime.UtcNow.Date && endDateParsed.Date >= DateTime.UtcNow.Date) { processImportWorker(layer); } } } catch (Exception e) { logsController.AddEntry(new LogEntry { Title = "Import error", Type = LogEntryType.error, LogType = LogType.import, Message = e.ToString(), CreatedAt = DateTime.UtcNow }); return BadRequest(e.ToString()); } return Ok(); } [HttpGet] [Route("AutoProcess/{apiKey}")] [AllowAnonymous] public IActionResult AutoProcess(string apiKey) { if (Request.Host.Value != configuration["apiLocalUrl"] || apiKey != configuration["apiKey"]) { return Unauthorized(); } List processWorkerLayers; List layersToProcess; try { processWorkerLayers = db.Layers .Include(x => x.Records) .Where(x => x.Records!.Any(x => x.Code == "Type" && x.Desc1 == "ProcessWorker") && x.Records!.Any(x => x.Code == "IsEnabled" && x.Desc1 == "True") //&& x.Number == 215 ) .ToList(); layersToProcess = new List(); foreach (Layer processWorker in processWorkerLayers) { string? processType = processWorker?.Records?.Single(x => x.Code == "ProcessType")?.Desc1; if (processType == null) { logsController.AddEntry(new LogEntry { Title = "Process error", Type = LogEntryType.error, LogType = LogType.import, Message = processWorker?.Name + " ProcessType record not found", CreatedAt = DateTime.UtcNow }); return BadRequest(); } string? sourceName = processWorker?.Records?.Single(x => x.Code == "Source")?.Desc1; if (sourceName == null) { logsController.AddEntry(new LogEntry { Title = "Process error", Type = LogEntryType.error, LogType = LogType.import, Message = processWorker?.Name + " Source record not found", CreatedAt = DateTime.UtcNow }); return BadRequest(); } if (processType == "T3-SourceSummary") { if (processWorker != null) { T3SourceYearSummaryProcessor processor = new T3SourceYearSummaryProcessor(db, googleSheetValues, this); processor.process(processWorker); } } else { Layer sourceLayer = db.Layers.Include(x => x.Records) .Single(x => x.Name == sourceName); if (sourceLayer == null) { logsController.AddEntry(new LogEntry { Title = "Process error", Type = LogEntryType.error, LogType = LogType.import, Message = processWorker?.Name + " Source layer not found " + sourceLayer, CreatedAt = DateTime.UtcNow }); return BadRequest(); } string startDate = sourceLayer.Records!.Where(x => x.Code == "StartDate").First().Desc1!; string endDate = sourceLayer.Records!.Where(x => x.Code == "EndDate").First().Desc1!; var startDateParsed = DateTime.ParseExact(startDate, "yyyy.MM.dd", null); var endDateParsed = DateTime.ParseExact(endDate, "yyyy.MM.dd", null); if (startDateParsed.Date <= DateTime.UtcNow.Date && endDateParsed.Date >= DateTime.UtcNow.Date) { switch (processType) { case "Copy": CopyProcessor cp = new CopyProcessor(db, googleSheetValues, this); cp.process(sourceLayer, processWorker?.Id); break; case "Deaggregation": DeaggregationProcessor dp = new DeaggregationProcessor(db, googleSheetValues, this); dp.process(sourceLayer, processWorker?.Id); break; case "T3-SingleSource": T3SingleSourceProcessor processor = new T3SingleSourceProcessor(db, googleSheetValues, this); processor.process(sourceLayer, processWorker?.Id); break; } logsController.AddEntry(new LogEntry { Title = $"Process Success, {sourceLayer.Name}", Type = LogEntryType.info, LogType = LogType.process, CreatedAt = DateTime.UtcNow }); } else if (endDateParsed.Date >= DateTime.UtcNow.Date) { // TODO: make isEnabled = false - layer is out of date var name = processWorker.Name; } } } return Ok(); } catch (Exception e) { logsController.AddEntry(new LogEntry { Title = "Process error", Type = LogEntryType.error, LogType = LogType.process, Message = e.ToString(), CreatedAt = DateTime.UtcNow }); return BadRequest(e.ToString()); } } [HttpGet] [Route("checkDates")] public IActionResult checkDates() { var warsawTZ = TimeZoneInfo.FindSystemTimeZoneById("Singapore Standard Time"); DateTime date = DateTime.UtcNow; return Ok(date); } // private void processImportWorker(Layer importWorker) { // get and check settings string? sheetId = importWorker.Records!.Where(x => x.Code == "SheetId").FirstOrDefault()?.Desc1; if (sheetId == null) { throw new Exception($"SheetId not found, {importWorker.Name}"); } string? sheetTabName = importWorker.Records!.Where(x => x.Code == "SheetTabName").FirstOrDefault()?.Desc1; if (sheetTabName == null) { throw new Exception($"SheetTabName not found, {importWorker.Name}"); } string? importYearCell = importWorker.Records!.Where(x => x.Code == "ImportYear").FirstOrDefault()?.Desc1; if (importYearCell == null) { throw new Exception($"ImportYear not found, {importWorker.Name}"); } string? importMonthCell = importWorker.Records!.Where(x => x.Code == "ImportMonth").FirstOrDefault()?.Desc1; if (importMonthCell == null) { throw new Exception($"ImportMonth not found, {importWorker.Name}"); } string? importNameCell = importWorker.Records!.Where(x => x.Code == "ImportName").FirstOrDefault()?.Desc1; if (importNameCell == null) { throw new Exception($"ImportName not found, {importWorker.Name}"); } string? checkSumCell = importWorker.Records!.Where(x => x.Code == "SheetId").FirstOrDefault()?.Desc1; if (checkSumCell == null) { throw new Exception($"SheetId not found, {importWorker.Name}"); } string? dataRange = importWorker.Records!.Where(x => x.Code == "DataRange").FirstOrDefault()?.Desc1; if (dataRange == null) { throw new Exception($"DataRange not found, {importWorker.Name}"); } // open excel and read data var nameResponse = googleSheetValues.Get(sheetId, $"{sheetTabName}!{importNameCell}:{importNameCell}").Execute(); string? name = nameResponse.Values?[0][0].ToString(); if (name == null) { throw new Exception($"ImportName cell is empty, {importWorker.Name}"); } var yearResponse = googleSheetValues.Get(sheetId, $"{sheetTabName}!{importYearCell}:{importYearCell}").Execute(); string? year = yearResponse.Values[0][0].ToString(); if (year == null) { throw new Exception($"ImportYear cell is empty, {importWorker.Name}"); } var monthResponse = googleSheetValues.Get(sheetId, $"{sheetTabName}!{importMonthCell}:{importMonthCell}").Execute(); string? month = monthResponse.Values[0][0].ToString(); if (month == null) { throw new Exception($"ImportMonth cell is empty, {importWorker.Name}"); } Layer layer = new Layer { Source = "GoogleSheet", Number = db.Layers.Count() + 1, ParentId = importWorker.Id }; layer.Name = $"L{layer.Number}-I-{name}-{year}/{month}-{DateTime.Now.ToString("yyyyMMddHHmm")}"; layer.Type = LayerType.import; layer.Records = new List(); var dataRangeResponse = googleSheetValues.Get(sheetId, $"{sheetTabName}!{dataRange}").Execute(); var data = dataRangeResponse.Values; for (int i = 0; i < data[1].Count; i++) { float value; if ( data[0][i].ToString()?.Length > 0 && float.TryParse(data[1][i].ToString(), CultureInfo.GetCultureInfo("pl-PL"), out value)) { Record record = new Record { Id = Guid.NewGuid(), Code = data[0][i].ToString(), Value1 = value, CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow }; layer.Records.Add(record); }; } AddLayer(layer, Guid.Parse("F392209E-123E-4651-A5A4-0B1D6CF9FF9D")); logsController.AddEntry(new LogEntry { Title = $"Import Success, {importWorker.Name}", Type = LogEntryType.info, LogType = LogType.import, CreatedAt = DateTime.UtcNow }); } internal Layer AddLayer(Layer input, Guid currentUserId) { input.CreatedById = currentUserId; input.ModifiedById = currentUserId; input.CreatedAt = DateTime.UtcNow; input.ModifiedAt = DateTime.UtcNow; db.Layers.Add(input); SaveRecords(input.Id, input.Records!, currentUserId); db.SaveChanges(); return input; } internal void SaveRecords(Guid id, ICollection records, Guid currentUserId) { try { List toDelete = db.Records.Where(x => x.LayerId == id).ToList(); if (toDelete.Count > 0) { db.Records.RemoveRange(toDelete); } foreach (Record record in records) { record.CreatedById = currentUserId; record.CreatedAt = DateTime.UtcNow; record.ModifiedById = currentUserId; record.ModifiedAt = DateTime.UtcNow; record.LayerId = id; db.Records.Add(record); } } catch (Exception) { throw; } } private void SaveSources(ICollection sources) { try { foreach (ProcessSource processSource in sources) { Console.WriteLine($"{processSource.LayerId} {processSource.SourceId}"); db.ProcessSources.Add(processSource); } } catch (Exception) { throw; } } } }