diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/EntityFrameworkCore/Repositories/PaymentRequestRepository.cs b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/EntityFrameworkCore/Repositories/PaymentRequestRepository.cs index 2ac40543b..f26ca656c 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/EntityFrameworkCore/Repositories/PaymentRequestRepository.cs +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/EntityFrameworkCore/Repositories/PaymentRequestRepository.cs @@ -58,6 +58,7 @@ public async Task GetTotalPaymentRequestAmountByCorrelationIdAsync(Guid .Where(p => p.Status != PaymentRequestStatus.L1Declined && p.Status != PaymentRequestStatus.L2Declined && p.Status != PaymentRequestStatus.L3Declined + && p.InvoiceStatus != CasPaymentRequestStatus.Cancelled && p.InvoiceStatus != CasPaymentRequestStatus.NotFound && p.InvoiceStatus != CasPaymentRequestStatus.ErrorFromCas) .GroupBy(p => p.CorrelationId) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/AIGenerationRequestJobHelper.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/AIGenerationRequestJobHelper.cs index 843b09120..978b3d587 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/AIGenerationRequestJobHelper.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/AIGenerationRequestJobHelper.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Unity.GrantManager.GrantApplications; using Volo.Abp.Domain.Repositories; +using Volo.Abp.Uow; namespace Unity.GrantManager.GrantApplications.Automation.BackgroundJobs; @@ -49,6 +50,40 @@ public static async Task MarkFailedAsync( await generationRequestRepository.UpdateAsync(request, autoSave: true); } + public static async Task MarkRunningInNewUowAsync( + IUnitOfWorkManager unitOfWorkManager, + IRepository generationRequestRepository, + string requestKey) + { + using var uow = unitOfWorkManager.Begin(requiresNew: true, isTransactional: false); + var request = await GetLatestRequestAsync(generationRequestRepository, x => x.RequestKey == requestKey); + await MarkRunningAsync(generationRequestRepository, request); + await uow.CompleteAsync(); + } + + public static async Task MarkCompletedInNewUowAsync( + IUnitOfWorkManager unitOfWorkManager, + IRepository generationRequestRepository, + string requestKey) + { + using var uow = unitOfWorkManager.Begin(requiresNew: true, isTransactional: false); + var request = await GetLatestRequestAsync(generationRequestRepository, x => x.RequestKey == requestKey); + await MarkCompletedAsync(generationRequestRepository, request); + await uow.CompleteAsync(); + } + + public static async Task MarkFailedInNewUowAsync( + IUnitOfWorkManager unitOfWorkManager, + IRepository generationRequestRepository, + string requestKey, + string? failureReason) + { + using var uow = unitOfWorkManager.Begin(requiresNew: true, isTransactional: false); + var request = await GetLatestRequestAsync(generationRequestRepository, x => x.RequestKey == requestKey); + await MarkFailedAsync(generationRequestRepository, request, failureReason); + await uow.CompleteAsync(); + } + public static async Task GetLatestRequestAsync( IRepository generationRequestRepository, Expression> predicate) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateApplicationAnalysisJob.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateApplicationAnalysisJob.cs index 30ce556bf..b7a78850a 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateApplicationAnalysisJob.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateApplicationAnalysisJob.cs @@ -7,6 +7,7 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Repositories; using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; namespace Unity.GrantManager.GrantApplications.Automation.BackgroundJobs; @@ -14,25 +15,25 @@ public class GenerateApplicationAnalysisJob( IApplicationAnalysisService applicationAnalysisService, IRepository generationRequestRepository, ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, ILogger logger) : AsyncBackgroundJob, ITransientDependency { public override async Task ExecuteAsync(GenerateApplicationAnalysisBackgroundJobArgs args) { using (currentTenant.Change(args.TenantId)) { - var request = await AIGenerationRequestJobHelper.GetLatestRequestAsync(generationRequestRepository, x => x.RequestKey == args.RequestKey); - await AIGenerationRequestJobHelper.MarkRunningAsync(generationRequestRepository, request); + await AIGenerationRequestJobHelper.MarkRunningInNewUowAsync(unitOfWorkManager, generationRequestRepository, args.RequestKey); try { logger.LogInformation("Executing AI application analysis job for application {ApplicationId}.", args.ApplicationId); await applicationAnalysisService.RegenerateAndSaveAsync(args.ApplicationId, args.PromptVersion); logger.LogInformation("Completed AI application analysis job for application {ApplicationId}.", args.ApplicationId); - await AIGenerationRequestJobHelper.MarkCompletedAsync(generationRequestRepository, request); + await AIGenerationRequestJobHelper.MarkCompletedInNewUowAsync(unitOfWorkManager, generationRequestRepository, args.RequestKey); } catch (Exception ex) { - await AIGenerationRequestJobHelper.MarkFailedAsync(generationRequestRepository, request, ex.Message); + await AIGenerationRequestJobHelper.MarkFailedInNewUowAsync(unitOfWorkManager, generationRequestRepository, args.RequestKey, ex.Message); throw; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateApplicationScoringJob.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateApplicationScoringJob.cs index 87a0eed6a..62900413b 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateApplicationScoringJob.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateApplicationScoringJob.cs @@ -6,6 +6,7 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Repositories; using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; namespace Unity.GrantManager.GrantApplications.Automation.BackgroundJobs; @@ -13,24 +14,24 @@ public class GenerateApplicationScoringJob( IApplicationScoringAppService applicationScoringAppService, IRepository generationRequestRepository, ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, ILogger logger) : AsyncBackgroundJob, ITransientDependency { public override async Task ExecuteAsync(GenerateApplicationScoringBackgroundJobArgs args) { using (currentTenant.Change(args.TenantId)) { - var request = await AIGenerationRequestJobHelper.GetLatestRequestAsync(generationRequestRepository, x => x.RequestKey == args.RequestKey); - await AIGenerationRequestJobHelper.MarkRunningAsync(generationRequestRepository, request); + await AIGenerationRequestJobHelper.MarkRunningInNewUowAsync(unitOfWorkManager, generationRequestRepository, args.RequestKey); try { logger.LogInformation("Executing AI application scoring job for application {ApplicationId}.", args.ApplicationId); await applicationScoringAppService.GenerateApplicationScoringAsync(args.ApplicationId, args.PromptVersion); logger.LogInformation("Completed AI application scoring job for application {ApplicationId}.", args.ApplicationId); - await AIGenerationRequestJobHelper.MarkCompletedAsync(generationRequestRepository, request); + await AIGenerationRequestJobHelper.MarkCompletedInNewUowAsync(unitOfWorkManager, generationRequestRepository, args.RequestKey); } catch (Exception ex) { - await AIGenerationRequestJobHelper.MarkFailedAsync(generationRequestRepository, request, ex.Message); + await AIGenerationRequestJobHelper.MarkFailedInNewUowAsync(unitOfWorkManager, generationRequestRepository, args.RequestKey, ex.Message); throw; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateAttachmentSummaryJob.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateAttachmentSummaryJob.cs index b6c1b186f..b9a710478 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateAttachmentSummaryJob.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateAttachmentSummaryJob.cs @@ -7,6 +7,7 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Repositories; using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; namespace Unity.GrantManager.GrantApplications.Automation.BackgroundJobs; @@ -14,25 +15,25 @@ public class GenerateAttachmentSummaryJob( IAttachmentSummaryService attachmentSummaryService, IRepository generationRequestRepository, ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, ILogger logger) : AsyncBackgroundJob, ITransientDependency { public override async Task ExecuteAsync(GenerateAttachmentSummaryBackgroundJobArgs args) { using (currentTenant.Change(args.TenantId)) { - var request = await AIGenerationRequestJobHelper.GetLatestRequestAsync(generationRequestRepository, x => x.RequestKey == args.RequestKey); - await AIGenerationRequestJobHelper.MarkRunningAsync(generationRequestRepository, request); + await AIGenerationRequestJobHelper.MarkRunningInNewUowAsync(unitOfWorkManager, generationRequestRepository, args.RequestKey); try { logger.LogInformation( "Executing AI attachment summary job for application {ApplicationId}.", args.ApplicationId); await attachmentSummaryService.GenerateForApplicationAsync(args.ApplicationId, args.PromptVersion); - await AIGenerationRequestJobHelper.MarkCompletedAsync(generationRequestRepository, request); + await AIGenerationRequestJobHelper.MarkCompletedInNewUowAsync(unitOfWorkManager, generationRequestRepository, args.RequestKey); } catch (Exception ex) { - await AIGenerationRequestJobHelper.MarkFailedAsync(generationRequestRepository, request, ex.Message); + await AIGenerationRequestJobHelper.MarkFailedInNewUowAsync(unitOfWorkManager, generationRequestRepository, args.RequestKey, ex.Message); throw; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/RunApplicationAIPipelineJob.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/RunApplicationAIPipelineJob.cs index c749f3ff8..9ecd21a82 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/RunApplicationAIPipelineJob.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/RunApplicationAIPipelineJob.cs @@ -13,6 +13,7 @@ using Volo.Abp.EventBus.Local; using Volo.Abp.Features; using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; namespace Unity.GrantManager.GrantApplications.Automation.BackgroundJobs; @@ -25,6 +26,7 @@ public class RunApplicationAIPipelineJob( ILocalEventBus localEventBus, IRepository generationRequestRepository, ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, ILogger logger) : AsyncBackgroundJob, ITransientDependency { public override async Task ExecuteAsync(RunApplicationAIPipelineJobArgs args) @@ -36,11 +38,7 @@ public override async Task ExecuteAsync(RunApplicationAIPipelineJobArgs args) using (currentTenant.Change(args.TenantId)) { - var request = await AIGenerationRequestJobHelper.GetLatestRequestAsync( - generationRequestRepository, - x => x.RequestKey == args.RequestKey); - - await AIGenerationRequestJobHelper.MarkRunningAsync(generationRequestRepository, request); + await AIGenerationRequestJobHelper.MarkRunningInNewUowAsync(unitOfWorkManager, generationRequestRepository, args.RequestKey); try { @@ -51,7 +49,7 @@ public override async Task ExecuteAsync(RunApplicationAIPipelineJobArgs args) if (!attachmentSummariesEnabled && !applicationAnalysisEnabled && !scoringEnabled) { logger.LogDebug("All AI features are disabled, skipping queued AI generation for application {ApplicationId}.", args.ApplicationId); - await AIGenerationRequestJobHelper.MarkCompletedAsync(generationRequestRepository, request); + await AIGenerationRequestJobHelper.MarkCompletedInNewUowAsync(unitOfWorkManager, generationRequestRepository, args.RequestKey); return; } @@ -114,11 +112,11 @@ await localEventBus.PublishAsync(new ApplicationAIScoringGeneratedEvent throw analysisException; } - await AIGenerationRequestJobHelper.MarkCompletedAsync(generationRequestRepository, request); + await AIGenerationRequestJobHelper.MarkCompletedInNewUowAsync(unitOfWorkManager, generationRequestRepository, args.RequestKey); } catch (Exception ex) { - await AIGenerationRequestJobHelper.MarkFailedAsync(generationRequestRepository, request, ex.Message); + await AIGenerationRequestJobHelper.MarkFailedInNewUowAsync(unitOfWorkManager, generationRequestRepository, args.RequestKey, ex.Message); throw; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.css index bac97ee3c..24e633622 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.css +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.css @@ -75,12 +75,10 @@ .ai-generate-btn { height: 2.25rem; - min-width: 8rem; } .ai-generate-btn.btn-sm { height: 2rem; - min-width: 7rem; } .ai-generate-btn .spinner-border-sm { diff --git a/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/GrantApplications/Automation/RunApplicationAIPipelineJobTests.cs b/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/GrantApplications/Automation/RunApplicationAIPipelineJobTests.cs index 9bcde4f0f..c8ef48d05 100644 --- a/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/GrantApplications/Automation/RunApplicationAIPipelineJobTests.cs +++ b/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/GrantApplications/Automation/RunApplicationAIPipelineJobTests.cs @@ -13,6 +13,7 @@ using Volo.Abp.EventBus.Local; using Volo.Abp.Features; using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; using Xunit; using Xunit.Abstractions; @@ -78,7 +79,7 @@ await localEventBus.Received(1).PublishAsync( Arg.Is(x => x.ApplicationId == request.ApplicationId)); } - private static RunApplicationAIPipelineJob BuildJob( + private RunApplicationAIPipelineJob BuildJob( IFeatureChecker featureChecker, IRepository generationRequestRepository, ILocalEventBus? localEventBus = null, @@ -95,6 +96,7 @@ private static RunApplicationAIPipelineJob BuildJob( localEventBus ?? Substitute.For(), generationRequestRepository, Substitute.For(), + GetRequiredService(), NullLogger.Instance); }