From 6a2bc0b4ab9c479b49f79bc884e287731df2dace Mon Sep 17 00:00:00 2001
From: Chase Tucker <chase.tucker@infineon.com>
Date: Thu, 23 Jan 2025 07:44:12 -0700
Subject: [PATCH] Created ECN# autocomplete for PCR3 docs

---
 .../Controllers/ECNController.cs              | 32 ++++++++++++++++++
 .../Controllers/PCRBController.cs             |  1 +
 MesaFabApproval.API/Program.cs                |  3 --
 MesaFabApproval.API/Services/ECNService.cs    | 16 +++++++++
 .../Pages/Components/PCR3DocumentForm.razor   | 33 +++++++++++++------
 MesaFabApproval.Client/Services/ECNService.cs | 29 ++++++++++++++++
 6 files changed, 101 insertions(+), 13 deletions(-)

diff --git a/MesaFabApproval.API/Controllers/ECNController.cs b/MesaFabApproval.API/Controllers/ECNController.cs
index 1b8d431..92881d7 100644
--- a/MesaFabApproval.API/Controllers/ECNController.cs
+++ b/MesaFabApproval.API/Controllers/ECNController.cs
@@ -53,4 +53,36 @@ public class ECNController : ControllerBase {
             }
         }
     }
+
+    [HttpGet]
+    [Route("ecn/allNumbers")]
+    public async Task<IActionResult> GetAllECNNumbers() {
+        DateTime start = DateTime.Now;
+        bool isInternalError = false;
+        string errorMessage = "";
+
+        try {
+            _logger.LogInformation($"Attempting to get all ECN#s");
+            
+            IEnumerable<int> allEcnNumbers = await _ecnService.GetAllECNNumbers();
+
+            return Ok(allEcnNumbers);
+        } catch (Exception ex) {
+            isInternalError = true;
+            errorMessage = $"Cannot get all ECN#s, because {ex.Message}";
+            return Problem(errorMessage);
+        } finally {
+            string metricName = "GetAllECNNumbers";
+            DateTime end = DateTime.Now;
+            double millisecondsDiff = (end - start).TotalMilliseconds;
+            _monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
+
+            if (isInternalError) {
+                _logger.LogError(errorMessage);
+                _monInClient.PostStatus(metricName, StatusValue.Critical);
+            } else {
+                _monInClient.PostStatus(metricName, StatusValue.Ok);
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/MesaFabApproval.API/Controllers/PCRBController.cs b/MesaFabApproval.API/Controllers/PCRBController.cs
index f950583..79216eb 100644
--- a/MesaFabApproval.API/Controllers/PCRBController.cs
+++ b/MesaFabApproval.API/Controllers/PCRBController.cs
@@ -265,6 +265,7 @@ public class PCRBController : ControllerBase {
 
     [HttpPost]
     [Route("pcrb/attachment")]
+    [ApiExplorerSettings(IgnoreApi = true)]
     public async Task<IActionResult> UploadAttachment([FromForm] IFormFile file, [FromForm] PCRBAttachment attachment) {
         DateTime start = DateTime.Now;
         bool isArgumentError = false;
diff --git a/MesaFabApproval.API/Program.cs b/MesaFabApproval.API/Program.cs
index 56916bd..0246239 100644
--- a/MesaFabApproval.API/Program.cs
+++ b/MesaFabApproval.API/Program.cs
@@ -132,9 +132,6 @@ builder.Services.AddSwaggerGen(c => {
 
 WebApplication app = builder.Build();
 
-if (Debugger.IsAttached)
-    app.Services.GetRequiredService<IApprovalService>();
-
 app.UseCors();
 
 // Configure the HTTP request pipeline.
diff --git a/MesaFabApproval.API/Services/ECNService.cs b/MesaFabApproval.API/Services/ECNService.cs
index 5a89462..f5b278b 100644
--- a/MesaFabApproval.API/Services/ECNService.cs
+++ b/MesaFabApproval.API/Services/ECNService.cs
@@ -4,6 +4,7 @@ namespace MesaFabApproval.API.Services;
 
 public interface IECNService {
     Task<bool> IsValidECNNumber(int number);
+    Task<IEnumerable<int>> GetAllECNNumbers();
 }
 
 public class ECNService : IECNService {
@@ -43,4 +44,19 @@ public class ECNService : IECNService {
             throw;
         }
     }
+
+    public async Task<IEnumerable<int>> GetAllECNNumbers() {
+        try {
+            _logger.LogInformation("Attempting to get all ECN#s");
+
+            string sql = "select ECNNumber from ECN where Deleted=0 and Cancelled=0";
+
+            IEnumerable<int> allEcnNumbers = await _dalService.QueryAsync<int>(sql);
+
+            return allEcnNumbers;
+        } catch (Exception ex) {
+            _logger.LogError($"Unable to get all ECN#s, because {ex.Message}");
+            throw;
+        }
+    }
 }
\ No newline at end of file
diff --git a/MesaFabApproval.Client/Pages/Components/PCR3DocumentForm.razor b/MesaFabApproval.Client/Pages/Components/PCR3DocumentForm.razor
index 315f379..53fcd19 100644
--- a/MesaFabApproval.Client/Pages/Components/PCR3DocumentForm.razor
+++ b/MesaFabApproval.Client/Pages/Components/PCR3DocumentForm.razor
@@ -31,16 +31,16 @@
                                   Immediate
                                   AutoGrow />
                 } else {
-                    <MudTextField @bind-Value="@document.ECNNumber"
-                                  Required
-                                  RequiredError="You must provide a valid ECN#"
-                                  Clearable
-                                  Variant="Variant.Outlined"
-                                  InputType="@InputType.Number"
-                                  Validation="@(new Func<int, Task<string>>(ECNNoIsValid))"
-                                  Label="ECN#"
-                                  Immediate
-                                  AutoGrow />
+                    <MudAutocomplete @bind-Value="@document.ECNNumber"
+                                     T="int"
+                                     SearchFunc="Search"
+                                     Required
+                                     Clearable
+                                     RequiredError="You must provide a valid ECN#"
+                                     Variant="Variant.Outlined"
+                                     Validation="@(new Func<int, Task<string>>(ECNNoIsValid))"
+                                     Label="ECN#"
+                                     Immediate />
                 }
                 <MudCheckBox Label="Complete"
                              Color="Color.Tertiary"
@@ -79,6 +79,8 @@
     [Parameter]
     public required PCR3Document document { get; set; }
 
+    private IEnumerable<int> allEcnNumbers = new List<int>();
+
     private string[] errors = { };
 
     private bool complete = false;
@@ -89,6 +91,8 @@
 
     protected override async Task OnParametersSetAsync() {
         complete = document.CompletedByID > 0;
+
+        allEcnNumbers = await ecnService.GetAllECNNumbers();
     }
 
     private async Task Save() {
@@ -155,4 +159,13 @@
         StateHasChanged();
         return result;
     }
+
+    private async Task<IEnumerable<int>> Search(string searchValue, CancellationToken token) {
+        if (string.IsNullOrWhiteSpace(searchValue))
+            return allEcnNumbers;
+
+        return allEcnNumbers
+                .Where(x => x.ToString().StartsWith(searchValue, StringComparison.InvariantCultureIgnoreCase))
+                .Order();
+    }
 }
diff --git a/MesaFabApproval.Client/Services/ECNService.cs b/MesaFabApproval.Client/Services/ECNService.cs
index 2aed656..50a0cc1 100644
--- a/MesaFabApproval.Client/Services/ECNService.cs
+++ b/MesaFabApproval.Client/Services/ECNService.cs
@@ -5,6 +5,7 @@ namespace MesaFabApproval.Client.Services;
 public interface IECNService {
     Task<string> ECNNumberIsValidStr(int ecnNumber);
     Task<bool> ECNNumberIsValid(int number);
+    Task<IEnumerable<int>> GetAllECNNumbers();
 }
 
 public class ECNService : IECNService {
@@ -49,4 +50,32 @@ public class ECNService : IECNService {
             throw new Exception($"Unable to determine if {number} is a valid ECN#, because {ex.Message}");
         }
     }
+
+    public async Task<IEnumerable<int>> GetAllECNNumbers() {
+        try {
+            HttpClient httpClient = _httpClientFactory.CreateClient("API");
+
+            HttpRequestMessage requestMessage = new(HttpMethod.Get, $"ecn/allNumbers");
+
+            HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage);
+
+            if (responseMessage.IsSuccessStatusCode) {
+                string responseContent = await responseMessage.Content.ReadAsStringAsync();
+
+                JsonSerializerOptions jsonSerializerOptions = new() {
+                    PropertyNameCaseInsensitive = true
+                };
+
+                IEnumerable<int> allEcnNumbers =
+                    JsonSerializer.Deserialize<IEnumerable<int>>(responseContent, jsonSerializerOptions) ??
+                    new List<int>();
+
+                return allEcnNumbers;
+            } else {
+                throw new Exception(responseMessage.ReasonPhrase);
+            }
+        } catch (Exception ex) {
+            throw new Exception($"Unable to get all ECN#s, because {ex.Message}");
+        }
+    }
 }