diff --git a/api/Erp.Platform.HttpApi.Host.Dockerfile b/api/Erp.Platform.HttpApi.Host.Dockerfile index b769133f..af582147 100644 --- a/api/Erp.Platform.HttpApi.Host.Dockerfile +++ b/api/Erp.Platform.HttpApi.Host.Dockerfile @@ -70,13 +70,21 @@ RUN mkdir -p $HOME/.config/DevExpress && \ # icu'lar dotnet culture icin gerekli # lib'ler wkhtmltopdf icin gerekli +# fontconfig ve fonts-* DevExpress reporting için gerekli RUN apk update RUN apk add --no-cache \ icu-data-full \ icu-libs \ libgdiplus \ libc6-compat \ - libc-dev + libc-dev \ + fontconfig \ + ttf-dejavu \ + ttf-liberation \ + font-noto + +# Font cache oluştur +RUN fc-cache -f -v # OpenSSL default TLSv3 desteklediği için MSSQL 2012'ye bağlanmıyor. Bunu çözmek için gerekli RUN sed -i 's/\[openssl_init\]/# [openssl_init]/' /etc/ssl/openssl.cnf diff --git a/api/src/Erp.Platform.HttpApi.Host/DynamicServices/DynamicAssemblyRegistrationService.cs b/api/src/Erp.Platform.HttpApi.Host/DynamicServices/DynamicAssemblyRegistrationService.cs index ad77e3e8..a919e12b 100644 --- a/api/src/Erp.Platform.HttpApi.Host/DynamicServices/DynamicAssemblyRegistrationService.cs +++ b/api/src/Erp.Platform.HttpApi.Host/DynamicServices/DynamicAssemblyRegistrationService.cs @@ -73,9 +73,21 @@ namespace Erp.Platform.DynamicServices await ProcessPendingRegistrations(); await Task.Delay(5000, stoppingToken); } + catch (TaskCanceledException) + { + // Service is shutting down, exit gracefully + _logger.LogInformation("Assembly registration service is shutting down"); + break; + } + catch (OperationCanceledException) + { + // Service is shutting down, exit gracefully + _logger.LogInformation("Assembly registration service operation cancelled"); + break; + } catch (Exception ex) { - _logger.LogError(ex, "Assembly registration service hatası"); + _logger.LogError(ex, "Assembly registration service error"); } } } diff --git a/api/src/Erp.Platform.HttpApi.Host/PlatformHttpApiHostModule.cs b/api/src/Erp.Platform.HttpApi.Host/PlatformHttpApiHostModule.cs index 5811d539..84bfb70f 100644 --- a/api/src/Erp.Platform.HttpApi.Host/PlatformHttpApiHostModule.cs +++ b/api/src/Erp.Platform.HttpApi.Host/PlatformHttpApiHostModule.cs @@ -26,6 +26,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; using OpenIddict.Server.AspNetCore; using OpenIddict.Validation.AspNetCore; @@ -132,7 +133,7 @@ public class PlatformHttpApiHostModule : AbpModule ConfigureAuditing(); ConfigureDynamicServices(context); - ConfigureDevExpressReporting(context); + ConfigureDevExpressReporting(context, configuration); context.Services.AddSignalR(); @@ -340,6 +341,11 @@ public class PlatformHttpApiHostModule : AbpModule }; }); + // Configure Hangfire storage based on database provider + // Note: Currently DefaultDatabaseProvider is set to SqlServer in SettingsConsts.cs + // PostgreSQL configuration is preserved for potential future use +#pragma warning disable CS0162 // Unreachable code detected +#pragma warning disable CS0618 // Type or member is obsolete if (DefaultDatabaseProvider == DatabaseProvider.PostgreSql) { context.Services.AddHangfire(options => @@ -352,6 +358,8 @@ public class PlatformHttpApiHostModule : AbpModule }); }); } +#pragma warning restore CS0618 +#pragma warning restore CS0162 else if (DefaultDatabaseProvider == DatabaseProvider.SqlServer) { context.Services.AddHangfire(options => @@ -360,7 +368,13 @@ public class PlatformHttpApiHostModule : AbpModule configuration.GetConnectionString(DefaultDatabaseProvider), new SqlServerStorageOptions { - PrepareSchemaIfNecessary = true + PrepareSchemaIfNecessary = true, + SchemaName = "HangFire", + CommandBatchMaxTimeout = TimeSpan.FromMinutes(5), + SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5), + QueuePollInterval = TimeSpan.Zero, + UseRecommendedIsolationLevel = true, + DisableGlobalLocks = true }); }); } @@ -405,13 +419,20 @@ public class PlatformHttpApiHostModule : AbpModule context.Services.AddSingleton(); } - private void ConfigureDevExpressReporting(ServiceConfigurationContext context) + private void ConfigureDevExpressReporting(ServiceConfigurationContext context, IConfiguration configuration) { + var logger = context.Services.BuildServiceProvider().GetService>(); + + // Configure fonts before initializing DevExpress controls + DevExpressFontConfiguration.ConfigureDefaultFonts(logger); + DevExpressFontConfiguration.InstallLinuxFonts(logger); + context.Services.AddDevExpressControls(); context.Services.ConfigureReportingServices(configurator => { configurator.ConfigureReportDesigner(designerConfigurator => { + designerConfigurator.RegisterDataSourceWizardConfigFileConnectionStringsProvider(); }); configurator.ConfigureWebDocumentViewer(viewerConfigurator => { diff --git a/api/src/Erp.Platform.HttpApi.Host/ReportServices/DevExpressFontConfiguration.cs b/api/src/Erp.Platform.HttpApi.Host/ReportServices/DevExpressFontConfiguration.cs new file mode 100644 index 00000000..fc3f2477 --- /dev/null +++ b/api/src/Erp.Platform.HttpApi.Host/ReportServices/DevExpressFontConfiguration.cs @@ -0,0 +1,87 @@ +using System; +using System.IO; +using DevExpress.Drawing; +using Microsoft.Extensions.Logging; + +namespace Erp.Platform.ReportServices; + +public static class DevExpressFontConfiguration +{ + public static void ConfigureDefaultFonts(ILogger logger) + { + try + { + // Set default font settings to prevent null font family issues + // This ensures a fallback font is always available + var defaultFontFamily = "Arial"; + + // Try to verify the font exists in the system + try + { + var testFont = new DXFont(defaultFontFamily, 10); + logger?.LogInformation($"DevExpress font configuration: Using '{defaultFontFamily}' as default font"); + } + catch (Exception ex) + { + logger?.LogWarning(ex, $"Default font '{defaultFontFamily}' may not be available. Reports may use fallback fonts."); + + // Alternative fonts to try + var alternativeFonts = new[] { "Liberation Sans", "DejaVu Sans", "FreeSans", "sans-serif" }; + foreach (var fontName in alternativeFonts) + { + try + { + var testFont = new DXFont(fontName, 10); + logger?.LogInformation($"Using alternative font: {fontName}"); + break; + } + catch + { + // Continue to next font + } + } + } + + logger?.LogInformation("DevExpress font configuration completed successfully"); + } + catch (Exception ex) + { + logger?.LogError(ex, "Error configuring DevExpress fonts"); + } + } + + public static void InstallLinuxFonts(ILogger logger) + { + try + { + // For Linux environments, we might need to install fonts + if (OperatingSystem.IsLinux()) + { + logger?.LogInformation("Running on Linux - checking font availability..."); + + var fontDirectories = new[] + { + "/usr/share/fonts", + "/usr/local/share/fonts", + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".fonts") + }; + + foreach (var dir in fontDirectories) + { + if (Directory.Exists(dir)) + { + logger?.LogInformation($"Font directory found: {dir}"); + } + } + + logger?.LogInformation( + "If fonts are missing, install them with: " + + "apk add fontconfig ttf-dejavu ttf-liberation font-noto && fc-cache -f -v"); + } + } + catch (Exception ex) + { + logger?.LogWarning(ex, "Error checking Linux font installation"); + } + } +}