mirror of https://github.com/EasyAbp/EShop.git
committed by
GitHub
217 changed files with 11815 additions and 14 deletions
@ -0,0 +1 @@ |
|||
**/wwwroot/libs/** linguist-vendored |
|||
@ -0,0 +1,262 @@ |
|||
## 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 |
|||
|
|||
# Promotions |
|||
host/EasyAbp.EShop.Plugins.Promotions.AuthServer/Logs/logs.txt |
|||
host/EasyAbp.EShop.Plugins.Promotions.HttpApi.Host/Logs/logs.txt |
|||
host/EasyAbp.EShop.Plugins.Promotions.Web.Host/Logs/logs.txt |
|||
host/EasyAbp.EShop.Plugins.Promotions.Web.Unified/Logs/logs.txt |
|||
host/EasyAbp.EShop.Plugins.Promotions.Blazor.Server.Host/Logs/logs.txt |
|||
|
|||
# Use abp install-libs to restore. |
|||
**/wwwroot/libs/* |
|||
@ -0,0 +1,5 @@ |
|||
{ |
|||
"singleQuote": true, |
|||
"useTabs": false, |
|||
"tabWidth": 4 |
|||
} |
|||
@ -0,0 +1,111 @@ |
|||
{ |
|||
"folders": { |
|||
"items": { |
|||
"src": {}, |
|||
"test": {}, |
|||
"host": {} |
|||
} |
|||
}, |
|||
"packages": { |
|||
"EasyAbp.EShop.Plugins.Promotions.Domain.Shared": { |
|||
"path": "src/EasyAbp.EShop.Plugins.Promotions.Domain.Shared/EasyAbp.EShop.Plugins.Promotions.Domain.Shared.abppkg.json", |
|||
"folder": "src" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.Domain": { |
|||
"path": "src/EasyAbp.EShop.Plugins.Promotions.Domain/EasyAbp.EShop.Plugins.Promotions.Domain.abppkg.json", |
|||
"folder": "src" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.Application.Contracts": { |
|||
"path": "src/EasyAbp.EShop.Plugins.Promotions.Application.Contracts/EasyAbp.EShop.Plugins.Promotions.Application.Contracts.abppkg.json", |
|||
"folder": "src" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.Application": { |
|||
"path": "src/EasyAbp.EShop.Plugins.Promotions.Application/EasyAbp.EShop.Plugins.Promotions.Application.abppkg.json", |
|||
"folder": "src" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore": { |
|||
"path": "src/EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore/EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore.abppkg.json", |
|||
"folder": "src" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.MongoDB": { |
|||
"path": "src/EasyAbp.EShop.Plugins.Promotions.MongoDB/EasyAbp.EShop.Plugins.Promotions.MongoDB.abppkg.json", |
|||
"folder": "src" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.HttpApi": { |
|||
"path": "src/EasyAbp.EShop.Plugins.Promotions.HttpApi/EasyAbp.EShop.Plugins.Promotions.HttpApi.abppkg.json", |
|||
"folder": "src" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.HttpApi.Client": { |
|||
"path": "src/EasyAbp.EShop.Plugins.Promotions.HttpApi.Client/EasyAbp.EShop.Plugins.Promotions.HttpApi.Client.abppkg.json", |
|||
"folder": "src" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.TestBase": { |
|||
"path": "test/EasyAbp.EShop.Plugins.Promotions.TestBase/EasyAbp.EShop.Plugins.Promotions.TestBase.abppkg.json", |
|||
"folder": "test" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore.Tests": { |
|||
"path": "test/EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore.Tests/EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore.Tests.abppkg.json", |
|||
"folder": "test" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.MongoDB.Tests": { |
|||
"path": "test/EasyAbp.EShop.Plugins.Promotions.MongoDB.Tests/EasyAbp.EShop.Plugins.Promotions.MongoDB.Tests.abppkg.json", |
|||
"folder": "test" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.Domain.Tests": { |
|||
"path": "test/EasyAbp.EShop.Plugins.Promotions.Domain.Tests/EasyAbp.EShop.Plugins.Promotions.Domain.Tests.abppkg.json", |
|||
"folder": "test" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.Application.Tests": { |
|||
"path": "test/EasyAbp.EShop.Plugins.Promotions.Application.Tests/EasyAbp.EShop.Plugins.Promotions.Application.Tests.abppkg.json", |
|||
"folder": "test" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.HttpApi.Host": { |
|||
"path": "host/EasyAbp.EShop.Plugins.Promotions.HttpApi.Host/EasyAbp.EShop.Plugins.Promotions.HttpApi.Host.abppkg.json", |
|||
"folder": "host" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.Web": { |
|||
"path": "src/EasyAbp.EShop.Plugins.Promotions.Web/EasyAbp.EShop.Plugins.Promotions.Web.abppkg.json", |
|||
"folder": "src" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.HttpApi.Client.ConsoleTestApp": { |
|||
"path": "test/EasyAbp.EShop.Plugins.Promotions.HttpApi.Client.ConsoleTestApp/EasyAbp.EShop.Plugins.Promotions.HttpApi.Client.ConsoleTestApp.abppkg.json", |
|||
"folder": "test" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.Web.Host": { |
|||
"path": "host/EasyAbp.EShop.Plugins.Promotions.Web.Host/EasyAbp.EShop.Plugins.Promotions.Web.Host.abppkg.json", |
|||
"folder": "host" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.AuthServer": { |
|||
"path": "host/EasyAbp.EShop.Plugins.Promotions.AuthServer/EasyAbp.EShop.Plugins.Promotions.AuthServer.abppkg.json", |
|||
"folder": "host" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.Host.Shared": { |
|||
"path": "host/EasyAbp.EShop.Plugins.Promotions.Host.Shared/EasyAbp.EShop.Plugins.Promotions.Host.Shared.abppkg.json", |
|||
"folder": "host" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.Web.Unified": { |
|||
"path": "host/EasyAbp.EShop.Plugins.Promotions.Web.Unified/EasyAbp.EShop.Plugins.Promotions.Web.Unified.abppkg.json", |
|||
"folder": "host" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.Blazor": { |
|||
"path": "src/EasyAbp.EShop.Plugins.Promotions.Blazor/EasyAbp.EShop.Plugins.Promotions.Blazor.abppkg.json", |
|||
"folder": "src" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.Blazor.Host": { |
|||
"path": "host/EasyAbp.EShop.Plugins.Promotions.Blazor.Host/EasyAbp.EShop.Plugins.Promotions.Blazor.Host.abppkg.json", |
|||
"folder": "host" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.Blazor.Server": { |
|||
"path": "src/EasyAbp.EShop.Plugins.Promotions.Blazor.Server/EasyAbp.EShop.Plugins.Promotions.Blazor.Server.abppkg.json", |
|||
"folder": "src" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.Blazor.WebAssembly": { |
|||
"path": "src/EasyAbp.EShop.Plugins.Promotions.Blazor.WebAssembly/EasyAbp.EShop.Plugins.Promotions.Blazor.WebAssembly.abppkg.json", |
|||
"folder": "src" |
|||
}, |
|||
"EasyAbp.EShop.Plugins.Promotions.Blazor.Server.Host": { |
|||
"path": "host/EasyAbp.EShop.Plugins.Promotions.Blazor.Server.Host/EasyAbp.EShop.Plugins.Promotions.Blazor.Server.Host.abppkg.json", |
|||
"folder": "host" |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
{ |
|||
"modules": { |
|||
"EasyAbp.EShop.Plugins.Promotions": { |
|||
"path": "EasyAbp.EShop.Plugins.Promotions.abpmdl.json" |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,146 @@ |
|||
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00 |
|||
# Visual Studio Version 16 |
|||
VisualStudioVersion = 16.0.29001.49 |
|||
MinimumVisualStudioVersion = 10.0.40219.1 |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.Promotions.Domain.Shared", "src\EasyAbp.EShop.Plugins.Promotions.Domain.Shared\EasyAbp.EShop.Plugins.Promotions.Domain.Shared.csproj", "{D64C1577-4929-4B60-939E-96DE1534891A}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.Promotions.Domain", "src\EasyAbp.EShop.Plugins.Promotions.Domain\EasyAbp.EShop.Plugins.Promotions.Domain.csproj", "{F2840BC7-0188-4606-9126-DADD0F5ABF7A}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.Promotions.Application.Contracts", "src\EasyAbp.EShop.Plugins.Promotions.Application.Contracts\EasyAbp.EShop.Plugins.Promotions.Application.Contracts.csproj", "{BD65D04F-08D5-40C1-8C24-77CA0BACB877}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.Promotions.Application", "src\EasyAbp.EShop.Plugins.Promotions.Application\EasyAbp.EShop.Plugins.Promotions.Application.csproj", "{78040F9E-3501-4A40-82DF-00A597710F35}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{649A3FFA-182F-4E56-9717-E6A9A2BEC545}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "host", "host", "{E400416D-2895-4512-9D17-90681EEC7E0A}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore", "src\EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore\EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore.csproj", "{0CE86223-D31D-4315-A1F5-87BA3EE1B844}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.Promotions.MongoDB", "src\EasyAbp.EShop.Plugins.Promotions.MongoDB\EasyAbp.EShop.Plugins.Promotions.MongoDB.csproj", "{F1C58097-4C08-4D88-8976-6B3389391481}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.Promotions.HttpApi", "src\EasyAbp.EShop.Plugins.Promotions.HttpApi\EasyAbp.EShop.Plugins.Promotions.HttpApi.csproj", "{077AA5F8-8B61-420C-A6B5-0150A66FDB34}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.Promotions.HttpApi.Client", "src\EasyAbp.EShop.Plugins.Promotions.HttpApi.Client\EasyAbp.EShop.Plugins.Promotions.HttpApi.Client.csproj", "{36E2735F-CEAB-44C8-A6D1-2CDAFF399751}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.Promotions.TestBase", "test\EasyAbp.EShop.Plugins.Promotions.TestBase\EasyAbp.EShop.Plugins.Promotions.TestBase.csproj", "{C5BB573D-3030-4BCB-88B7-F6A85C32766C}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore.Tests", "test\EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore.Tests\EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore.Tests.csproj", "{527F645C-C1FC-406E-8479-81386C8ECF13}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.Promotions.MongoDB.Tests", "test\EasyAbp.EShop.Plugins.Promotions.MongoDB.Tests\EasyAbp.EShop.Plugins.Promotions.MongoDB.Tests.csproj", "{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.Promotions.Domain.Tests", "test\EasyAbp.EShop.Plugins.Promotions.Domain.Tests\EasyAbp.EShop.Plugins.Promotions.Domain.Tests.csproj", "{E60895E5-79C4-447D-88B7-85CB5BA336A4}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.Promotions.Application.Tests", "test\EasyAbp.EShop.Plugins.Promotions.Application.Tests\EasyAbp.EShop.Plugins.Promotions.Application.Tests.csproj", "{90CB5DC4-C040-45C7-8900-9688B26405BC}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.Promotions.Web", "src\EasyAbp.EShop.Plugins.Promotions.Web\EasyAbp.EShop.Plugins.Promotions.Web.csproj", "{3B7B6317-1B85-4164-8E11-75574F80AE17}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.Promotions.HttpApi.Client.ConsoleTestApp", "test\EasyAbp.EShop.Plugins.Promotions.HttpApi.Client.ConsoleTestApp\EasyAbp.EShop.Plugins.Promotions.HttpApi.Client.ConsoleTestApp.csproj", "{1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.Promotions.Host.Shared", "host\EasyAbp.EShop.Plugins.Promotions.Host.Shared\EasyAbp.EShop.Plugins.Promotions.Host.Shared.csproj", "{F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB}" |
|||
EndProject |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyAbp.EShop.Plugins.Promotions.Installer", "src\EasyAbp.EShop.Plugins.Promotions.Installer\EasyAbp.EShop.Plugins.Promotions.Installer.csproj", "{BE39FD00-745B-4049-8161-FC129817CBE4}" |
|||
EndProject |
|||
Global |
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|||
Debug|Any CPU = Debug|Any CPU |
|||
Release|Any CPU = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
|||
{D64C1577-4929-4B60-939E-96DE1534891A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{D64C1577-4929-4B60-939E-96DE1534891A}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{D64C1577-4929-4B60-939E-96DE1534891A}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{D64C1577-4929-4B60-939E-96DE1534891A}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{BD65D04F-08D5-40C1-8C24-77CA0BACB877}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{BD65D04F-08D5-40C1-8C24-77CA0BACB877}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{BD65D04F-08D5-40C1-8C24-77CA0BACB877}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{BD65D04F-08D5-40C1-8C24-77CA0BACB877}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{78040F9E-3501-4A40-82DF-00A597710F35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{78040F9E-3501-4A40-82DF-00A597710F35}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{78040F9E-3501-4A40-82DF-00A597710F35}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{78040F9E-3501-4A40-82DF-00A597710F35}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{F1C58097-4C08-4D88-8976-6B3389391481}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{F1C58097-4C08-4D88-8976-6B3389391481}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{F1C58097-4C08-4D88-8976-6B3389391481}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{F1C58097-4C08-4D88-8976-6B3389391481}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{077AA5F8-8B61-420C-A6B5-0150A66FDB34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{077AA5F8-8B61-420C-A6B5-0150A66FDB34}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{077AA5F8-8B61-420C-A6B5-0150A66FDB34}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{077AA5F8-8B61-420C-A6B5-0150A66FDB34}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{36E2735F-CEAB-44C8-A6D1-2CDAFF399751}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{36E2735F-CEAB-44C8-A6D1-2CDAFF399751}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{36E2735F-CEAB-44C8-A6D1-2CDAFF399751}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{36E2735F-CEAB-44C8-A6D1-2CDAFF399751}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{527F645C-C1FC-406E-8479-81386C8ECF13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{527F645C-C1FC-406E-8479-81386C8ECF13}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{527F645C-C1FC-406E-8479-81386C8ECF13}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{527F645C-C1FC-406E-8479-81386C8ECF13}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{E60895E5-79C4-447D-88B7-85CB5BA336A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{E60895E5-79C4-447D-88B7-85CB5BA336A4}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{E60895E5-79C4-447D-88B7-85CB5BA336A4}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{E60895E5-79C4-447D-88B7-85CB5BA336A4}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{90CB5DC4-C040-45C7-8900-9688B26405BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{90CB5DC4-C040-45C7-8900-9688B26405BC}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{90CB5DC4-C040-45C7-8900-9688B26405BC}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{90CB5DC4-C040-45C7-8900-9688B26405BC}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{3B7B6317-1B85-4164-8E11-75574F80AE17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{3B7B6317-1B85-4164-8E11-75574F80AE17}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{3B7B6317-1B85-4164-8E11-75574F80AE17}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{3B7B6317-1B85-4164-8E11-75574F80AE17}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{BE39FD00-745B-4049-8161-FC129817CBE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{BE39FD00-745B-4049-8161-FC129817CBE4}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{BE39FD00-745B-4049-8161-FC129817CBE4}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{BE39FD00-745B-4049-8161-FC129817CBE4}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(SolutionProperties) = preSolution |
|||
HideSolutionNode = FALSE |
|||
EndGlobalSection |
|||
GlobalSection(NestedProjects) = preSolution |
|||
{D64C1577-4929-4B60-939E-96DE1534891A} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} |
|||
{F2840BC7-0188-4606-9126-DADD0F5ABF7A} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} |
|||
{BD65D04F-08D5-40C1-8C24-77CA0BACB877} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} |
|||
{78040F9E-3501-4A40-82DF-00A597710F35} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} |
|||
{0CE86223-D31D-4315-A1F5-87BA3EE1B844} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} |
|||
{F1C58097-4C08-4D88-8976-6B3389391481} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} |
|||
{077AA5F8-8B61-420C-A6B5-0150A66FDB34} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} |
|||
{36E2735F-CEAB-44C8-A6D1-2CDAFF399751} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} |
|||
{C5BB573D-3030-4BCB-88B7-F6A85C32766C} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D} |
|||
{527F645C-C1FC-406E-8479-81386C8ECF13} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D} |
|||
{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D} |
|||
{E60895E5-79C4-447D-88B7-85CB5BA336A4} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D} |
|||
{90CB5DC4-C040-45C7-8900-9688B26405BC} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D} |
|||
{3B7B6317-1B85-4164-8E11-75574F80AE17} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} |
|||
{1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D} |
|||
{F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB} = {E400416D-2895-4512-9D17-90681EEC7E0A} |
|||
{BE39FD00-745B-4049-8161-FC129817CBE4} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} |
|||
EndGlobalSection |
|||
GlobalSection(ExtensibilityGlobals) = postSolution |
|||
SolutionGuid = {4324B3B4-B60B-4E3C-91D8-59576B4E26DD} |
|||
EndGlobalSection |
|||
EndGlobal |
|||
@ -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> |
|||
@ -0,0 +1,5 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<configuration> |
|||
<packageSources> |
|||
</packageSources> |
|||
</configuration> |
|||
@ -0,0 +1 @@ |
|||
{} |
|||
@ -0,0 +1,11 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<RootNamespace>EasyAbp.EShop.Plugins.Promotions</RootNamespace> |
|||
</PropertyGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -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> |
|||
@ -0,0 +1,9 @@ |
|||
namespace EasyAbp.EShop.Plugins.Promotions.MultiTenancy; |
|||
|
|||
public static class MultiTenancyConsts |
|||
{ |
|||
/* Enable/disable multi-tenancy in a single point |
|||
* to test your module with multi-tenancy. |
|||
*/ |
|||
public const bool IsEnabled = false; |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"role": "lib.domain" |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net7.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\modules\EasyAbp.EShop.Orders\src\EasyAbp.EShop.Orders.Domain\EasyAbp.EShop.Orders.Domain.csproj" /> |
|||
<ProjectReference Include="..\EasyAbp.EShop.Plugins.Promotions.Application.Contracts\EasyAbp.EShop.Plugins.Promotions.Application.Contracts.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,12 @@ |
|||
using EasyAbp.EShop.Plugins.Promotions; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace EasyAbp.EShop.Orders.Plugins.Promotions; |
|||
|
|||
[DependsOn( |
|||
typeof(EShopPluginsPromotionsApplicationContractsModule), |
|||
typeof(EShopOrdersDomainModule) |
|||
)] |
|||
public class EShopOrdersPluginsPromotionsDomainModule : AbpModule |
|||
{ |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
using EasyAbp.EShop.Plugins.Promotions.Promotions.Dtos; |
|||
using EasyAbp.EShop.Orders.Orders; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace EasyAbp.EShop.Orders.Plugins.Promotions; |
|||
|
|||
public class PromotionOrderDiscountProvider : IOrderDiscountProvider, ITransientDependency |
|||
{ |
|||
public static int PromotionOrderDiscountEffectOrder { get; set; } = 5000; |
|||
|
|||
public int EffectOrder => PromotionOrderDiscountEffectOrder; |
|||
|
|||
protected IPromotionIntegrationService PromotionIntegrationService { get; } |
|||
|
|||
public PromotionOrderDiscountProvider(IPromotionIntegrationService promotionIntegrationService) |
|||
{ |
|||
PromotionIntegrationService = promotionIntegrationService; |
|||
} |
|||
|
|||
public virtual async Task DiscountAsync(OrderDiscountContext context) |
|||
{ |
|||
var dto = await PromotionIntegrationService.DiscountOrderAsync(new DiscountOrderInputDto(context)); |
|||
|
|||
if (dto.Context.Equals(context)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
context.CandidateDiscounts.Clear(); |
|||
context.CandidateDiscounts.AddRange(dto.Context.CandidateDiscounts); |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -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> |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"role": "lib.application-contracts" |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="$(AbpVersion)" /> |
|||
<PackageReference Include="Volo.Abp.Authorization" Version="$(AbpVersion)" /> |
|||
<ProjectReference Include="..\..\..\..\modules\EasyAbp.EShop.Orders\src\EasyAbp.EShop.Orders.Domain.Shared\EasyAbp.EShop.Orders.Domain.Shared.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\modules\EasyAbp.EShop.Products\src\EasyAbp.EShop.Products.Domain.Shared\EasyAbp.EShop.Products.Domain.Shared.csproj" /> |
|||
<ProjectReference Include="..\EasyAbp.EShop.Plugins.Promotions.Domain.Shared\EasyAbp.EShop.Plugins.Promotions.Domain.Shared.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,18 @@ |
|||
using EasyAbp.EShop.Orders; |
|||
using EasyAbp.EShop.Products; |
|||
using Volo.Abp.Application; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Authorization; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions; |
|||
|
|||
[DependsOn( |
|||
typeof(EShopPluginsPromotionsDomainSharedModule), |
|||
typeof(EShopProductsDomainSharedModule), |
|||
typeof(EShopOrdersDomainSharedModule), |
|||
typeof(AbpDddApplicationContractsModule), |
|||
typeof(AbpAuthorizationModule) |
|||
)] |
|||
public class EShopPluginsPromotionsApplicationContractsModule : AbpModule |
|||
{ |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
namespace EasyAbp.EShop.Plugins.Promotions; |
|||
|
|||
public class EShopPluginsPromotionsRemoteServiceConsts |
|||
{ |
|||
public const string RemoteServiceName = "EasyAbpEShopPluginsPromotions"; |
|||
|
|||
public const string ModuleName = "easyAbpEShopPluginsPromotions"; |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
using EasyAbp.EShop.Plugins.Promotions.Localization; |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Permissions; |
|||
|
|||
public class PromotionsPermissionDefinitionProvider : PermissionDefinitionProvider |
|||
{ |
|||
public override void Define(IPermissionDefinitionContext context) |
|||
{ |
|||
var myGroup = context.AddGroup(PromotionsPermissions.GroupName, L("Permission:Promotions")); |
|||
|
|||
var promotionPermission = myGroup.AddPermission(PromotionsPermissions.Promotion.Default, L("Permission:Promotion")); |
|||
promotionPermission.AddChild(PromotionsPermissions.Promotion.CrossStore, L("Permission:CrossStore")); |
|||
promotionPermission.AddChild(PromotionsPermissions.Promotion.Create, L("Permission:Create")); |
|||
promotionPermission.AddChild(PromotionsPermissions.Promotion.Update, L("Permission:Update")); |
|||
promotionPermission.AddChild(PromotionsPermissions.Promotion.Delete, L("Permission:Delete")); |
|||
} |
|||
|
|||
private static LocalizableString L(string name) |
|||
{ |
|||
return LocalizableString.Create<PromotionsResource>(name); |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
using Volo.Abp.Reflection; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Permissions; |
|||
|
|||
public class PromotionsPermissions |
|||
{ |
|||
public const string GroupName = "EasyAbp.EShop.Plugins.Promotions"; |
|||
|
|||
public static string[] GetAll() |
|||
{ |
|||
return ReflectionHelper.GetPublicConstantsRecursively(typeof(PromotionsPermissions)); |
|||
} |
|||
|
|||
public class Promotion |
|||
{ |
|||
public const string Default = GroupName + ".Promotion"; |
|||
public const string CrossStore = Default + ".CrossStore"; |
|||
public const string Update = Default + ".Update"; |
|||
public const string Create = Default + ".Create"; |
|||
public const string Delete = Default + ".Delete"; |
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
using System; |
|||
using EasyAbp.EShop.Stores.Stores; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions.Dtos; |
|||
|
|||
[Serializable] |
|||
public class CreatePromotionDto : IMultiStore |
|||
{ |
|||
public Guid StoreId { get; set; } |
|||
|
|||
public string PromotionType { get; set; } |
|||
|
|||
public string UniqueName { get; set; } |
|||
|
|||
public string DisplayName { get; set; } |
|||
|
|||
public string Configurations { get; set; } |
|||
|
|||
public DateTime? FromTime { get; set; } |
|||
|
|||
public DateTime? ToTime { get; set; } |
|||
|
|||
public bool Disabled { get; set; } |
|||
|
|||
public int Priority { get; set; } |
|||
|
|||
public CreatePromotionDto() |
|||
{ |
|||
} |
|||
|
|||
public CreatePromotionDto(Guid storeId, string promotionType, string uniqueName, string displayName, |
|||
string configurations, DateTime? fromTime, DateTime? toTime, bool disabled, int priority) |
|||
{ |
|||
StoreId = storeId; |
|||
PromotionType = promotionType; |
|||
UniqueName = uniqueName; |
|||
DisplayName = displayName; |
|||
Configurations = configurations; |
|||
FromTime = fromTime; |
|||
ToTime = toTime; |
|||
Disabled = disabled; |
|||
Priority = priority; |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using System; |
|||
using EasyAbp.EShop.Orders.Orders; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions.Dtos; |
|||
|
|||
[Serializable] |
|||
public class DiscountOrderInputDto |
|||
{ |
|||
public OrderDiscountContext Context { get; set; } |
|||
|
|||
public DiscountOrderInputDto() |
|||
{ |
|||
} |
|||
|
|||
public DiscountOrderInputDto(OrderDiscountContext context) |
|||
{ |
|||
Context = context; |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using System; |
|||
using EasyAbp.EShop.Orders.Orders; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions.Dtos; |
|||
|
|||
[Serializable] |
|||
public class DiscountOrderOutputDto |
|||
{ |
|||
public OrderDiscountContext Context { get; set; } |
|||
|
|||
public DiscountOrderOutputDto() |
|||
{ |
|||
} |
|||
|
|||
public DiscountOrderOutputDto(OrderDiscountContext context) |
|||
{ |
|||
Context = context; |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using System; |
|||
using EasyAbp.EShop.Products.Products; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions.Dtos; |
|||
|
|||
[Serializable] |
|||
public class DiscountProductInputDto |
|||
{ |
|||
public ProductDiscountContext Context { get; set; } |
|||
|
|||
public DiscountProductInputDto() |
|||
{ |
|||
} |
|||
|
|||
public DiscountProductInputDto(ProductDiscountContext context) |
|||
{ |
|||
Context = context; |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using System; |
|||
using EasyAbp.EShop.Products.Products; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions.Dtos; |
|||
|
|||
[Serializable] |
|||
public class DiscountProductOutputDto |
|||
{ |
|||
public ProductDiscountContext Context { get; set; } |
|||
|
|||
public DiscountProductOutputDto() |
|||
{ |
|||
} |
|||
|
|||
public DiscountProductOutputDto(ProductDiscountContext context) |
|||
{ |
|||
Context = context; |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
using System; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions.Dtos; |
|||
|
|||
[Serializable] |
|||
public class PromotionDto : FullAuditedEntityDto<Guid> |
|||
{ |
|||
public Guid StoreId { get; set; } |
|||
|
|||
public string PromotionType { get; set; } |
|||
|
|||
public string UniqueName { get; set; } |
|||
|
|||
public string DisplayName { get; set; } |
|||
|
|||
public string Configurations { get; set; } |
|||
|
|||
public DateTime? FromTime { get; set; } |
|||
|
|||
public DateTime? ToTime { get; set; } |
|||
|
|||
public bool Disabled { get; set; } |
|||
|
|||
public int Priority { get; set; } |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions.Dtos; |
|||
|
|||
[Serializable] |
|||
public class PromotionGetListInput : PagedAndSortedResultRequestDto |
|||
{ |
|||
public Guid? StoreId { get; set; } |
|||
|
|||
public string? PromotionType { get; set; } |
|||
|
|||
public string? UniqueName { get; set; } |
|||
|
|||
public string? DisplayName { get; set; } |
|||
|
|||
public DateTime? FromTime { get; set; } |
|||
|
|||
public DateTime? ToTime { get; set; } |
|||
|
|||
public bool? Disabled { get; set; } |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using System; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions.Dtos; |
|||
|
|||
[Serializable] |
|||
public class PromotionTypeDto |
|||
{ |
|||
public string Name { get; set; } |
|||
|
|||
public string DisplayName { get; set; } |
|||
|
|||
public string ConfigurationsTemplate { get; set; } |
|||
|
|||
public PromotionTypeDto(string name, string displayName, string configurationsTemplate) |
|||
{ |
|||
Name = name; |
|||
DisplayName = displayName; |
|||
ConfigurationsTemplate = configurationsTemplate; |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
using System; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions.Dtos; |
|||
|
|||
[Serializable] |
|||
public class UpdatePromotionDto |
|||
{ |
|||
public string DisplayName { get; set; } |
|||
|
|||
public string Configurations { get; set; } |
|||
|
|||
public DateTime? FromTime { get; set; } |
|||
|
|||
public DateTime? ToTime { get; set; } |
|||
|
|||
public bool Disabled { get; set; } |
|||
|
|||
public int Priority { get; set; } |
|||
|
|||
public UpdatePromotionDto() |
|||
{ |
|||
} |
|||
|
|||
public UpdatePromotionDto(string displayName, string configurations, DateTime? fromTime, DateTime? toTime, |
|||
bool disabled, int priority) |
|||
{ |
|||
DisplayName = displayName; |
|||
Configurations = configurations; |
|||
FromTime = fromTime; |
|||
ToTime = toTime; |
|||
Disabled = disabled; |
|||
Priority = priority; |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Plugins.Promotions.Promotions.Dtos; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
|
|||
public interface IPromotionAppService : |
|||
ICrudAppService< |
|||
PromotionDto, |
|||
Guid, |
|||
PromotionGetListInput, |
|||
CreatePromotionDto, |
|||
UpdatePromotionDto> |
|||
{ |
|||
Task<ListResultDto<PromotionTypeDto>> GetPromotionTypesAsync(); |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Plugins.Promotions.Promotions.Dtos; |
|||
using Volo.Abp; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
|
|||
[IntegrationService] |
|||
public interface IPromotionIntegrationService |
|||
{ |
|||
Task<DiscountProductOutputDto> DiscountProductAsync(DiscountProductInputDto input); |
|||
|
|||
Task<DiscountOrderOutputDto> DiscountOrderAsync(DiscountOrderInputDto input); |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -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> |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"role": "lib.application" |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net7.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.AutoMapper" Version="$(AbpVersion)" /> |
|||
<PackageReference Include="Volo.Abp.Ddd.Application" Version="$(AbpVersion)" /> |
|||
<ProjectReference Include="..\..\..\..\modules\EasyAbp.EShop.Stores\src\EasyAbp.EShop.Stores.Application.Shared\EasyAbp.EShop.Stores.Application.Shared.csproj" /> |
|||
<ProjectReference Include="..\EasyAbp.EShop.Plugins.Promotions.Application.Contracts\EasyAbp.EShop.Plugins.Promotions.Application.Contracts.csproj" /> |
|||
<ProjectReference Include="..\EasyAbp.EShop.Plugins.Promotions.Domain\EasyAbp.EShop.Plugins.Promotions.Domain.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,13 @@ |
|||
using EasyAbp.EShop.Plugins.Promotions.Localization; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions; |
|||
|
|||
public abstract class EShopPluginsPromotionsAppService : ApplicationService |
|||
{ |
|||
protected EShopPluginsPromotionsAppService() |
|||
{ |
|||
LocalizationResource = typeof(PromotionsResource); |
|||
ObjectMapperContext = typeof(EShopPluginsPromotionsApplicationModule); |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
using EasyAbp.EShop.Stores; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.AutoMapper; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Application; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions; |
|||
|
|||
[DependsOn( |
|||
typeof(EShopPluginsPromotionsDomainModule), |
|||
typeof(EShopPluginsPromotionsApplicationContractsModule), |
|||
typeof(EShopStoresApplicationSharedModule), |
|||
typeof(AbpDddApplicationModule), |
|||
typeof(AbpAutoMapperModule) |
|||
)] |
|||
public class EShopPluginsPromotionsApplicationModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddAutoMapperObjectMapper<EShopPluginsPromotionsApplicationModule>(); |
|||
Configure<AbpAutoMapperOptions>(options => |
|||
{ |
|||
options.AddMaps<EShopPluginsPromotionsApplicationModule>(validate: true); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Plugins.Promotions.Localization; |
|||
using EasyAbp.EShop.Plugins.Promotions.Options; |
|||
using EasyAbp.EShop.Plugins.Promotions.Permissions; |
|||
using EasyAbp.EShop.Plugins.Promotions.Promotions.Dtos; |
|||
using EasyAbp.EShop.Plugins.Promotions.PromotionTypes; |
|||
using EasyAbp.EShop.Stores.Stores; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Json; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
|
|||
public class PromotionAppService : MultiStoreCrudAppService<Promotion, PromotionDto, Guid, PromotionGetListInput, |
|||
CreatePromotionDto, UpdatePromotionDto>, IPromotionAppService |
|||
{ |
|||
protected override string GetPolicyName { get; set; } = PromotionsPermissions.Promotion.Default; |
|||
protected override string GetListPolicyName { get; set; } = PromotionsPermissions.Promotion.Default; |
|||
protected override string CreatePolicyName { get; set; } = PromotionsPermissions.Promotion.Create; |
|||
protected override string UpdatePolicyName { get; set; } = PromotionsPermissions.Promotion.Update; |
|||
protected override string DeletePolicyName { get; set; } = PromotionsPermissions.Promotion.Delete; |
|||
protected override string CrossStorePolicyName { get; set; } = PromotionsPermissions.Promotion.CrossStore; |
|||
|
|||
private readonly IPromotionRepository _repository; |
|||
|
|||
protected IJsonSerializer JsonSerializer { get; } |
|||
protected PromotionManager PromotionManager { get; } |
|||
protected EShopPluginsPromotionsOptions Options { get; } |
|||
|
|||
public PromotionAppService( |
|||
IJsonSerializer jsonSerializer, |
|||
IOptions<EShopPluginsPromotionsOptions> options, |
|||
PromotionManager promotionManager, |
|||
IPromotionRepository repository) : base(repository) |
|||
{ |
|||
JsonSerializer = jsonSerializer; |
|||
PromotionManager = promotionManager; |
|||
Options = options.Value; |
|||
_repository = repository; |
|||
|
|||
LocalizationResource = typeof(PromotionsResource); |
|||
ObjectMapperContext = typeof(EShopPluginsPromotionsApplicationModule); |
|||
} |
|||
|
|||
protected override async Task<IQueryable<Promotion>> CreateFilteredQueryAsync(PromotionGetListInput input) |
|||
{ |
|||
// TODO: AbpHelper generated
|
|||
return (await base.CreateFilteredQueryAsync(input)) |
|||
.WhereIf(input.StoreId != null, x => x.StoreId == input.StoreId) |
|||
.WhereIf(!input.PromotionType.IsNullOrWhiteSpace(), x => x.PromotionType.Contains(input.PromotionType!)) |
|||
.WhereIf(!input.UniqueName.IsNullOrWhiteSpace(), x => x.UniqueName.Contains(input.UniqueName!)) |
|||
.WhereIf(!input.DisplayName.IsNullOrWhiteSpace(), x => x.DisplayName.Contains(input.DisplayName!)) |
|||
.WhereIf(input.FromTime != null, x => x.FromTime == input.FromTime) |
|||
.WhereIf(input.ToTime != null, x => x.ToTime == input.ToTime) |
|||
.WhereIf(input.Disabled != null, x => x.Disabled == input.Disabled) |
|||
; |
|||
} |
|||
|
|||
public virtual async Task<ListResultDto<PromotionTypeDto>> GetPromotionTypesAsync() |
|||
{ |
|||
var promotionTypes = Options.PromotionTypes.GetAll(); |
|||
|
|||
var dtos = new List<PromotionTypeDto>(); |
|||
|
|||
foreach (var promotionType in promotionTypes) |
|||
{ |
|||
var handler = GetPromotionHandler(promotionType); |
|||
|
|||
var configurationsTemplate = await handler.CreateConfigurationsObjectOrNullAsync(); |
|||
|
|||
dtos.Add(new PromotionTypeDto(promotionType.Name, L[promotionType.Name], |
|||
configurationsTemplate is null ? "{}" : JsonSerializer.Serialize(configurationsTemplate))); |
|||
} |
|||
|
|||
return new ListResultDto<PromotionTypeDto>(dtos); |
|||
} |
|||
|
|||
protected virtual IPromotionHandler GetPromotionHandler(PromotionTypeDefinition definition) |
|||
{ |
|||
return (IPromotionHandler)LazyServiceProvider.LazyGetRequiredService(definition.PromotionHandlerType); |
|||
} |
|||
|
|||
protected override async Task<Promotion> MapToEntityAsync(CreatePromotionDto createInput) |
|||
{ |
|||
return await PromotionManager.CreateAsync(createInput.StoreId, createInput.PromotionType, |
|||
createInput.UniqueName, createInput.DisplayName, createInput.Configurations, createInput.FromTime, |
|||
createInput.ToTime, createInput.Disabled, createInput.Priority); |
|||
} |
|||
|
|||
protected override async Task MapToEntityAsync(UpdatePromotionDto updateInput, Promotion entity) |
|||
{ |
|||
await PromotionManager.UpdateAsync(entity, updateInput.DisplayName, updateInput.Configurations, |
|||
updateInput.FromTime, updateInput.ToTime, updateInput.Disabled, updateInput.Priority); |
|||
} |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Plugins.Promotions.Options; |
|||
using EasyAbp.EShop.Plugins.Promotions.Promotions.Dtos; |
|||
using EasyAbp.EShop.Plugins.Promotions.PromotionTypes; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
|
|||
public class PromotionIntegrationService : ApplicationService, IPromotionIntegrationService |
|||
{ |
|||
protected IPromotionRepository PromotionRepository { get; } |
|||
protected EShopPluginsPromotionsOptions Options { get; } |
|||
|
|||
public PromotionIntegrationService( |
|||
IPromotionRepository promotionRepository, |
|||
IOptions<EShopPluginsPromotionsOptions> options) |
|||
{ |
|||
PromotionRepository = promotionRepository; |
|||
Options = options.Value; |
|||
} |
|||
|
|||
public virtual async Task<DiscountProductOutputDto> DiscountProductAsync(DiscountProductInputDto input) |
|||
{ |
|||
var context = input.Context; |
|||
|
|||
var promotions = await GetUnexpiredPromotionsAsync(context.Product.StoreId, context.Now, true); |
|||
|
|||
foreach (var promotion in promotions.OrderByDescending(x => x.Priority)) |
|||
{ |
|||
var promotionHandler = GetPromotionHandler(promotion.PromotionType); |
|||
|
|||
await promotionHandler.HandleProductAsync(context, promotion); |
|||
} |
|||
|
|||
return new DiscountProductOutputDto(context); |
|||
} |
|||
|
|||
public virtual async Task<DiscountOrderOutputDto> DiscountOrderAsync(DiscountOrderInputDto input) |
|||
{ |
|||
var context = input.Context; |
|||
|
|||
var promotions = await GetUnexpiredPromotionsAsync(context.Order.StoreId, context.Now, false); |
|||
|
|||
foreach (var promotion in promotions.OrderByDescending(x => x.Priority)) |
|||
{ |
|||
var promotionHandler = GetPromotionHandler(promotion.PromotionType); |
|||
|
|||
await promotionHandler.HandleOrderAsync(context, promotion); |
|||
} |
|||
|
|||
return new DiscountOrderOutputDto(context); |
|||
} |
|||
|
|||
protected virtual async Task<List<Promotion>> GetUnexpiredPromotionsAsync(Guid storeId, DateTime now, |
|||
bool includesNotStarted) |
|||
{ |
|||
// skip the expired promotions.
|
|||
var queryable = (await PromotionRepository.GetQueryableAsync()).Where(x => |
|||
x.StoreId == storeId && !x.Disabled && (!x.ToTime.HasValue || now <= x.ToTime)); |
|||
|
|||
queryable.WhereIf(!includesNotStarted, x => !x.FromTime.HasValue || now >= x.FromTime); |
|||
|
|||
return await AsyncExecuter.ToListAsync(queryable); |
|||
} |
|||
|
|||
protected virtual IPromotionHandler GetPromotionHandler(string promotionType) |
|||
{ |
|||
var definition = Options.PromotionTypes.GetOrNull(promotionType); |
|||
|
|||
if (definition is null) |
|||
{ |
|||
throw new BusinessException(PromotionsErrorCodes.InvalidPromotionType); |
|||
} |
|||
|
|||
return (IPromotionHandler)LazyServiceProvider.LazyGetRequiredService(definition.PromotionHandlerType); |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
using EasyAbp.EShop.Plugins.Promotions.Promotions.Dtos; |
|||
using AutoMapper; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions; |
|||
|
|||
public class PromotionsApplicationAutoMapperProfile : Profile |
|||
{ |
|||
public PromotionsApplicationAutoMapperProfile() |
|||
{ |
|||
/* You can configure your AutoMapper mapping configuration here. |
|||
* Alternatively, you can split your mapping configurations |
|||
* into multiple profile classes for a better organization. */ |
|||
CreateMap<Promotion, PromotionDto>(); |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -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> |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"role": "lib.domain-shared" |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<RootNamespace /> |
|||
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.Validation" Version="$(AbpVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="7.0.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<EmbeddedResource Include="EasyAbp\EShop\Plugins\Promotions\Localization\*.json" /> |
|||
<Content Remove="EasyAbp\EShop\Plugins\Promotions\Localization\*.json" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,36 @@ |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Localization; |
|||
using EasyAbp.EShop.Plugins.Promotions.Localization; |
|||
using Volo.Abp.Localization.ExceptionHandling; |
|||
using Volo.Abp.Validation; |
|||
using Volo.Abp.Validation.Localization; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpValidationModule) |
|||
)] |
|||
public class EShopPluginsPromotionsDomainSharedModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<EShopPluginsPromotionsDomainSharedModule>(); |
|||
}); |
|||
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.Resources |
|||
.Add<PromotionsResource>("en") |
|||
.AddBaseTypes(typeof(AbpValidationResource)) |
|||
.AddVirtualJson("/EasyAbp/EShop/Plugins/Promotions/Localization"); |
|||
}); |
|||
|
|||
Configure<AbpExceptionLocalizationOptions>(options => |
|||
{ |
|||
options.MapCodeNamespace("EasyAbp.EShop.Plugins.Promotions", typeof(PromotionsResource)); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Localization; |
|||
|
|||
[LocalizationResourceName("EasyAbpEShopPluginsPromotions")] |
|||
public class PromotionsResource |
|||
{ |
|||
|
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
{ |
|||
"culture": "en", |
|||
"texts": { |
|||
"SimpleProductDiscount": "Simple product discount", |
|||
"MinQuantityOrderDiscount": "Min-quantity based order discount", |
|||
"Permission:Promotion": "Promotion", |
|||
"Permission:CrossStore": "Cross-store", |
|||
"Permission:Create": "Create", |
|||
"Permission:Update": "Update", |
|||
"Permission:Delete": "Delete", |
|||
"Menu:EasyAbpEShop": "EShop", |
|||
"Menu:PromotionManagement": "Promotion", |
|||
"Menu:Promotion": "Promotion", |
|||
"Promotion": "Promotion", |
|||
"PromotionStoreId": "Store ID", |
|||
"PromotionPromotionType": "Promotion type", |
|||
"PromotionUniqueName": "Unique name", |
|||
"PromotionDisplayName": "Display name", |
|||
"PromotionConfigurations": "Configurations", |
|||
"PromotionFromTime": "From time", |
|||
"PromotionToTime": "To time", |
|||
"PromotionDisabled": "Disabled", |
|||
"PromotionPriority": "Priority", |
|||
"CreatePromotion": "Create", |
|||
"EditPromotion": "Edit", |
|||
"PromotionDeletionConfirmationMessage": "Are you sure to delete the promotion {0}?", |
|||
"SuccessfullyDeleted": "Successfully deleted", |
|||
"TableFilter": "Filter", |
|||
"EasyAbp.EShop.Plugins.Promotions:DuplicatePromotionUniqueName": "Duplicate promotion unique name", |
|||
"EasyAbp.EShop.Plugins.Promotions:InvalidPromotionType": "Invalid promotion type", |
|||
"EasyAbp.EShop.Plugins.Promotions:InvalidPromotionConfigurations": "Invalid promotion configurations" |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
{ |
|||
"culture": "zh-Hans", |
|||
"texts": { |
|||
"SimpleProductDiscount": "简单商品折扣", |
|||
"MinQuantityOrderDiscount": "基于最小数量的订单折扣", |
|||
"Permission:Promotion": "优惠策略", |
|||
"Permission:CrossStore": "跨店管理", |
|||
"Permission:Create": "新建", |
|||
"Permission:Update": "更新", |
|||
"Permission:Delete": "删除", |
|||
"Menu:EasyAbpEShop": "EShop 商城", |
|||
"Menu:PromotionManagement": "优惠活动", |
|||
"Menu:Promotion": "优惠策略", |
|||
"Promotion": "优惠策略", |
|||
"PromotionStoreId": "店铺 ID", |
|||
"PromotionPromotionType": "优惠策略类型", |
|||
"PromotionUniqueName": "唯一编号", |
|||
"PromotionDisplayName": "显示名称", |
|||
"PromotionConfigurations": "配置", |
|||
"PromotionFromTime": "生效时间", |
|||
"PromotionToTime": "结束时间", |
|||
"PromotionDisabled": "停用", |
|||
"PromotionPriority": "优先度", |
|||
"CreatePromotion": "新建", |
|||
"EditPromotion": "编辑", |
|||
"PromotionDeletionConfirmationMessage": "确认删除优惠策略 {0}?", |
|||
"SuccessfullyDeleted": "删除成功", |
|||
"TableFilter": "筛选器", |
|||
"EasyAbp.EShop.Plugins.Promotions:DuplicatePromotionUniqueName": "重复的优惠策略唯一编号", |
|||
"EasyAbp.EShop.Plugins.Promotions:InvalidPromotionType": "不正确的优惠策略类型", |
|||
"EasyAbp.EShop.Plugins.Promotions:InvalidPromotionConfigurations": "不正确的优惠策略配置" |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
{ |
|||
"culture": "zh-Hant", |
|||
"texts": { |
|||
"SimpleProductDiscount": "簡單商品折扣", |
|||
"MinQuantityOrderDiscount": "基於最小數量的訂單折扣", |
|||
"Permission:Promotion": "優惠策略", |
|||
"Permission:CrossStore": "跨店管理", |
|||
"Permission:Create": "新建", |
|||
"Permission:Update": "更新", |
|||
"Permission:Delete": "刪除", |
|||
"Menu:EasyAbpEShop": "EShop 商城", |
|||
"Menu:PromotionManagement": "優惠活動", |
|||
"Menu:Promotion": "優惠策略", |
|||
"Promotion": "優惠策略", |
|||
"PromotionStoreId": "店鋪 ID", |
|||
"PromotionPromotionType": "優惠策略類型", |
|||
"PromotionUniqueName": "唯一編號", |
|||
"PromotionDisplayName": "顯示名稱", |
|||
"PromotionConfigurations": "配置", |
|||
"PromotionFromTime": "生效時間", |
|||
"PromotionToTime": "結束時間", |
|||
"PromotionDisabled": "停用", |
|||
"PromotionPriority": "優先度", |
|||
"CreatePromotion": "新建", |
|||
"EditPromotion": "編輯", |
|||
"PromotionDeletionConfirmationMessage": "確認刪除優惠策略 {0}?", |
|||
"SuccessfullyDeleted": "刪除成功", |
|||
"TableFilter": "篩選器", |
|||
"EasyAbp.EShop.Plugins.Promotions:DuplicatePromotionUniqueName": "重複的優惠策略唯一編號", |
|||
"EasyAbp.EShop.Plugins.Promotions:InvalidPromotionType": "不正確的優惠策略類型", |
|||
"EasyAbp.EShop.Plugins.Promotions:InvalidPromotionConfigurations": "不正確的優惠策略配置" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
namespace EasyAbp.EShop.Plugins.Promotions; |
|||
|
|||
public static class PromotionConsts |
|||
{ |
|||
public static string PromotionDiscountName { get; set; } = "Promotion"; |
|||
|
|||
public static string PromotionEffectGroup { get; set; } = "Promotion"; |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
namespace EasyAbp.EShop.Plugins.Promotions; |
|||
|
|||
public static class PromotionsErrorCodes |
|||
{ |
|||
public const string DuplicatePromotionUniqueName = "EasyAbp.EShop.Plugins.Promotions:DuplicatePromotionUniqueName"; |
|||
|
|||
public const string InvalidPromotionType = "EasyAbp.EShop.Plugins.Promotions:InvalidPromotionType"; |
|||
|
|||
public const string InvalidPromotionConfigurations = |
|||
"EasyAbp.EShop.Plugins.Promotions:InvalidPromotionConfigurations"; |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -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> |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"role": "lib.domain" |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net7.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="NodaMoney" Version="$(NodaMoneyVersion)" /> |
|||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> |
|||
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="$(AbpVersion)" /> |
|||
<ProjectReference Include="..\..\..\..\modules\EasyAbp.EShop.Orders\src\EasyAbp.EShop.Orders.Domain.Shared\EasyAbp.EShop.Orders.Domain.Shared.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\modules\EasyAbp.EShop.Products\src\EasyAbp.EShop.Products.Domain.Shared\EasyAbp.EShop.Products.Domain.Shared.csproj" /> |
|||
<ProjectReference Include="..\EasyAbp.EShop.Plugins.Promotions.Domain.Shared\EasyAbp.EShop.Plugins.Promotions.Domain.Shared.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,16 @@ |
|||
using EasyAbp.EShop.Orders; |
|||
using EasyAbp.EShop.Products; |
|||
using Volo.Abp.Domain; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpDddDomainModule), |
|||
typeof(EShopPluginsPromotionsDomainSharedModule), |
|||
typeof(EShopProductsDomainSharedModule), |
|||
typeof(EShopOrdersDomainSharedModule) |
|||
)] |
|||
public class EShopPluginsPromotionsDomainModule : AbpModule |
|||
{ |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
namespace EasyAbp.EShop.Plugins.Promotions.Options; |
|||
|
|||
public class EShopPluginsPromotionsOptions |
|||
{ |
|||
public PromotionTypeConfigurations PromotionTypes { get; set; } = new(); |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using EasyAbp.EShop.Plugins.Promotions.PromotionTypes; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Options; |
|||
|
|||
public class PromotionTypeConfigurations |
|||
{ |
|||
private Dictionary<string, PromotionTypeDefinition> PromotionTypes { get; } = new(); |
|||
|
|||
public List<PromotionTypeDefinition> GetAll() |
|||
{ |
|||
return PromotionTypes.Values.ToList(); |
|||
} |
|||
|
|||
public PromotionTypeDefinition? GetOrNull(string promotionTypeName) |
|||
{ |
|||
return PromotionTypes.TryGetValue(promotionTypeName, out var type) ? type : null; |
|||
} |
|||
|
|||
public void AddOrUpdate(PromotionTypeDefinition definition) |
|||
{ |
|||
PromotionTypes[definition.Name] = definition; |
|||
} |
|||
|
|||
public void Remove(string promotionTypeName) |
|||
{ |
|||
PromotionTypes.Remove(promotionTypeName); |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using System; |
|||
using System.Linq; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.PromotionTypes; |
|||
|
|||
public static class HasProductScopesExtensions |
|||
{ |
|||
public static bool IsInScope(this IHasProductScopes scopes, string productGroupName, Guid productId, |
|||
Guid productSkuId) |
|||
{ |
|||
return scopes.ProductScopes.Any(x => |
|||
x.ProductGroupName == productGroupName || x.ProductId == productId || x.ProductSkuId == productSkuId); |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.PromotionTypes; |
|||
|
|||
public interface IHasProductScopes |
|||
{ |
|||
List<ProductScopeModel> ProductScopes { get; } |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Orders.Orders; |
|||
using EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
using EasyAbp.EShop.Products.Products; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.PromotionTypes; |
|||
|
|||
public interface IPromotionHandler |
|||
{ |
|||
Task HandleProductAsync(ProductDiscountContext context, Promotion promotion); |
|||
|
|||
Task HandleOrderAsync(OrderDiscountContext context, Promotion promotion); |
|||
|
|||
Task<object?> CreateConfigurationsObjectOrNullAsync(); |
|||
|
|||
bool IsConfigurationValid(string configurations); |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.PromotionTypes.MinQuantityOrderDiscount; |
|||
|
|||
public class MinQuantityOrderDiscountConfigurations |
|||
{ |
|||
public List<MinQuantityOrderDiscountModel> Discounts { get; set; } = new(); |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
using System.Collections.Generic; |
|||
using EasyAbp.EShop.Products.Products; |
|||
using Volo.Abp; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.PromotionTypes.MinQuantityOrderDiscount; |
|||
|
|||
public class MinQuantityOrderDiscountModel : IHasProductScopes, IHasDynamicDiscountAmount |
|||
{ |
|||
public List<ProductScopeModel> ProductScopes { get; set; } = new(); |
|||
|
|||
/// <summary>
|
|||
/// This discount takes effect when the quantity of the order line equals to or greater than <see cref="MinQuantity"/>.
|
|||
/// It's important to note that this promotion type only applies to one OrderLine.
|
|||
/// The promotion will not apply if you have multiple OrderLines and the total quantity of all OrderLines meets the condition.
|
|||
/// </summary>
|
|||
public int MinQuantity { get; set; } |
|||
|
|||
public DynamicDiscountAmountModel DynamicDiscountAmount { get; set; } |
|||
|
|||
public MinQuantityOrderDiscountModel() |
|||
{ |
|||
} |
|||
|
|||
public MinQuantityOrderDiscountModel(List<ProductScopeModel> productScopes, int minQuantity, |
|||
DynamicDiscountAmountModel dynamicDiscountAmount) |
|||
{ |
|||
if (!productScopes.IsNullOrEmpty()) |
|||
{ |
|||
ProductScopes = productScopes; |
|||
} |
|||
|
|||
MinQuantity = minQuantity; |
|||
DynamicDiscountAmount = Check.NotNull(dynamicDiscountAmount, nameof(dynamicDiscountAmount)); |
|||
} |
|||
} |
|||
@ -0,0 +1,89 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Orders.Orders; |
|||
using EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
using EasyAbp.EShop.Products.Products; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Json; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.PromotionTypes.MinQuantityOrderDiscount; |
|||
|
|||
public class MinQuantityOrderDiscountPromotionHandler : PromotionHandlerBase, IScopedDependency |
|||
{ |
|||
public static string MinQuantityOrderDiscountPromotionTypeName { get; set; } = "MinQuantityOrderDiscount"; |
|||
|
|||
public MinQuantityOrderDiscountPromotionHandler(IJsonSerializer jsonSerializer) : base(jsonSerializer) |
|||
{ |
|||
} |
|||
|
|||
public override Task HandleProductAsync(ProductDiscountContext context, Promotion promotion) |
|||
{ |
|||
foreach (var discountModel in GetConfigurations<MinQuantityOrderDiscountConfigurations>(promotion).Discounts) |
|||
{ |
|||
if (!discountModel.IsInScope(context.Product.ProductGroupName, context.Product.Id, context.ProductSku.Id)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var newDiscount = new OrderDiscountPreviewInfoModel(PromotionConsts.PromotionEffectGroup, |
|||
PromotionConsts.PromotionDiscountName, promotion.UniqueName, promotion.DisplayName, promotion.FromTime, |
|||
promotion.ToTime); |
|||
|
|||
context.OrderDiscountPreviews.Add(newDiscount); |
|||
} |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
public override Task HandleOrderAsync(OrderDiscountContext context, Promotion promotion) |
|||
{ |
|||
foreach (var discountModel in GetConfigurations<MinQuantityOrderDiscountConfigurations>(promotion).Discounts) |
|||
{ |
|||
if (context.Order.Currency != discountModel.DynamicDiscountAmount.Currency) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
foreach (var orderLine in context.Order.OrderLines) |
|||
{ |
|||
if (discountModel.MinQuantity > orderLine.Quantity) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
if (!discountModel.IsInScope(orderLine.ProductGroupName, orderLine.ProductId, orderLine.ProductSkuId)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var dynamicDiscountAmountModel = new DynamicDiscountAmountModel( |
|||
discountModel.DynamicDiscountAmount.Currency, |
|||
discountModel.DynamicDiscountAmount.DiscountAmount * orderLine.Quantity, |
|||
discountModel.DynamicDiscountAmount.DiscountRate, |
|||
discountModel.DynamicDiscountAmount.CalculatorName); |
|||
|
|||
context.CandidateDiscounts.Add(new OrderDiscountInfoModel(new List<Guid> { orderLine.Id }, |
|||
PromotionConsts.PromotionEffectGroup, PromotionConsts.PromotionDiscountName, promotion.UniqueName, |
|||
promotion.DisplayName, dynamicDiscountAmountModel)); |
|||
} |
|||
} |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
public override Task<object?> CreateConfigurationsObjectOrNullAsync() |
|||
{ |
|||
var configuration = new MinQuantityOrderDiscountConfigurations(); |
|||
|
|||
configuration.Discounts.Add(new MinQuantityOrderDiscountModel(new List<ProductScopeModel> { new() }, |
|||
2, new DynamicDiscountAmountModel("USD", 0m, 0m, null))); |
|||
|
|||
return Task.FromResult<object?>(configuration); |
|||
} |
|||
|
|||
public override bool IsConfigurationValid(string configurations) |
|||
{ |
|||
return JsonSerializer.Deserialize<MinQuantityOrderDiscountConfigurations>(configurations) is not null; |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using EasyAbp.EShop.Plugins.Promotions.Options; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.PromotionTypes.MinQuantityOrderDiscount; |
|||
|
|||
public static class MinQuantityOrderDiscountPromotionTypeConfigurationsExtensions |
|||
{ |
|||
public static void AddMinQuantityOrderDiscountPromotionType(this PromotionTypeConfigurations configurations) |
|||
{ |
|||
configurations.AddOrUpdate(new PromotionTypeDefinition( |
|||
MinQuantityOrderDiscountPromotionHandler.MinQuantityOrderDiscountPromotionTypeName, |
|||
typeof(MinQuantityOrderDiscountPromotionHandler))); |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
using System; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.PromotionTypes; |
|||
|
|||
public class ProductScopeModel |
|||
{ |
|||
/// <summary>
|
|||
/// The specified product group is affected when this property is set.
|
|||
/// </summary>
|
|||
public string? ProductGroupName { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The specified product (including all SKUs) is affected when this property is set.
|
|||
/// </summary>
|
|||
public Guid? ProductId { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The specified product SKU is affected when this property is set.
|
|||
/// </summary>
|
|||
public Guid? ProductSkuId { get; set; } |
|||
|
|||
public string? CustomScope { get; set; } |
|||
|
|||
public ProductScopeModel() |
|||
{ |
|||
} |
|||
|
|||
public ProductScopeModel(string? productGroupName, Guid? productId, Guid? productSkuId, string? customScope) |
|||
{ |
|||
ProductGroupName = productGroupName; |
|||
ProductId = productId; |
|||
ProductSkuId = productSkuId; |
|||
CustomScope = customScope; |
|||
} |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
using System; |
|||
using System.Collections.Concurrent; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Orders.Orders; |
|||
using EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
using EasyAbp.EShop.Products.Products; |
|||
using Volo.Abp.Json; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.PromotionTypes; |
|||
|
|||
public abstract class PromotionHandlerBase : IPromotionHandler |
|||
{ |
|||
protected ConcurrentDictionary<string, object?> ConfigurationCaches { get; } = new(); |
|||
|
|||
protected IJsonSerializer JsonSerializer { get; } |
|||
|
|||
public PromotionHandlerBase(IJsonSerializer jsonSerializer) |
|||
{ |
|||
JsonSerializer = jsonSerializer; |
|||
} |
|||
|
|||
public abstract Task HandleProductAsync(ProductDiscountContext context, Promotion promotion); |
|||
|
|||
public abstract Task HandleOrderAsync(OrderDiscountContext context, Promotion promotion); |
|||
|
|||
public abstract Task<object?> CreateConfigurationsObjectOrNullAsync(); |
|||
|
|||
public abstract bool IsConfigurationValid(string configurations); |
|||
|
|||
protected virtual TConfigurations GetConfigurations<TConfigurations>(Promotion promotion) |
|||
{ |
|||
if (promotion.Configurations.IsNullOrWhiteSpace()) |
|||
{ |
|||
return CreateEmptyConfigurations<TConfigurations>(); |
|||
} |
|||
|
|||
var cachedConfigurations = ConfigurationCaches.GetOrAdd(promotion.Configurations, |
|||
JsonSerializer.Deserialize<TConfigurations>(promotion.Configurations)); |
|||
|
|||
return cachedConfigurations is not null |
|||
? (TConfigurations)cachedConfigurations |
|||
: CreateEmptyConfigurations<TConfigurations>(); |
|||
} |
|||
|
|||
protected virtual TConfigurations CreateEmptyConfigurations<TConfigurations>() |
|||
{ |
|||
return JsonSerializer.Deserialize<TConfigurations>("{}"); |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.PromotionTypes; |
|||
|
|||
public class PromotionTypeDefinition |
|||
{ |
|||
public string Name { get; } |
|||
|
|||
public Type PromotionHandlerType { get; } |
|||
|
|||
public PromotionTypeDefinition(string name, Type promotionHandlerType) |
|||
{ |
|||
Name = name; |
|||
PromotionHandlerType = promotionHandlerType; |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.PromotionTypes.SimpleProductDiscount; |
|||
|
|||
public class SimpleProductDiscountConfigurations |
|||
{ |
|||
public List<SimpleProductDiscountModel> Discounts { get; set; } = new(); |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
using System.Collections.Generic; |
|||
using EasyAbp.EShop.Products.Products; |
|||
using Volo.Abp; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.PromotionTypes.SimpleProductDiscount; |
|||
|
|||
public class SimpleProductDiscountModel : IHasProductScopes, IHasDynamicDiscountAmount |
|||
{ |
|||
public List<ProductScopeModel> ProductScopes { get; set; } = new(); |
|||
|
|||
public DynamicDiscountAmountModel DynamicDiscountAmount { get; set; } |
|||
|
|||
public SimpleProductDiscountModel() |
|||
{ |
|||
} |
|||
|
|||
public SimpleProductDiscountModel(List<ProductScopeModel> productScopes, |
|||
DynamicDiscountAmountModel dynamicDiscountAmount) |
|||
{ |
|||
if (!productScopes.IsNullOrEmpty()) |
|||
{ |
|||
ProductScopes = productScopes; |
|||
} |
|||
|
|||
DynamicDiscountAmount = Check.NotNull(dynamicDiscountAmount, nameof(dynamicDiscountAmount)); |
|||
} |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Orders.Orders; |
|||
using EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
using EasyAbp.EShop.Products.Products; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Json; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.PromotionTypes.SimpleProductDiscount; |
|||
|
|||
public class SimpleProductDiscountPromotionHandler : PromotionHandlerBase, IScopedDependency |
|||
{ |
|||
public static string SimpleProductDiscountPromotionTypeName { get; set; } = "SimpleProductDiscount"; |
|||
|
|||
public SimpleProductDiscountPromotionHandler(IJsonSerializer jsonSerializer) : base(jsonSerializer) |
|||
{ |
|||
} |
|||
|
|||
public override Task HandleProductAsync(ProductDiscountContext context, Promotion promotion) |
|||
{ |
|||
foreach (var discountModel in GetConfigurations<SimpleProductDiscountConfigurations>(promotion).Discounts) |
|||
{ |
|||
if (context.ProductSku.Currency != discountModel.DynamicDiscountAmount.Currency) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
if (!discountModel.IsInScope(context.Product.ProductGroupName, context.Product.Id, context.ProductSku.Id)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var discount = new CandidateProductDiscountInfoModel(PromotionConsts.PromotionEffectGroup, |
|||
PromotionConsts.PromotionDiscountName, promotion.UniqueName, promotion.DisplayName, |
|||
discountModel.DynamicDiscountAmount, promotion.FromTime, promotion.ToTime); |
|||
|
|||
context.CandidateProductDiscounts.Add(discount); |
|||
} |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
public override Task HandleOrderAsync(OrderDiscountContext context, Promotion promotion) |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
public override Task<object?> CreateConfigurationsObjectOrNullAsync() |
|||
{ |
|||
var configuration = new SimpleProductDiscountConfigurations(); |
|||
|
|||
configuration.Discounts.Add(new SimpleProductDiscountModel(new List<ProductScopeModel> { new() }, |
|||
new DynamicDiscountAmountModel("USD", 0m, 0m, null))); |
|||
|
|||
return Task.FromResult<object?>(configuration); |
|||
} |
|||
|
|||
public override bool IsConfigurationValid(string configurations) |
|||
{ |
|||
return JsonSerializer.Deserialize<SimpleProductDiscountConfigurations>(configurations) is not null; |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using EasyAbp.EShop.Plugins.Promotions.Options; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.PromotionTypes.SimpleProductDiscount; |
|||
|
|||
public static class SimpleProductDiscountPromotionTypeConfigurationsExtensions |
|||
{ |
|||
public static void AddSimpleProductDiscountPromotionType(this PromotionTypeConfigurations configurations) |
|||
{ |
|||
configurations.AddOrUpdate(new PromotionTypeDefinition( |
|||
SimpleProductDiscountPromotionHandler.SimpleProductDiscountPromotionTypeName, |
|||
typeof(SimpleProductDiscountPromotionHandler))); |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using System; |
|||
using Volo.Abp.Domain.Repositories; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
|
|||
public interface IPromotionRepository : IRepository<Promotion, Guid> |
|||
{ |
|||
} |
|||
@ -0,0 +1,70 @@ |
|||
using System; |
|||
using EasyAbp.EShop.Stores.Stores; |
|||
using Volo.Abp.Domain.Entities.Auditing; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
|
|||
public class Promotion : FullAuditedAggregateRoot<Guid>, IMultiTenant, IMultiStore |
|||
{ |
|||
public virtual Guid? TenantId { get; protected set; } |
|||
|
|||
public virtual Guid StoreId { get; protected set; } |
|||
|
|||
/// <summary>
|
|||
/// Value of the promotion type name. It is used as the DiscountName (with EffectGroup == `Promotion`)
|
|||
/// </summary>
|
|||
/// <example>SimpleProductDiscount</example>
|
|||
public virtual string PromotionType { get; protected set; } |
|||
|
|||
/// <summary>
|
|||
/// An immutable and unique name for the promotion. It is used as the DiscountKey (with EffectGroup == `Promotion`).
|
|||
/// </summary>
|
|||
public virtual string UniqueName { get; protected set; } |
|||
|
|||
public virtual string DisplayName { get; protected set; } |
|||
|
|||
/// <summary>
|
|||
/// The promotion type-specific serialized configurations value.
|
|||
/// </summary>
|
|||
public virtual string Configurations { get; protected set; } |
|||
|
|||
public virtual DateTime? FromTime { get; protected set; } |
|||
|
|||
public virtual DateTime? ToTime { get; protected set; } |
|||
|
|||
public virtual bool Disabled { get; protected set; } |
|||
|
|||
public virtual int Priority { get; protected set; } |
|||
|
|||
protected Promotion() |
|||
{ |
|||
} |
|||
|
|||
internal Promotion(Guid id, Guid? tenantId, Guid storeId, string promotionType, string uniqueName, |
|||
string displayName, string configurations, DateTime? fromTime, DateTime? toTime, bool disabled, |
|||
int priority) : base(id) |
|||
{ |
|||
TenantId = tenantId; |
|||
StoreId = storeId; |
|||
PromotionType = promotionType; |
|||
UniqueName = uniqueName; |
|||
DisplayName = displayName; |
|||
Configurations = configurations; |
|||
FromTime = fromTime; |
|||
ToTime = toTime; |
|||
Disabled = disabled; |
|||
Priority = priority; |
|||
} |
|||
|
|||
internal void Update(string displayName, string configurations, DateTime? fromTime, DateTime? toTime, bool disabled, |
|||
int priority) |
|||
{ |
|||
DisplayName = displayName; |
|||
Configurations = configurations; |
|||
FromTime = fromTime; |
|||
ToTime = toTime; |
|||
Disabled = disabled; |
|||
Priority = priority; |
|||
} |
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Plugins.Promotions.Options; |
|||
using EasyAbp.EShop.Plugins.Promotions.PromotionTypes; |
|||
using Microsoft.Extensions.Options; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Domain.Repositories; |
|||
using Volo.Abp.Domain.Services; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
|
|||
public class PromotionManager : DomainService |
|||
{ |
|||
protected IPromotionRepository Repository => LazyServiceProvider.LazyGetRequiredService<IPromotionRepository>(); |
|||
|
|||
protected EShopPluginsPromotionsOptions Options => |
|||
LazyServiceProvider.LazyGetRequiredService<IOptions<EShopPluginsPromotionsOptions>>().Value; |
|||
|
|||
[UnitOfWork] |
|||
public virtual async Task<Promotion> CreateAsync(Guid storeId, string promotionType, string uniqueName, |
|||
string displayName, string configurations, DateTime? fromTime, DateTime? toTime, bool disabled, int priority) |
|||
{ |
|||
if (await Repository.AnyAsync(x => x.StoreId == storeId && x.UniqueName == uniqueName)) |
|||
{ |
|||
throw new BusinessException(PromotionsErrorCodes.DuplicatePromotionUniqueName); |
|||
} |
|||
|
|||
return new Promotion(GuidGenerator.Create(), CurrentTenant.Id, storeId, promotionType, uniqueName, displayName, |
|||
VerifyAndMinifyConfigurations(promotionType, configurations), fromTime, toTime, disabled, priority); |
|||
} |
|||
|
|||
public virtual Task UpdateAsync(Promotion promotion, string displayName, string configurations, |
|||
DateTime? fromTime, DateTime? toTime, bool disabled, int priority) |
|||
{ |
|||
promotion.Update(displayName, configurations, fromTime, toTime, disabled, priority); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
protected virtual string VerifyAndMinifyConfigurations(string promotionType, string inputConfigurations) |
|||
{ |
|||
var promotionTypeDefinition = Options.PromotionTypes.GetOrNull(promotionType); |
|||
|
|||
if (promotionTypeDefinition is null) |
|||
{ |
|||
throw new BusinessException(PromotionsErrorCodes.InvalidPromotionType); |
|||
} |
|||
|
|||
var handler = GetPromotionHandler(promotionTypeDefinition); |
|||
|
|||
var formattedJson = JToken.Parse(inputConfigurations).ToString(Formatting.None); |
|||
|
|||
if (!handler.IsConfigurationValid(formattedJson)) |
|||
{ |
|||
throw new BusinessException(PromotionsErrorCodes.InvalidPromotionConfigurations); |
|||
} |
|||
|
|||
return formattedJson; |
|||
} |
|||
|
|||
protected virtual IPromotionHandler GetPromotionHandler(PromotionTypeDefinition definition) |
|||
{ |
|||
return (IPromotionHandler)LazyServiceProvider.LazyGetRequiredService(definition.PromotionHandlerType); |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
namespace EasyAbp.EShop.Plugins.Promotions; |
|||
|
|||
public static class PromotionsDbProperties |
|||
{ |
|||
public static string DbTablePrefix { get; set; } = "EasyAbpEShopPluginsPromotions"; |
|||
|
|||
public static string? DbSchema { get; set; } = null; |
|||
|
|||
public const string ConnectionStringName = "EasyAbpEShopPluginsPromotions"; |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using Volo.Abp.Settings; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Settings; |
|||
|
|||
public class PromotionsSettingDefinitionProvider : SettingDefinitionProvider |
|||
{ |
|||
public override void Define(ISettingDefinitionContext context) |
|||
{ |
|||
/* Define module settings here. |
|||
* Use names from PromotionsSettings class. |
|||
*/ |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
namespace EasyAbp.EShop.Plugins.Promotions.Settings; |
|||
|
|||
public static class PromotionsSettings |
|||
{ |
|||
public const string GroupName = "EasyAbp.EShop.Plugins.Promotions"; |
|||
|
|||
/* Add constants for setting names. Example: |
|||
* public const string MySettingName = GroupName + ".MySettingName"; |
|||
*/ |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -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> |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"role": "lib.ef" |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net7.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="$(AbpVersion)" /> |
|||
<ProjectReference Include="..\EasyAbp.EShop.Plugins.Promotions.Domain\EasyAbp.EShop.Plugins.Promotions.Domain.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Folder Include="EasyAbp\EShop\Plugins\Promotions" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,24 @@ |
|||
using EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore; |
|||
|
|||
[DependsOn( |
|||
typeof(EShopPluginsPromotionsDomainModule), |
|||
typeof(AbpEntityFrameworkCoreModule) |
|||
)] |
|||
public class EShopPluginsPromotionsEntityFrameworkCoreModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddAbpDbContext<PromotionsDbContext>(options => |
|||
{ |
|||
/* Add custom repositories here. Example: |
|||
* options.AddRepository<Question, EfCoreQuestionRepository>(); |
|||
*/ |
|||
options.AddRepository<Promotion, PromotionRepository>(); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
using EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore; |
|||
|
|||
[ConnectionStringName(PromotionsDbProperties.ConnectionStringName)] |
|||
public interface IPromotionsDbContext : IEfCoreDbContext |
|||
{ |
|||
/* Add DbSet for each Aggregate Root here. Example: |
|||
* DbSet<Question> Questions { get; } |
|||
*/ |
|||
DbSet<Promotion> Promotions { get; set; } |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
using EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore; |
|||
|
|||
[ConnectionStringName(PromotionsDbProperties.ConnectionStringName)] |
|||
public class PromotionsDbContext : AbpDbContext<PromotionsDbContext>, IPromotionsDbContext |
|||
{ |
|||
/* Add DbSet for each Aggregate Root here. Example: |
|||
* public DbSet<Question> Questions { get; set; } |
|||
*/ |
|||
public DbSet<Promotion> Promotions { get; set; } |
|||
|
|||
public PromotionsDbContext(DbContextOptions<PromotionsDbContext> options) |
|||
: base(options) |
|||
{ |
|||
|
|||
} |
|||
|
|||
protected override void OnModelCreating(ModelBuilder builder) |
|||
{ |
|||
base.OnModelCreating(builder); |
|||
|
|||
builder.ConfigureEShopPluginsPromotions(); |
|||
} |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
using EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Volo.Abp; |
|||
using Volo.Abp.EntityFrameworkCore.Modeling; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore; |
|||
|
|||
public static class PromotionsDbContextModelCreatingExtensions |
|||
{ |
|||
public static void ConfigureEShopPluginsPromotions( |
|||
this ModelBuilder builder) |
|||
{ |
|||
Check.NotNull(builder, nameof(builder)); |
|||
|
|||
/* Configure all entities here. Example: |
|||
|
|||
builder.Entity<Question>(b => |
|||
{ |
|||
//Configure table & schema name
|
|||
b.ToTable(PromotionsDbProperties.DbTablePrefix + "Questions", PromotionsDbProperties.DbSchema); |
|||
|
|||
b.ConfigureByConvention(); |
|||
|
|||
//Properties
|
|||
b.Property(q => q.Title).IsRequired().HasMaxLength(QuestionConsts.MaxTitleLength); |
|||
|
|||
//Relations
|
|||
b.HasMany(question => question.Tags).WithOne().HasForeignKey(qt => qt.QuestionId); |
|||
|
|||
//Indexes
|
|||
b.HasIndex(q => q.CreationTime); |
|||
}); |
|||
*/ |
|||
|
|||
|
|||
builder.Entity<Promotion>(b => |
|||
{ |
|||
b.ToTable(PromotionsDbProperties.DbTablePrefix + "Promotions", PromotionsDbProperties.DbSchema); |
|||
b.ConfigureByConvention(); |
|||
|
|||
|
|||
/* Configure more properties here */ |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using System.Linq; |
|||
using Microsoft.EntityFrameworkCore; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
|
|||
public static class PromotionEfCoreQueryableExtensions |
|||
{ |
|||
public static IQueryable<Promotion> IncludeDetails(this IQueryable<Promotion> queryable, bool include = true) |
|||
{ |
|||
if (!include) |
|||
{ |
|||
return queryable; |
|||
} |
|||
|
|||
return queryable |
|||
// .Include(x => x.xxx) // TODO: AbpHelper generated
|
|||
; |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Plugins.Promotions.EntityFrameworkCore; |
|||
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions.Promotions; |
|||
|
|||
public class PromotionRepository : EfCoreRepository<IPromotionsDbContext, Promotion, Guid>, IPromotionRepository |
|||
{ |
|||
public PromotionRepository(IDbContextProvider<IPromotionsDbContext> dbContextProvider) : base(dbContextProvider) |
|||
{ |
|||
} |
|||
|
|||
public override async Task<IQueryable<Promotion>> WithDetailsAsync() |
|||
{ |
|||
return (await GetQueryableAsync()).IncludeDetails(); |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -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> |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"role": "lib.http-api-client" |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.Http.Client" Version="$(AbpVersion)" /> |
|||
<ProjectReference Include="..\EasyAbp.EShop.Plugins.Promotions.Application.Contracts\EasyAbp.EShop.Plugins.Promotions.Application.Contracts.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<EmbeddedResource Include="**\*generate-proxy.json" /> |
|||
<Content Remove="**\*generate-proxy.json" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,26 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Http.Client; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace EasyAbp.EShop.Plugins.Promotions; |
|||
|
|||
[DependsOn( |
|||
typeof(EShopPluginsPromotionsApplicationContractsModule), |
|||
typeof(AbpHttpClientModule))] |
|||
public class EShopPluginsPromotionsHttpApiClientModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddHttpClientProxies( |
|||
typeof(EShopPluginsPromotionsApplicationContractsModule).Assembly, |
|||
EShopPluginsPromotionsRemoteServiceConsts.RemoteServiceName |
|||
); |
|||
|
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<EShopPluginsPromotionsHttpApiClientModule>(); |
|||
}); |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue