init project

This commit is contained in:
Sedat ÖZTÜRK 2025-05-06 09:45:49 +03:00
commit e1a9562b22
1346 changed files with 1138526 additions and 0 deletions

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
configs/**/data/**
**/node_modules
**/.DS_Store
files/

700
My_workflow.json Normal file

File diff suppressed because one or more lines are too long

4
api/.dockerignore Normal file
View file

@ -0,0 +1,4 @@
**/bin
**/obj
bin/
obj/

147
api/.editorconfig Normal file
View file

@ -0,0 +1,147 @@
# To learn more about .editorconfig see https://aka.ms/editorconfigdocs
###############################
# Core EditorConfig Options #
###############################
root = true
# All files
[*]
indent_style = space
end_of_line = crlf
# XML project files
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
indent_size = 2
# XML config files
[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
indent_size = 2
# Code files
[*.{cs,csx,vb,vbx}]
indent_size = 4
insert_final_newline = true
charset = utf-8-bom
###############################
# .NET Coding Conventions #
###############################
[*.{cs,vb}]
# Organize usings
dotnet_sort_system_directives_first = true
# this. preferences
dotnet_style_qualification_for_field = false:silent
dotnet_style_qualification_for_property = false:silent
dotnet_style_qualification_for_method = false:silent
dotnet_style_qualification_for_event = false:silent
# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
dotnet_style_predefined_type_for_member_access = true:silent
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
# Modifier preferences
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
dotnet_style_readonly_field = true:suggestion
# Expression-level preferences
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
dotnet_style_prefer_conditional_expression_over_return = true:silent
###############################
# Naming Conventions #
###############################
# Style Definitions
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# Use PascalCase for constant fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.constant_fields.applicable_kinds = field
dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
dotnet_naming_symbols.constant_fields.required_modifiers = const
dotnet_style_operator_placement_when_wrapping = beginning_of_line
tab_width = 4
end_of_line = crlf
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
dotnet_style_prefer_compound_assignment = true:suggestion
dotnet_style_prefer_simplified_interpolation = true:suggestion
dotnet_style_namespace_match_folder = true:suggestion
###############################
# C# Coding Conventions #
###############################
[*.cs]
# var preferences
csharp_style_var_for_built_in_types = true:silent
csharp_style_var_when_type_is_apparent = true:silent
csharp_style_var_elsewhere = true:silent
# Expression-bodied members
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_accessors = true:silent
# Pattern matching preferences
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
# Null-checking preferences
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
# Modifier preferences
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
# Expression-level preferences
csharp_prefer_braces = true:silent
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
###############################
# C# Formatting Rules #
###############################
# New line preferences
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left
# Space preferences
csharp_space_after_cast = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_around_binary_operators = before_and_after
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
# Wrapping preferences
csharp_preserve_single_line_statements = true
csharp_preserve_single_line_blocks = true
csharp_using_directive_placement = outside_namespace:silent
csharp_prefer_simple_using_statement = true:suggestion
csharp_style_namespace_declarations = block_scoped:silent
csharp_style_prefer_method_group_conversion = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
###############################
# VB Coding Conventions #
###############################
[*.vb]
# Modifier preferences
visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion

1
api/.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
**/wwwroot/libs/** linguist-vendored

266
api/.gitignore vendored Normal file
View file

@ -0,0 +1,266 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# Platform
src/Kurs.Platform.Web/Logs/*
src/Kurs.Platform.Web.Host/Logs/*
src/Kurs.Platform.AuthServer/Logs/*
src/Kurs.Platform.HttpApi.Host/Logs/*
src/Kurs.Platform.HttpApi.Host/Logs/*
src/Kurs.Platform.DbMigrator/Logs/*
src/Kurs.Platform.Blazor.Server/Logs/*
src/Kurs.Platform.Blazor.Server.Tiered/Logs/*
# Use abp install-libs to restore.
**/wwwroot/libs/*
*appsettings.development.json

5
api/.prettierrc Normal file
View file

@ -0,0 +1,5 @@
{
"singleQuote": true,
"useTabs": false,
"tabWidth": 4
}

View file

@ -0,0 +1,46 @@
FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
ENV DOTNET_NUGET_SIGNATURE_VERIFICATION=false
WORKDIR /app
COPY "modules/Kurs.Languages/Kurs.Languages.Application.Contracts/Kurs.Languages.Application.Contracts.csproj" "modules/Kurs.Languages/Kurs.Languages.Application.Contracts/"
COPY "modules/Kurs.Languages/Kurs.Languages.Domain/Kurs.Languages.Domain.csproj" "modules/Kurs.Languages/Kurs.Languages.Domain/"
COPY "modules/Kurs.Languages/Kurs.Languages.Domain.Shared/Kurs.Languages.Domain.Shared.csproj" "modules/Kurs.Languages/Kurs.Languages.Domain.Shared/"
COPY "modules/Kurs.Languages/Kurs.Languages.EntityFrameworkCore/Kurs.Languages.EntityFrameworkCore.csproj" "modules/Kurs.Languages/Kurs.Languages.EntityFrameworkCore/"
COPY "modules/Kurs.MailQueue/Kurs.MailQueue.csproj" "modules/Kurs.MailQueue/"
COPY "modules/Kurs.Notifications/Kurs.Notifications.Application.Contracts/Kurs.Notifications.Application.Contracts.csproj" "modules/Kurs.Notifications/Kurs.Notifications.Application.Contracts/"
COPY "modules/Kurs.Notifications/Kurs.Notifications.Domain/Kurs.Notifications.Domain.csproj" "modules/Kurs.Notifications/Kurs.Notifications.Domain/"
COPY "modules/Kurs.Notifications/Kurs.Notifications.Domain.Shared/Kurs.Notifications.Domain.Shared.csproj" "modules/Kurs.Notifications/Kurs.Notifications.Domain.Shared/"
COPY "modules/Kurs.Notifications/Kurs.Notifications.EntityFrameworkCore/Kurs.Notifications.EntityFrameworkCore.csproj" "modules/Kurs.Notifications/Kurs.Notifications.EntityFrameworkCore/"
COPY "modules/Kurs.Sender/Kurs.Sender.csproj" "modules/Kurs.Sender/"
COPY "modules/Kurs.Settings/Kurs.Settings.Application.Contracts/Kurs.Settings.Application.Contracts.csproj" "modules/Kurs.Settings/Kurs.Settings.Application.Contracts/"
COPY "modules/Kurs.Settings/Kurs.Settings.Domain/Kurs.Settings.Domain.csproj" "modules/Kurs.Settings/Kurs.Settings.Domain/"
COPY "modules/Kurs.Settings/Kurs.Settings.Domain.Shared/Kurs.Settings.Domain.Shared.csproj" "modules/Kurs.Settings/Kurs.Settings.Domain.Shared/"
COPY "modules/Kurs.Settings/Kurs.Settings.EntityFrameworkCore/Kurs.Settings.EntityFrameworkCore.csproj" "modules/Kurs.Settings/Kurs.Settings.EntityFrameworkCore/"
COPY "src/Kurs.Platform.Application.Contracts/Kurs.Platform.Application.Contracts.csproj" "src/Kurs.Platform.Application.Contracts/"
COPY "src/Kurs.Platform.DbMigrator/Kurs.Platform.DbMigrator.csproj" "src/Kurs.Platform.DbMigrator/"
COPY "src/Kurs.Platform.Domain/Kurs.Platform.Domain.csproj" "src/Kurs.Platform.Domain/"
COPY "src/Kurs.Platform.Domain.Shared/Kurs.Platform.Domain.Shared.csproj" "src/Kurs.Platform.Domain.Shared/"
COPY "src/Kurs.Platform.EntityFrameworkCore/Kurs.Platform.EntityFrameworkCore.csproj" "src/Kurs.Platform.EntityFrameworkCore/"
RUN dotnet restore "src/Kurs.Platform.DbMigrator/Kurs.Platform.DbMigrator.csproj"
COPY . .
RUN dotnet publish "src/Kurs.Platform.DbMigrator/Kurs.Platform.DbMigrator.csproj" -c Release -o /app/publish --no-restore
FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false \
LC_ALL=tr_TR.UTF-8 \
LANG=tr_TR.UTF-8
# icu'lar dotnet culture icin gerekli
# lib'ler wkhtmltopdf icin gerekli
RUN apk update
RUN apk add --no-cache \
icu-data-full \
icu-libs \
libgdiplus \
libc6-compat \
libc-dev
WORKDIR /srv/app
COPY --from=build /app/publish .
ENTRYPOINT ["./Kurs.Platform.DbMigrator"]

View file

@ -0,0 +1,75 @@
FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
ENV DOTNET_NUGET_SIGNATURE_VERIFICATION=false
WORKDIR /app
RUN apk update && apk upgrade
RUN apk add nodejs~=22 npm~=10
RUN dotnet tool install -g Volo.Abp.Cli
ENV PATH="/root/.dotnet/tools:${PATH}"
COPY "src/Kurs.Platform.HttpApi.Host/Kurs.Platform.HttpApi.Host.csproj" "src/Kurs.Platform.HttpApi.Host/"
COPY "src/Kurs.Platform.HttpApi.Host/package.json" "src/Kurs.Platform.HttpApi.Host/"
COPY "src/Kurs.Platform.HttpApi.Host/package-lock.json" "src/Kurs.Platform.HttpApi.Host/"
WORKDIR /app/src/Kurs.Platform.HttpApi.Host
RUN abp install-libs
WORKDIR /app
COPY "modules/Kurs.Languages/Kurs.Languages.Application/Kurs.Languages.Application.csproj" "modules/Kurs.Languages/Kurs.Languages.Application/"
COPY "modules/Kurs.Languages/Kurs.Languages.Application.Contracts/Kurs.Languages.Application.Contracts.csproj" "modules/Kurs.Languages/Kurs.Languages.Application.Contracts/"
COPY "modules/Kurs.Languages/Kurs.Languages.Domain/Kurs.Languages.Domain.csproj" "modules/Kurs.Languages/Kurs.Languages.Domain/"
COPY "modules/Kurs.Languages/Kurs.Languages.Domain.Shared/Kurs.Languages.Domain.Shared.csproj" "modules/Kurs.Languages/Kurs.Languages.Domain.Shared/"
COPY "modules/Kurs.Languages/Kurs.Languages.EntityFrameworkCore/Kurs.Languages.EntityFrameworkCore.csproj" "modules/Kurs.Languages/Kurs.Languages.EntityFrameworkCore/"
COPY "modules/Kurs.MailQueue/Kurs.MailQueue.csproj" "modules/Kurs.MailQueue/"
COPY "modules/Kurs.Notifications/Kurs.Notifications.Application/Kurs.Notifications.Application.csproj" "modules/Kurs.Notifications/Kurs.Notifications.Application/"
COPY "modules/Kurs.Notifications/Kurs.Notifications.Application.Contracts/Kurs.Notifications.Application.Contracts.csproj" "modules/Kurs.Notifications/Kurs.Notifications.Application.Contracts/"
COPY "modules/Kurs.Notifications/Kurs.Notifications.Domain/Kurs.Notifications.Domain.csproj" "modules/Kurs.Notifications/Kurs.Notifications.Domain/"
COPY "modules/Kurs.Notifications/Kurs.Notifications.Domain.Shared/Kurs.Notifications.Domain.Shared.csproj" "modules/Kurs.Notifications/Kurs.Notifications.Domain.Shared/"
COPY "modules/Kurs.Notifications/Kurs.Notifications.EntityFrameworkCore/Kurs.Notifications.EntityFrameworkCore.csproj" "modules/Kurs.Notifications/Kurs.Notifications.EntityFrameworkCore/"
COPY "modules/Kurs.Sender/Kurs.Sender.csproj" "modules/Kurs.Sender/"
COPY "modules/Kurs.Settings/Kurs.Settings.Application/Kurs.Settings.Application.csproj" "modules/Kurs.Settings/Kurs.Settings.Application/"
COPY "modules/Kurs.Settings/Kurs.Settings.Application.Contracts/Kurs.Settings.Application.Contracts.csproj" "modules/Kurs.Settings/Kurs.Settings.Application.Contracts/"
COPY "modules/Kurs.Settings/Kurs.Settings.Domain/Kurs.Settings.Domain.csproj" "modules/Kurs.Settings/Kurs.Settings.Domain/"
COPY "modules/Kurs.Settings/Kurs.Settings.Domain.Shared/Kurs.Settings.Domain.Shared.csproj" "modules/Kurs.Settings/Kurs.Settings.Domain.Shared/"
COPY "modules/Kurs.Settings/Kurs.Settings.EntityFrameworkCore/Kurs.Settings.EntityFrameworkCore.csproj" "modules/Kurs.Settings/Kurs.Settings.EntityFrameworkCore/"
COPY "src/Kurs.Platform.Application/Kurs.Platform.Application.csproj" "src/Kurs.Platform.Application/"
COPY "src/Kurs.Platform.Application.Contracts/Kurs.Platform.Application.Contracts.csproj" "src/Kurs.Platform.Application.Contracts/"
COPY "src/Kurs.Platform.Domain/Kurs.Platform.Domain.csproj" "src/Kurs.Platform.Domain/"
COPY "src/Kurs.Platform.Domain.Shared/Kurs.Platform.Domain.Shared.csproj" "src/Kurs.Platform.Domain.Shared/"
COPY "src/Kurs.Platform.EntityFrameworkCore/Kurs.Platform.EntityFrameworkCore.csproj" "src/Kurs.Platform.EntityFrameworkCore/"
COPY "src/Kurs.Platform.HttpApi/Kurs.Platform.HttpApi.csproj" "src/Kurs.Platform.HttpApi/"
COPY "src/Kurs.Platform.HttpApi.Client/Kurs.Platform.HttpApi.Client.csproj" "src/Kurs.Platform.HttpApi.Client/"
COPY "src/Kurs.Platform.HttpApi.Host/Kurs.Platform.HttpApi.Host.csproj" "src/Kurs.Platform.HttpApi.Host/"
COPY "test/Kurs.Platform.EntityFrameworkCore.Tests/Kurs.Platform.EntityFrameworkCore.Tests.csproj" "test/Kurs.Platform.EntityFrameworkCore.Tests/"
COPY "test/Kurs.Platform.TestBase/Kurs.Platform.TestBase.csproj" "test/Kurs.Platform.TestBase/"
RUN dotnet restore "src/Kurs.Platform.HttpApi.Host/Kurs.Platform.HttpApi.Host.csproj"
COPY . .
RUN mkdir -p publish
RUN dotnet publish "src/Kurs.Platform.HttpApi.Host/Kurs.Platform.HttpApi.Host.csproj" -c Release -o /app/publish --no-restore
FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false \
LC_ALL=tr_TR.UTF-8 \
LANG=tr_TR.UTF-8
# icu'lar dotnet culture icin gerekli
# lib'ler wkhtmltopdf icin gerekli
RUN apk update
RUN apk add --no-cache \
icu-data-full \
icu-libs \
libgdiplus \
libc6-compat \
libc-dev
# 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
RUN printf "\n\n[openssl_init]\nssl_conf = ssl_sect" >> /etc/ssl/openssl.cnf
RUN printf "\n\n[ssl_sect]\nsystem_default = ssl_default_sect" >> /etc/ssl/openssl.cnf
RUN printf "\n\n[ssl_default_sect]\nMinProtocol = TLSv1\nCipherString = DEFAULT@SECLEVEL=0\n" >> /etc/ssl/openssl.cnf
EXPOSE 80
EXPOSE 443
WORKDIR /srv/app
COPY --from=build /app/publish .
ENTRYPOINT ["./Kurs.Platform.HttpApi.Host"]

243
api/Kurs.Platform.sln Normal file
View file

@ -0,0 +1,243 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33213.308
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.Domain", "src\Kurs.Platform.Domain\Kurs.Platform.Domain.csproj", "{554AD327-6DBA-4F8F-96F8-81CE7A0C863F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.Application", "src\Kurs.Platform.Application\Kurs.Platform.Application.csproj", "{1A94A50E-06DC-43C1-80B5-B662820EC3EB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.EntityFrameworkCore", "src\Kurs.Platform.EntityFrameworkCore\Kurs.Platform.EntityFrameworkCore.csproj", "{C956DD76-69C8-4A9C-83EA-D17DF83340FD}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{CA9AC87F-097E-4F15-8393-4BC07735A5B0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.Domain.Shared", "src\Kurs.Platform.Domain.Shared\Kurs.Platform.Domain.Shared.csproj", "{42F719ED-8413-4895-B5B4-5AB56079BC66}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.Application.Contracts", "src\Kurs.Platform.Application.Contracts\Kurs.Platform.Application.Contracts.csproj", "{520659C8-C734-4298-A3DA-B539DB9DFC0B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.HttpApi", "src\Kurs.Platform.HttpApi\Kurs.Platform.HttpApi.csproj", "{4164BDF7-F527-4E85-9CE6-E3C2D7426A27}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.HttpApi.Client", "src\Kurs.Platform.HttpApi.Client\Kurs.Platform.HttpApi.Client.csproj", "{3B5A0094-670D-4BB1-BFDD-61B88A8773DC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.DbMigrator", "src\Kurs.Platform.DbMigrator\Kurs.Platform.DbMigrator.csproj", "{AA94D832-1CCC-4715-95A9-A483F23A1A5D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.HttpApi.Host", "src\Kurs.Platform.HttpApi.Host\Kurs.Platform.HttpApi.Host.csproj", "{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{03E1C8DA-035E-4882-AF81-F392139FCF38}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Kurs.Sender", "Kurs.Sender", "{4D886EEF-D4CF-4879-A10D-249D762E4ED9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Sender", "modules\Kurs.Sender\Kurs.Sender.csproj", "{21B52B6A-FC09-4EDA-8A73-9516726BF50B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Kurs.Languages", "Kurs.Languages", "{3B18248C-EE9C-43ED-9025-D3A78986EA7D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Languages.Application", "modules\Kurs.Languages\Kurs.Languages.Application\Kurs.Languages.Application.csproj", "{E9D256F2-B12F-4A90-8CF6-B52724716A94}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Languages.Application.Contracts", "modules\Kurs.Languages\Kurs.Languages.Application.Contracts\Kurs.Languages.Application.Contracts.csproj", "{F1EC497F-D361-4927-AFE6-156A0F7D8A1C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Languages.Domain", "modules\Kurs.Languages\Kurs.Languages.Domain\Kurs.Languages.Domain.csproj", "{9020ECD8-81D6-4604-A379-260796918C28}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Languages.Domain.Shared", "modules\Kurs.Languages\Kurs.Languages.Domain.Shared\Kurs.Languages.Domain.Shared.csproj", "{A3933E06-9DFE-480D-85C4-66F28F076164}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Languages.EntityFrameworkCore", "modules\Kurs.Languages\Kurs.Languages.EntityFrameworkCore\Kurs.Languages.EntityFrameworkCore.csproj", "{556AC2C2-9765-4B3D-8F38-9EAF3DA61AC5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Kurs.Settings", "Kurs.Settings", "{4D880243-0276-49A9-9FF2-FAD8BA727F74}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Settings.Application", "modules\Kurs.Settings\Kurs.Settings.Application\Kurs.Settings.Application.csproj", "{5F288ACC-A9CF-470B-BB68-B1C8B102CDDD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Settings.Application.Contracts", "modules\Kurs.Settings\Kurs.Settings.Application.Contracts\Kurs.Settings.Application.Contracts.csproj", "{A926F04F-631B-4A05-853C-6C76555BF26A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Settings.Domain", "modules\Kurs.Settings\Kurs.Settings.Domain\Kurs.Settings.Domain.csproj", "{E14E0128-D4FF-462D-B684-7238EA876D69}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Settings.Domain.Shared", "modules\Kurs.Settings\Kurs.Settings.Domain.Shared\Kurs.Settings.Domain.Shared.csproj", "{DBFD0F4B-5592-4E34-8624-04F7540E34B9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Settings.EntityFrameworkCore", "modules\Kurs.Settings\Kurs.Settings.EntityFrameworkCore\Kurs.Settings.EntityFrameworkCore.csproj", "{C2F5630E-A6E2-48D5-B182-5FE9278D3E37}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{62A235F3-B95E-4CB4-B59E-AAE30A0E6C5B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.TestBase", "test\Kurs.Platform.TestBase\Kurs.Platform.TestBase.csproj", "{3E13749E-82D1-434B-B867-F7B094B66065}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.EntityFrameworkCore.Tests", "test\Kurs.Platform.EntityFrameworkCore.Tests\Kurs.Platform.EntityFrameworkCore.Tests.csproj", "{620D9F08-EB9F-469F-806A-64E915437154}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Kurs.MailQueue", "Kurs.MailQueue", "{70BCE3C5-D122-4EF8-97EC-DB804AEE92D5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.MailQueue", "modules\Kurs.MailQueue\Kurs.MailQueue.csproj", "{088B3139-68D3-4A5F-B159-0C8FE94CD969}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Kurs.Notifications", "Kurs.Notifications", "{41A473FE-2537-4223-8CF3-A4A2A4A4F41E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Notifications.Application", "modules\Kurs.Notifications\Kurs.Notifications.Application\Kurs.Notifications.Application.csproj", "{A972109D-D974-4BB2-BA01-72BD845ACBBA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Notifications.Application.Contracts", "modules\Kurs.Notifications\Kurs.Notifications.Application.Contracts\Kurs.Notifications.Application.Contracts.csproj", "{297B7268-DEF3-4669-98DF-78FA08619EDF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Notifications.Domain", "modules\Kurs.Notifications\Kurs.Notifications.Domain\Kurs.Notifications.Domain.csproj", "{631092C7-B59D-4EA7-92D0-5E181AB4F9F6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Notifications.Domain.Shared", "modules\Kurs.Notifications\Kurs.Notifications.Domain.Shared\Kurs.Notifications.Domain.Shared.csproj", "{23659070-58F7-403B-8973-B2E20B5E9BE1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Notifications.EntityFrameworkCore", "modules\Kurs.Notifications\Kurs.Notifications.EntityFrameworkCore\Kurs.Notifications.EntityFrameworkCore.csproj", "{D9E0D333-60F3-493F-A5B2-5758ACA42A17}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{722BAAEF-70B8-4381-A8AD-7F2C205D2D0A}"
ProjectSection(SolutionItems) = preProject
README.md = README.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Release|Any CPU.Build.0 = Release|Any CPU
{1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Release|Any CPU.Build.0 = Release|Any CPU
{C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Release|Any CPU.Build.0 = Release|Any CPU
{42F719ED-8413-4895-B5B4-5AB56079BC66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{42F719ED-8413-4895-B5B4-5AB56079BC66}.Debug|Any CPU.Build.0 = Debug|Any CPU
{42F719ED-8413-4895-B5B4-5AB56079BC66}.Release|Any CPU.ActiveCfg = Release|Any CPU
{42F719ED-8413-4895-B5B4-5AB56079BC66}.Release|Any CPU.Build.0 = Release|Any CPU
{520659C8-C734-4298-A3DA-B539DB9DFC0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{520659C8-C734-4298-A3DA-B539DB9DFC0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{520659C8-C734-4298-A3DA-B539DB9DFC0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{520659C8-C734-4298-A3DA-B539DB9DFC0B}.Release|Any CPU.Build.0 = Release|Any CPU
{4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Release|Any CPU.Build.0 = Release|Any CPU
{3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Release|Any CPU.Build.0 = Release|Any CPU
{AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Release|Any CPU.Build.0 = Release|Any CPU
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Release|Any CPU.Build.0 = Release|Any CPU
{21B52B6A-FC09-4EDA-8A73-9516726BF50B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{21B52B6A-FC09-4EDA-8A73-9516726BF50B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{21B52B6A-FC09-4EDA-8A73-9516726BF50B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{21B52B6A-FC09-4EDA-8A73-9516726BF50B}.Release|Any CPU.Build.0 = Release|Any CPU
{E9D256F2-B12F-4A90-8CF6-B52724716A94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E9D256F2-B12F-4A90-8CF6-B52724716A94}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E9D256F2-B12F-4A90-8CF6-B52724716A94}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E9D256F2-B12F-4A90-8CF6-B52724716A94}.Release|Any CPU.Build.0 = Release|Any CPU
{F1EC497F-D361-4927-AFE6-156A0F7D8A1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F1EC497F-D361-4927-AFE6-156A0F7D8A1C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F1EC497F-D361-4927-AFE6-156A0F7D8A1C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F1EC497F-D361-4927-AFE6-156A0F7D8A1C}.Release|Any CPU.Build.0 = Release|Any CPU
{9020ECD8-81D6-4604-A379-260796918C28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9020ECD8-81D6-4604-A379-260796918C28}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9020ECD8-81D6-4604-A379-260796918C28}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9020ECD8-81D6-4604-A379-260796918C28}.Release|Any CPU.Build.0 = Release|Any CPU
{A3933E06-9DFE-480D-85C4-66F28F076164}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A3933E06-9DFE-480D-85C4-66F28F076164}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A3933E06-9DFE-480D-85C4-66F28F076164}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A3933E06-9DFE-480D-85C4-66F28F076164}.Release|Any CPU.Build.0 = Release|Any CPU
{556AC2C2-9765-4B3D-8F38-9EAF3DA61AC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{556AC2C2-9765-4B3D-8F38-9EAF3DA61AC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{556AC2C2-9765-4B3D-8F38-9EAF3DA61AC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{556AC2C2-9765-4B3D-8F38-9EAF3DA61AC5}.Release|Any CPU.Build.0 = Release|Any CPU
{5F288ACC-A9CF-470B-BB68-B1C8B102CDDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5F288ACC-A9CF-470B-BB68-B1C8B102CDDD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5F288ACC-A9CF-470B-BB68-B1C8B102CDDD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5F288ACC-A9CF-470B-BB68-B1C8B102CDDD}.Release|Any CPU.Build.0 = Release|Any CPU
{A926F04F-631B-4A05-853C-6C76555BF26A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A926F04F-631B-4A05-853C-6C76555BF26A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A926F04F-631B-4A05-853C-6C76555BF26A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A926F04F-631B-4A05-853C-6C76555BF26A}.Release|Any CPU.Build.0 = Release|Any CPU
{E14E0128-D4FF-462D-B684-7238EA876D69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E14E0128-D4FF-462D-B684-7238EA876D69}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E14E0128-D4FF-462D-B684-7238EA876D69}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E14E0128-D4FF-462D-B684-7238EA876D69}.Release|Any CPU.Build.0 = Release|Any CPU
{DBFD0F4B-5592-4E34-8624-04F7540E34B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DBFD0F4B-5592-4E34-8624-04F7540E34B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DBFD0F4B-5592-4E34-8624-04F7540E34B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DBFD0F4B-5592-4E34-8624-04F7540E34B9}.Release|Any CPU.Build.0 = Release|Any CPU
{C2F5630E-A6E2-48D5-B182-5FE9278D3E37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C2F5630E-A6E2-48D5-B182-5FE9278D3E37}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2F5630E-A6E2-48D5-B182-5FE9278D3E37}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2F5630E-A6E2-48D5-B182-5FE9278D3E37}.Release|Any CPU.Build.0 = Release|Any CPU
{3E13749E-82D1-434B-B867-F7B094B66065}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E13749E-82D1-434B-B867-F7B094B66065}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E13749E-82D1-434B-B867-F7B094B66065}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E13749E-82D1-434B-B867-F7B094B66065}.Release|Any CPU.Build.0 = Release|Any CPU
{620D9F08-EB9F-469F-806A-64E915437154}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{620D9F08-EB9F-469F-806A-64E915437154}.Debug|Any CPU.Build.0 = Debug|Any CPU
{620D9F08-EB9F-469F-806A-64E915437154}.Release|Any CPU.ActiveCfg = Release|Any CPU
{620D9F08-EB9F-469F-806A-64E915437154}.Release|Any CPU.Build.0 = Release|Any CPU
{088B3139-68D3-4A5F-B159-0C8FE94CD969}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{088B3139-68D3-4A5F-B159-0C8FE94CD969}.Debug|Any CPU.Build.0 = Debug|Any CPU
{088B3139-68D3-4A5F-B159-0C8FE94CD969}.Release|Any CPU.ActiveCfg = Release|Any CPU
{088B3139-68D3-4A5F-B159-0C8FE94CD969}.Release|Any CPU.Build.0 = Release|Any CPU
{A972109D-D974-4BB2-BA01-72BD845ACBBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A972109D-D974-4BB2-BA01-72BD845ACBBA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A972109D-D974-4BB2-BA01-72BD845ACBBA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A972109D-D974-4BB2-BA01-72BD845ACBBA}.Release|Any CPU.Build.0 = Release|Any CPU
{297B7268-DEF3-4669-98DF-78FA08619EDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{297B7268-DEF3-4669-98DF-78FA08619EDF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{297B7268-DEF3-4669-98DF-78FA08619EDF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{297B7268-DEF3-4669-98DF-78FA08619EDF}.Release|Any CPU.Build.0 = Release|Any CPU
{631092C7-B59D-4EA7-92D0-5E181AB4F9F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{631092C7-B59D-4EA7-92D0-5E181AB4F9F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{631092C7-B59D-4EA7-92D0-5E181AB4F9F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{631092C7-B59D-4EA7-92D0-5E181AB4F9F6}.Release|Any CPU.Build.0 = Release|Any CPU
{23659070-58F7-403B-8973-B2E20B5E9BE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{23659070-58F7-403B-8973-B2E20B5E9BE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{23659070-58F7-403B-8973-B2E20B5E9BE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{23659070-58F7-403B-8973-B2E20B5E9BE1}.Release|Any CPU.Build.0 = Release|Any CPU
{D9E0D333-60F3-493F-A5B2-5758ACA42A17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D9E0D333-60F3-493F-A5B2-5758ACA42A17}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D9E0D333-60F3-493F-A5B2-5758ACA42A17}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D9E0D333-60F3-493F-A5B2-5758ACA42A17}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{554AD327-6DBA-4F8F-96F8-81CE7A0C863F} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
{1A94A50E-06DC-43C1-80B5-B662820EC3EB} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
{C956DD76-69C8-4A9C-83EA-D17DF83340FD} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
{42F719ED-8413-4895-B5B4-5AB56079BC66} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
{520659C8-C734-4298-A3DA-B539DB9DFC0B} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
{4164BDF7-F527-4E85-9CE6-E3C2D7426A27} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
{3B5A0094-670D-4BB1-BFDD-61B88A8773DC} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
{AA94D832-1CCC-4715-95A9-A483F23A1A5D} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
{4D886EEF-D4CF-4879-A10D-249D762E4ED9} = {03E1C8DA-035E-4882-AF81-F392139FCF38}
{21B52B6A-FC09-4EDA-8A73-9516726BF50B} = {4D886EEF-D4CF-4879-A10D-249D762E4ED9}
{3B18248C-EE9C-43ED-9025-D3A78986EA7D} = {03E1C8DA-035E-4882-AF81-F392139FCF38}
{E9D256F2-B12F-4A90-8CF6-B52724716A94} = {3B18248C-EE9C-43ED-9025-D3A78986EA7D}
{F1EC497F-D361-4927-AFE6-156A0F7D8A1C} = {3B18248C-EE9C-43ED-9025-D3A78986EA7D}
{9020ECD8-81D6-4604-A379-260796918C28} = {3B18248C-EE9C-43ED-9025-D3A78986EA7D}
{A3933E06-9DFE-480D-85C4-66F28F076164} = {3B18248C-EE9C-43ED-9025-D3A78986EA7D}
{556AC2C2-9765-4B3D-8F38-9EAF3DA61AC5} = {3B18248C-EE9C-43ED-9025-D3A78986EA7D}
{4D880243-0276-49A9-9FF2-FAD8BA727F74} = {03E1C8DA-035E-4882-AF81-F392139FCF38}
{5F288ACC-A9CF-470B-BB68-B1C8B102CDDD} = {4D880243-0276-49A9-9FF2-FAD8BA727F74}
{A926F04F-631B-4A05-853C-6C76555BF26A} = {4D880243-0276-49A9-9FF2-FAD8BA727F74}
{E14E0128-D4FF-462D-B684-7238EA876D69} = {4D880243-0276-49A9-9FF2-FAD8BA727F74}
{DBFD0F4B-5592-4E34-8624-04F7540E34B9} = {4D880243-0276-49A9-9FF2-FAD8BA727F74}
{C2F5630E-A6E2-48D5-B182-5FE9278D3E37} = {4D880243-0276-49A9-9FF2-FAD8BA727F74}
{3E13749E-82D1-434B-B867-F7B094B66065} = {62A235F3-B95E-4CB4-B59E-AAE30A0E6C5B}
{620D9F08-EB9F-469F-806A-64E915437154} = {62A235F3-B95E-4CB4-B59E-AAE30A0E6C5B}
{70BCE3C5-D122-4EF8-97EC-DB804AEE92D5} = {03E1C8DA-035E-4882-AF81-F392139FCF38}
{088B3139-68D3-4A5F-B159-0C8FE94CD969} = {70BCE3C5-D122-4EF8-97EC-DB804AEE92D5}
{41A473FE-2537-4223-8CF3-A4A2A4A4F41E} = {03E1C8DA-035E-4882-AF81-F392139FCF38}
{A972109D-D974-4BB2-BA01-72BD845ACBBA} = {41A473FE-2537-4223-8CF3-A4A2A4A4F41E}
{297B7268-DEF3-4669-98DF-78FA08619EDF} = {41A473FE-2537-4223-8CF3-A4A2A4A4F41E}
{631092C7-B59D-4EA7-92D0-5E181AB4F9F6} = {41A473FE-2537-4223-8CF3-A4A2A4A4F41E}
{23659070-58F7-403B-8973-B2E20B5E9BE1} = {41A473FE-2537-4223-8CF3-A4A2A4A4F41E}
{D9E0D333-60F3-493F-A5B2-5758ACA42A17} = {41A473FE-2537-4223-8CF3-A4A2A4A4F41E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {28315BFD-90E7-4E14-A2EA-F3D23AF4126F}
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,23 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeEditing/Intellisense/CodeCompletion/IntelliSenseCompletingCharacters/CSharpCompletingCharacters/UpgradedFromVSSettings/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceDoWhileStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceFixedStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceForeachStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceForStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceIfStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceLockStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceUsingStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceWhileStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOR/@EntryValue">Required</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOREACH/@EntryValue">Required</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_IFELSE/@EntryValue">Required</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">Required</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_REDUNDANT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Implementations/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=Async/@EntryIndexedValue">False</s:String>
<s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=Mutable/@EntryIndexedValue">False</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Overrides/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Generate/=Overrides/Options/=Async/@EntryIndexedValue">False</s:String>
<s:String x:Key="/Default/CodeStyle/Generate/=Overrides/Options/=Mutable/@EntryIndexedValue">False</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SQL/@EntryIndexedValue">SQL</s:String>
</wpf:ResourceDictionary>

5
api/NuGet.Config Normal file
View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
</packageSources>
</configuration>

110
api/README.md Normal file
View file

@ -0,0 +1,110 @@
# Yeni Modul Ekleme
`abp new Kurs.Notification -t module --no-ui -m none --database-provider ef --version 7.2.2 --old`
# Code Format
`dotnet format --include .\modules\Kurs.Notification\ --folder`
# Migrations
- Yeni migration ekleme
`EntityFrameworkCore projesine gir`
`dotnet ef migrations add ""`
`dotnet ef database update`
- Son migrationi siler ve snapshot revert eder
`dotnet ef migrations remove`
`dotnet ef database update "20240822114716_ABP_822"`
# Public Api
```
Token İsteği Örnek:
POST /connect/token HTTP/1.1
Host: localhost:44344
Content-Type: application/x-www-form-urlencoded
username=sedat%40kadifeteks.com
&password=...
&grant_type=password
&client_id=Platform_PublicApi
&scope=offline_access%20Platform
```
## Whatsapp Ayarları
- Normal facebook üyeliği yapılır.
- https://developers.facebook.com/ sitesinden yeni developer üyeliği oluşturulur. Developer üyeliği seçilir.
- CreateApp butonu ile yeni uygulama oluşturulur. Uygulama adı belirlenir. 'Sozsoft Messenger'
- AppType olarak İşletme seçilir ve App oluşturulur.
- Add Products kısmında WhatsApp seçilir ve Business Account oluşturulur.
- 3 noktadan (menüden) WhatsApp Manager sayfasına gidilir. Manage Templates seçilir, istenirse yeni template oluşturulur. 'hello_world'
- WhatsApp Manager üzerinde menüden Settings -> Users -> System Users eklenir. Kullanıcı adı 'admin' ve Role ise 'Admin' seçilir.
- Eklenen 'admin' kullanıcısında 'Assign Assets' seçilir ve full yetki verilir.
- admin kullanıcısı üzerinden 'Generate Token' seçilir ve aşağıdaki yetkiler verilir.
```
- whatsapp_business_management'
- 'whatsapp_business_messaging'
```
- WhatsApp -> API Setup kısmından "From" kısmında yeni telefon numarası eklenir.
- WhatsApp -> API Setup kısmından Generate Access Token oluşturulur.
- token: EAASM83pDJf0BO0ZCYBr3Fx4SES0ox8XiZCgP3FIteprYpwawZCkGYjpMlKk4OZCWgRNZC2Ttofgf8amMf929ZBuDcgYIOsXkPMGBNmVxm2czipzq63LmtbYfyCWsKVy0q1jtay0nRoeDuO2FKhqCfLLtNn9cSWjINVLcz26ptK8a2Oko83cZBzrNsp3cpIECnzqRfEjHdEz1U73y3ZB1MZBOhHilax7yZALf4ZA1Tmk
- WhatsApp telefon numarasını Register etmek için aşağıdaki postman Curl gönderilir.
```
curl --location 'https://graph.facebook.com/v21.0/521106361082067/register' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <access token>' \
--data '{
"messaging_product": "whatsapp",
"pin": "238567"
}'
```
- Message göndermek için url : https://graph.facebook.com/v21.0/521106361082067/messages
```
{
"messaging_product": "whatsapp",
"to": "{+gönderilecek gsm numarası}",
"type": "template",
"template": {
"name": "{message_template_name}",
"language": {
"code": "en"
},
"components": [
{
"type": "body",
"parameters": [
{
"type": "text",
"text": "Test mesajı"
}
]
}
]
}
}
```
# ABP Update
- https://abp.io/docs/latest/release-info/upgrading
- https://abp.io/docs/9.0/release-info/migration-guides/abp-9-0
- https://learn.microsoft.com/en-us/aspnet/core/migration/80-90?view=aspnetcore-9.0&tabs=visual-studio-code
- Adımlar:
- abp cli güncellenir dotnet tool update --global Volo.Abp.Cli
- abp update ile sln içindeki referanslar update edilir
- modules/ klasörü *.csproj içinde ara&düzenle ile update edilir (örn. 8.3.4 -> 9.0.2)
- .net sürümü arttıysa Microsoft'un dotnet upgrade dokümanı takip edilir
- Yeni dotnet sdk kurulumu yapılır (örn dotnet 9 sdk)
- ef tools güncellenir (dotnet tool update --global dotnet-ef)
- Dockerfile dosyalarındaki base imajlar yeni dotnet sürümüne güncellenir
- Abp upgrade dokümanı takip edilir
- Proje build olmuyorsa hatalar çözülür
- Yeni migration eklenir (varsa). Migration boş çıkıyorsa kaldırılır. (Örn dotnet ef migrations add Abp902 ve dotnet ef migrations remove)
- Migration boş değilse çalıştırılır (dotnet ef database update)

19
api/common.props Normal file
View file

@ -0,0 +1,19 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>1.0.0</Version>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<AbpProjectType>app</AbpProjectType>
</PropertyGroup>
<Target Name="NoWarnOnRazorViewImportedTypeConflicts" BeforeTargets="RazorCoreCompile">
<PropertyGroup>
<NoWarn>$(NoWarn);0436</NoWarn>
</PropertyGroup>
</Target>
<ItemGroup>
<Content Remove="$(UserProfile)\.nuget\packages\*\*\contentFiles\any\*\*.abppkg*.json" />
</ItemGroup>
</Project>

6
api/global.json Normal file
View file

@ -0,0 +1,6 @@
{
"sdk": {
"version": "9.0.101",
"rollForward": "latestMajor"
}
}

1
api/migrate-database.ps1 Normal file
View file

@ -0,0 +1 @@
dotnet run --project src/Kurs.Platform.DbMigrator

View file

@ -0,0 +1,24 @@
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Application.Dtos;
namespace Kurs.Languages;
public class LanguageDto : FullAuditedEntityDto<Guid>
{
[Required]
public string CultureName { get; set; }
[Required]
public string UiCultureName { get; set; }
[Required]
public string DisplayName { get; set; }
[Required]
public bool IsEnabled { get; set; }
/// <summary> multiple select icin test amacli olarak eklendi
/// </summary>
public string MultipleCultures { get; set; }
}

View file

@ -0,0 +1,14 @@
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Application.Dtos;
namespace Kurs.Languages;
public class LanguageKeyDto : FullAuditedEntityDto<Guid>
{
[Required]
public string Key { get; set; }
[Required]
public string ResourceName { get; set; }
}

View file

@ -0,0 +1,18 @@
using System.ComponentModel.DataAnnotations;
namespace Kurs.Languages;
public class LanguageTextCreateUpdateDto
{
[Required]
public string CultureName { get; set; }
[Required]
public string Key { get; set; }
[Required]
public string Value { get; set; }
[Required]
public string ResourceName { get; set; }
}

View file

@ -0,0 +1,12 @@
using System;
using Volo.Abp.Application.Dtos;
namespace Kurs.Languages;
public class LanguageTextDto : FullAuditedEntityDto<Guid>
{
public string CultureName { get; set; }
public string ResourceName { get; set; }
public string Key { get; set; }
public string Value { get; set; }
}

View file

@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
namespace Kurs.Languages;
public class LanguageTextFilteredDto
{
[Required]
public string CultureName { get; set; }
[Required]
public string ResourceName { get; set; }
[Required]
public string Key { get; set; }
}

View file

@ -0,0 +1,14 @@
using System;
using Volo.Abp.Application.Dtos;
namespace Kurs.Languages;
public class LanguageTextTranslatedDto : FullAuditedEntityDto<Guid>
{
public string BaseCultureName { get; set; }
public string BaseValue { get; set; }
public string TargetCultureName { get; set; }
public string TargetValue { get; set; }
public string ResourceName { get; set; }
public string Key { get; set; }
}

View file

@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Application.Dtos;
namespace Kurs.Languages;
public class LanguageTextTranslatedRequestDto : PagedAndSortedResultRequestDto
{
[Required]
public string BaseCultureName { get; set; }
[Required]
public string TargetCultureName { get; set; }
public string ResourceName { get; set; }
public string Key { get; set; }
}

View file

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

View file

@ -0,0 +1,14 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace Kurs.Languages;
public interface ILanguageAppService : ICrudAppService<
LanguageDto,
Guid,
PagedAndSortedResultRequestDto>
{
Task<LanguageDto> GetLanguageByCultureNameAsync(string CultureName);
}

View file

@ -0,0 +1,13 @@
using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace Kurs.Languages;
public interface ILanguageKeyAppService : ICrudAppService<
LanguageKeyDto,
Guid,
PagedAndSortedResultRequestDto>
{
}

View file

@ -0,0 +1,21 @@
using System.Threading.Tasks;
using Volo.Abp;
namespace Kurs.Languages;
[IntegrationService]
public interface ILanguageKeyIntegrationService
{
Task CreateKeysForSettingsAsync(
string NameKey,
string DescriptionKey,
string MainGroupKey,
string SubGroupKey
);
Task DeleteKeysForSettingsAsync(
string NameKey,
string DescriptionKey,
string MainGroupKey,
string SubGroupKey);
}

View file

@ -0,0 +1,17 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace Kurs.Languages;
public interface ILanguageTextAppService : ICrudAppService<
LanguageTextDto,
Guid,
PagedAndSortedResultRequestDto,
LanguageTextCreateUpdateDto>
{
Task<PagedResultDto<LanguageTextTranslatedDto>> GetLanguageTextTranslatedAsync(LanguageTextTranslatedRequestDto input);
Task<LanguageTextDto> GetLanguageTextAsync(LanguageTextFilteredDto input);
Task UpdateLanguageTextAsync(LanguageTextCreateUpdateDto input);
}

View file

@ -0,0 +1,3 @@
{
"role": "lib.application-contracts"
}

View file

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\common.props" />
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<RootNamespace>Kurs.Languages</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="9.0.2" />
<PackageReference Include="Volo.Abp.Authorization" Version="9.0.2" />
<ProjectReference Include="..\Kurs.Languages.Domain.Shared\Kurs.Languages.Domain.Shared.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,15 @@
using Volo.Abp.Application;
using Volo.Abp.Modularity;
using Volo.Abp.Authorization;
namespace Kurs.Languages;
[DependsOn(
typeof(LanguagesDomainSharedModule),
typeof(AbpDddApplicationContractsModule),
typeof(AbpAuthorizationModule)
)]
public class LanguagesApplicationContractsModule : AbpModule
{
}

View file

@ -0,0 +1,8 @@
namespace Kurs.Languages;
public class LanguagesRemoteServiceConsts
{
public const string RemoteServiceName = "Languages";
public const string ModuleName = "languages";
}

View file

@ -0,0 +1,18 @@
using Kurs.Languages.Localization;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;
namespace Kurs.Languages.Permissions;
public class LanguagesPermissionDefinitionProvider : PermissionDefinitionProvider
{
public override void Define(IPermissionDefinitionContext context)
{
var myGroup = context.AddGroup(LanguagesPermissions.GroupName, L("Permission:Languages"));
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<LanguagesResource>(name);
}
}

View file

@ -0,0 +1,13 @@
using Volo.Abp.Reflection;
namespace Kurs.Languages.Permissions;
public class LanguagesPermissions
{
public const string GroupName = "Languages";
public static string[] GetAll()
{
return ReflectionHelper.GetPublicConstantsRecursively(typeof(LanguagesPermissions));
}
}

View file

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

View file

@ -0,0 +1,3 @@
{
"role": "lib.application"
}

View file

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\common.props" />
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<RootNamespace>Kurs.Languages</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AutoMapper" Version="9.0.2" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="9.0.2" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="9.0.2" />
<ProjectReference Include="..\Kurs.Languages.Application.Contracts\Kurs.Languages.Application.Contracts.csproj" />
<ProjectReference Include="..\Kurs.Languages.Domain\Kurs.Languages.Domain.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,53 @@
using Kurs.Languages.Entities;
using Kurs.Languages.Localization;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Validation;
namespace Kurs.Languages;
public class LanguageAppService : CrudAppService<
Language,
LanguageDto,
Guid,
PagedAndSortedResultRequestDto>,
ILanguageAppService
{
public LanguageAppService(IRepository<Language, Guid> repository) : base(repository)
{
LocalizationResource = typeof(LanguagesResource);
ObjectMapperContext = typeof(LanguagesApplicationModule);
}
public override async Task<LanguageDto> CreateAsync(LanguageDto input)
{
var recordExists = await Repository.AnyAsync(a => a.CultureName == input.CultureName);
if (recordExists)
{
var validationErrors = new ValidationResult(
L["Error:UniqueControl"],
new string[] { "CultureName" }
);
throw new AbpValidationException(new List<ValidationResult> { validationErrors });
}
return await base.CreateAsync(input);
}
public async Task<LanguageDto> GetLanguageByCultureNameAsync(string CultureName)
{
var item = await Repository.FirstOrDefaultAsync(a => a.CultureName == CultureName);
if (item is null)
{
throw new EntityNotFoundException(L["RecordNotFound"]);
}
return ObjectMapper.Map<Language, LanguageDto>(item);
}
}

View file

@ -0,0 +1,48 @@
using Kurs.Languages.Entities;
using Kurs.Languages.Localization;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Validation;
namespace Kurs.Languages;
public class LanguageKeyAppService : CrudAppService<
LanguageKey,
LanguageKeyDto,
Guid,
PagedAndSortedResultRequestDto>,
ILanguageKeyAppService
{
private readonly IRepository<LanguageKey, Guid> _repository;
public LanguageKeyAppService(
IRepository<LanguageKey, Guid> repository
) : base(repository)
{
LocalizationResource = typeof(LanguagesResource);
ObjectMapperContext = typeof(LanguagesApplicationModule);
_repository = repository;
}
public override async Task<LanguageKeyDto> CreateAsync(LanguageKeyDto input)
{
var recordExists = await _repository.AnyAsync(
a => a.ResourceName == input.ResourceName
&& a.Key == input.Key);
if (recordExists)
{
var validationErrors = new ValidationResult(
L["Error:UniqueControl"],
new string[] { "ResourceName", "Key" }
);
throw new AbpValidationException(new List<ValidationResult> { validationErrors });
}
return await base.CreateAsync(input);
}
}

View file

@ -0,0 +1,63 @@
using System;
using System.Threading.Tasks;
using Kurs.Languages.Entities;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
namespace Kurs.Languages;
[IntegrationService]
public class LanguageKeyIntegrationService : ILanguageKeyIntegrationService, ITransientDependency
{
private readonly IRepository<LanguageKey, Guid> _repository;
public LanguageKeyIntegrationService(IRepository<LanguageKey, Guid> repository)
{
_repository = repository;
}
public async Task CreateKeysForSettingsAsync(
string NameKey,
string DescriptionKey,
string MainGroupKey,
string SubGroupKey
)
{
//NameKey
if (!await _repository.AnyAsync(a => a.Key == NameKey && a.ResourceName == LanguagesConsts.AppName))
{
await _repository.InsertAsync(new LanguageKey { Key = NameKey, ResourceName = LanguagesConsts.AppName });
}
//DescriptionKey
if (!await _repository.AnyAsync(a => a.Key == DescriptionKey && a.ResourceName == LanguagesConsts.AppName))
{
await _repository.InsertAsync(new LanguageKey { Key = DescriptionKey, ResourceName = LanguagesConsts.AppName });
}
//MainGroupKey
if (!await _repository.AnyAsync(a => a.Key == MainGroupKey && a.ResourceName == LanguagesConsts.AppName))
{
await _repository.InsertAsync(new LanguageKey { Key = MainGroupKey, ResourceName = LanguagesConsts.AppName });
}
//SubGroupKey
if (!await _repository.AnyAsync(a => a.Key == SubGroupKey && a.ResourceName == LanguagesConsts.AppName))
{
await _repository.InsertAsync(new LanguageKey { Key = SubGroupKey, ResourceName = LanguagesConsts.AppName });
}
}
public async Task DeleteKeysForSettingsAsync(
string NameKey,
string DescriptionKey,
string MainGroupKey,
string SubGroupKey)
{
await _repository.DeleteAsync(a => a.Key == NameKey && a.ResourceName == LanguagesConsts.AppName);
await _repository.DeleteAsync(a => a.Key == DescriptionKey && a.ResourceName == LanguagesConsts.AppName);
await _repository.DeleteAsync(a => a.Key == MainGroupKey && a.ResourceName == LanguagesConsts.AppName);
await _repository.DeleteAsync(a => a.Key == SubGroupKey && a.ResourceName == LanguagesConsts.AppName);
}
}

View file

@ -0,0 +1,164 @@
using Kurs.Languages.Entities;
using Kurs.Languages.Localization;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Auditing;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Validation;
namespace Kurs.Languages;
public class LanguageTextAppService : CrudAppService<
LanguageText,
LanguageTextDto,
Guid,
PagedAndSortedResultRequestDto,
LanguageTextCreateUpdateDto>,
ILanguageTextAppService
{
private readonly IRepository<LanguageText, Guid> _repositoryText;
private readonly IRepository<LanguageKey, Guid> _repositoryKey;
public LanguageTextAppService(
IRepository<LanguageText, Guid> repositoryText,
IRepository<LanguageKey, Guid> repositoryKey
)
: base(repositoryText)
{
LocalizationResource = typeof(LanguagesResource);
ObjectMapperContext = typeof(LanguagesApplicationModule);
_repositoryText = repositoryText;
_repositoryKey = repositoryKey;
}
public override async Task<LanguageTextDto> CreateAsync(LanguageTextCreateUpdateDto input)
{
var recordExists = await _repositoryText.AnyAsync(
a => a.CultureName == input.CultureName &&
a.Key == input.Key &&
a.ResourceName == input.ResourceName);
if (recordExists)
{
var validationErrors = new ValidationResult(
L["Error:UniqueControl"],
new string[] { "CultureName", "Key", "ResourceName" }
);
throw new AbpValidationException(new List<ValidationResult> { validationErrors });
}
return await base.CreateAsync(input);
}
public async Task UpdateLanguageTextAsync(LanguageTextCreateUpdateDto input)
{
var entity = await _repositoryText.GetAsync(
a => a.CultureName == input.CultureName &&
a.ResourceName == input.ResourceName &&
a.Key == input.Key);
if (entity != null)
{
entity.Value = input.Value;
await _repositoryText.UpdateAsync(entity);
}
}
public async Task<PagedResultDto<LanguageTextTranslatedDto>> GetLanguageTextTranslatedAsync(LanguageTextTranslatedRequestDto input)
{
var query = await _repositoryKey.GetQueryableAsync();
query = query
.WhereIf(!input.ResourceName.IsNullOrEmpty(), a => a.ResourceName == input.ResourceName)
.WhereIf(!input.Key.IsNullOrEmpty(), a => a.Key == input.Key);
var totalCount = await query.CountAsync();
query = ApplySorting(query, input);
query = ApplyPaging(query, input);
var keys = await query.ToListAsync();
var dtoLanguageTextTranslate = ObjectMapper.Map<List<LanguageKey>, List<LanguageTextTranslatedDto>>(keys);
var dtoBaseCulturesValue = await _repositoryText.GetListAsync(a => a.CultureName == input.BaseCultureName);
var dtoTargetCulturesValue = await _repositoryText.GetListAsync(a => a.CultureName == input.TargetCultureName);
dtoLanguageTextTranslate.ForEach(dto =>
{
var baseEntity = dtoBaseCulturesValue.FirstOrDefault(a => a.Key == dto.Key && a.ResourceName == dto.ResourceName);
dto.BaseCultureName = input.BaseCultureName;
dto.BaseValue = baseEntity?.Value;
var targetEntity = dtoTargetCulturesValue.FirstOrDefault(a => a.Key == dto.Key && a.ResourceName == dto.ResourceName);
dto.TargetCultureName = input.TargetCultureName;
dto.TargetValue = targetEntity?.Value;
});
return new PagedResultDto<LanguageTextTranslatedDto>(totalCount, dtoLanguageTextTranslate);
}
public async Task<LanguageTextDto> GetLanguageTextAsync(LanguageTextFilteredDto input)
{
var entity = await _repositoryText.FirstOrDefaultAsync(a =>
a.CultureName == input.CultureName &&
a.ResourceName == input.ResourceName &&
a.Key == input.Key);
return ObjectMapper.Map<LanguageText, LanguageTextDto>(entity);
}
protected virtual IQueryable<LanguageKey> ApplySorting(IQueryable<LanguageKey> query, LanguageTextTranslatedRequestDto input)
{
//Try to sort query if available
if (input is ISortedResultRequest sortInput)
{
if (!sortInput.Sorting.IsNullOrWhiteSpace())
{
return query.OrderBy(sortInput.Sorting);
}
}
//IQueryable.Task requires sorting, so we should sort if Take will be used.
if (input is ILimitedResultRequest)
{
return ApplyDefaultSorting(query);
}
//No sorting
return query;
}
protected virtual IQueryable<LanguageKey> ApplyDefaultSorting(IQueryable<LanguageKey> query)
{
if (typeof(LanguageKey).IsAssignableTo<IHasCreationTime>())
{
return query.OrderByDescending(e => ((IHasCreationTime)e).CreationTime);
}
throw new AbpException("No sorting specified but this query requires sorting. Override the ApplyDefaultSorting method for your application service derived from AbstractKeyReadOnlyAppService!");
}
protected virtual IQueryable<LanguageKey> ApplyPaging(IQueryable<LanguageKey> query, LanguageTextTranslatedRequestDto input)
{
//Try to use paging if available
if (input is IPagedResultRequest pagedInput)
{
return query.PageBy(pagedInput);
}
//Try to limit query result if available
if (input is ILimitedResultRequest limitedInput)
{
return query.Take(limitedInput.MaxResultCount);
}
//No paging
return query;
}
}

View file

@ -0,0 +1,13 @@
using Kurs.Languages.Localization;
using Volo.Abp.Application.Services;
namespace Kurs.Languages;
public abstract class LanguagesAppService : ApplicationService
{
protected LanguagesAppService()
{
LocalizationResource = typeof(LanguagesResource);
ObjectMapperContext = typeof(LanguagesApplicationModule);
}
}

View file

@ -0,0 +1,26 @@
using AutoMapper;
using Kurs.Languages.Entities;
using Volo.Abp.AutoMapper;
using Volo.Abp.Localization;
namespace Kurs.Languages;
public class LanguagesApplicationAutoMapperProfile : Profile
{
public LanguagesApplicationAutoMapperProfile()
{
CreateMap<Language, LanguageInfo>();
CreateMap<Language, LanguageDto>();
CreateMap<LanguageKey, LanguageKeyDto>();
CreateMap<LanguageText, LanguageTextDto>();
CreateMap<LanguageText, LanguageTextEto>();
CreateMap<LanguageTextCreateUpdateDto, LanguageText>()
.IgnoreAllPropertiesWithAnInaccessibleSetter()
.IgnoreFullAuditedObjectProperties();
CreateMap<LanguageKey, LanguageTextTranslatedDto>()
.ForMember(d => d.Key, o => o.MapFrom(s => s.Key))
.ForMember(d => d.ResourceName, o => o.MapFrom(s => s.ResourceName))
.ForAllMembers(o => o.Ignore());
}
}

View file

@ -0,0 +1,25 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Application;
using Volo.Abp.AutoMapper;
using Volo.Abp.Modularity;
namespace Kurs.Languages;
[DependsOn(
typeof(LanguagesDomainModule),
typeof(LanguagesApplicationContractsModule),
typeof(AbpDddApplicationModule),
typeof(AbpAutoMapperModule)
)]
public class LanguagesApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAutoMapperObjectMapper<LanguagesApplicationModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<LanguagesApplicationModule>(validate: true);
});
}
}

View file

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

View file

@ -0,0 +1,3 @@
{
"role": "lib.domain-shared"
}

View file

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\common.props" />
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Domain.Shared" Version="9.0.2" />
<PackageReference Include="Volo.Abp.Validation" Version="9.0.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.0" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,7 @@
namespace Kurs.Languages;
public static class LanguagesConsts
{
public const string AppName = "Languages";
}

View file

@ -0,0 +1,34 @@
using Kurs.Languages.Localization;
using Volo.Abp.Domain;
using Volo.Abp.Localization;
using Volo.Abp.Localization.ExceptionHandling;
using Volo.Abp.Modularity;
using Volo.Abp.Validation;
using Volo.Abp.VirtualFileSystem;
namespace Kurs.Languages;
[DependsOn(
typeof(AbpValidationModule),
typeof(AbpDddDomainSharedModule)
)]
public class LanguagesDomainSharedModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<LanguagesDomainSharedModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources.Add<LanguagesResource>("en");
});
Configure<AbpExceptionLocalizationOptions>(options =>
{
options.MapCodeNamespace("Languages", typeof(LanguagesResource));
});
}
}

View file

@ -0,0 +1,6 @@
namespace Kurs.Languages;
public static class LanguagesErrorCodes
{
//Add your business exception error codes here...
}

View file

@ -0,0 +1,44 @@
namespace Kurs.Languages.Languages
{
public static class LanguageCodes
{
public const string Ar = "ar";
public const string Cs = "cs";
public const string De = "de-DE";
public const string En = "en";
public const string Es = "es";
public const string Fi = "fi";
public const string Fr = "fr";
public const string Hi = "hi";
public const string Hr = "hr";
public const string Hu = "hu";
public const string It = "it";
public const string Pt = "pt-BR";
public const string Ru = "ru";
public const string Sk = "sk";
public const string Sl = "sl";
public const string Tr = "tr";
public const string Zh = "zh-Hans";
}
public static class LanguageNames
{
public const string Ar = "العربية";
public const string Cs = "Čeština";
public const string De = "Deutsch";
public const string En = "English";
public const string Es = "Español";
public const string Fi = "Finnish";
public const string Fr = "Français";
public const string Hi = "Hindi";
public const string Hr = "Croatian";
public const string Hu = "Magyar";
public const string It = "Italiano";
public const string Pt = "Português";
public const string Ru = "Русский";
public const string Sk = "Slovak";
public const string Sl = "Slovenščina";
public const string Tr = "Türkçe";
public const string Zh = "繁體中文";
}
}

View file

@ -0,0 +1,9 @@
using Volo.Abp.Localization;
namespace Kurs.Languages.Localization;
[LocalizationResourceName(LanguagesConsts.AppName)]
public class LanguagesResource
{
}

View file

@ -0,0 +1,17 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
namespace Kurs.Languages.Entities;
public class Language : FullAuditedEntity<Guid>
{
public string CultureName { get; set; }
public string UiCultureName { get; set; }
public string DisplayName { get; set; }
public bool IsEnabled { get; set; }
public string TwoLetterISOLanguageName { get; set; }
/// <summary> multiple select icin test amacli olarak eklendi
/// </summary>
public string MultipleCultures { get; set; }
}

View file

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Domain.Entities.Auditing;
namespace Kurs.Languages.Entities;
public class LanguageKey : FullAuditedEntity<Guid>
{
public string Key { get; set; }
public string ResourceName { get; set; }
public ICollection<LanguageText> Texts { get; set; }
}

View file

@ -0,0 +1,13 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
namespace Kurs.Languages.Entities;
public class LanguageText : FullAuditedEntity<Guid>
{
public string CultureName { get; set; }
public string? Key { get; set; }
public string Value { get; set; }
public string? ResourceName { get; set; }
}

View file

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

View file

@ -0,0 +1,3 @@
{
"role": "lib.domain"
}

View file

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\common.props" />
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<RootNamespace>Kurs.Languages</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="9.0.2" />
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="9.0.2" />
<ProjectReference Include="..\Kurs.Languages.Domain.Shared\Kurs.Languages.Domain.Shared.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,9 @@
using System.Collections.Generic;
using Volo.Abp.Localization;
namespace Kurs.Languages;
public class LanguageListCacheItem
{
public IReadOnlyList<LanguageInfo> Languages { get; set; }
}

View file

@ -0,0 +1,17 @@
using System.Collections.Generic;
namespace Kurs.Languages;
public class LanguageTextCacheItem : object
{
public Dictionary<string, string> Dictionary { get; set; }
public LanguageTextCacheItem()
{ }
public static string CalculateCacheKey(string resourceName, string cultureName)
{
// .en.Kurs.Dynamics
return $".{cultureName}.{resourceName}";
}
}

View file

@ -0,0 +1,28 @@
using System.Threading.Tasks;
using Kurs.Languages.Entities;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.EventBus;
namespace Kurs.Languages;
public class LanguageTextCacheItemInvalidator :
ILocalEventHandler<EntityChangedEventData<LanguageText>>,
ITransientDependency
{
private readonly IDistributedCache<LanguageTextCacheItem> cache;
public LanguageTextCacheItemInvalidator(IDistributedCache<LanguageTextCacheItem> cache)
{
this.cache = cache;
}
public async Task HandleEventAsync(EntityChangedEventData<LanguageText> eventData)
{
//distributedCacheOptions.Value.KeyPrefix
var key = LanguageTextCacheItem.CalculateCacheKey(eventData.Entity.ResourceName, eventData.Entity.CultureName);
await cache.RemoveAsync(key);
return;
}
}

View file

@ -0,0 +1,77 @@
using Kurs.Languages.Entities;
using System;
using System.Threading.Tasks;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.EventBus.Distributed;
namespace Kurs.Languages;
public class LanguageTextCacheItemInvalidatorDistributed :
IDistributedEventHandler<EntityCreatedEto<LanguageTextEto>>,
IDistributedEventHandler<EntityUpdatedEto<LanguageTextEto>>,
IDistributedEventHandler<EntityDeletedEto<LanguageTextEto>>,
ITransientDependency
{
private readonly IRepository<LanguageText, Guid> languageTextRepository;
private readonly IDistributedCache<LanguageTextCacheItem> cache;
public LanguageTextCacheItemInvalidatorDistributed(
IRepository<LanguageText, Guid> languageTextRepository,
IDistributedCache<LanguageTextCacheItem> cache)
{
this.languageTextRepository = languageTextRepository;
this.cache = cache;
}
public async Task HandleEventAsync(EntityCreatedEto<LanguageTextEto> eventData)
{
await InvalidateCacheAsync(eventData.Entity);
}
public async Task HandleEventAsync(EntityUpdatedEto<LanguageTextEto> eventData)
{
await InvalidateCacheAsync(eventData.Entity);
}
public async Task HandleEventAsync(EntityDeletedEto<LanguageTextEto> eventData)
{
await InvalidateCacheAsync(eventData.Entity);
}
private async Task InvalidateCacheAsync(LanguageTextEto eventData)
{
var key = LanguageTextCacheItem.CalculateCacheKey(eventData.ResourceName, eventData.CultureName);
await cache.RemoveAsync(key);
}
}
public class LanguageTextEto
{
public string CultureName { get; set; }
public string ResourceName { get; set; }
}
// For distributed event bus
//private void ConfigureDistributedEventBus()
//{
// Configure<AbpDistributedEntityEventOptions>(options =>
// {
// //Enable for all entities
// //options.AutoEventSelectors.AddAll();
// //Enable for a single entity
// options.AutoEventSelectors.Add<LanguageText>();
// options.EtoMappings.Add<LanguageText, LanguageTextEto>();
// //Enable for all entities in a namespace (and child namespaces)
// //options.AutoEventSelectors.AddNamespace("MyProject.Products");
// //Custom predicate expression that should return true to select a type
// //options.AutoEventSelectors.Add(type => type.Namespace.StartsWith("MyProject."));
// });
//}

View file

@ -0,0 +1,10 @@
namespace Kurs.Languages;
public static class LanguagesDbProperties
{
public static string DbTablePrefix { get; set; } = "P";
public static string? DbSchema { get; set; } = null;
public const string ConnectionStringName = "Languages";
}

View file

@ -0,0 +1,24 @@
using Kurs.Languages.Localization;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.Domain;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace Kurs.Languages;
[DependsOn(
typeof(AbpDddDomainModule),
typeof(AbpLocalizationModule),
typeof(AbpCachingStackExchangeRedisModule),
typeof(LanguagesDomainSharedModule)
)]
public class LanguagesDomainModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpLocalizationOptions>(options =>
{
options.GlobalContributors.Add<DatabaseLocalizationResourceContributor>();
});
}
}

View file

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Kurs.Languages.Entities;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Localization;
namespace Kurs.Languages.Localization;
[Dependency(ReplaceServices = true)]
public class DatabaseLanguageProvider : ILanguageProvider, ITransientDependency
{
private readonly IReadOnlyBasicRepository<Language, Guid> languageRepository;
private readonly IDistributedCache<LanguageListCacheItem> cache;
public const string CacheKey = "Languages";
public DatabaseLanguageProvider(
IReadOnlyBasicRepository<Language, Guid> languageRepository,
IDistributedCache<LanguageListCacheItem> cache)
{
this.languageRepository = languageRepository;
this.cache = cache;
}
public async Task<IReadOnlyList<LanguageInfo>> GetLanguagesAsync()
{
var langs = await cache.GetOrAddAsync(CacheKey, GetLanguagesFromDB);
return langs.Languages;
}
private async Task<LanguageListCacheItem> GetLanguagesFromDB()
{
var langs = await languageRepository.GetListAsync();
return new LanguageListCacheItem
{
Languages = langs.OrderBy(o => o.DisplayName)
.Select(a => new LanguageInfo(a.CultureName, a.UiCultureName, a.DisplayName))
.ToList()
};
}
}

View file

@ -0,0 +1,45 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Volo.Abp.Localization;
namespace Kurs.Languages.Localization;
public class DatabaseLocalizationResourceContributor : ILocalizationResourceContributor
{
private LocalizationResourceBase _resource;
private IDatabaseResourceLocalizer _databaseResourceLocalizer;
private ILanguageProvider _languageProvider;
public bool IsDynamic => false;
public void Initialize(LocalizationResourceInitializationContext context)
{
_resource = context.Resource;
_databaseResourceLocalizer = context.ServiceProvider.GetRequiredService<IDatabaseResourceLocalizer>();
_languageProvider = context.ServiceProvider.GetRequiredService<ILanguageProvider>();
}
public LocalizedString GetOrNull(string cultureName, string name)
{
return _databaseResourceLocalizer.GetOrNull(_resource, cultureName, name);
}
public async Task FillAsync(string cultureName, Dictionary<string, LocalizedString> dictionary)
{
await _databaseResourceLocalizer.FillAsync(_resource, cultureName, dictionary);
}
public void Fill(string cultureName, Dictionary<string, LocalizedString> dictionary)
{
_databaseResourceLocalizer.Fill(_resource, cultureName, dictionary);
}
public async Task<IEnumerable<string>> GetSupportedCulturesAsync()
{
var langs = await _languageProvider.GetLanguagesAsync();
return langs.Select(a => a.CultureName).ToList();
}
}

View file

@ -0,0 +1,89 @@
using Kurs.Languages.Entities;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Localization;
using Volo.Abp.Threading;
namespace Kurs.Languages.Localization;
public class DatabaseResourceLocalizer : IDatabaseResourceLocalizer, ISingletonDependency
{
private readonly IRepository<LanguageText, Guid> languageTextRepository;
private readonly IDistributedCache<LanguageTextCacheItem> cache;
public DatabaseResourceLocalizer(
IRepository<LanguageText, Guid> languageTextRepository,
IDistributedCache<LanguageTextCacheItem> cache)
{
this.languageTextRepository = languageTextRepository;
this.cache = cache;
}
public LocalizedString GetOrNull(LocalizationResourceBase resource, string cultureName, string name)
{
var item = GetCacheItem(resource, cultureName);
var value = item.Dictionary?.GetOrDefault(name);
if (item == null || value == null)
{
return null;
}
return new LocalizedString(name, value);
}
protected LanguageTextCacheItem GetCacheItem(LocalizationResourceBase resource, string cultureName)
{
// culture, resource, key
var key = LanguageTextCacheItem.CalculateCacheKey(resource.ResourceName, cultureName);
return cache.GetOrAdd(key, () => CreateCacheItem(resource, cultureName));
}
public void Fill(LocalizationResourceBase resource, string cultureName, Dictionary<string, LocalizedString> dictionary)
{
var item = GetCacheItem(resource, cultureName);
foreach (var kvp in item.Dictionary)
{
dictionary[kvp.Key] = new LocalizedString(kvp.Key, kvp.Value);
}
}
protected virtual LanguageTextCacheItem CreateCacheItem(LocalizationResourceBase resource, string cultureName)
{
//TODO VT'den textleri alip cache'e dolduran kismi yazalim
//TODO:SÖ
var task = languageTextRepository.GetListAsync(a => a.ResourceName == resource.ResourceName && a.CultureName == cultureName);
var texts = AsyncHelper.RunSync(() => task);
return new LanguageTextCacheItem
{
Dictionary = texts.ToDictionary(a => a.Key, a => a.Value)
};
}
public async Task FillAsync(LocalizationResourceBase resource, string cultureName, Dictionary<string, LocalizedString> dictionary)
{
var key = LanguageTextCacheItem.CalculateCacheKey(resource.ResourceName, cultureName);
var item = await cache.GetOrAddAsync(key, () => CreateCacheItemAsync(resource, cultureName));
foreach (var kvp in item.Dictionary)
{
dictionary[kvp.Key] = new LocalizedString(kvp.Key, kvp.Value);
}
}
protected virtual async Task<LanguageTextCacheItem> CreateCacheItemAsync(LocalizationResourceBase resource, string cultureName)
{
var texts = await languageTextRepository.GetListAsync(a => a.ResourceName == resource.ResourceName && a.CultureName == cultureName);
return new LanguageTextCacheItem
{
Dictionary = texts.ToDictionary(a => a.Key, a => a.Value)
};
}
}

View file

@ -0,0 +1,13 @@
using Microsoft.Extensions.Localization;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Localization;
namespace Kurs.Languages.Localization;
public interface IDatabaseResourceLocalizer
{
void Fill(LocalizationResourceBase resource, string cultureName, Dictionary<string, LocalizedString> dictionary);
Task FillAsync(LocalizationResourceBase resource, string cultureName, Dictionary<string, LocalizedString> dictionary);
LocalizedString GetOrNull(LocalizationResourceBase resource, string cultureName, string name);
}

View file

@ -0,0 +1,12 @@
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
namespace Kurs.Languages.EntityFrameworkCore;
[ConnectionStringName(LanguagesDbProperties.ConnectionStringName)]
public interface ILanguagesDbContext : IEfCoreDbContext
{
/* Add DbSet for each Aggregate Root here. Example:
* DbSet<Question> Questions { get; }
*/
}

View file

@ -0,0 +1,27 @@
using Kurs.Languages.Entities;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
namespace Kurs.Languages.EntityFrameworkCore;
[ConnectionStringName(LanguagesDbProperties.ConnectionStringName)]
public class LanguagesDbContext : AbpDbContext<LanguagesDbContext>, ILanguagesDbContext
{
public DbSet<Language> Languages { get; set; }
public DbSet<LanguageKey> LanguageKeys { get; set; }
public DbSet<LanguageText> LanguageTexts { get; set; }
public LanguagesDbContext(DbContextOptions<LanguagesDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ConfigureLanguages();
}
}

View file

@ -0,0 +1,50 @@
using Kurs.Languages.Entities;
using Microsoft.EntityFrameworkCore;
using Volo.Abp;
using Volo.Abp.EntityFrameworkCore.Modeling;
namespace Kurs.Languages.EntityFrameworkCore;
public static class LanguagesDbContextModelCreatingExtensions
{
public static void ConfigureLanguages(
this ModelBuilder builder)
{
Check.NotNull(builder, nameof(builder));
builder.Entity<Language>(b =>
{
b.ToTable(LanguagesDbProperties.DbTablePrefix + nameof(Language), LanguagesDbProperties.DbSchema);
b.ConfigureByConvention();
b.Property(a => a.CultureName).HasMaxLength(10).IsRequired();
b.Property(a => a.UiCultureName).HasMaxLength(10).IsRequired();
b.Property(a => a.DisplayName).HasMaxLength(50).IsRequired();
});
builder.Entity<LanguageKey>(b =>
{
b.ToTable(LanguagesDbProperties.DbTablePrefix + nameof(LanguageKey), LanguagesDbProperties.DbSchema);
b.ConfigureByConvention();
b.HasKey(a => new { a.ResourceName, a.Key });
b.HasMany(a => a.Texts).WithOne()
.HasForeignKey(a => new { a.ResourceName, a.Key })
.OnDelete(DeleteBehavior.SetNull);
b.Property(a => a.Key).HasMaxLength(100).IsRequired();
b.Property(a => a.ResourceName).HasMaxLength(50).IsRequired();
});
builder.Entity<LanguageText>(b =>
{
b.ToTable(LanguagesDbProperties.DbTablePrefix + nameof(LanguageText), LanguagesDbProperties.DbSchema);
b.ConfigureByConvention();
b.Property(a => a.CultureName).HasMaxLength(10).IsRequired();
b.Property(a => a.ResourceName).HasMaxLength(50);
b.Property(a => a.Key).HasMaxLength(100);
b.Property(a => a.Value).HasMaxLength(250).IsRequired();
});
}
}

View file

@ -0,0 +1,23 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;
namespace Kurs.Languages.EntityFrameworkCore;
[DependsOn(
typeof(LanguagesDomainModule),
typeof(AbpEntityFrameworkCoreModule)
)]
public class LanguagesEntityFrameworkCoreModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAbpDbContext<LanguagesDbContext>(options =>
{
/* Add custom repositories here. Example:
* options.AddRepository<Question, EfCoreQuestionRepository>();
*/
options.AddDefaultRepositories(includeAllEntities: true);
});
}
}

View file

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

View file

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\common.props" />
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<RootNamespace>Kurs.Languages</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="9.0.2" />
<ProjectReference Include="..\Kurs.Languages.Domain\Kurs.Languages.Domain.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,24 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>0.1.0</Version>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<AbpProjectType>module</AbpProjectType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ConfigureAwait.Fody" Version="3.3.1" PrivateAssets="All" />
<PackageReference Include="Fody" Version="6.5.3">
<PrivateAssets>All</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
<Target Name="NoWarnOnRazorViewImportedTypeConflicts" BeforeTargets="RazorCoreCompile">
<PropertyGroup>
<NoWarn>$(NoWarn);0436</NoWarn>
</PropertyGroup>
</Target>
</Project>

View file

@ -0,0 +1,13 @@
using Kurs.MailQueue.Domain.Shared;
using Volo.Abp.Application.Services;
namespace Kurs.MailQueue.Application;
public abstract class MailQueueAppService : ApplicationService
{
protected MailQueueAppService()
{
LocalizationResource = typeof(KursMailQueueResource);
ObjectMapperContext = typeof(KursMailQueueModule);
}
}

View file

@ -0,0 +1,12 @@
using AutoMapper;
namespace Kurs.MailQueue.Application;
public class MailQueueAutoMapperProfile : Profile
{
public MailQueueAutoMapperProfile()
{
}
}

View file

@ -0,0 +1,8 @@
using Volo.Abp.Localization;
namespace Kurs.MailQueue.Domain.Shared;
[LocalizationResourceName(MailQueueConsts.AppName)]
public class KursMailQueueResource
{
}

View file

@ -0,0 +1,7 @@
namespace Kurs.MailQueue.Domain.Shared;
public static class MailQueueConsts
{
public const string AppName = "MailQueue";
}

View file

@ -0,0 +1,9 @@
namespace Kurs.MailQueue.Domain.Shared;
public class MailQueueWorkerOptions
{
public string MailType { get; set; } // Template Tipi
public string MailSubject { get; set; } // Mail konusu
public string MailTemplate { get; set; } // Render edilecek html template
public string Tablo { get; set; } // Bu maildeki tablolar örn. {0:MT3_GECIKEN_SIPARIS:IN:Order Delay Notification:0:}
}

View file

@ -0,0 +1,34 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Volo.Abp.Domain.Entities.Auditing;
namespace Kurs.MailQueue.Domain.Entities;
public class BackgroundWorker_MailQueue : FullAuditedEntity<Guid>
{
public Guid TemplateId { get; set; }
[Required]
[StringLength(100)]
public string From { get; set; }
[Required]
[StringLength(100)]
public string To { get; set; }
[StringLength(8000)]
public string MailParameter { get; set; } //{0:KURYE=FEDEX&ABWNO=777705877048}
[StringLength(100)]
public string Table { get; set; }
[StringLength(500)]
public string TableParameter { get; set; }
[StringLength(100)]
public string Attachment { get; set; }
[StringLength(500)]
public string AttachmentParameter { get; set; }
public bool SendStatus { get; set; } // Mail gönderildi mi, vs
// [Column(TypeName = "datetime")]
public DateTime? SendTime { get; set; } // Gönderim zamanı
[StringLength(100)]
public string AwsMessageId { get; set; } // AWS'ten gelen response
[StringLength(100)]
public string RelatedRecordId { get; set; } // İlgili kaydın ID'si
}

View file

@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Volo.Abp.Domain.Entities.Auditing;
namespace Kurs.MailQueue.Domain.Entities;
public partial class BackgroundWorker_MailQueueEvents : FullAuditedEntity<Guid>
{
[Required]
[StringLength(100)]
public string AwsMessageId { get; set; }
// [Column(TypeName = "datetime")]
public DateTime? EventDate { get; set; }
[StringLength(20)]
public string Event { get; set; }
[StringLength(100)]
public string MailAddress { get; set; }
public string ResponseDescription { get; set; }
}

View file

@ -0,0 +1,33 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Entities;
namespace Kurs.MailQueue.Domain.Entities;
[Index(nameof(TableName), nameof(Order), Name = "IX_MailQueueTableFormat", IsUnique = true)]
public partial class BackgroundWorker_MailQueueTableFormat : Entity<int>
{
[Required]
[StringLength(100)]
public string TableName { get; set; }
public short Order { get; set; }
[StringLength(50)]
public string ColumnName { get; set; }
[StringLength(50)]
public string Caption { get; set; }
[StringLength(1000)]
public string HeaderCss { get; set; }
[StringLength(1000)]
public string Css { get; set; }
[StringLength(1000)]
public string FooterCss { get; set; }
[StringLength(50)]
public string DataType { get; set; }
[StringLength(50)]
public string DataFormat { get; set; }
public bool IsHidden { get; set; }
public bool IsProtected { get; set; } // Excel'deki sutun korumali mi olacak?
[StringLength(50)]
public string SubTotal { get; set; }
public int Width { get; set; }
}

View file

@ -0,0 +1,42 @@
using Microsoft.Extensions.Logging;
using Volo.Abp.Domain.Services;
namespace Kurs.MailQueue.Domain;
public interface ILogManager : IDomainService
{
void Log(
LogLevel logTipi,
string logDetayi,
string kategori = null,
string kayitTipi = null,
Guid? kayitId = null,
string jobId = null);
void LogInformation(string logDetayi, string kategori = null, string kayitTipi = null, Guid? kayitId = null, string jobId = null);
void LogError(string logDetayi, string kategori = null, string kayitTipi = null, Guid? kayitId = null, string jobId = null);
void LogWarning(string logDetayi, string kategori = null, string kayitTipi = null, Guid? kayitId = null, string jobId = null);
}
public class NullLogManager : DomainService, ILogManager
{
public NullLogManager()
{
}
public void Log(
LogLevel logTipi,
string logDetayi,
string kategori = null,
string kayitTipi = null,
Guid? kayitId = null,
string jobId = null)
{
Logger.Log(logTipi, logDetayi);
}
public void LogInformation(string logDetayi, string kategori = null, string kayitTipi = null, Guid? kayitId = null, string jobId = null) => Log(LogLevel.Information, logDetayi, kategori, kayitTipi, kayitId, jobId);
public void LogError(string logDetayi, string kategori = null, string kayitTipi = null, Guid? kayitId = null, string jobId = null) => Log(LogLevel.Error, logDetayi, kategori, kayitTipi, kayitId, jobId);
public void LogWarning(string logDetayi, string kategori = null, string kayitTipi = null, Guid? kayitId = null, string jobId = null) => Log(LogLevel.Warning, logDetayi, kategori, kayitTipi, kayitId, jobId);
}

View file

@ -0,0 +1,63 @@
using Kurs.MailQueue.MailGeneration.Models;
using Volo.Abp.DependencyInjection;
namespace Kurs.MailQueue.Domain.MailGeneration;
public interface IAttachmentExtractor
{
IList<AttachmentModel> Extract(string attachment, string attachmentParametre);
}
public class AttachmentExtractor : IAttachmentExtractor, ITransientDependency
{
protected readonly IParameterExtractor ParameterExtractor;
public AttachmentExtractor(
IParameterExtractor parameterExtractor)
{
ParameterExtractor = parameterExtractor;
}
public IList<AttachmentModel> Extract(string attachment, string attachmentParametre)
{
var result = new List<AttachmentModel>();
if (attachment.IsNullOrWhiteSpace())
return result;
var parameters = ParameterExtractor.Extract(attachmentParametre);
/*
Dict<
0, Dict<
Tarih, 1232
No 4334
>
1, Dict<
QUERY, ghghg
QUERYSQL select ffddf
*/
//Attachment:
//{0:MRP:rpt_DepoCikisCekiListesi:PDF:MailEkteGozukecekAd};{1:CRM:rpt_DepoCikisCekiListesiCarpet:XLS:MailEkteGozukecekAd}
//AttachmentParametre:
//Filtre değerleri olabilir {0:Tarih=1232&No=4334};{1:Tarih=213}
//Veya query olabilir {0:QUERY=…&QUERYSQL=..};{1:QUERY=…&QUERYSQL=..}
foreach (var item in attachment.Split("};{"))
{
var keyValue = item.Trim('{').Trim('}').Split(":");
if (keyValue.Length == 5)
{
result.Add(new AttachmentModel
{
Index = keyValue[0],
DbAdi = keyValue[1],
RaporAdi = keyValue[2],
ExportDosyaTipi = keyValue[3],
Filtreler = parameters.GetOrDefault(keyValue[0]),
MailEkAdi = keyValue[4]
});
}
}
return result;
}
}

View file

@ -0,0 +1,43 @@
using Volo.Abp.DependencyInjection;
namespace Kurs.MailQueue.Domain.MailGeneration;
public interface ICssExtractor
{
Dictionary<string, string> Extract(string text);
}
public class CssExtractor : ICssExtractor, ITransientDependency
{
//color: #FFF;background-color:#000;
// color=#FFF
// background-color=#000
public Dictionary<string, string> Extract(string text)
{
if (text.IsNullOrWhiteSpace())
return null;
var values = new Dictionary<string, string>();
try
{
foreach (var css in text.Split(";", StringSplitOptions.RemoveEmptyEntries))
{
var rule = css.Split(":", StringSplitOptions.RemoveEmptyEntries);
if (rule.Length == 2)
{
var key = rule[0].Trim();
var value = rule[1].Trim();
if (values.ContainsKey(key))
values.Add(key, value);
else
values[key] = value;
}
}
}
catch (Exception)
{
}
return values;
}
}

View file

@ -0,0 +1,79 @@
using Volo.Abp.DependencyInjection;
namespace Kurs.MailQueue.Domain.MailGeneration;
public interface IParameterExtractor
{
Dictionary<string, Dictionary<string, string>> Extract(string text);
}
public class ParameterExtractor : IParameterExtractor, ITransientDependency
{
//{0:FISID=xyz&TARIH=12321};{1:FISID=abc&TARIH=32121}
// [0]=> FISID=xyz,TARIH=12321
// [1]=> FISID=abc,TARIH=32121
public Dictionary<string, Dictionary<string, string>> Extract(string text)
{
return ExtractPart(text)
.Select(a => ExtractParameters(a))
.Where(a => a.HasValue)
.Select(a => a.Value)
.ToDictionary(x => x.Key, x => x.Value);
}
/*
0=>{FISID=xyz&TARIH=12321}
0.0=>FISID=xyz
0.1=>TARIH=12321
1=>{FISID=xyz&TARIH=12321}
1.0=>FISID=xyz
1.1=>TARIH=12321
*/
//{0:FISID=xyz&TARIH=12321};{1:FISID=xyz&TARIH=12321}
// [0] => 0:FISID=xyz&TARIH=12321, [1] => 1:FISID=xyz&TARIH=12321
//{x=1};{y=2};{z=3}
// [0] => x=1, [1] => y=2, [2] => z=3
private List<string> ExtractPart(string text)
{
return text?
.Split("};{")
.Select(a => a.Trim('{').Trim('}'))
.ToList() ?? new List<string>();
}
//2:FISID=xyz&TARIH=12321
// 2 => List([0] => FISID=xyz, [1] => TARIH=12321)
private KeyValuePair<string, Dictionary<string, string>>? ExtractParameters(string text)
{
if (text.IsNullOrWhiteSpace())
return null;
var index = "0";
if (text.Contains(":"))
{
index = text.Substring(0, text.IndexOf(':'));
text = text.Substring(text.IndexOf(':') + 1);
}
var values = text
.Split("&")?
.Select(a => ExtractKeyValue(a))
.Where(a => a.HasValue)
.Select(a => a.Value)
.ToDictionary(x => x.Key, x => x.Value);
return new KeyValuePair<string, Dictionary<string, string>>(index, values);
}
//x=1
// [x] => 1
private KeyValuePair<string, string>? ExtractKeyValue(string text)
{
var keyValue = text?.Split("=");
if (keyValue != null && keyValue.Length == 2)
return new KeyValuePair<string, string>(keyValue[0], keyValue[1]);
return null;
}
}

View file

@ -0,0 +1,48 @@
using Kurs.MailQueue.MailGeneration.Models;
using Volo.Abp.DependencyInjection;
namespace Kurs.MailQueue.Domain.MailGeneration;
public interface ITableExtractor
{
IList<MailTemplateTableModel> Extract(string text, string parameters);
}
public class TableExtractor : ITableExtractor, ITransientDependency
{
public IParameterExtractor ParameterExtractor { get; }
public TableExtractor(IParameterExtractor parameterExtractor)
{
ParameterExtractor = parameterExtractor;
}
public IList<MailTemplateTableModel> Extract(string text, string parameters)
{
var result = new List<MailTemplateTableModel>();
if (text.IsNullOrWhiteSpace())
return result;
var parametreler = ParameterExtractor.Extract(parameters);
//{0:MT3_GECIKEN_SIPARIS:IN:DosyaAdi;0:};{1:MT7_SIPARIS_DURUM:PDF:DosyaAdi.pdf:0:BRU,3,1}
foreach (var item in text.Split("};{"))
{
var keyValue = item.Trim('{').Trim('}').Split(":");
if (keyValue.Length == 6)
result.Add(new MailTemplateTableModel
{
Index = keyValue[0],
TabloAdi = keyValue[1],
DosyaTipi = keyValue[2],
MailEkAdi = keyValue[3],
Korumalimi = keyValue[4],
DosyaAciklama = keyValue[5],
Parametreler = parametreler.GetOrDefault(keyValue[0])
});
}
return result;
}
}

View file

@ -0,0 +1,226 @@
using Kurs.MailQueue.FileGeneration;
using Kurs.MailQueue.MailGeneration.Models;
using Microsoft.Extensions.Configuration;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.TextTemplating;
namespace Kurs.MailQueue.Domain.MailGeneration;
public interface IAttachmentGenerator
{
Task<Dictionary<string, string>> GenerateAsync(
Guid kuyrukId,
string attachment,
string attachmentParametre,
string jobId = null);
Task<Dictionary<string, string>> GenerateAsync(List<MailTemplateTableModel> tables, Guid? kuyrukId = null, string jobId = null);
}
public class AttachmentGenerator : IAttachmentGenerator, ITransientDependency
{
public IParameterExtractor ParameterExtractor { get; }
public IAttachmentExtractor AttachmentExtractor { get; }
public ITemplateRenderer TemplateRenderer { get; }
public IGuidGenerator GuidGenerator { get; }
public IServiceProvider ServiceProvider { get; }
protected ILogManager LogManager { get; }
private readonly IConfiguration Configuration;
public AttachmentGenerator(
IAttachmentExtractor attachmentExtractor,
ITemplateRenderer templateRenderer,
IGuidGenerator guidGenerator,
IServiceProvider serviceProvider,
ILogManager logManager,
IConfiguration configuration
)
{
AttachmentExtractor = attachmentExtractor;
TemplateRenderer = templateRenderer;
GuidGenerator = guidGenerator;
ServiceProvider = serviceProvider;
LogManager = logManager;
Configuration = configuration;
}
/// <summary>
/// Verilen parametreler (attachment parametreleri) ile KIM raporlari ile istenilen formatta dosya uretir
/// </summary>
/// <param name="attachment">Export edilecek olan attachmentlar</param>
/// <param name="attachmentParametre">Her attachment için parametreler</param>
/// <returns>Uretilen ekleri Key: MailEkAdi, Value: Base64 encode edilmis dosya olan dictionary olarak döner</returns>
public async Task<Dictionary<string, string>> GenerateAsync(
Guid kuyrukId,
string attachment,
string attachmentParametre,
string jobId)
{
var result = new Dictionary<string, string>();
var models = AttachmentExtractor.Extract(attachment, attachmentParametre);
var attachmentFolder = $"{kuyrukId}-{jobId}";
foreach (var item in models)
{
var file = GenerateAttachment(item, attachmentFolder);
if (file.IsNullOrEmpty())
{
LogManager.LogError($"Attachment oluşturulamadı. Index: {item.Index}", "ATTACHMENT", "KUYRUK", kuyrukId, jobId);
continue;
}
var base64 = await ConvertFileToBase64Async(file);
var key = item.MailEkAdi;
if (result.ContainsKey(key))
{
key = result.Count + "-" + item.MailEkAdi;
}
result.Add(key, base64);
}
return result;
}
/// <summary>
/// Verilan tablo modeli ile istenilen dosya tipinde (PDF, XLS, TXT) ek üretir
/// </summary>
/// <param name="tables">Tablo modeli listesi</param>
/// <returns>Uretilen ekleri Key: MailEkAdi, Value: Base64 encode edilmis dosya olan dictionary olarak döner</returns>
public async Task<Dictionary<string, string>> GenerateAsync(List<MailTemplateTableModel> tables, Guid? kuyrukId = null, string jobId = null)
{
var attachments = new Dictionary<string, string>();
foreach (var table in tables.Where(a => a.DosyaTipi != "IN"))
{
IFileGenerator fileGenerator = null;
switch (table.DosyaTipi)
{
case "PDF":
fileGenerator = (IFileGenerator)ServiceProvider.GetService(typeof(PDFFileGenerator));
break;
case "XLS":
fileGenerator = (IFileGenerator)ServiceProvider.GetService(typeof(XLSFileGenerator));
break;
case "TXT":
fileGenerator = (IFileGenerator)ServiceProvider.GetService(typeof(TXTFileGenerator));
break;
default:
break;
}
if (fileGenerator == null)
{
LogManager.LogError($"File Generator oluşturulamadı. Index: {table.Index}, Dosya Tipi: {table.DosyaTipi}", "ATTACHMENT-TABLO", "KUYRUK", kuyrukId, jobId);
continue;
}
try
{
var attachment = await fileGenerator.Generate(table);
if (kuyrukId.HasValue)
{
LogToFile(kuyrukId.Value, attachment, table.MailEkAdi);
}
var base64 = Convert.ToBase64String(attachment);
attachments.Add(table.MailEkAdi, base64);
}
catch (Exception ex)
{
LogManager.LogError($"Dosya oluşturulamadı. Index: {table.Index}. {ex}", "ATTACHMENT-TABLO", "KUYRUK", kuyrukId, jobId);
continue;
}
}
return attachments;
}
private string GenerateAttachment(AttachmentModel model, string attachmentFolder)
{
if (model.Filtreler.IsNullOrEmpty() || model.RaporAdi.IsNullOrWhiteSpace())
{
return null;
}
return null;
// if (model.Filtreler.ContainsKey("QUERY") && model.Filtreler.ContainsKey("QUERYSQL"))
// {
// /*
//Parametrelerden asagidaki sekilde gelen queryleri en alttaki formata donusturuyoruz
//params
//0 =>
// QUERY -> qryDepo_Cikis_CekiListesi_Detayli
// QUERYSQL -> Ksp_Depo_Cikis_CekiListesi_Detayli 252993
// QUERY2 -> qryDepo_Cikis_CekiListesi_Sub
// QUERY2SQL -> KSp_Depo_Cikis_CekiListesi_Sub 252993
//SQL olan keyvalue'lari cikar ve sadece querylerde foreach yap
// QUERY -> qryDepo_Cikis_CekiListesi_Detayli
// dict.add(item.Value, params[item.Key + "SQL"].Value)
// QUERY2 -> qryDepo_Cikis_CekiListesi_Sub
// dict.add(item.Value, params[item.Key + "SQL"].Value)
//Bunlari yeni dict'e ekle
//dict
//qryDepo_Cikis_CekiListesi_Detayli -> Ksp_Depo_Cikis_CekiListesi_Detayli 252993
//qryDepo_Cikis_CekiListesi_Sub -> KSp_Depo_Cikis_CekiListesi_Sub 252993
// */
// //dict -> key (name), value (sql)
// var queries = model.Filtreler
// .Where(a => a.Key.StartsWith("QUERY"))
// .Where(a => !a.Key.EndsWith("SQL"))
// .Where(a => !a.Value.IsNullOrWhiteSpace())
// .ToDictionary(x => x.Value, x => model.Filtreler.GetValueOrDefault(x.Key + "SQL"));
// return MsAccessReportManager.GenerateAccessReport(
// model.DbAdi,
// model.Index,
// model.RaporAdi,
// model.ExportDosyaTipi,
// queries,
// attachmentFolder);
// }
// else
// {
// return MsAccessReportManager.GenerateAccessReport(
// model.DbAdi,
// model.Index,
// model.RaporAdi,
// string.Join(" AND ", model.Filtreler.Select(a => $"{a.Key}={a.Value}")),
// model.ExportDosyaTipi,
// attachmentFolder);
// }
}
private async Task<string> ConvertFileToBase64Async(string filePath)
{
var bytes = await File.ReadAllBytesAsync(filePath);
return Convert.ToBase64String(bytes);
}
private void LogToFile(Guid id, byte[] content, string fileName)
{
if (!Configuration.GetValue<bool>("App:LogMailToFile"))
{
return;
}
var path = Configuration.GetValue<string>("App:AttachmentsPath");
if (path.IsNullOrWhiteSpace())
{
return;
}
path = Path.Combine(path, id.ToString());
try
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
File.WriteAllBytes(Path.Combine(path, fileName), content);
}
catch
{
LogManager.LogError($"Dosya diske kaydedilemedi. Yol:{path}, Dosya: {fileName}", "ATTACHMENT-TABLO", "KUYRUK", id);
}
}
}

View file

@ -0,0 +1,103 @@
using Kurs.MailQueue.MailGeneration.Models;
using Microsoft.Extensions.Configuration;
using Volo.Abp.DependencyInjection;
using Volo.Abp.TextTemplating;
namespace Kurs.MailQueue.Domain.MailGeneration;
public interface IMailBodyGenerator
{
Task<string> GenerateAsync(
string templateName,
string mailParametreleri,
Guid kuyrukId,
Dictionary<string, MailTemplateTableModel> tablolar,
string jobId = null
);
}
public class MailBodyGenerator : IMailBodyGenerator, ITransientDependency
{
private readonly IConfiguration configuration;
public IParameterExtractor ParameterExtractor { get; }
public ITemplateRenderer TemplateRenderer { get; }
protected ILogManager LogManager { get; }
public MailBodyGenerator(
IParameterExtractor parameterExtractor,
ITemplateRenderer templateRenderer,
IConfiguration configuration,
ILogManager logManager)
{
ParameterExtractor = parameterExtractor;
TemplateRenderer = templateRenderer;
this.configuration = configuration;
LogManager = logManager;
}
/// <summary>
/// Verilen parametreler ile mail body render eder
/// </summary>
/// <param name="templateName">Render edilecek olan template adı</param>
/// <param name="mailParametreleri">Dinamik parametreler</param>
/// <returns></returns>
public async Task<string> GenerateAsync(
string templateName,
string mailParametreleri,
Guid kuyrukId,
Dictionary<string, MailTemplateTableModel> tablolar,
string jobId = null
)
{
var parametreler = ParameterExtractor.Extract(mailParametreleri);
//Mail icin 0: ile baslayan tek bir parametre grubu oldugu icin, onu aliyoruz
var model = new MailTemplateModel
{
MailParametreleri = parametreler.GetOrDefault("0"),
Tablolar = tablolar
};
try
{
var result = await TemplateRenderer.RenderAsync(templateName, model);
LogToFile(kuyrukId, result);
return result;
}
catch (Exception)
{
LogManager.LogError($"Template Render Başarısız: {templateName}", "MAILBODY", "KUYRUK", kuyrukId, jobId);
throw;
}
}
private void LogToFile(Guid id, string content)
{
if (!configuration.GetValue<bool>("App:LogMailToFile"))
{
return;
}
var path = configuration.GetValue<string>("App:AttachmentsPath");
if (path.IsNullOrWhiteSpace())
{
return;
}
path = Path.Combine(path, id.ToString());
var date = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss");
var dosyaAdi = $"mail-{id}-{date}.html ";
try
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
File.AppendAllText(Path.Combine(path, dosyaAdi), content);
}
catch
{
LogManager.LogError($"Mail diske kaydedilemedi. Yol:{path}: Dosya {dosyaAdi}", "MAILBODY", "KUYRUK", id);
}
}
}

View file

@ -0,0 +1,104 @@
using System.Data;
using Kurs.MailQueue.Domain.Entities;
using Kurs.MailQueue.EntityFrameworkCore;
using Kurs.MailQueue.MailGeneration.Models;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.TextTemplating;
namespace Kurs.MailQueue.Domain.MailGeneration;
public interface ITableGenerator
{
Task<Dictionary<string, MailTemplateTableModel>>
GenerateAsync(
string tabloTemplate,
string tabloParametreleri,
Guid kuyrukId);
}
public class TableGenerator : ITableGenerator, ITransientDependency
{
public ITableExtractor TableExtractor { get; }
public ITemplateRenderer TemplateRenderer { get; }
public IRepository<BackgroundWorker_MailQueueTableFormat> RepositoryTablo { get; }
public IQueryRepository QueryHelper { get; }
public ICssExtractor CssExtractor { get; }
public TableGenerator(
ITableExtractor tableExtractor,
ITemplateRenderer templateRenderer,
IRepository<BackgroundWorker_MailQueueTableFormat> repositoryTablo,
IQueryRepository queryHelper,
ICssExtractor cssExtractor
)
{
TableExtractor = tableExtractor;
TemplateRenderer = templateRenderer;
RepositoryTablo = repositoryTablo;
QueryHelper = queryHelper;
CssExtractor = cssExtractor;
}
/// <summary>
/// Verilen parametreler ile tablo render eder
/// </summary>
/// <param name="templateName">Render edilecek olan template adı</param>
/// <param name="mailParametreleri">Dinamik parametreler</param>
/// <returns></returns>
public async Task<Dictionary<string, MailTemplateTableModel>> GenerateAsync(string tabloTemplate, string tabloParametreleri, Guid kuyrukId)
{
var tablolar = TableExtractor.Extract(tabloTemplate, tabloParametreleri);
int i = 0;
foreach (var tablo in tablolar)
{
var query = await RepositoryTablo.GetQueryableAsync();
var sutunlar = await query.Where(a => a.TableName == tablo.TabloAdi)
.OrderBy(o => o.Order)
.ToListAsync();
var table = await QueryHelper.QueryAsync(tablo.TabloAdi, tablo.Parametreler);
tablo.TabloSutunlari = sutunlar
.Select(a => new MailTemplateTableColumnModel
{
SiraNo = a.Order,
SutunAdi = a.ColumnName,
SutunBaslik = a.Caption,
BaslikCss = CssExtractor.Extract(a.HeaderCss),
Css = CssExtractor.Extract(a.Css),
AltBilgiCss = CssExtractor.Extract(a.FooterCss),
VeriTipi = a.DataType,
VeriFormati = a.DataFormat,
Gizlimi = a.IsHidden,
Korumalimi = a.IsProtected,
AltToplam = a.SubTotal,
Genislik = a.Width
})
.ToList();
var degerler = new List<Dictionary<string, object>>();
foreach (var row in table.AsEnumerable())
{
var dict = new Dictionary<string, object>();
for (int j = 0; j < table.Columns.Count; j++)
{
var column = table.Columns[j];
dict.Add(
column.ColumnName,
row[column.ColumnName]);
}
degerler.Add(dict);
}
tablo.TabloDegerleri = degerler;
i++;
}
return tablolar.ToDictionary(
x => $"{x.DosyaTipi}{x.Index}",
x => x);
}
}

View file

@ -0,0 +1,11 @@
namespace Kurs.MailQueue.MailGeneration.Models;
public class AttachmentModel
{
public string Index { get; set; }
public string DbAdi { get; set; } //MRP.mdb, CRM.mdb
public string RaporAdi { get; set; }
public string ExportDosyaTipi { get; set; } //PDF, TXT, XLS, ..
public Dictionary<string, string> Filtreler { get; set; }
public string MailEkAdi { get; set; }
}

View file

@ -0,0 +1,8 @@
namespace Kurs.MailQueue.MailGeneration.Models;
public class MailTemplateModel
{
public Dictionary<string, string> MailParametreleri { get; set; }
public Dictionary<string, MailTemplateTableModel> Tablolar { get; set; }
}

View file

@ -0,0 +1,18 @@
namespace Kurs.MailQueue.MailGeneration.Models;
public class MailTemplateTableColumnModel
{
public int SiraNo { get; set; }
public string SutunAdi { get; set; }
public string SutunBaslik { get; set; }
public Dictionary<string, string> BaslikCss { get; set; }
public Dictionary<string, string> Css { get; set; }
public Dictionary<string, string> AltBilgiCss { get; set; }
public string VeriTipi { get; set; }
public string VeriFormati { get; set; }
public bool Gizlimi { get; set; }
public bool Korumalimi { get; set; }
public string AltToplam { get; set; }
public int Genislik { get; set; }
}

Some files were not shown because too many files have changed in this diff Show more