Skip to content

Commit c32fd43

Browse files
authored
Merge pull request #332 from bcgov/applicationscore-poc
Changes after QA Deployment
2 parents 2cc6d87 + ba06d1a commit c32fd43

File tree

5 files changed

+193
-91
lines changed

5 files changed

+193
-91
lines changed

OFM.Application.WebResources/Scripts/FormHandler/ofm_application.Ribbon.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,19 @@ OFM.Application.Ribbon = {
6565
},
6666
openRecalculateScoreWindow: function (primaryControl) {
6767
var formContext = primaryControl;
68-
var recordId = formContext.data.entity.getId().replace(/[{}]/g, "");
68+
var recordId = "";
69+
if (primaryControl.getGrid == null) {
70+
recordId = formContext.data.entity.getId().replace(/[{}]/g, "");
71+
}
72+
if (primaryControl.getGrid != null) {
73+
var records = new Array();
74+
primaryControl.getGrid().getSelectedRows().forEach(function (selectedRow, i) {
75+
records.push(selectedRow.getData().getEntity().getId().replace(/[{}]/g, ""));
76+
});
77+
recordId = records.join(",");
78+
}
79+
80+
6981
var window_width = 400;
7082
var window_height = 300;
7183
var pageInput = {

OFM.Infrastructure.WebAPI/Extensions/HttpClientExtensions.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
using Polly;
44
using System.Net.Http.Headers;
55
using System.Text;
6+
using Polly.Timeout;
7+
using Microsoft.Extensions.DependencyInjection;
68

79
namespace OFM.Infrastructure.WebAPI.Extensions;
810

@@ -17,8 +19,8 @@ public static IServiceCollection AddD365HttpClient(this IServiceCollection servi
1719
{
1820
client.Timeout = TimeSpan.FromSeconds(authSettings.TimeOutInSeconds);
1921
client.DefaultRequestHeaders.Add("Accept", "application/json");
20-
}).AddPolicyHandler(GetRetryPolicy(appSettings));
21-
22+
}).AddPolicyHandler(GetRetryPolicy(appSettings)).AddPolicyHandler(GetTimeoutRetryPolicy(appSettings));
23+
2224
return services;
2325
}
2426

@@ -50,7 +52,21 @@ private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy(AppSettings appS
5052
onRetryAsync: (_, _, _, _) => { return Task.CompletedTask; }
5153
);
5254
}
55+
private static IAsyncPolicy<HttpResponseMessage> GetTimeoutRetryPolicy(AppSettings appSettings)
56+
{
57+
return Policy
58+
.HandleResult<HttpResponseMessage>(response => !response.IsSuccessStatusCode)
59+
.Or<HttpRequestException>() // Handles transient HTTP failures
60+
.WaitAndRetryAsync(
61+
retryCount: appSettings.MaxRetries,
62+
sleepDurationProvider: attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)), // Exponential backoff
63+
onRetry: (response, timeSpan, retryCount, context) =>
64+
{
65+
66+
});
67+
5368

69+
}
5470
public static async Task<string> ToRawString(this HttpRequestMessage request)
5571
{
5672
var sb = new StringBuilder();
@@ -125,7 +141,8 @@ public static T As<T>(this HttpResponseMessage response) where T : HttpResponseM
125141

126142
//Copy the properties
127143
typedResponse.StatusCode = response.StatusCode;
128-
response.Headers.ToList().ForEach(h => {
144+
response.Headers.ToList().ForEach(h =>
145+
{
129146
typedResponse.Headers.TryAddWithoutValidation(h.Key, h.Value);
130147
});
131148
typedResponse.Content = response.Content;

OFM.Infrastructure.WebAPI/Services/Processes/ApplicationScore/DataverseRepository.cs

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,11 @@ public class DataverseRepository(ID365AppUserService appUserService, ID365WebApi
120120
public async Task<OFMApplication> GetFundingApplicationAsync(Guid applicationId)
121121
{
122122
var response = await d365WebApiService.SendRetrieveRequestAsync(appUserService.AZSystemAppUser, $"{string.Format(DataverseQueries.FundingApplicationQuery, applicationId)}", formatted: true, pageSize: 5000);
123-
response.EnsureSuccessStatusCode();
123+
if (!response.IsSuccessStatusCode)
124+
{
125+
var responseBody = await response.Content.ReadAsStringAsync();
126+
throw new Exception($"GetFundingApplicationAsync({applicationId}): HTTP Failure: {responseBody}");
127+
}
124128
var json = await response.Content.ReadFromJsonAsync<JsonObject>();
125129
return new OFMApplication(json);
126130
}
@@ -129,7 +133,11 @@ public async Task<IEnumerable<OFMApplication>> GetUnprocessedApplicationsAsync(D
129133
{
130134
var formattedTime = lastTime.ToString("yyyy-MM-ddTHH:mm:ssZ");
131135
var response = await d365WebApiService.SendRetrieveRequestAsync(appUserService.AZSystemAppUser, $"{string.Format(DataverseQueries.UnprocessedApplicationsQuery, formattedTime)}", formatted: true, pageSize: 5000);
132-
response.EnsureSuccessStatusCode();
136+
if (!response.IsSuccessStatusCode)
137+
{
138+
var responseBody = await response.Content.ReadAsStringAsync();
139+
throw new Exception($"GetUnprocessedApplicationsAsync({lastTime}): HTTP Failure: {responseBody}");
140+
}
133141
var json = await response.Content.ReadFromJsonAsync<JsonObject>();
134142
var values = json["value"]?.AsArray() ?? new JsonArray();
135143
return values.Select(v => new OFMApplication(v.AsObject()));
@@ -139,7 +147,11 @@ public async Task<IEnumerable<OFMApplication>> GetModifiedApplicationsAsync(Date
139147
{
140148
var formattedTime = lastProcessedTime.ToString("yyyy-MM-ddTHH:mm:ssZ");
141149
var response = await d365WebApiService.SendRetrieveRequestAsync(appUserService.AZSystemAppUser, $"{string.Format(DataverseQueries.ModifiedApplicationsQuery, formattedTime)}", formatted: true, pageSize: 5000);
142-
response.EnsureSuccessStatusCode();
150+
if (!response.IsSuccessStatusCode)
151+
{
152+
var responseBody = await response.Content.ReadAsStringAsync();
153+
throw new Exception($"GetModifiedApplicationsAsync({lastProcessedTime}):HTTP Failure: {responseBody}");
154+
}
143155
var json = await response.Content.ReadFromJsonAsync<JsonObject>();
144156
var values = json["value"]?.AsArray() ?? new JsonArray();
145157
return values.Select(v => new OFMApplication(v.AsObject()));
@@ -148,7 +160,11 @@ public async Task<IEnumerable<OFMApplication>> GetModifiedApplicationsAsync(Date
148160
public async Task<IEnumerable<ScoreParameter>> GetScoreParametersAsync(Guid calculatorId)
149161
{
150162
var response = await d365WebApiService.SendRetrieveRequestAsync(appUserService.AZSystemAppUser, $"{string.Format(DataverseQueries.ScoreParametersQuery, calculatorId)}", formatted: true, pageSize: 5000);
151-
response.EnsureSuccessStatusCode();
163+
if (!response.IsSuccessStatusCode)
164+
{
165+
var responseBody = await response.Content.ReadAsStringAsync();
166+
throw new Exception($"GetScoreParametersAsync({calculatorId}):HTTP Failure: {responseBody}");
167+
}
152168
var json = await response.Content.ReadFromJsonAsync<JsonObject>();
153169
var values = json["value"]?.AsArray() ?? new JsonArray();
154170
return values.Select(v => new ScoreParameter(v.AsObject()));
@@ -157,7 +173,11 @@ public async Task<IEnumerable<ScoreParameter>> GetScoreParametersAsync(Guid calc
157173
public async Task<Facility> GetFacilityDataAsync(Guid facilityId)
158174
{
159175
var response = await d365WebApiService.SendRetrieveRequestAsync(appUserService.AZSystemAppUser, $"{string.Format(DataverseQueries.facilityQuery, facilityId)}", formatted: true, pageSize: 5000);
160-
response.EnsureSuccessStatusCode();
176+
if (!response.IsSuccessStatusCode)
177+
{
178+
var responseBody = await response.Content.ReadAsStringAsync();
179+
throw new Exception($"GetFacilityDataAsync(Guid {facilityId}): HTTP Failure: {responseBody}");
180+
}
161181
var json = await response.Content.ReadFromJsonAsync<JsonObject>();
162182
return new Facility(json);
163183
}
@@ -167,7 +187,11 @@ public async Task<Facility> GetFacilityDataAsync(Guid facilityId)
167187
var output = new JsonObject();
168188
var outputObjects = new List<JsonObject>();
169189
var response = await d365WebApiService.SendRetrieveRequestAsync(appUserService.AZSystemAppUser, $"{string.Format(DataverseQueries.LicenseSpaces, facilityId, submittedOn)}", formatted: true, pageSize: 5000);
170-
response.EnsureSuccessStatusCode();
190+
if (!response.IsSuccessStatusCode)
191+
{
192+
var responseBody = await response.Content.ReadAsStringAsync();
193+
throw new Exception($"GetLicenseDataAsync(Guid {facilityId}, DateTime? {submittedOn}):HTTP Failure: {responseBody}");
194+
}
171195
var json = await response.Content.ReadFromJsonAsync<JsonObject>();
172196
var values = json["value"]?.AsArray() ?? new JsonArray();
173197
return new LicenseSpaces(values.First().AsObject());
@@ -176,7 +200,11 @@ public async Task<Facility> GetFacilityDataAsync(Guid facilityId)
176200
public async Task<ACCBIncomeIndicator?> GetIncomeDataAsync(string postalCode, Guid calculatorId)
177201
{
178202
var response = await d365WebApiService.SendRetrieveRequestAsync(appUserService.AZSystemAppUser, $"{string.Format(DataverseQueries.IncomeDataQuery, postalCode, calculatorId)}", formatted: true, pageSize: 5000);
179-
response.EnsureSuccessStatusCode();
203+
if (!response.IsSuccessStatusCode)
204+
{
205+
var responseBody = await response.Content.ReadAsStringAsync();
206+
throw new Exception($"GetIncomeDataAsync(string {postalCode}, Guid {calculatorId}): HTTP Failure: {responseBody}");
207+
}
180208
var json = await response.Content.ReadFromJsonAsync<JsonObject>();
181209
var values = json["value"]?.AsArray() ?? new JsonArray();
182210
return values.Any() ? new ACCBIncomeIndicator(values.First().AsObject()) : null;
@@ -185,7 +213,11 @@ public async Task<Facility> GetFacilityDataAsync(Guid facilityId)
185213
public async Task<IEnumerable<ApprovedParentFee>> GetFeeDataAsync(Guid facId)
186214
{
187215
var response = await d365WebApiService.SendRetrieveRequestAsync(appUserService.AZSystemAppUser, $"{string.Format(DataverseQueries.AppovedFeeDataQuery, facId)}", formatted: true, pageSize: 5000);
188-
response.EnsureSuccessStatusCode();
216+
if (!response.IsSuccessStatusCode)
217+
{
218+
var responseBody = await response.Content.ReadAsStringAsync();
219+
throw new Exception($"GetFeeDataAsync(Guid {facId}): HTTP Failure: {responseBody}");
220+
}
189221
var json = await response.Content.ReadFromJsonAsync<JsonObject>();
190222
var values = json["value"]?.AsArray() ?? new JsonArray();
191223
return values.Select(v => new ApprovedParentFee(v.AsObject()));
@@ -194,7 +226,11 @@ public async Task<IEnumerable<ApprovedParentFee>> GetFeeDataAsync(Guid facId)
194226
public async Task<IEnumerable<FortyPercentileThresholdFee>> GetThresholdDataAsync(Guid calculatorId)
195227
{
196228
var response = await d365WebApiService.SendRetrieveRequestAsync(appUserService.AZSystemAppUser, $"{string.Format(DataverseQueries.ThresholdFeeDataQuery, calculatorId)}",formatted: true, pageSize: 5000);
197-
response.EnsureSuccessStatusCode();
229+
if (!response.IsSuccessStatusCode)
230+
{
231+
var responseBody = await response.Content.ReadAsStringAsync();
232+
throw new Exception($"GetThresholdDataAsync(Guid {calculatorId}): HTTP Failure: {responseBody}");
233+
}
198234
var json = await response.Content.ReadFromJsonAsync<JsonObject>();
199235
var values = json["value"]?.AsArray() ?? new JsonArray();
200236
return values.Select(v => new FortyPercentileThresholdFee(v.AsObject()));
@@ -204,25 +240,35 @@ public async Task CreateScoreAsync(JsonObject score)
204240
{
205241
var jsonContent = new StringContent(score.ToJsonString(), System.Text.Encoding.UTF8, "application/json");
206242
var response = await d365WebApiService.SendCreateRequestAsync(appUserService.AZSystemAppUser, $"{DataverseQueries.CreateScoreEndpoint}", JsonSerializer.Serialize(score));
207-
response.EnsureSuccessStatusCode();
243+
if (!response.IsSuccessStatusCode)
244+
{
245+
var responseBody = await response.Content.ReadAsStringAsync();
246+
throw new Exception($"CreateScoreAsync(JsonObject {score}): HTTP Failure: {responseBody}");
247+
}
208248
}
209249

210250
public async Task UpdateApplicationAsync(Guid applicationId, JsonObject application)
211251
{
212252
var jsonContent = new StringContent(application.ToJsonString(), System.Text.Encoding.UTF8, "application/json");
213253
var response = await d365WebApiService.SendPatchRequestAsync(appUserService.AZSystemAppUser, $"{string.Format(DataverseQueries.UpdateApplicationEndpoint, applicationId)}", JsonSerializer.Serialize(application));
214-
response.EnsureSuccessStatusCode();
215-
}
216-
public async Task UpsertApplicationScoreAsync(string Keys, JsonObject applicationScore)
217-
{
218-
var jsonContent = new StringContent(applicationScore.ToJsonString(), System.Text.Encoding.UTF8, "application/json");
219-
var response = await d365WebApiService.SendPatchRequestAsync(appUserService.AZSystemAppUser, $"{string.Format(DataverseQueries.UpsertApplicationScoreEndpoint, Keys)}", JsonSerializer.Serialize(applicationScore));
220254
if (!response.IsSuccessStatusCode)
221255
{
222256
var responseBody = await response.Content.ReadAsStringAsync();
223-
throw new Exception($"HTTP Failure: {responseBody}");
257+
throw new Exception($"UpdateApplicationAsync(Guid {applicationId}, JsonObject {application}): HTTP Failure: {responseBody}");
224258
}
225259
}
260+
public async Task UpsertApplicationScoreAsync(string Keys, JsonObject applicationScore)
261+
{
262+
263+
var jsonContent = new StringContent(applicationScore.ToJsonString(), System.Text.Encoding.UTF8, "application/json");
264+
var response = await d365WebApiService.SendPatchRequestAsync(appUserService.AZSystemAppUser, $"{string.Format(DataverseQueries.UpsertApplicationScoreEndpoint, Keys)}", JsonSerializer.Serialize(applicationScore));
265+
if (!response.IsSuccessStatusCode)
266+
{
267+
var responseBody = await response.Content.ReadAsStringAsync();
268+
throw new Exception($"Upsert Application Score failed with request with Key = { Keys } and score Object = { applicationScore} renponse {responseBody}");
269+
}
270+
271+
}
226272
public async Task UpsertApplicationScoresBatchAsync(Dictionary<string, JsonObject> scores)
227273
{
228274
var batchRequests = scores.Select(x => new PatchRequest($"{string.Format(DataverseQueries.UpsertApplicationScoreEndpoint, x.Key)}", x.Value)).ToList<HttpRequestMessage>();
@@ -235,15 +281,23 @@ public async Task UpsertApplicationScoresBatchAsync(Dictionary<string, JsonObjec
235281
public async Task<PopulationCentre?> GetPopulationDataAsync(string city, Guid calculatorId)
236282
{
237283
var response = await d365WebApiService.SendRetrieveRequestAsync(appUserService.AZSystemAppUser, $"{string.Format(DataverseQueries.PopulationCentreQuery, city, calculatorId)}", formatted: true, pageSize: 5000);
238-
response.EnsureSuccessStatusCode();
284+
if (!response.IsSuccessStatusCode)
285+
{
286+
var responseBody = await response.Content.ReadAsStringAsync();
287+
throw new Exception($"GetPopulationDataAsyncstring {city}, Guid {calculatorId}): HTTP Failure: {responseBody}");
288+
}
239289
var json = await response.Content.ReadFromJsonAsync<JsonObject>();
240290
var values = json["value"]?.AsArray() ?? new JsonArray();
241291
return values.Any() ? new PopulationCentre(values.First().AsObject()) : null;
242292
}
243293
public async Task<SchoolDistrict?> GetSchoolDistrictDataAsync(string postalCode, Guid calculatorId)
244294
{
245295
var response = await d365WebApiService.SendRetrieveRequestAsync(appUserService.AZSystemAppUser, $"{string.Format(DataverseQueries.SchoolDistrictQuery, postalCode, calculatorId)}", formatted: true, pageSize: 5000);
246-
response.EnsureSuccessStatusCode();
296+
if (!response.IsSuccessStatusCode)
297+
{
298+
var responseBody = await response.Content.ReadAsStringAsync();
299+
throw new Exception($"GetSchoolDistrictDataAsync(string {postalCode}, Guid {calculatorId}): HTTP Failure: {responseBody}");
300+
}
247301
var json = await response.Content.ReadFromJsonAsync<JsonObject>();
248302
var values = json["value"]?.AsArray() ?? new JsonArray();
249303
return values.Any() ? new SchoolDistrict(values.First().AsObject()) : null;

0 commit comments

Comments
 (0)