Skip to content

Commit

Permalink
Update unlocking provider reports and deactivate report process (#106)
Browse files Browse the repository at this point in the history
* Update unlocking provider reports and deactivate report process

* Update version number when unlock
  • Loading branch information
yiyiwang-cgi authored May 22, 2024
1 parent 94e5d12 commit a82089c
Show file tree
Hide file tree
Showing 7 changed files with 345 additions and 9 deletions.
23 changes: 20 additions & 3 deletions ECC.Core.DataContext/Entities/Entities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54794,7 +54794,8 @@ public partial class Fields
public const string ofm_contactyominame = "ofm_contactyominame";
public const string ofm_current_version = "ofm_current_version";
public const string ofm_current_versionname = "ofm_current_versionname";
public const string ofm_duration = "ofm_duration";
public const string ofm_duedate = "ofm_duedate";
public const string ofm_duration = "ofm_duration";
public const string ofm_end_date = "ofm_end_date";
public const string ofm_facility = "ofm_facility";
public const string ofm_facility_survey_response = "ofm_facility_survey_response";
Expand Down Expand Up @@ -55220,8 +55221,24 @@ public string ofm_current_versionname
}
}
}

[Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("ofm_duration")]

[Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("ofm_duedate")]
public System.Nullable<System.DateTime> ofm_duedate
{
[System.Diagnostics.DebuggerNonUserCode()]
get
{
return this.GetAttributeValue<System.Nullable<System.DateTime>>("ofm_duedate");
}
[System.Diagnostics.DebuggerNonUserCode()]
set
{
this.SetAttributeValue("ofm_duedate", value);
}
}


[Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("ofm_duration")]
public string ofm_duration
{
[System.Diagnostics.DebuggerNonUserCode()]
Expand Down
97 changes: 97 additions & 0 deletions OFM.Infrastructure.Plugins/ProviderReports/SetDueDate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using ECC.Core.DataContext;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace OFM.Infrastructure.Plugins.Provider_Reports
{
/// <summary>
/// Plugin development guide: https://docs.microsoft.com/powerapps/developer/common-data-service/plug-ins
/// Best practices and guidance: https://docs.microsoft.com/powerapps/developer/common-data-service/best-practices/business-logic/
/// </summary>
public class SetDueDate : PluginBase
{
public SetDueDate(string unsecureConfiguration, string secureConfiguration)
: base(typeof(SetDueDate))
{
// TODO: Implement your custom configuration handling
// https://docs.microsoft.com/powerapps/developer/common-data-service/register-plug-in#set-configuration-data
}

// Entry point for custom business logic execution
protected override void ExecuteDataversePlugin(ILocalPluginContext localPluginContext)
{
if (localPluginContext == null)
{
throw new InvalidPluginExecutionException(nameof(localPluginContext), new Dictionary<string, string>() { ["failedRecordId"] = localPluginContext.Target.Id.ToString() });
}

localPluginContext.Trace("Start SetDueDate Plug-in");

if (localPluginContext.Target.Contains(ECC.Core.DataContext.ofm_survey_response.Fields.ofm_survey_responseid) && !localPluginContext.Target.Contains(ECC.Core.DataContext.ofm_survey_response.Fields.ofm_current_version))
{
// Getting latest data to get the value

using (var crmContext = new DataverseContext(localPluginContext.PluginUserService))
{
var currentDate = DateTime.UtcNow;

localPluginContext.Trace($"CurrentDate {currentDate}");

//Set the duedate base on fiscal year and report month

var fiscal_year_ref = localPluginContext.Target.GetAttributeValue<EntityReference>(ofm_survey_response.Fields.ofm_fiscal_year);
var report_month_ref = localPluginContext.Target.GetAttributeValue<EntityReference>(ofm_survey_response.Fields.ofm_reporting_month);


if (fiscal_year_ref != null && report_month_ref != null)
{
var fiscal_year = crmContext.ofm_fiscal_yearSet.Where(year => year.Id == fiscal_year_ref.Id).FirstOrDefault();
var fiscal_year_start = fiscal_year.GetAttributeValue<DateTime>(ofm_fiscal_year.Fields.ofm_start_date);
var fiscal_year_end = fiscal_year.GetAttributeValue<DateTime>(ofm_fiscal_year.Fields.ofm_end_date);

//converted to PST to compare
var fiscal_year_start_in_PST = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(fiscal_year_start, "Pacific Standard Time");
var fiscal_year_end_in_PST = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(fiscal_year_end, "Pacific Standard Time");

localPluginContext.Trace($"fiscal_year_start_in_PST {fiscal_year_start_in_PST}");
localPluginContext.Trace($"fiscal_year_end_in_PST {fiscal_year_end_in_PST}");

var report_month = crmContext.ofm_monthSet.Where(month => month.Id == report_month_ref.Id).FirstOrDefault();
var report_month_name = report_month.GetAttributeValue<string>(ofm_month.Fields.ofm_name);

localPluginContext.Trace($"report_month_name {report_month_name}");

int month_num = DateTime.ParseExact(report_month_name, "MMMM", CultureInfo.CurrentCulture).Month;
var report_month_date = (fiscal_year_start_in_PST <= new DateTime(fiscal_year_start.Year, month_num, 01, 0, 0, 0) && fiscal_year_end_in_PST >= new DateTime(fiscal_year_start.Year, month_num, 01, 0, 0, 0)) ? new DateTime(fiscal_year_start.Year, month_num, 01, 23, 59, 0): new DateTime(fiscal_year_end.Year, month_num, 01, 23, 59, 0);
localPluginContext.Trace($"report_month_date {report_month_date}");

var duedateInPST = report_month_date.AddMonths(2).AddDays(-1);

TimeZoneInfo PSTZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");

var duedateInUTC = TimeZoneInfo.ConvertTimeToUtc(duedateInPST, PSTZone);

localPluginContext.Trace($"duedateInPST {duedateInPST}");
localPluginContext.Trace($"duedateInUTC {duedateInUTC}");

//Update the duedate
var entity = new ofm_survey_response
{
Id = localPluginContext.Target.Id,
ofm_duedate = duedateInUTC
};
UpdateRequest updateRequest = new UpdateRequest { Target = entity };
crmContext.Execute(updateRequest);
}

localPluginContext.Trace("Completed with no errors.");
}
}
}
}
}
6 changes: 3 additions & 3 deletions OFM.Infrastructure.WebAPI/Extensions/SetupInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ public static class Payments
public static class FundingReports
{
public const Int16 CloneFundingReportResponseId = 600;
public const string CloneFundingReportResponseName = "Clone Funding Report Response";
public const string CloneFundingReportResponseName = "Clone Provider Report Responses";

public const Int16 GeneratePaymentLinesId = 505;
public const string GeneratePaymentLinesName = "Generate Payment Lines";
public const Int16 CloseDuedReportsId = 605;
public const string CloseDuedReportsName = "Automatically Close Provider Reports at the Due Date";
}
public static class Reporting
{
Expand Down
1 change: 1 addition & 0 deletions OFM.Infrastructure.WebAPI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
services.AddScoped<ID365ProcessProvider, P510ReadPaymentResponseProvider>();
services.AddScoped<ID365ProcessProvider, P600CloneFundingReportResponse>();
services.AddScoped<ID365ProcessProvider, P610CreateQuestionProvider>();
services.AddScoped<ID365ProcessProvider, P605CloseDuedReportsProvider>();

services.AddScoped<D365Email>();
services.AddScoped<ID365BackgroundProcessHandler, D365BackgroundProcessHandler>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using OFM.Infrastructure.WebAPI.Messages;
using OFM.Infrastructure.WebAPI.Models;
using OFM.Infrastructure.WebAPI.Services.Processes;
using System.Net;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
Expand Down Expand Up @@ -113,13 +114,18 @@ public async Task<BatchResult> SendBatchMessageAsync(AZAppUser spn, List<HttpReq

Int16 processed = 0;
List<string> errors = [];
List<JsonObject> results = [];

if (batchResponse.IsSuccessStatusCode)
batchResponse.HttpResponseMessages.ForEach(async res =>
{
if (res.IsSuccessStatusCode)
{
processed++;
if (res.StatusCode != HttpStatusCode.NoContent)
{
results.Add(await res.Content.ReadFromJsonAsync<JsonObject>());
}
}
else
{
Expand All @@ -139,7 +145,7 @@ public async Task<BatchResult> SendBatchMessageAsync(AZAppUser spn, List<HttpReq
return batchResult;
}

return BatchResult.Success(null, processed, requestMessages.Count); ;
return BatchResult.Success(results, processed, requestMessages.Count); ;
}

public async Task<HttpResponseMessage> SendBulkEmailTemplateMessageAsync(AZAppUser spn, JsonObject contentBody, Guid? callerObjectId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices.JavaScript;
using System.Text.Json;
using System.Text.Json.Nodes;
using static OFM.Infrastructure.WebAPI.Extensions.Setup.Process;
using JsonSerializer = System.Text.Json.JsonSerializer;

namespace OFM.Infrastructure.WebAPI.Services.Processes.FundingReports;

Expand Down Expand Up @@ -102,7 +104,7 @@ public async Task<ProcessData> GetDataAsync()
if (!response.IsSuccessStatusCode)
{
var responseBody = await response.Content.ReadAsStringAsync();
_logger.LogError(CustomLogEvent.Process, "Failed to query email reminders with the server error {responseBody}", responseBody.CleanLog());
_logger.LogError(CustomLogEvent.Process, "Failed to query question response with the server error {responseBody}", responseBody.CleanLog());

return await Task.FromResult(new ProcessData(string.Empty));
}
Expand All @@ -114,7 +116,7 @@ public async Task<ProcessData> GetDataAsync()
{
if (currentValue?.AsArray().Count == 0)
{
_logger.LogInformation(CustomLogEvent.Process, "No emails found with query {requestUri}", RequestUri);
_logger.LogInformation(CustomLogEvent.Process, "No question response found with query {requestUri}", RequestUri);
}
d365Result = currentValue!;
}
Expand Down Expand Up @@ -157,6 +159,25 @@ public async Task<JsonObject> RunProcessAsync(ID365AppUserService appUserService
var newFundingReportResponse = await sendNewFundingReportResponseRequestResult.Content.ReadFromJsonAsync<JsonObject>();
var newFundingReportResponseId = newFundingReportResponse?["ofm_survey_responseid"];

//Update the original funding report version number by 1
var orignialVersionNumber = (int)newFundingReportResponse?["ofm_version_number"];
var newVersionNumber = orignialVersionNumber + 1;

var updateFundingReportData = new JsonObject
{
{"ofm_version_number", newVersionNumber }
};

var updateFundingReportRequest = JsonSerializer.Serialize(updateFundingReportData);

var updateFundingReportResult = await d365WebApiService.SendPatchRequestAsync(_appUserService.AZSystemAppUser, $"ofm_survey_responses({_processParams.FundingReport.FundingReportId})", updateFundingReportRequest);

if (!updateFundingReportResult.IsSuccessStatusCode)
{
var responseBody = await updateFundingReportResult.Content.ReadAsStringAsync();
_logger.LogError(CustomLogEvent.Process, "Failed to deactivate the record with the server error {responseBody}", responseBody.CleanLog());
}


//Fetch Question Response from the funding report response
var questionResponseData = await GetDataAsync();
Expand All @@ -175,6 +196,7 @@ public async Task<JsonObject> RunProcessAsync(ID365AppUserService appUserService

//Create a new questionResponse
var newQuestionResponseRequest = new CreateRequest("ofm_question_responses", questionData);
newQuestionResponseRequest.Headers.Add("Prefer", "return=representation");
questionResponseRequestList.Add(newQuestionResponseRequest);

}
Expand All @@ -188,6 +210,56 @@ public async Task<JsonObject> RunProcessAsync(ID365AppUserService appUserService
return sendQuestionResponseError.SimpleProcessResult;
}


//Deactivate the copied funding report
var deactivateFundingReportData = new JsonObject
{
{"statuscode", 2 },
{"statecode", 1 }
};

var deactivateFundingReportRequest = JsonSerializer.Serialize(deactivateFundingReportData);

var deactivateFundingReportRequestResult = await d365WebApiService.SendPatchRequestAsync(_appUserService.AZSystemAppUser, $"ofm_survey_responses({newFundingReportResponseId})", deactivateFundingReportRequest);

if (!deactivateFundingReportRequestResult.IsSuccessStatusCode)
{
var responseBody = await deactivateFundingReportRequestResult.Content.ReadAsStringAsync();
_logger.LogError(CustomLogEvent.Process, "Failed to deactivate the record with the server error {responseBody}", responseBody.CleanLog());
}

//Deactivate the copied question responses
var createResult = sendquestionResponseRequestBatchResult.Result;

if(createResult?.Count() > 0)
{
List<HttpRequestMessage> deactivatedQuestionResponseRequestList = [];

foreach (var res in createResult)
{
var deactivatedQuestionResponseId = res["ofm_question_responseid"].ToString();
var deactivateQuestionResponseData = new JsonObject
{
{"statuscode", 2},
{"statecode", 1 }
};
deactivatedQuestionResponseRequestList.Add(new D365UpdateRequest(new EntityReference("ofm_question_responses", new Guid(deactivatedQuestionResponseId)), deactivateQuestionResponseData));


}

var deactivatedQuestionResponseRequestResult = await d365WebApiService.SendBatchMessageAsync(appUserService.AZSystemAppUser, deactivatedQuestionResponseRequestList, null);

if (deactivatedQuestionResponseRequestResult.Errors.Any())
{
var deactivatedQuestionResponseError = ProcessResult.Failure(ProcessId, deactivatedQuestionResponseRequestResult.Errors, deactivatedQuestionResponseRequestResult.TotalProcessed, deactivatedQuestionResponseRequestResult.TotalRecords);
_logger.LogError(CustomLogEvent.Process, "Failed to deactivate question response with an error: {error}", JsonValue.Create(deactivatedQuestionResponseError)!.ToString());

return deactivatedQuestionResponseError.SimpleProcessResult;
}

}

}

_logger.LogInformation(CustomLogEvent.Process, "A new copy of funding report response is created");
Expand Down
Loading

0 comments on commit a82089c

Please sign in to comment.