11
11
using CCOF . Infrastructure . WebAPI . Services . Processes ;
12
12
using CCOF . Infrastructure . WebAPI . Messages ;
13
13
using Microsoft . Extensions . Options ;
14
+ using System ;
15
+ using CCOF . Infrastructure . WebAPI . Services . D365WebAPI ;
16
+ using CCOF . Core . DataContext ;
17
+ using System . Drawing . Text ;
14
18
15
19
namespace CCOF . Infrastructure . WebAPI . Services . Processes . Payments
16
20
{
17
- public class P505GeneratePaymentLinesProvider ( ID365AppUserService appUserService , ID365WebApiService d365WebApiService , ILoggerFactory loggerFactory ) : ID365ProcessProvider
21
+ public class P505GeneratePaymentLinesProvider ( IOptionsSnapshot < ExternalServices > bccasApiSettings , ID365AppUserService appUserService , ID365WebApiService d365WebApiService , ILoggerFactory loggerFactory ) : ID365ProcessProvider
18
22
{
19
- // private readonly BCCASApi _BCCASApi = bccasApiSettings.Value.BCCASApi;
23
+ private readonly BCCASApi _BCCASApi = bccasApiSettings . Value . BCCASApi ;
20
24
private readonly ID365AppUserService _appUserService = appUserService ;
21
25
private readonly ID365WebApiService _d365WebApiService = d365WebApiService ;
22
26
private readonly ILogger _logger = loggerFactory . CreateLogger ( LogCategory . Process ) ;
23
-
24
-
25
27
private ProcessParameter ? _processParams ;
26
-
27
-
28
28
public Int16 ProcessId => Setup . Process . Payments . GeneratePaymentLinesId ;
29
29
public string ProcessName => Setup . Process . Payments . GeneratePaymentLinesName ;
30
-
31
- public Task < ProcessData > GetDataAsync ( )
32
- {
33
- throw new NotImplementedException ( ) ;
34
- }
35
-
36
30
#region Data Queries
37
-
38
- public string applicationCCFRIs
39
- {
31
+ public string BusinessClosuresRequestUri
32
+ { // ofm_holiday_type" operator="eq" value="1" Standard for CCOF. 2 for OFM
40
33
get
41
34
{
42
- // For reference only
43
35
var fetchXml = $$ """
44
- <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true">
45
- <entity name="ccof_application_ccfri_closure">
46
- <attribute name="ccof_name" />
47
- <attribute name="ccof_application_ccfri_closureid" />
48
- <attribute name="ccof_startdate" />
49
- <attribute name="ccof_enddate" />
50
- <attribute name="ccof_is_full_closure" />
51
- <attribute name="ccof_totalworkdays" />
52
- <attribute name="ccof_totaldays" />
53
- <attribute name="ccof_paidclosure" />
54
- <attribute name="ccof_closure_status" />
55
- <attribute name="ccof_facilityinfo" />
56
- <attribute name="ccof_closure_type" />
57
- <filter type="and">
58
- <condition attribute="ccof_approved_as" operator="eq" value="100000000" />
59
- <condition attribute="ccof_facilityinfo" operator="eq" value="e4077ebe-0310-f011-9989-000d3a09ed17" />
60
- <condition attribute="ccof_closure_status" operator="eq" value="100000003" />
61
- <condition attribute="ccof_program_year" operator="eq" value="fdc2fce3-d1a2-ef11-8a6a-000d3af474a4" uiname="2025-26 FY" uitype="ccof_program_year" />
36
+ <fetch>
37
+ <entity name="ofm_stat_holiday">
38
+ <attribute name="ofm_date_observed" />
39
+ <attribute name="ofm_holiday_type" />
40
+ <attribute name="ofm_stat_holidayid" />
41
+ <filter>
42
+ <condition attribute="ofm_holiday_type" operator="eq" value="1" />
62
43
</filter>
63
44
</entity>
64
45
</fetch>
65
46
""" ;
66
47
67
48
var requestUri = $ """
68
- ccof_application_ccfri_closures?$select=ccof_name,ccof_application_ccfri_closureid,ccof_startdate,ccof_enddate,ccof_is_full_closure,ccof_totalworkdays,ccof_totaldays,ccof_paidclosure,ccof_closure_status,_ccof_facilityinfo_value,ccof_closure_type&$filter=(ccof_approved_as eq 100000000 and ccof_closure_status eq 100000003)
49
+ ofm_stat_holidaies?fetchXml= { WebUtility . UrlEncode ( fetchXml ) }
69
50
""" ;
70
51
71
52
return requestUri ;
72
53
}
73
54
}
74
-
75
-
55
+ public string EnrolmentReportPaymentUri
56
+ {
57
+ get
58
+ {
59
+ var fetchXml = $$ """
60
+ <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
61
+ <entity name="ccof_monthlyenrollmentreport">
62
+ <attribute name="ccof_ccfri_external_status" />
63
+ <attribute name="ccof_ccfri_internal_status" />
64
+ <attribute name="ccof_ccfri_verification" />
65
+ <attribute name="ccof_ccof_base_verification" />
66
+ <attribute name="ccof_ccof_external_status" />
67
+ <attribute name="ccof_ccof_internal_status" />
68
+ <attribute name="ccof_facility" />
69
+ <attribute name="ccof_grandtotalbase" />
70
+ <attribute name="ccof_grandtotalccfri" />
71
+ <attribute name="ccof_grandtotalccfriprovider" />
72
+ <attribute name="ccof_month" />
73
+ <attribute name="ccof_monthlyenrollmentreportid" />
74
+ <attribute name="ccof_organization" />
75
+ <attribute name="ccof_programyear" />
76
+ <attribute name="ccof_reportversion" />
77
+ <attribute name="ccof_year" />
78
+ <attribute name="statecode" />
79
+ <attribute name="statuscode" />
80
+ <attribute name="ccof_ccfri_approved_date" />
81
+ <attribute name="ccof_ccof_approved_date" />
82
+ <link-entity name="account" from="accountid" to="ccof_facility" link-type="inner" alias="facility">
83
+ <attribute name="name" />
84
+ <attribute name="accountnumber" />
85
+ </link-entity>
86
+ <filter>
87
+ <condition attribute="ccof_monthlyenrollmentreportid" operator="eq" value="{{ _processParams . EnrolmentReportid . ToString ( ) }} " />
88
+ </filter>
89
+ </entity>
90
+ </fetch>
91
+ """ ;
92
+ var requestUri = $ """
93
+ ccof_monthlyenrollmentreports?fetchXml={ WebUtility . UrlEncode ( fetchXml ) }
94
+ """ ;
95
+ return requestUri ;
96
+ }
97
+ }
76
98
#endregion
77
99
public async Task < ProcessData > GetBusinessClosuresDataAsync ( )
78
100
{
79
101
_logger . LogDebug ( CustomLogEvent . Process , nameof ( GetBusinessClosuresDataAsync ) ) ;
80
102
81
- var response = await _d365WebApiService . SendRetrieveRequestAsync ( _appUserService . AZSystemAppUser , applicationCCFRIs , false , 0 , true ) ;
103
+ var response = await _d365WebApiService . SendRetrieveRequestAsync ( _appUserService . AZSystemAppUser , BusinessClosuresRequestUri , false , 0 , true ) ;
82
104
83
105
if ( ! response . IsSuccessStatusCode )
84
106
{
85
107
var responseBody = await response . Content . ReadAsStringAsync ( ) ;
86
- _logger . LogError ( CustomLogEvent . Process , "Failed to query record information with the server error {responseBody}" , responseBody . CleanLog ( ) ) ;
108
+ _logger . LogError ( CustomLogEvent . Process , "Failed to query Funding record information with the server error {responseBody}" , responseBody . CleanLog ( ) ) ;
87
109
88
110
return await Task . FromResult ( new ProcessData ( string . Empty ) ) ;
89
111
}
@@ -95,7 +117,7 @@ public async Task<ProcessData> GetBusinessClosuresDataAsync()
95
117
{
96
118
if ( currentValue ? . AsArray ( ) . Count == 0 )
97
119
{
98
- _logger . LogInformation ( CustomLogEvent . Process , "No records found with query {requestUri}" , applicationCCFRIs . CleanLog ( ) ) ;
120
+ _logger . LogInformation ( CustomLogEvent . Process , "No records found with query {requestUri}" , BusinessClosuresRequestUri . CleanLog ( ) ) ;
99
121
}
100
122
d365Result = currentValue ! ;
101
123
}
@@ -104,28 +126,127 @@ public async Task<ProcessData> GetBusinessClosuresDataAsync()
104
126
105
127
return await Task . FromResult ( new ProcessData ( d365Result ) ) ;
106
128
}
129
+ public async Task < ProcessData > GetDataAsync ( )
130
+ {
131
+ _logger . LogDebug ( CustomLogEvent . Process , "GetDataAsync" ) ;
107
132
108
- public async Task < JsonObject > RunProcessAsync ( ID365AppUserService appUserService , ID365WebApiService d365WebApiService , ProcessParameter processParams )
133
+ var response = await _d365WebApiService . SendRetrieveRequestAsync ( _appUserService . AZSystemAppUser , EnrolmentReportPaymentUri ) ;
109
134
110
- {
111
- #region Validation & Setup
112
- var entitySetName = "ccof_application_ccfri_closures" ;
113
- var payload2 = new JsonObject {
114
- { "ccof_name" , "test123" }
115
-
116
- } ;
117
- var requestBody2 = JsonSerializer . Serialize ( payload2 ) ;
118
- var CreateResponse2 = await d365WebApiService . SendCreateRequestAsync ( appUserService . AZSystemAppUser , entitySetName , requestBody2 ) ;
119
- _logger . LogTrace ( CustomLogEvent . Process , "Start processing payments for the test." ) ;
120
-
121
-
122
- #endregion
123
- return ProcessResult . Completed ( ProcessId ) . SimpleProcessResult ;
124
-
125
- }
135
+ if ( ! response . IsSuccessStatusCode )
136
+ {
137
+ var responseBody = await response . Content . ReadAsStringAsync ( ) ;
138
+ _logger . LogError ( CustomLogEvent . Process , "Failed to query Expense record information with the server error {responseBody}" , responseBody . CleanLog ( ) ) ;
126
139
140
+ return await Task . FromResult ( new ProcessData ( string . Empty ) ) ;
141
+ }
127
142
128
- }
143
+ var jsonObject = await response . Content . ReadFromJsonAsync < JsonObject > ( ) ;
129
144
145
+ JsonNode d365Result = string . Empty ;
146
+ if ( jsonObject ? . TryGetPropertyValue ( "value" , out var currentValue ) == true )
147
+ {
148
+ if ( currentValue ? . AsArray ( ) . Count == 0 )
149
+ {
150
+ _logger . LogInformation ( CustomLogEvent . Process , "No records found with query {requestUri}" , EnrolmentReportPaymentUri . CleanLog ( ) ) ;
151
+ }
152
+ d365Result = currentValue ! ;
153
+ }
154
+
155
+ _logger . LogDebug ( CustomLogEvent . Process , "Query Result {queryResult}" , d365Result . ToString ( ) . CleanLog ( ) ) ;
156
+
157
+ return await Task . FromResult ( new ProcessData ( d365Result ) ) ;
158
+ }
159
+ private async Task < JsonObject > CreateSinglePayment ( JsonNode enrolmentReport ,
160
+ DateTime paymentDate ,
161
+ decimal ? totalAmount ,
162
+ ProcessParameter processParams ,
163
+ List < DateTime > holidaysList )
164
+ {
165
+ DateTime invoiceDate = paymentDate . GetPreviousBusinessDay ( holidaysList ) ;
166
+ DateTime invoiceReceivedDate = invoiceDate . AddBusinessDays ( _BCCASApi . PayableInDays , holidaysList ) ;
167
+ DateTime effectiveDate = invoiceDate ;
168
+ string paymentType = ( int ) processParams . programapproved switch
169
+ {
170
+ 7 => "CCOF" ,
171
+ 8 => "CCFRI" ,
172
+ 9 => "CCFRI Provider" ,
173
+ _ => "Unknown"
174
+ } ;
175
+ int invoiceLineNumber = ( int ) processParams . programapproved switch
176
+ {
177
+ 7 => 1 ,
178
+ 8 => 2 ,
179
+ 9 => 3 ,
180
+ _ => 999999
181
+ } ;
182
+ var payload = new JsonObject ( )
183
+ {
184
+ { "ofm_invoice_line_number" , invoiceLineNumber } ,
185
+ { "ofm_amount" , totalAmount } ,
186
+ { "ofm_payment_type" , ( int ) processParams . programapproved } ,
187
+ { "ccof_monthly_enrollment_report@odata.bind" , $ "/ccof_monthlyenrollmentreports({ enrolmentReport [ "ccof_monthlyenrollmentreportid" ] } )" } ,
188
+ { "ofm_invoice_date" , invoiceDate . ToString ( "yyyy-MM-dd" ) } ,
189
+ { "ofm_invoice_received_date" , invoiceReceivedDate . ToString ( "yyyy-MM-dd" ) } ,
190
+ { "ofm_effective_date" , effectiveDate . ToString ( "yyyy-MM-dd" ) } ,
191
+ { "ccof_program_year@odata.bind" , $ "/ccof_program_years({ enrolmentReport [ "_ccof_programyear_value" ] } )" } ,
192
+ { "statuscode" , 4 } , //Approved for Payment in PaymentLine table
193
+ { "ofm_facility@odata.bind" , $ "/accounts({ enrolmentReport [ "_ccof_facility_value" ] } )" } ,
194
+ { "ofm_organization@odata.bind" , $ "/accounts({ enrolmentReport [ "_ccof_organization_value" ] } )" } ,
195
+ { "ofm_description" , $ "{ enrolmentReport [ "facility.name" ] + " " + enrolmentReport [ "ccof_month" ] + "/" + enrolmentReport [ "ccof_year" ] + " " + paymentType } " } ,
196
+ } ;
197
+ var requestBody = JsonSerializer . Serialize ( payload ) ;
198
+ var response = await _d365WebApiService . SendCreateRequestAsync ( _appUserService . AZSystemAppUser , "ofm_payments" , requestBody ) ;
199
+ if ( ! response . IsSuccessStatusCode )
200
+ {
201
+ var responseBody = await response . Content . ReadAsStringAsync ( ) ;
202
+ _logger . LogError ( CustomLogEvent . Process , "Failed to create a payment with the server error {responseBody}. ProcessParam {param}" , responseBody . CleanLog ( ) , JsonValue . Create ( processParams ) ? . ToString ( ) ) ;
203
+
204
+ return ProcessResult . Failure ( ProcessId , [ responseBody ] , 0 , 0 ) . SimpleProcessResult ;
205
+ }
130
206
207
+ return ProcessResult . Completed ( ProcessId ) . SimpleProcessResult ;
208
+ }
209
+ public async Task < JsonObject > RunProcessAsync ( ID365AppUserService appUserService , ID365WebApiService d365WebApiService , ProcessParameter processParams )
210
+ {
211
+ var PSTZone = TimeZoneInfo . FindSystemTimeZoneById ( "Pacific Standard Time" ) ;
212
+ var pstTime = TimeZoneInfo . ConvertTimeFromUtc ( DateTime . UtcNow , PSTZone ) ;
213
+ _logger . LogInformation ( CustomLogEvent . Process , pstTime . ToString ( "yyyy-MM-dd HH:mm:ss" ) + "Process " + ProcessId + ": Begin to generate PaymentLine Process" ) ;
214
+ try
215
+ {
216
+ _processParams = processParams ;
217
+ var entitySetName = "ofm_payments" ;
218
+ var enrolmentReportString = await GetDataAsync ( ) ;
219
+ JsonArray ? enrolmentReportData = JsonSerializer . Deserialize < JsonArray > ( enrolmentReportString . Data ) ;
220
+ if ( enrolmentReportData is null || ! enrolmentReportData . Any ( ) )
221
+ {
222
+ _logger . LogError ( CustomLogEvent . Process , "Unable to retrieve the Monthly Enrolment Report record Id {enrolmentReportId}" , processParams ! . EnrolmentReportid ) ;
223
+ return ProcessResult . Completed ( ProcessId ) . SimpleProcessResult ;
224
+ }
225
+ JsonNode ? enrolmentReport = enrolmentReportData . First ( ) ;
226
+ var businessClosuresData = await GetBusinessClosuresDataAsync ( ) ;
227
+ var closures = JsonSerializer . Deserialize < JsonArray > ( businessClosuresData . Data . ToString ( ) ) ;
228
+ List < DateTime > holidaysList = closures ! . Select ( closure => ( DateTime ) closure [ "ofm_date_observed" ] ) . ToList ( ) ;
229
+ switch ( ( int ) processParams . programapproved )
230
+ {
231
+ case 7 : // ofm_payment_type CCOF
232
+ await CreateSinglePayment ( enrolmentReport , ( DateTime ) enrolmentReport [ "ccof_ccof_approved_date" ] , ( decimal ) enrolmentReport [ "ccof_grandtotalbase" ] , processParams ! , holidaysList ) ;
233
+ break ;
234
+ case 8 : // ofm_payment_type CCFRI
235
+ await CreateSinglePayment ( enrolmentReport , ( DateTime ) enrolmentReport [ "ccof_ccfri_approved_date" ] , ( ( decimal ? ) ( enrolmentReport [ "ccof_grandtotalccfriprovider" ] ) ?? 0 ) + ( ( decimal ? ) ( enrolmentReport [ "ccof_grandtotalccfri" ] ) ?? 0 ) , processParams ! , holidaysList ) ;
236
+ break ;
237
+ default :
238
+ _logger . LogError ( CustomLogEvent . Process , "Unable to generate payments for Erolment Report {ERid}. Invalid ApprovedType {programApproved}" , processParams ? . EnrolmentReportid , processParams ? . programapproved ) ;
239
+ break ;
240
+ }
241
+ }
242
+ catch ( Exception ex )
243
+ {
244
+ Console . WriteLine ( ex . Message ) ;
245
+ var returnObject = ProcessResult . Failure ( ProcessId , new String [ ] { "Critical error" , ex . StackTrace } , 0 , 0 ) . ODProcessResult ;
246
+ return returnObject ;
247
+ }
248
+ _logger . LogInformation ( CustomLogEvent . Process , pstTime . ToString ( "yyyy-MM-dd HH:mm:ss" ) + "Process " + ProcessId + ": End Process." ) ;
249
+ return ProcessResult . Completed ( ProcessId ) . SimpleProcessResult ;
250
+ }
251
+ }
131
252
}
0 commit comments