using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using System; using System.IO; using System.Linq; namespace OI.Metrology.Archive.ApiControllers; using OI.Metrology.Archive.Models; using OI.Metrology.Shared.DataModels; using OI.Metrology.Shared.Models.Stateless; using OI.Metrology.Shared.Services; using System.Collections.Generic; using System.Text.Json; // using System.Data.Common; public class ToolTypesController : Controller { // this controller powers the bulk of the UI // it is named after the /api/tooltypes prefix // the URL pattern is RESTful and the tool type is the root of every request private readonly AppSettings _AppSettings; private readonly IAttachmentsService _AttachmentsService; private readonly IMetrologyRepository _MetrologyRepository; public ToolTypesController(AppSettings appSettings, IMetrologyRepository metrologyRepository, IAttachmentsService attachmentsService) { _AppSettings = appSettings; _AttachmentsService = attachmentsService; _MetrologyRepository = metrologyRepository; } // Get a list of tooltypes, returns just Name and ID [HttpGet("/api/tooltypes")] public IActionResult Index() { var r = new { Results = _MetrologyRepository.GetToolTypes().Select(tt => new { tt.ToolTypeName, tt.ID }) }; return Json(r, new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true }); } // Gets the metadata for a tooltype, accepts a parameter which sorts the results // This is used to setup the grid displays on the UI [HttpGet("/api/tooltypes/{id}")] public IActionResult GetToolTypeMetadata(int id, string sortby = "") { ToolType tt = _MetrologyRepository.GetToolTypeByID(id); IEnumerable md = _MetrologyRepository.GetToolTypeMetadataByToolTypeID(id); if (string.Equals(sortby, "grid", StringComparison.OrdinalIgnoreCase)) md = md.OrderBy(f => f.GridDisplayOrder).ToList(); if (string.Equals(sortby, "table", StringComparison.OrdinalIgnoreCase)) md = md.OrderBy(f => f.GridDisplayOrder).ToList(); var r = new { Results = new { ToolType = tt, Metadata = md } }; return Json(r, new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true }); } // Just Changed here // Gets headers, request/response format is to allow paging with igniteUI // The headerid parameter is used for navigating directly to a header, when the button is clicked in Awaiting Dispo [HttpGet("/api/tooltypes/{id}/headers")] public IActionResult GetHeaders( int id, [FromQuery] DateTime? datebegin, [FromQuery] DateTime? dateend, [FromQuery] int? page, [FromQuery] int? pagesize, [FromQuery] long? headerid) { long totalRecs; System.Data.DataTable dt = _MetrologyRepository.GetHeaders(id, datebegin, dateend, page, pagesize, headerid, out totalRecs); var r = new { Results = dt, TotalRows = totalRecs, }; string json = JsonConvert.SerializeObject(r); return Content(json); } // Gets header titles, used in the Run Headers UI [HttpGet("/api/tooltypes/{id}/headertitles")] public IActionResult GetHeaderTitles( int id, [FromQuery] int? page, [FromQuery] int? pagesize) { long totalRecs; IEnumerable dt = _MetrologyRepository.GetHeaderTitles(id, page, pagesize, out totalRecs); var r = new { Results = dt, TotalRows = totalRecs, }; string json = JsonConvert.SerializeObject(r); return Content(json); } // Get all of the fields for a header, used with the Run Header UI [HttpGet("/api/tooltypes/{id}/headers/{headerid}/fields")] public IActionResult GetHeaderFields( int id, long headerid) { var r = new { Results = _MetrologyRepository.GetHeaderFields(id, headerid).Select(x => new { Column = x.Key, x.Value }).ToList() }; string json = JsonConvert.SerializeObject(r); return Content(json); } // Get the data for a header, used with the Run Info UI [HttpGet("/api/tooltypes/{id}/headers/{title}/data/isSharePoint")] public IActionResult GetData( int id, string title) { var r = new { Results = _MetrologyRepository.GetDataSharePoint(id, title) }; string json = JsonConvert.SerializeObject(r); return Content(json); } // Get the data for a header, used with the Run Info UI [HttpGet("/api/tooltypes/{id}/headers/{headerid}/data")] public IActionResult GetData( int id, long headerid) { var r = new { Results = _MetrologyRepository.GetData(id, headerid) }; string json = JsonConvert.SerializeObject(r); return Content(json); } // Display an attachment, used for Run Info - note it is by tool type ID and attachment GUID, so it is best for internal use [HttpGet("/api/tooltypes/{toolTypeId}/{tabletype}/files/{attachmentId}/{filename}")] public IActionResult GetAttachment( int toolTypeId, string tabletype, string attachmentId, string filename) { ToolType tt = _MetrologyRepository.GetToolTypeByID(toolTypeId); bool header = !string.Equals(tabletype.Trim(), "data", StringComparison.OrdinalIgnoreCase); Guid attachmentIdParsed; if (!Guid.TryParse(attachmentId, out attachmentIdParsed)) return Content("Invalid attachment id"); // figure out what content type to use. this is very simple because there are only two types being used string contenttype = "application/pdf"; if (filename.ToLower().TrimEnd().EndsWith(".txt")) contenttype = "text/plain"; // Get attachment stream and feed it to the client Stream fs = _AttachmentsService.GetAttachmentStreamByAttachmentId(tt, header, attachmentIdParsed, filename); return File(fs, contenttype); } // This endpoint triggers writing of the OI Export file [HttpPost("/api/tooltypes/{toolTypeId}/headers/{headerid}/oiexport")] public IActionResult OIExport(int toolTypeId, long headerid) { // Call the export stored procedure System.Data.DataSet ds = _MetrologyRepository.GetOIExportData(toolTypeId, headerid); try { // The SP must return 3 result tables if (ds.Tables.Count != 3) throw new Exception("Error exporting, invalid results"); // The first table has just one row, which is the export filename if (ds.Tables[0].Rows.Count != 1) throw new Exception("Error exporting, invalid filename"); string filename = Convert.ToString(ds.Tables[0].Rows[0][0]); // The second table has the header data if (ds.Tables[1].Rows.Count != 1) throw new Exception("Error exporting, invalid header data"); System.Text.StringBuilder sb = new(); foreach (object o in ds.Tables[1].Rows[0].ItemArray) { if ((o is not null) && (!Convert.IsDBNull(o))) _ = sb.Append(Convert.ToString(o)); _ = sb.Append('\t'); } // The third table has the detail data foreach (System.Data.DataRow dr in ds.Tables[2].Rows) { foreach (object o in dr.ItemArray) { if ((o is not null) && (!Convert.IsDBNull(o))) _ = sb.Append(Convert.ToString(o)); _ = sb.Append('\t'); } } _ = sb.AppendLine(); // The output file will only have one line, the header columns are output first // Then each detail rows has it's columns appended // H1, H2, H3, D1.1, D1.2, D1.3, D2.1, D2.2, D2.3, etc // Write the file System.IO.File.WriteAllText( Path.Join(_AppSettings.OIExportPath, filename), sb.ToString()); } catch (Exception ex) { string json = JsonConvert.SerializeObject(new { ex.Message, }); return BadRequest(json); } var r = new { Message = "OK", }; return Ok(r); } }