├── .dockerignore ├── .gitignore ├── EmailSendingService ├── EmailSendingService.csproj ├── Program.cs ├── Properties │ └── launchSettings.json ├── Worker.cs ├── appsettings.Development.json └── appsettings.json ├── Invoice.Applicaion ├── CQRS │ ├── Behaviors │ │ └── LoggingBehavior.cs │ ├── Commands │ │ └── AddProductCommand.cs │ ├── Handlers │ │ ├── AddProductHandler.cs │ │ ├── AuditLogHandler.cs │ │ ├── EmailHandler.cs │ │ └── GetProductsHandler.cs │ ├── Notifications │ │ └── ProductAddedNotification.cs │ └── Queries │ │ └── GetProductQuery.cs ├── Interfaces │ ├── ICustomerDapperService.cs │ ├── IInvoiceService.cs │ └── ITokenService.cs ├── Invoice.Applicaion.csproj ├── Services │ ├── CustomerDapperService.cs │ ├── InvoiceService.cs │ └── TokenService.cs └── Validations │ ├── CommonValidator.cs │ ├── InvoiceDetailsValidator.cs │ └── InvoiceInfoValidator.cs ├── Invoice.Domain ├── DTO │ ├── InvoiceDTO.cs │ ├── InvoiceDetailsDTO.cs │ └── InvoiceInfoDTO.cs ├── Entity │ ├── Customer.cs │ ├── InvoiceDetails.cs │ ├── InvoiceInfo.cs │ ├── Product.cs │ └── UserModel.cs ├── ErrorDetails.cs ├── Invoice.Domain.csproj ├── PagedList.cs └── PagingRequestModel.cs ├── Invoice.Infra.Data ├── AppDbContext.cs ├── Extention │ └── Sort.cs ├── Interfaces │ ├── ICustomeDapperRepository.cs │ ├── IGenericRepository.cs │ ├── IInvoiceDetailsRepository.cs │ ├── IInvoiceInfoRepository.cs │ ├── IProductRepository.cs │ └── IUnitOfWork.cs ├── Invoice.Infra.Data.csproj ├── Migrations │ ├── 20221030060130_initialmigration.Designer.cs │ ├── 20221030060130_initialmigration.cs │ ├── 20221106033723_createddateadded.Designer.cs │ ├── 20221106033723_createddateadded.cs │ ├── 20221113100754_addedInvoicedetails.Designer.cs │ ├── 20221113100754_addedInvoicedetails.cs │ ├── 20221117103840_namemodification.Designer.cs │ ├── 20221117103840_namemodification.cs │ ├── 20221117104032_namemodification1.Designer.cs │ ├── 20221117104032_namemodification1.cs │ ├── 20221202114309_addproduct.Designer.cs │ ├── 20221202114309_addproduct.cs │ ├── 20230109094723_add customer entity.Designer.cs │ ├── 20230109094723_add customer entity.cs │ └── AppDbContextModelSnapshot.cs ├── PagerExtension.cs └── Repository │ ├── CustomerDapperRepository.cs │ ├── GenericRepository.cs │ ├── InvoiceDetailsRepository.cs │ ├── InvoiceInfoRepository.cs │ ├── ProductRepository.cs │ └── UnitOfWork.cs ├── Invoice.Services.API ├── Controllers │ ├── CustomerController.cs │ ├── InvoiceController.cs │ ├── ProductController.cs │ ├── UserController.cs │ └── WeatherForecastController.cs ├── Dockerfile ├── ExceptionMiddleware.cs ├── Invoice.Services.API.csproj ├── MappingProfiles.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── WeatherForecast.cs ├── appsettings.Development.json └── appsettings.json ├── Invoice.sln └── README.md /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | LICENSE 25 | README.md -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | *.dll 13 | 14 | # User-specific files (MonoDevelop/Xamarin Studio) 15 | *.userprefs 16 | 17 | # Mono auto generated files 18 | mono_crash.* 19 | 20 | # Build results 21 | [Dd]ebug/ 22 | [Dd]ebugPublic/ 23 | [Rr]elease/ 24 | [Rr]eleases/ 25 | x64/ 26 | x86/ 27 | [Ww][Ii][Nn]32/ 28 | [Aa][Rr][Mm]/ 29 | [Aa][Rr][Mm]64/ 30 | bld/ 31 | [Bb]in/ 32 | [Oo]bj/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # Tye 67 | .tye/ 68 | 69 | # ASP.NET Scaffolding 70 | ScaffoldingReadMe.txt 71 | 72 | # StyleCop 73 | StyleCopReport.xml 74 | 75 | # Files built by Visual Studio 76 | *_i.c 77 | *_p.c 78 | *_h.h 79 | *.ilk 80 | *.meta 81 | *.obj 82 | *.iobj 83 | *.pch 84 | *.pdb 85 | *.ipdb 86 | *.pgc 87 | *.pgd 88 | *.rsp 89 | *.sbr 90 | *.tlb 91 | *.tli 92 | *.tlh 93 | *.tmp 94 | *.tmp_proj 95 | *_wpftmp.csproj 96 | *.log 97 | *.vspscc 98 | *.vssscc 99 | .builds 100 | *.pidb 101 | *.svclog 102 | *.scc 103 | 104 | # Chutzpah Test files 105 | _Chutzpah* 106 | 107 | # Visual C++ cache files 108 | ipch/ 109 | *.aps 110 | *.ncb 111 | *.opendb 112 | *.opensdf 113 | *.sdf 114 | *.cachefile 115 | *.VC.db 116 | *.VC.VC.opendb 117 | 118 | # Visual Studio profiler 119 | *.psess 120 | *.vsp 121 | *.vspx 122 | *.sap 123 | 124 | # Visual Studio Trace Files 125 | *.e2e 126 | 127 | # TFS 2012 Local Workspace 128 | $tf/ 129 | 130 | # Guidance Automation Toolkit 131 | *.gpState 132 | 133 | # ReSharper is a .NET coding add-in 134 | _ReSharper*/ 135 | *.[Rr]e[Ss]harper 136 | *.DotSettings.user 137 | 138 | # TeamCity is a build add-in 139 | _TeamCity* 140 | 141 | # DotCover is a Code Coverage Tool 142 | *.dotCover 143 | 144 | # AxoCover is a Code Coverage Tool 145 | .axoCover/* 146 | !.axoCover/settings.json 147 | 148 | # Coverlet is a free, cross platform Code Coverage Tool 149 | coverage*.json 150 | coverage*.xml 151 | coverage*.info 152 | 153 | # Visual Studio code coverage results 154 | *.coverage 155 | *.coveragexml 156 | 157 | # NCrunch 158 | _NCrunch_* 159 | .*crunch*.local.xml 160 | nCrunchTemp_* 161 | 162 | # MightyMoose 163 | *.mm.* 164 | AutoTest.Net/ 165 | 166 | # Web workbench (sass) 167 | .sass-cache/ 168 | 169 | # Installshield output folder 170 | [Ee]xpress/ 171 | 172 | # DocProject is a documentation generator add-in 173 | DocProject/buildhelp/ 174 | DocProject/Help/*.HxT 175 | DocProject/Help/*.HxC 176 | DocProject/Help/*.hhc 177 | DocProject/Help/*.hhk 178 | DocProject/Help/*.hhp 179 | DocProject/Help/Html2 180 | DocProject/Help/html 181 | 182 | # Click-Once directory 183 | publish/ 184 | 185 | # Publish Web Output 186 | *.[Pp]ublish.xml 187 | *.azurePubxml 188 | # Note: Comment the next line if you want to checkin your web deploy settings, 189 | # but database connection strings (with potential passwords) will be unencrypted 190 | *.pubxml 191 | *.publishproj 192 | 193 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 194 | # checkin your Azure Web App publish settings, but sensitive information contained 195 | # in these scripts will be unencrypted 196 | PublishScripts/ 197 | 198 | # NuGet Packages 199 | *.nupkg 200 | # NuGet Symbol Packages 201 | *.snupkg 202 | # The packages folder can be ignored because of Package Restore 203 | **/[Pp]ackages/* 204 | # except build/, which is used as an MSBuild target. 205 | !**/[Pp]ackages/build/ 206 | # Uncomment if necessary however generally it will be regenerated when needed 207 | #!**/[Pp]ackages/repositories.config 208 | # NuGet v3's project.json files produces more ignorable files 209 | *.nuget.props 210 | *.nuget.targets 211 | 212 | # Microsoft Azure Build Output 213 | csx/ 214 | *.build.csdef 215 | 216 | # Microsoft Azure Emulator 217 | ecf/ 218 | rcf/ 219 | 220 | # Windows Store app package directories and files 221 | AppPackages/ 222 | BundleArtifacts/ 223 | Package.StoreAssociation.xml 224 | _pkginfo.txt 225 | *.appx 226 | *.appxbundle 227 | *.appxupload 228 | 229 | # Visual Studio cache files 230 | # files ending in .cache can be ignored 231 | *.[Cc]ache 232 | # but keep track of directories ending in .cache 233 | !?*.[Cc]ache/ 234 | 235 | # Others 236 | ClientBin/ 237 | ~$* 238 | *~ 239 | *.dbmdl 240 | *.dbproj.schemaview 241 | *.jfm 242 | *.pfx 243 | *.publishsettings 244 | orleans.codegen.cs 245 | 246 | # Including strong name files can present a security risk 247 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 248 | #*.snk 249 | 250 | # Since there are multiple workflows, uncomment next line to ignore bower_components 251 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 252 | #bower_components/ 253 | 254 | # RIA/Silverlight projects 255 | Generated_Code/ 256 | 257 | # Backup & report files from converting an old project file 258 | # to a newer Visual Studio version. Backup files are not needed, 259 | # because we have git ;-) 260 | _UpgradeReport_Files/ 261 | Backup*/ 262 | UpgradeLog*.XML 263 | UpgradeLog*.htm 264 | ServiceFabricBackup/ 265 | *.rptproj.bak 266 | 267 | # SQL Server files 268 | *.mdf 269 | *.ldf 270 | *.ndf 271 | 272 | # Business Intelligence projects 273 | *.rdl.data 274 | *.bim.layout 275 | *.bim_*.settings 276 | *.rptproj.rsuser 277 | *- [Bb]ackup.rdl 278 | *- [Bb]ackup ([0-9]).rdl 279 | *- [Bb]ackup ([0-9][0-9]).rdl 280 | 281 | # Microsoft Fakes 282 | FakesAssemblies/ 283 | 284 | # GhostDoc plugin setting file 285 | *.GhostDoc.xml 286 | 287 | # Node.js Tools for Visual Studio 288 | .ntvs_analysis.dat 289 | node_modules/ 290 | 291 | # Visual Studio 6 build log 292 | *.plg 293 | 294 | # Visual Studio 6 workspace options file 295 | *.opt 296 | 297 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 298 | *.vbw 299 | 300 | # Visual Studio LightSwitch build output 301 | **/*.HTMLClient/GeneratedArtifacts 302 | **/*.DesktopClient/GeneratedArtifacts 303 | **/*.DesktopClient/ModelManifest.xml 304 | **/*.Server/GeneratedArtifacts 305 | **/*.Server/ModelManifest.xml 306 | _Pvt_Extensions 307 | 308 | # Paket dependency manager 309 | .paket/paket.exe 310 | paket-files/ 311 | 312 | # FAKE - F# Make 313 | .fake/ 314 | 315 | # CodeRush personal settings 316 | .cr/personal 317 | 318 | # Python Tools for Visual Studio (PTVS) 319 | __pycache__/ 320 | *.pyc 321 | 322 | # Cake - Uncomment if you are using it 323 | # tools/** 324 | # !tools/packages.config 325 | 326 | # Tabs Studio 327 | *.tss 328 | 329 | # Telerik's JustMock configuration file 330 | *.jmconfig 331 | 332 | # BizTalk build output 333 | *.btp.cs 334 | *.btm.cs 335 | *.odx.cs 336 | *.xsd.cs 337 | 338 | # OpenCover UI analysis results 339 | OpenCover/ 340 | 341 | # Azure Stream Analytics local run output 342 | ASALocalRun/ 343 | 344 | # MSBuild Binary and Structured Log 345 | *.binlog 346 | 347 | # NVidia Nsight GPU debugger configuration file 348 | *.nvuser 349 | 350 | # MFractors (Xamarin productivity tool) working folder 351 | .mfractor/ 352 | 353 | # Local History for Visual Studio 354 | .localhistory/ 355 | 356 | # BeatPulse healthcheck temp database 357 | healthchecksdb 358 | 359 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 360 | MigrationBackup/ 361 | 362 | # Ionide (cross platform F# VS Code tools) working folder 363 | .ionide/ 364 | 365 | # Fody - auto-generated XML schema 366 | FodyWeavers.xsd 367 | 368 | ## 369 | ## Visual studio for Mac 370 | ## 371 | 372 | 373 | # globs 374 | Makefile.in 375 | *.userprefs 376 | *.usertasks 377 | config.make 378 | config.status 379 | aclocal.m4 380 | install-sh 381 | autom4te.cache/ 382 | *.tar.gz 383 | tarballs/ 384 | test-results/ 385 | 386 | # Mac bundle stuff 387 | *.dmg 388 | *.app 389 | 390 | # content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore 391 | # General 392 | .DS_Store 393 | .AppleDouble 394 | .LSOverride 395 | 396 | # Icon must end with two \r 397 | Icon 398 | 399 | 400 | # Thumbnails 401 | ._* 402 | 403 | # Files that might appear in the root of a volume 404 | .DocumentRevisions-V100 405 | .fseventsd 406 | .Spotlight-V100 407 | .TemporaryItems 408 | .Trashes 409 | .VolumeIcon.icns 410 | .com.apple.timemachine.donotpresent 411 | 412 | # Directories potentially created on remote AFP share 413 | .AppleDB 414 | .AppleDesktop 415 | Network Trash Folder 416 | Temporary Items 417 | .apdisk 418 | 419 | # content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore 420 | # Windows thumbnail cache files 421 | Thumbs.db 422 | ehthumbs.db 423 | ehthumbs_vista.db 424 | 425 | # Dump file 426 | *.stackdump 427 | 428 | # Folder config file 429 | [Dd]esktop.ini 430 | 431 | # Recycle Bin used on file shares 432 | $RECYCLE.BIN/ 433 | 434 | # Windows Installer files 435 | *.cab 436 | *.msi 437 | *.msix 438 | *.msm 439 | *.msp 440 | 441 | # Windows shortcuts 442 | *.lnk 443 | 444 | # JetBrains Rider 445 | .idea/ 446 | *.sln.iml 447 | 448 | ## 449 | ## Visual Studio Code 450 | ## 451 | .vscode/* 452 | !.vscode/settings.json 453 | !.vscode/tasks.json 454 | !.vscode/launch.json 455 | !.vscode/extensions.json 456 | -------------------------------------------------------------------------------- /EmailSendingService/EmailSendingService.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | dotnet-EmailSendingService-54BABC2A-BEDE-4557-AB29-B76C0FA1E2A2 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /EmailSendingService/Program.cs: -------------------------------------------------------------------------------- 1 | using EmailSendingService; 2 | 3 | IHost host = Host.CreateDefaultBuilder(args) 4 | .ConfigureServices(services => 5 | { 6 | services.AddHostedService(); 7 | }) 8 | .Build(); 9 | 10 | await host.RunAsync(); 11 | -------------------------------------------------------------------------------- /EmailSendingService/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "EmailSendingService": { 4 | "commandName": "Project", 5 | "dotnetRunMessages": true, 6 | "environmentVariables": { 7 | "DOTNET_ENVIRONMENT": "Development" 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /EmailSendingService/Worker.cs: -------------------------------------------------------------------------------- 1 | using RabbitMQ.Client; 2 | using RabbitMQ.Client.Events; 3 | using System.Text; 4 | 5 | namespace EmailSendingService 6 | { 7 | public class Worker : BackgroundService 8 | { 9 | private readonly ILogger _logger; 10 | private readonly IConnection _connection; 11 | private readonly IModel _channel; 12 | 13 | public Worker(ILogger logger) 14 | { 15 | _logger = logger; 16 | var factory = new ConnectionFactory() { HostName = "localhost" }; 17 | _connection = factory.CreateConnection(); 18 | _channel = _connection.CreateModel(); 19 | _channel.QueueDeclare(queue: "myqueue", durable: false, exclusive: false, autoDelete: false, arguments: null); 20 | } 21 | 22 | protected override async Task ExecuteAsync(CancellationToken stoppingToken) 23 | { 24 | while (!stoppingToken.IsCancellationRequested) 25 | { 26 | //_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); 27 | //await Task.Delay(1000, stoppingToken); 28 | 29 | var consumer = new EventingBasicConsumer(_channel); 30 | consumer.Received += (model, ea) => 31 | { 32 | var body = ea.Body.ToArray(); 33 | var message = Encoding.UTF8.GetString(body); 34 | // Process the message 35 | Console.WriteLine("Received: {0}", message); 36 | }; 37 | _channel.BasicConsume(queue: "myqueue", autoAck: true, consumer: consumer); 38 | } 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /EmailSendingService/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.Hosting.Lifetime": "Information" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /EmailSendingService/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.Hosting.Lifetime": "Information" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Invoice.Applicaion/CQRS/Behaviors/LoggingBehavior.cs: -------------------------------------------------------------------------------- 1 | using MediatR; 2 | using Microsoft.Extensions.Logging; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using Newtonsoft.Json; 9 | 10 | namespace Invoice.Applicaion.CQRS.Behaviors 11 | { 12 | public class LoggingBehavior : IPipelineBehavior 13 | where TRequest : IRequest 14 | { 15 | private readonly ILogger> _logger; 16 | 17 | public LoggingBehavior(ILogger> logger) 18 | { 19 | _logger = logger; 20 | } 21 | 22 | public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) 23 | { 24 | _logger.LogInformation($"Request: {typeof(TRequest).Name}"); 25 | var response = await next(); 26 | _logger.LogInformation($"Response: { JsonConvert.SerializeObject(response)}"); 27 | return response; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Invoice.Applicaion/CQRS/Commands/AddProductCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Invoice.Domain.Entity; 7 | using MediatR; 8 | 9 | namespace Invoice.Applicaion.CQRS.Commands 10 | { 11 | public class AddProductCommand : IRequest 12 | { 13 | public Product product { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Invoice.Applicaion/CQRS/Handlers/AddProductHandler.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Applicaion.CQRS.Commands; 2 | using Invoice.Applicaion.CQRS.Notifications; 3 | using Invoice.Domain.Entity; 4 | using Invoice.Infra.Data.Interfaces; 5 | using MediatR; 6 | 7 | namespace Invoice.Applicaion.CQRS.Handlers 8 | { 9 | public class AddProductHandler : IRequestHandler 10 | { 11 | private readonly IProductRepository _productRepository; 12 | private readonly IMediator _mediator; 13 | public AddProductHandler(IProductRepository productRepository, IMediator mediator) 14 | { 15 | _productRepository = productRepository; 16 | _mediator = mediator; 17 | } 18 | 19 | public async Task Handle(AddProductCommand request, CancellationToken cancellationToken) 20 | { 21 | var result = await _productRepository.CreateProduct(request.product); 22 | await _mediator.Publish(new ProductAddedNotification() { product = result }); 23 | return result; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Invoice.Applicaion/CQRS/Handlers/AuditLogHandler.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Applicaion.CQRS.Notifications; 2 | using MediatR; 3 | using Microsoft.Extensions.Logging; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Invoice.Applicaion.CQRS.Handlers 11 | { 12 | public class AuditLogHandler : INotificationHandler 13 | { 14 | private readonly ILogger _logger; 15 | public AuditLogHandler(ILogger logger) 16 | { 17 | _logger = logger; 18 | } 19 | public Task Handle(ProductAddedNotification notification, CancellationToken cancellationToken) 20 | { 21 | _logger.LogInformation("Audit logs added"); 22 | return Task.CompletedTask; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Invoice.Applicaion/CQRS/Handlers/EmailHandler.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Applicaion.CQRS.Notifications; 2 | using MediatR; 3 | using Microsoft.Extensions.Logging; 4 | using Newtonsoft.Json; 5 | using RabbitMQ.Client; 6 | using System.Text; 7 | 8 | namespace Invoice.Applicaion.CQRS.Handlers 9 | { 10 | public class EmailHandler : INotificationHandler 11 | { 12 | private readonly ILogger _logger; 13 | private readonly IConnection _connection; 14 | private readonly IModel _channle; 15 | public EmailHandler(ILogger logger) 16 | { 17 | _logger = logger; 18 | var factory = new ConnectionFactory() { HostName = "localhost" }; 19 | _connection = factory.CreateConnection(); 20 | _channle = _connection.CreateModel(); 21 | _channle.QueueDeclare(queue: "myqueue", durable: false, exclusive: false, autoDelete: false, arguments: null); 22 | } 23 | public Task Handle(ProductAddedNotification notification, CancellationToken cancellationToken) 24 | { 25 | var body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(notification.product)); 26 | _channle.BasicPublish(exchange: "", routingKey:"myqueue", basicProperties: null, body: body); 27 | 28 | _logger.LogInformation("Email sent"); 29 | return Task.CompletedTask; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Invoice.Applicaion/CQRS/Handlers/GetProductsHandler.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Applicaion.CQRS.Queries; 2 | using Invoice.Domain.Entity; 3 | using Invoice.Infra.Data.Interfaces; 4 | using MediatR; 5 | using Microsoft.EntityFrameworkCore; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace Invoice.Applicaion.CQRS.Handlers 13 | { 14 | public class GetProductsHandler : IRequestHandler> 15 | { 16 | private readonly IProductRepository _productRepository; 17 | public GetProductsHandler(IProductRepository productRepository) 18 | { 19 | _productRepository = productRepository; 20 | } 21 | public Task> Handle(GetProductQuery request, CancellationToken cancellationToken) 22 | { 23 | return _productRepository.GetAll().ToListAsync(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Invoice.Applicaion/CQRS/Notifications/ProductAddedNotification.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Domain.Entity; 2 | using MediatR; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Invoice.Applicaion.CQRS.Notifications 10 | { 11 | public class ProductAddedNotification : INotification 12 | { 13 | public Product product { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Invoice.Applicaion/CQRS/Queries/GetProductQuery.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Domain.Entity; 2 | using MediatR; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Invoice.Applicaion.CQRS.Queries 10 | { 11 | public class GetProductQuery : IRequest> 12 | { 13 | IEnumerable product; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Invoice.Applicaion/Interfaces/ICustomerDapperService.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Domain.Entity; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Invoice.Applicaion.Interfaces 9 | { 10 | public interface ICustomerDapperService 11 | { 12 | List GetAll(); 13 | Customer GetById(int id); 14 | void Insert(Customer customer); 15 | void Update(Customer customer); 16 | void Delete(int id); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Invoice.Applicaion/Interfaces/IInvoiceService.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Domain.Entity; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Invoice.Applicaion.Interface 9 | { 10 | public interface IInvoiceService 11 | { 12 | Task SaveInvoice(InvoiceInfo invoiceInfo); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Invoice.Applicaion/Interfaces/ITokenService.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Domain.Entity; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Invoice.Applicaion.Interfaces 9 | { 10 | public interface ITokenService 11 | { 12 | public string BuildToken(string key,string issuerer,UserModel user); 13 | public bool IsValidToken(string key,string issuerer,string audience,string token); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Invoice.Applicaion/Invoice.Applicaion.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Invoice.Applicaion/Services/CustomerDapperService.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Applicaion.Interfaces; 2 | using Invoice.Domain.Entity; 3 | using Invoice.Infra.Data.Interfaces; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Invoice.Applicaion.Services 11 | { 12 | public class CustomerDapperService : ICustomerDapperService 13 | { 14 | private ICustomeDapperRepository _customeDapperRepository; 15 | public CustomerDapperService(ICustomeDapperRepository customeDapperRepository) 16 | { 17 | _customeDapperRepository = customeDapperRepository; 18 | } 19 | 20 | public List GetAll() 21 | { 22 | return _customeDapperRepository.GetAll(); 23 | } 24 | 25 | public Customer GetById(int id) 26 | { 27 | return _customeDapperRepository.Get(id); 28 | } 29 | 30 | public void Insert(Customer customer) 31 | { 32 | _customeDapperRepository.Insert(customer); 33 | } 34 | public void Update(Customer customer) 35 | { 36 | _customeDapperRepository.Update(customer); 37 | } 38 | public void Delete(int id) 39 | { 40 | _customeDapperRepository.Delete(id); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Invoice.Applicaion/Services/InvoiceService.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Applicaion.Interface; 2 | using Invoice.Domain.Entity; 3 | using Invoice.Infra.Data.Interfaces; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Invoice.Applicaion.Services 11 | { 12 | public class InvoiceService : IInvoiceService 13 | { 14 | private readonly IUnitOfWork _unitOfWork; 15 | 16 | public InvoiceService(IUnitOfWork unitOfWork) 17 | { 18 | _unitOfWork = unitOfWork; 19 | } 20 | 21 | public async Task SaveInvoice(InvoiceInfo invoiceInfo) 22 | { 23 | await _unitOfWork.InvoiceInfo.Add(invoiceInfo); 24 | foreach(InvoiceDetails inv in invoiceInfo.Details) 25 | { 26 | await _unitOfWork.InvoiceDetails.Add(inv); 27 | } 28 | _unitOfWork.complete(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Invoice.Applicaion/Services/TokenService.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Applicaion.Interfaces; 2 | using Invoice.Domain.Entity; 3 | using Microsoft.EntityFrameworkCore.Metadata; 4 | using Microsoft.EntityFrameworkCore.Metadata.Internal; 5 | using Microsoft.Extensions.Logging; 6 | using Microsoft.IdentityModel.Tokens; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.IdentityModel.Tokens.Jwt; 10 | using System.Linq; 11 | using System.Security.Claims; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace Invoice.Applicaion.Services 16 | { 17 | public class TokenService : ITokenService 18 | { 19 | private ILogger _logger; 20 | private const double EXPIRY_DURATION_MINUTES = 30; 21 | public TokenService(ILogger logger) 22 | { 23 | _logger = logger; 24 | } 25 | public string BuildToken(string key, string issuer, UserModel user) 26 | { 27 | _logger.LogTrace("Token generate"); 28 | var claims = new[] { 29 | new Claim(ClaimTypes.Name, user.UserName), 30 | new Claim(ClaimTypes.NameIdentifier, 31 | Guid.NewGuid().ToString()) 32 | }; 33 | 34 | var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)); 35 | var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature); 36 | var tokenDescriptor = new JwtSecurityToken(issuer, issuer, claims, 37 | expires: DateTime.Now.AddMinutes(EXPIRY_DURATION_MINUTES), signingCredentials: credentials); 38 | return new JwtSecurityTokenHandler().WriteToken(tokenDescriptor); 39 | } 40 | public bool IsValidToken(string key, string issuer, string audience, string token) 41 | { 42 | var mySecret = Encoding.UTF8.GetBytes(key); 43 | var mySecurityKey = new SymmetricSecurityKey(mySecret); 44 | var tokenHandler = new JwtSecurityTokenHandler(); 45 | try 46 | { 47 | tokenHandler.ValidateToken(token, 48 | new TokenValidationParameters 49 | { 50 | ValidateIssuerSigningKey = true, 51 | ValidateIssuer = true, 52 | ValidateAudience = true, 53 | ValidIssuer = issuer, 54 | ValidAudience = issuer, 55 | IssuerSigningKey = mySecurityKey, 56 | }, out SecurityToken validatedToken); 57 | } 58 | catch 59 | { 60 | return false; 61 | } 62 | return true; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Invoice.Applicaion/Validations/CommonValidator.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Invoice.Applicaion.Validations 9 | { 10 | public static class CommonValidator 11 | { 12 | public static IRuleBuilderOptionsConditions> ListMustContainThan(this IRuleBuilder> ruleBuilder, int num) 13 | { 14 | 15 | return ruleBuilder.Custom((list, context) => { 16 | if (list.Count == num) 17 | { 18 | context.AddFailure("The list must contain atleast one item"); 19 | } 20 | }); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Invoice.Applicaion/Validations/InvoiceDetailsValidator.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | using Invoice.Domain.Entity; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Invoice.Applicaion.Validations 10 | { 11 | public class InvoiceDetailsValidator : AbstractValidator 12 | { 13 | public InvoiceDetailsValidator() 14 | { 15 | RuleFor(x => x.ProductName).NotEmpty(); 16 | RuleFor(x => x.Price).NotEmpty().GreaterThan(0); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Invoice.Applicaion/Validations/InvoiceInfoValidator.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | using Invoice.Domain.Entity; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Runtime.CompilerServices; 7 | using System.Security.Cryptography.X509Certificates; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace Invoice.Applicaion.Validations 12 | { 13 | public class InvoiceInfoValidator : AbstractValidator 14 | { 15 | public InvoiceInfoValidator() 16 | { 17 | RuleFor(InvoiceInfo => InvoiceInfo.InvoiceNo).NotNull() 18 | .MinimumLength(3).WithMessage("Please enter InvoceNo!"); 19 | RuleFor(InvoiceInfo => InvoiceInfo.InvoiceDate).NotEmpty(); 20 | RuleFor(InvoiceInfo => InvoiceInfo.DueDate).NotEmpty().GreaterThan(InvoiceInfo => InvoiceInfo.InvoiceDate); 21 | RuleFor(InvoiceInfo => InvoiceInfo.Details.Count).GreaterThan(0); 22 | RuleForEach(InvoiceInfo => InvoiceInfo.Details).SetValidator(new InvoiceDetailsValidator()).When(x => x.Details.Count > 0); 23 | 24 | //RuleFor(x => x.invoiceDetails).Custom((list, context) => { 25 | // if (list.Count == 0) 26 | // { 27 | // context.AddFailure("Invoice list must contains items"); 28 | // } 29 | //}); 30 | 31 | //RuleFor(x => x.invoiceDetails).ListMustContainThan(1); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Invoice.Domain/DTO/InvoiceDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Invoice.Domain.DTO 8 | { 9 | public class InvoiceDTO 10 | { 11 | public int BillTo { get; set; } 12 | public string InvoiceNo { get; set; } = string.Empty; 13 | public DateTime InvoiceDate { get; set; } 14 | public DateTime DueDate { get; set; } 15 | public string Status { get; set; } = string.Empty; 16 | public double SubTotal { get; set; } 17 | public double TotalTax { get; set; } 18 | public double GrandTotal { get; set; } 19 | public string InvoiceNote { get; set; } 20 | public List Details { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Invoice.Domain/DTO/InvoiceDetailsDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Invoice.Domain.DTO 8 | { 9 | public class InvoiceDetailsDTO 10 | { 11 | public string ProductName { get; set; } 12 | public string Desc { get; set; } 13 | public double Price { get; set; } 14 | public int Qunatity { get; set; } 15 | public decimal Tax { get; set; } 16 | public double Total { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Invoice.Domain/DTO/InvoiceInfoDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Invoice.Domain.Entity; 7 | 8 | namespace Invoice.Domain.DTO 9 | { 10 | public class InvoiceInfoDTO 11 | { 12 | public int Id { get; set; } 13 | public string Customer { get; set; } 14 | public string InvoiceNo { get; set; } = String.Empty; 15 | public DateTime InvoiceDate { get; set; } 16 | public DateTime DueDate { get; set; } 17 | public string Status { get; set; } = String.Empty; 18 | public List invoiceDetails { get; set; } 19 | 20 | public int TotalRecords { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Invoice.Domain/Entity/Customer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Invoice.Domain.Entity 9 | { 10 | public class Customer 11 | { 12 | [Key] 13 | public int Id { get; set; } 14 | public string Name { get; set; } 15 | public string Address { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Invoice.Domain/Entity/InvoiceDetails.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Invoice.Domain.Entity 9 | { 10 | public class InvoiceDetails 11 | { 12 | [Key] 13 | public int Id { get; set; } 14 | public int InvoiceInfoId { get; set; } 15 | public string ProductName { get; set; } 16 | public string Description { get; set; } 17 | public double Price { get; set; } 18 | public int Qunatity { get; set; } 19 | public decimal Tax { get; set; } 20 | public double Total { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Invoice.Domain/Entity/InvoiceInfo.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Invoice.Domain.Entity 4 | { 5 | public class InvoiceInfo 6 | { 7 | [Key] 8 | public int Id { get; set; } 9 | public int BillTo { get; set; } 10 | public string InvoiceNo { get; set; } = string.Empty; 11 | public DateTime InvoiceDate { get; set; } 12 | public DateTime DueDate { get; set; } 13 | public string Status { get; set; } = string.Empty; 14 | public DateTime CreatedDate { get; set; } 15 | public double SubTotal { get; set; } 16 | public double TotalTax { get; set; } 17 | public double GrandTotal { get; set; } 18 | public string InvoiceNote { get; set; } 19 | public List Details { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /Invoice.Domain/Entity/Product.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Invoice.Domain.Entity 9 | { 10 | public class Product 11 | { 12 | [Key] 13 | public int Id { get; set; } 14 | public string? Name { get; set; } 15 | public decimal price { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Invoice.Domain/Entity/UserModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Invoice.Domain.Entity 8 | { 9 | public class UserModel 10 | { 11 | public string UserName { get; set; } = string.Empty; 12 | public string Password { get; set; } = string.Empty; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Invoice.Domain/ErrorDetails.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.Json; 6 | using System.Threading.Tasks; 7 | 8 | namespace Invoice.Domain 9 | { 10 | public class ErrorDetails 11 | { 12 | public int StatusCode { get; set; } 13 | public string Message { get; set; } 14 | public override string ToString() 15 | { 16 | return JsonSerializer.Serialize(this); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Invoice.Domain/Invoice.Domain.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Invoice.Domain/PagedList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Invoice.Domain 8 | { 9 | public class PagedList : List 10 | { 11 | public int CurrentPage { get; private set; } 12 | public int TotalPages { get; private set; } 13 | public int PageSize { get; private set; } 14 | public int TotalCount { get; private set; } 15 | 16 | public bool hasPrivious => CurrentPage > 1; 17 | public bool hasNext => TotalPages > CurrentPage; 18 | public PagedList(List items, int count, int pageNumber, int pagesize) 19 | { 20 | TotalCount = count; 21 | PageSize = pagesize; 22 | CurrentPage = pageNumber; 23 | TotalPages = (int)Math.Ceiling((double)count / pagesize); 24 | AddRange(items); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Invoice.Domain/PagingRequestModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Invoice.Domain 8 | { 9 | public class PagingRequestModel 10 | { 11 | const int maxPageSize = 50; 12 | public int PageNumber { get; set; } 13 | private int pageSize; 14 | public int PageSize { 15 | get 16 | { 17 | return pageSize; 18 | } 19 | set 20 | { 21 | pageSize = value > maxPageSize ? maxPageSize : value; 22 | } 23 | } 24 | public string orderBy { get; set; } 25 | public string direction { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/AppDbContext.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Domain.Entity; 2 | using Microsoft.EntityFrameworkCore; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Invoice.Infra.Data 10 | { 11 | public class AppDbContext : DbContext 12 | { 13 | public AppDbContext(DbContextOptions options) : base(options) 14 | { 15 | 16 | } 17 | 18 | public DbSet InvoiceInfo => Set(); 19 | public DbSet InvoiceDetails => Set(); 20 | 21 | public DbSet Products => Set(); 22 | 23 | public DbSet Customers => Set(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Extention/Sort.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Domain; 2 | using Invoice.Domain.Entity; 3 | using Invoice.Infra.Data.Interfaces; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Linq.Expressions; 8 | using System.Net.Http.Headers; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace Invoice.Infra.Data.Extention 13 | { 14 | public static class Sort 15 | { 16 | public static IQueryable OrderByDynamic(this IQueryable query, string orderByMember, string direction) 17 | { 18 | var queryElementTypeParam = Expression.Parameter(typeof(T)); 19 | var memberAccess = Expression.PropertyOrField(queryElementTypeParam, orderByMember); 20 | var keySelector = Expression.Lambda(memberAccess, queryElementTypeParam); 21 | 22 | var orderBy = Expression.Call( 23 | typeof(Queryable), 24 | direction == "asc" ? "OrderBy" : "OrderByDescending", 25 | new Type[] { typeof(T), memberAccess.Type }, 26 | query.Expression, 27 | Expression.Quote(keySelector)); 28 | 29 | return query.Provider.CreateQuery(orderBy); 30 | } 31 | 32 | public static IQueryable Paging(this IQueryable query, int pageSize = 10, int pageNumber = 1) where TModel : class 33 | { 34 | var count = query.Count(); 35 | return pageSize > 0 && pageNumber > 0 ? query.Skip((pageNumber - 1) * pageSize).Take(pageSize) : query; 36 | } 37 | 38 | //public static IQueryable Paging(this IQueryable query, int pageSize = 10, int pageNumber = 1) where TModel : class 39 | // => pageSize > 0 && pageNumber > 0 ? query.Skip((pageNumber - 1) * pageSize).Take(pageSize) : query; 40 | 41 | public static IQueryable ApplySort(this IQueryable invoices, string orderbystring) 42 | { 43 | //if (!invoices.Any()) 44 | // return; 45 | 46 | if (string.IsNullOrWhiteSpace(orderbystring)) 47 | { 48 | invoices = invoices.OrderBy(x => x.InvoiceDate); 49 | } 50 | 51 | //var orderParams = orderbystring.Trim().Split(","); 52 | var queryBuilder = new StringBuilder(); 53 | //foreach(var param in orderParams) 54 | //{ 55 | // if (string.IsNullOrWhiteSpace(param)) 56 | // continue; 57 | 58 | var propertyInfos = typeof(InvoiceInfo).GetProperty(orderbystring); 59 | //if (propertyInfos == null) 60 | // return; 61 | 62 | queryBuilder.Append($"{propertyInfos.Name}"); 63 | //} 64 | 65 | var orderQuery = queryBuilder.ToString(); 66 | 67 | return invoices.OrderBy(x => propertyInfos.Name); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Interfaces/ICustomeDapperRepository.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Domain.Entity; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Invoice.Infra.Data.Interfaces 9 | { 10 | public interface ICustomeDapperRepository 11 | { 12 | List GetAll(); 13 | Customer Get(int id); 14 | void Insert(Customer customer); 15 | void Update(Customer customer); 16 | void Delete(int id); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Interfaces/IGenericRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Invoice.Infra.Data.Interfaces 9 | { 10 | public interface IGenericRepository where T : class 11 | { 12 | Task GetById(int id); 13 | IQueryable GetAll(); 14 | Task Add(T entity); 15 | void Delete(T entity); 16 | void Update(T entity); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Interfaces/IInvoiceDetailsRepository.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Domain.Entity; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Invoice.Infra.Data.Interfaces 9 | { 10 | public interface IInvoiceDetailsRepository : IGenericRepository 11 | { 12 | List GetByInvoiceId(int invoiceId); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Interfaces/IInvoiceInfoRepository.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Domain; 2 | using Invoice.Domain.DTO; 3 | using Invoice.Domain.Entity; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Invoice.Infra.Data.Interfaces 11 | { 12 | public interface IInvoiceInfoRepository : IGenericRepository 13 | { 14 | Task> GetInvoiceByCustomerID(int custId); 15 | 16 | PagedList GetInvoiceWithPaging(PagingRequestModel pagingModel); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Interfaces/IProductRepository.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Domain.Entity; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Invoice.Infra.Data.Interfaces 9 | { 10 | public interface IProductRepository: IGenericRepository 11 | { 12 | Task CreateProduct(Product product); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Interfaces/IUnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Invoice.Infra.Data.Interfaces 8 | { 9 | public interface IUnitOfWork //: IDisposable 10 | { 11 | IInvoiceInfoRepository InvoiceInfo { get; } 12 | IInvoiceDetailsRepository InvoiceDetails { get; } 13 | int complete(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Invoice.Infra.Data.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | 16 | 17 | 18 | all 19 | runtime; build; native; contentfiles; analyzers; buildtransitive 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Migrations/20221030060130_initialmigration.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Invoice.Infra.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | #nullable disable 11 | 12 | namespace Invoice.Infra.Data.Migrations 13 | { 14 | [DbContext(typeof(AppDbContext))] 15 | [Migration("20221030060130_initialmigration")] 16 | partial class initialmigration 17 | { 18 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 19 | { 20 | #pragma warning disable 612, 618 21 | modelBuilder 22 | .HasAnnotation("ProductVersion", "6.0.10") 23 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 24 | 25 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); 26 | 27 | modelBuilder.Entity("Invoice.Domain.InvoiceInfo", b => 28 | { 29 | b.Property("Id") 30 | .ValueGeneratedOnAdd() 31 | .HasColumnType("int"); 32 | 33 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 34 | 35 | b.Property("BillTo") 36 | .HasColumnType("int"); 37 | 38 | b.Property("DueDate") 39 | .HasColumnType("datetime2"); 40 | 41 | b.Property("InvoiceDate") 42 | .HasColumnType("datetime2"); 43 | 44 | b.Property("InvoiceNo") 45 | .IsRequired() 46 | .HasColumnType("nvarchar(max)"); 47 | 48 | b.Property("Status") 49 | .IsRequired() 50 | .HasColumnType("nvarchar(max)"); 51 | 52 | b.HasKey("Id"); 53 | 54 | b.ToTable("InvoieInfo"); 55 | }); 56 | #pragma warning restore 612, 618 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Migrations/20221030060130_initialmigration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | #nullable disable 5 | 6 | namespace Invoice.Infra.Data.Migrations 7 | { 8 | public partial class initialmigration : Migration 9 | { 10 | protected override void Up(MigrationBuilder migrationBuilder) 11 | { 12 | migrationBuilder.CreateTable( 13 | name: "InvoieInfo", 14 | columns: table => new 15 | { 16 | Id = table.Column(type: "int", nullable: false) 17 | .Annotation("SqlServer:Identity", "1, 1"), 18 | BillTo = table.Column(type: "int", nullable: false), 19 | InvoiceNo = table.Column(type: "nvarchar(max)", nullable: false), 20 | InvoiceDate = table.Column(type: "datetime2", nullable: false), 21 | DueDate = table.Column(type: "datetime2", nullable: false), 22 | Status = table.Column(type: "nvarchar(max)", nullable: false) 23 | }, 24 | constraints: table => 25 | { 26 | table.PrimaryKey("PK_InvoieInfo", x => x.Id); 27 | }); 28 | } 29 | 30 | protected override void Down(MigrationBuilder migrationBuilder) 31 | { 32 | migrationBuilder.DropTable( 33 | name: "InvoieInfo"); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Migrations/20221106033723_createddateadded.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Invoice.Infra.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | #nullable disable 11 | 12 | namespace Invoice.Infra.Data.Migrations 13 | { 14 | [DbContext(typeof(AppDbContext))] 15 | [Migration("20221106033723_createddateadded")] 16 | partial class createddateadded 17 | { 18 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 19 | { 20 | #pragma warning disable 612, 618 21 | modelBuilder 22 | .HasAnnotation("ProductVersion", "6.0.10") 23 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 24 | 25 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); 26 | 27 | modelBuilder.Entity("Invoice.Domain.InvoiceInfo", b => 28 | { 29 | b.Property("Id") 30 | .ValueGeneratedOnAdd() 31 | .HasColumnType("int"); 32 | 33 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 34 | 35 | b.Property("BillTo") 36 | .HasColumnType("int"); 37 | 38 | b.Property("CreatedDate") 39 | .HasColumnType("datetime2"); 40 | 41 | b.Property("DueDate") 42 | .HasColumnType("datetime2"); 43 | 44 | b.Property("InvoiceDate") 45 | .HasColumnType("datetime2"); 46 | 47 | b.Property("InvoiceNo") 48 | .IsRequired() 49 | .HasColumnType("nvarchar(max)"); 50 | 51 | b.Property("Status") 52 | .IsRequired() 53 | .HasColumnType("nvarchar(max)"); 54 | 55 | b.HasKey("Id"); 56 | 57 | b.ToTable("InvoieInfo"); 58 | }); 59 | #pragma warning restore 612, 618 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Migrations/20221106033723_createddateadded.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | #nullable disable 5 | 6 | namespace Invoice.Infra.Data.Migrations 7 | { 8 | public partial class createddateadded : Migration 9 | { 10 | protected override void Up(MigrationBuilder migrationBuilder) 11 | { 12 | migrationBuilder.AddColumn( 13 | name: "CreatedDate", 14 | table: "InvoieInfo", 15 | type: "datetime2", 16 | nullable: false, 17 | defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); 18 | } 19 | 20 | protected override void Down(MigrationBuilder migrationBuilder) 21 | { 22 | migrationBuilder.DropColumn( 23 | name: "CreatedDate", 24 | table: "InvoieInfo"); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Migrations/20221113100754_addedInvoicedetails.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Invoice.Infra.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | #nullable disable 11 | 12 | namespace Invoice.Infra.Data.Migrations 13 | { 14 | [DbContext(typeof(AppDbContext))] 15 | [Migration("20221113100754_addedInvoicedetails")] 16 | partial class addedInvoicedetails 17 | { 18 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 19 | { 20 | #pragma warning disable 612, 618 21 | modelBuilder 22 | .HasAnnotation("ProductVersion", "6.0.10") 23 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 24 | 25 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); 26 | 27 | modelBuilder.Entity("Invoice.Domain.InvoiceDetails", b => 28 | { 29 | b.Property("Id") 30 | .ValueGeneratedOnAdd() 31 | .HasColumnType("int"); 32 | 33 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 34 | 35 | b.Property("Description") 36 | .IsRequired() 37 | .HasColumnType("nvarchar(max)"); 38 | 39 | b.Property("GrandTotal") 40 | .HasColumnType("float"); 41 | 42 | b.Property("InvoiceInfoId") 43 | .HasColumnType("int"); 44 | 45 | b.Property("InvoiceNote") 46 | .IsRequired() 47 | .HasColumnType("nvarchar(max)"); 48 | 49 | b.Property("Price") 50 | .HasColumnType("float"); 51 | 52 | b.Property("ProductName") 53 | .IsRequired() 54 | .HasColumnType("nvarchar(max)"); 55 | 56 | b.Property("Qunatity") 57 | .HasColumnType("int"); 58 | 59 | b.Property("SubTotal") 60 | .HasColumnType("float"); 61 | 62 | b.Property("Tax") 63 | .HasColumnType("decimal(18,2)"); 64 | 65 | b.Property("Total") 66 | .HasColumnType("float"); 67 | 68 | b.Property("TotalTax") 69 | .HasColumnType("float"); 70 | 71 | b.HasKey("Id"); 72 | 73 | b.HasIndex("InvoiceInfoId"); 74 | 75 | b.ToTable("InvoiceDetails"); 76 | }); 77 | 78 | modelBuilder.Entity("Invoice.Domain.InvoiceInfo", b => 79 | { 80 | b.Property("Id") 81 | .ValueGeneratedOnAdd() 82 | .HasColumnType("int"); 83 | 84 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 85 | 86 | b.Property("BillTo") 87 | .HasColumnType("int"); 88 | 89 | b.Property("CreatedDate") 90 | .HasColumnType("datetime2"); 91 | 92 | b.Property("DueDate") 93 | .HasColumnType("datetime2"); 94 | 95 | b.Property("InvoiceDate") 96 | .HasColumnType("datetime2"); 97 | 98 | b.Property("InvoiceNo") 99 | .IsRequired() 100 | .HasColumnType("nvarchar(max)"); 101 | 102 | b.Property("Status") 103 | .IsRequired() 104 | .HasColumnType("nvarchar(max)"); 105 | 106 | b.HasKey("Id"); 107 | 108 | b.ToTable("InvoieInfo"); 109 | }); 110 | 111 | modelBuilder.Entity("Invoice.Domain.InvoiceDetails", b => 112 | { 113 | b.HasOne("Invoice.Domain.InvoiceInfo", null) 114 | .WithMany("invoiceDetails") 115 | .HasForeignKey("InvoiceInfoId") 116 | .OnDelete(DeleteBehavior.Cascade) 117 | .IsRequired(); 118 | }); 119 | 120 | modelBuilder.Entity("Invoice.Domain.InvoiceInfo", b => 121 | { 122 | b.Navigation("invoiceDetails"); 123 | }); 124 | #pragma warning restore 612, 618 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Migrations/20221113100754_addedInvoicedetails.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace Invoice.Infra.Data.Migrations 6 | { 7 | public partial class addedInvoicedetails : Migration 8 | { 9 | protected override void Up(MigrationBuilder migrationBuilder) 10 | { 11 | migrationBuilder.CreateTable( 12 | name: "InvoiceDetails", 13 | columns: table => new 14 | { 15 | Id = table.Column(type: "int", nullable: false) 16 | .Annotation("SqlServer:Identity", "1, 1"), 17 | InvoiceInfoId = table.Column(type: "int", nullable: false), 18 | ProductName = table.Column(type: "nvarchar(max)", nullable: false), 19 | Description = table.Column(type: "nvarchar(max)", nullable: false), 20 | Price = table.Column(type: "float", nullable: false), 21 | Qunatity = table.Column(type: "int", nullable: false), 22 | Tax = table.Column(type: "decimal(18,2)", nullable: false), 23 | Total = table.Column(type: "float", nullable: false), 24 | SubTotal = table.Column(type: "float", nullable: false), 25 | TotalTax = table.Column(type: "float", nullable: false), 26 | GrandTotal = table.Column(type: "float", nullable: false), 27 | InvoiceNote = table.Column(type: "nvarchar(max)", nullable: false) 28 | }, 29 | constraints: table => 30 | { 31 | table.PrimaryKey("PK_InvoiceDetails", x => x.Id); 32 | table.ForeignKey( 33 | name: "FK_InvoiceDetails_InvoieInfo_InvoiceInfoId", 34 | column: x => x.InvoiceInfoId, 35 | principalTable: "InvoieInfo", 36 | principalColumn: "Id", 37 | onDelete: ReferentialAction.Cascade); 38 | }); 39 | 40 | migrationBuilder.CreateIndex( 41 | name: "IX_InvoiceDetails_InvoiceInfoId", 42 | table: "InvoiceDetails", 43 | column: "InvoiceInfoId"); 44 | } 45 | 46 | protected override void Down(MigrationBuilder migrationBuilder) 47 | { 48 | migrationBuilder.DropTable( 49 | name: "InvoiceDetails"); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Migrations/20221117103840_namemodification.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Invoice.Infra.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | #nullable disable 11 | 12 | namespace Invoice.Infra.Data.Migrations 13 | { 14 | [DbContext(typeof(AppDbContext))] 15 | [Migration("20221117103840_namemodification")] 16 | partial class namemodification 17 | { 18 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 19 | { 20 | #pragma warning disable 612, 618 21 | modelBuilder 22 | .HasAnnotation("ProductVersion", "6.0.10") 23 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 24 | 25 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); 26 | 27 | modelBuilder.Entity("Invoice.Domain.InvoiceDetails", b => 28 | { 29 | b.Property("Id") 30 | .ValueGeneratedOnAdd() 31 | .HasColumnType("int"); 32 | 33 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 34 | 35 | b.Property("Description") 36 | .IsRequired() 37 | .HasColumnType("nvarchar(max)"); 38 | 39 | b.Property("GrandTotal") 40 | .HasColumnType("float"); 41 | 42 | b.Property("InvoiceInfoId") 43 | .HasColumnType("int"); 44 | 45 | b.Property("InvoiceNote") 46 | .IsRequired() 47 | .HasColumnType("nvarchar(max)"); 48 | 49 | b.Property("Price") 50 | .HasColumnType("float"); 51 | 52 | b.Property("ProductName") 53 | .IsRequired() 54 | .HasColumnType("nvarchar(max)"); 55 | 56 | b.Property("Qunatity") 57 | .HasColumnType("int"); 58 | 59 | b.Property("SubTotal") 60 | .HasColumnType("float"); 61 | 62 | b.Property("Tax") 63 | .HasColumnType("decimal(18,2)"); 64 | 65 | b.Property("Total") 66 | .HasColumnType("float"); 67 | 68 | b.Property("TotalTax") 69 | .HasColumnType("float"); 70 | 71 | b.HasKey("Id"); 72 | 73 | b.HasIndex("InvoiceInfoId"); 74 | 75 | b.ToTable("InvoieDetails"); 76 | }); 77 | 78 | modelBuilder.Entity("Invoice.Domain.InvoiceInfo", b => 79 | { 80 | b.Property("Id") 81 | .ValueGeneratedOnAdd() 82 | .HasColumnType("int"); 83 | 84 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 85 | 86 | b.Property("BillTo") 87 | .HasColumnType("int"); 88 | 89 | b.Property("CreatedDate") 90 | .HasColumnType("datetime2"); 91 | 92 | b.Property("DueDate") 93 | .HasColumnType("datetime2"); 94 | 95 | b.Property("InvoiceDate") 96 | .HasColumnType("datetime2"); 97 | 98 | b.Property("InvoiceNo") 99 | .IsRequired() 100 | .HasColumnType("nvarchar(max)"); 101 | 102 | b.Property("Status") 103 | .IsRequired() 104 | .HasColumnType("nvarchar(max)"); 105 | 106 | b.HasKey("Id"); 107 | 108 | b.ToTable("InvoiceInfo"); 109 | }); 110 | 111 | modelBuilder.Entity("Invoice.Domain.InvoiceDetails", b => 112 | { 113 | b.HasOne("Invoice.Domain.InvoiceInfo", null) 114 | .WithMany("invoiceDetails") 115 | .HasForeignKey("InvoiceInfoId") 116 | .OnDelete(DeleteBehavior.Cascade) 117 | .IsRequired(); 118 | }); 119 | 120 | modelBuilder.Entity("Invoice.Domain.InvoiceInfo", b => 121 | { 122 | b.Navigation("invoiceDetails"); 123 | }); 124 | #pragma warning restore 612, 618 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Migrations/20221117103840_namemodification.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace Invoice.Infra.Data.Migrations 6 | { 7 | public partial class namemodification : Migration 8 | { 9 | protected override void Up(MigrationBuilder migrationBuilder) 10 | { 11 | migrationBuilder.DropForeignKey( 12 | name: "FK_InvoiceDetails_InvoieInfo_InvoiceInfoId", 13 | table: "InvoiceDetails"); 14 | 15 | migrationBuilder.DropPrimaryKey( 16 | name: "PK_InvoieInfo", 17 | table: "InvoieInfo"); 18 | 19 | migrationBuilder.DropPrimaryKey( 20 | name: "PK_InvoiceDetails", 21 | table: "InvoiceDetails"); 22 | 23 | migrationBuilder.RenameTable( 24 | name: "InvoieInfo", 25 | newName: "InvoiceInfo"); 26 | 27 | migrationBuilder.RenameTable( 28 | name: "InvoiceDetails", 29 | newName: "InvoieDetails"); 30 | 31 | migrationBuilder.RenameIndex( 32 | name: "IX_InvoiceDetails_InvoiceInfoId", 33 | table: "InvoieDetails", 34 | newName: "IX_InvoieDetails_InvoiceInfoId"); 35 | 36 | migrationBuilder.AddPrimaryKey( 37 | name: "PK_InvoiceInfo", 38 | table: "InvoiceInfo", 39 | column: "Id"); 40 | 41 | migrationBuilder.AddPrimaryKey( 42 | name: "PK_InvoieDetails", 43 | table: "InvoieDetails", 44 | column: "Id"); 45 | 46 | migrationBuilder.AddForeignKey( 47 | name: "FK_InvoieDetails_InvoiceInfo_InvoiceInfoId", 48 | table: "InvoieDetails", 49 | column: "InvoiceInfoId", 50 | principalTable: "InvoiceInfo", 51 | principalColumn: "Id", 52 | onDelete: ReferentialAction.Cascade); 53 | } 54 | 55 | protected override void Down(MigrationBuilder migrationBuilder) 56 | { 57 | migrationBuilder.DropForeignKey( 58 | name: "FK_InvoieDetails_InvoiceInfo_InvoiceInfoId", 59 | table: "InvoieDetails"); 60 | 61 | migrationBuilder.DropPrimaryKey( 62 | name: "PK_InvoieDetails", 63 | table: "InvoieDetails"); 64 | 65 | migrationBuilder.DropPrimaryKey( 66 | name: "PK_InvoiceInfo", 67 | table: "InvoiceInfo"); 68 | 69 | migrationBuilder.RenameTable( 70 | name: "InvoieDetails", 71 | newName: "InvoiceDetails"); 72 | 73 | migrationBuilder.RenameTable( 74 | name: "InvoiceInfo", 75 | newName: "InvoieInfo"); 76 | 77 | migrationBuilder.RenameIndex( 78 | name: "IX_InvoieDetails_InvoiceInfoId", 79 | table: "InvoiceDetails", 80 | newName: "IX_InvoiceDetails_InvoiceInfoId"); 81 | 82 | migrationBuilder.AddPrimaryKey( 83 | name: "PK_InvoiceDetails", 84 | table: "InvoiceDetails", 85 | column: "Id"); 86 | 87 | migrationBuilder.AddPrimaryKey( 88 | name: "PK_InvoieInfo", 89 | table: "InvoieInfo", 90 | column: "Id"); 91 | 92 | migrationBuilder.AddForeignKey( 93 | name: "FK_InvoiceDetails_InvoieInfo_InvoiceInfoId", 94 | table: "InvoiceDetails", 95 | column: "InvoiceInfoId", 96 | principalTable: "InvoieInfo", 97 | principalColumn: "Id", 98 | onDelete: ReferentialAction.Cascade); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Migrations/20221117104032_namemodification1.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Invoice.Infra.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | #nullable disable 11 | 12 | namespace Invoice.Infra.Data.Migrations 13 | { 14 | [DbContext(typeof(AppDbContext))] 15 | [Migration("20221117104032_namemodification1")] 16 | partial class namemodification1 17 | { 18 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 19 | { 20 | #pragma warning disable 612, 618 21 | modelBuilder 22 | .HasAnnotation("ProductVersion", "6.0.10") 23 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 24 | 25 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); 26 | 27 | modelBuilder.Entity("Invoice.Domain.InvoiceDetails", b => 28 | { 29 | b.Property("Id") 30 | .ValueGeneratedOnAdd() 31 | .HasColumnType("int"); 32 | 33 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 34 | 35 | b.Property("Description") 36 | .IsRequired() 37 | .HasColumnType("nvarchar(max)"); 38 | 39 | b.Property("GrandTotal") 40 | .HasColumnType("float"); 41 | 42 | b.Property("InvoiceInfoId") 43 | .HasColumnType("int"); 44 | 45 | b.Property("InvoiceNote") 46 | .IsRequired() 47 | .HasColumnType("nvarchar(max)"); 48 | 49 | b.Property("Price") 50 | .HasColumnType("float"); 51 | 52 | b.Property("ProductName") 53 | .IsRequired() 54 | .HasColumnType("nvarchar(max)"); 55 | 56 | b.Property("Qunatity") 57 | .HasColumnType("int"); 58 | 59 | b.Property("SubTotal") 60 | .HasColumnType("float"); 61 | 62 | b.Property("Tax") 63 | .HasColumnType("decimal(18,2)"); 64 | 65 | b.Property("Total") 66 | .HasColumnType("float"); 67 | 68 | b.Property("TotalTax") 69 | .HasColumnType("float"); 70 | 71 | b.HasKey("Id"); 72 | 73 | b.HasIndex("InvoiceInfoId"); 74 | 75 | b.ToTable("InvoiceDetails"); 76 | }); 77 | 78 | modelBuilder.Entity("Invoice.Domain.InvoiceInfo", b => 79 | { 80 | b.Property("Id") 81 | .ValueGeneratedOnAdd() 82 | .HasColumnType("int"); 83 | 84 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 85 | 86 | b.Property("BillTo") 87 | .HasColumnType("int"); 88 | 89 | b.Property("CreatedDate") 90 | .HasColumnType("datetime2"); 91 | 92 | b.Property("DueDate") 93 | .HasColumnType("datetime2"); 94 | 95 | b.Property("InvoiceDate") 96 | .HasColumnType("datetime2"); 97 | 98 | b.Property("InvoiceNo") 99 | .IsRequired() 100 | .HasColumnType("nvarchar(max)"); 101 | 102 | b.Property("Status") 103 | .IsRequired() 104 | .HasColumnType("nvarchar(max)"); 105 | 106 | b.HasKey("Id"); 107 | 108 | b.ToTable("InvoiceInfo"); 109 | }); 110 | 111 | modelBuilder.Entity("Invoice.Domain.InvoiceDetails", b => 112 | { 113 | b.HasOne("Invoice.Domain.InvoiceInfo", null) 114 | .WithMany("invoiceDetails") 115 | .HasForeignKey("InvoiceInfoId") 116 | .OnDelete(DeleteBehavior.Cascade) 117 | .IsRequired(); 118 | }); 119 | 120 | modelBuilder.Entity("Invoice.Domain.InvoiceInfo", b => 121 | { 122 | b.Navigation("invoiceDetails"); 123 | }); 124 | #pragma warning restore 612, 618 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Migrations/20221117104032_namemodification1.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace Invoice.Infra.Data.Migrations 6 | { 7 | public partial class namemodification1 : Migration 8 | { 9 | protected override void Up(MigrationBuilder migrationBuilder) 10 | { 11 | migrationBuilder.DropForeignKey( 12 | name: "FK_InvoieDetails_InvoiceInfo_InvoiceInfoId", 13 | table: "InvoieDetails"); 14 | 15 | migrationBuilder.DropPrimaryKey( 16 | name: "PK_InvoieDetails", 17 | table: "InvoieDetails"); 18 | 19 | migrationBuilder.RenameTable( 20 | name: "InvoieDetails", 21 | newName: "InvoiceDetails"); 22 | 23 | migrationBuilder.RenameIndex( 24 | name: "IX_InvoieDetails_InvoiceInfoId", 25 | table: "InvoiceDetails", 26 | newName: "IX_InvoiceDetails_InvoiceInfoId"); 27 | 28 | migrationBuilder.AddPrimaryKey( 29 | name: "PK_InvoiceDetails", 30 | table: "InvoiceDetails", 31 | column: "Id"); 32 | 33 | migrationBuilder.AddForeignKey( 34 | name: "FK_InvoiceDetails_InvoiceInfo_InvoiceInfoId", 35 | table: "InvoiceDetails", 36 | column: "InvoiceInfoId", 37 | principalTable: "InvoiceInfo", 38 | principalColumn: "Id", 39 | onDelete: ReferentialAction.Cascade); 40 | } 41 | 42 | protected override void Down(MigrationBuilder migrationBuilder) 43 | { 44 | migrationBuilder.DropForeignKey( 45 | name: "FK_InvoiceDetails_InvoiceInfo_InvoiceInfoId", 46 | table: "InvoiceDetails"); 47 | 48 | migrationBuilder.DropPrimaryKey( 49 | name: "PK_InvoiceDetails", 50 | table: "InvoiceDetails"); 51 | 52 | migrationBuilder.RenameTable( 53 | name: "InvoiceDetails", 54 | newName: "InvoieDetails"); 55 | 56 | migrationBuilder.RenameIndex( 57 | name: "IX_InvoiceDetails_InvoiceInfoId", 58 | table: "InvoieDetails", 59 | newName: "IX_InvoieDetails_InvoiceInfoId"); 60 | 61 | migrationBuilder.AddPrimaryKey( 62 | name: "PK_InvoieDetails", 63 | table: "InvoieDetails", 64 | column: "Id"); 65 | 66 | migrationBuilder.AddForeignKey( 67 | name: "FK_InvoieDetails_InvoiceInfo_InvoiceInfoId", 68 | table: "InvoieDetails", 69 | column: "InvoiceInfoId", 70 | principalTable: "InvoiceInfo", 71 | principalColumn: "Id", 72 | onDelete: ReferentialAction.Cascade); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Migrations/20221202114309_addproduct.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Invoice.Infra.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | #nullable disable 11 | 12 | namespace Invoice.Infra.Data.Migrations 13 | { 14 | [DbContext(typeof(AppDbContext))] 15 | [Migration("20221202114309_addproduct")] 16 | partial class addproduct 17 | { 18 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 19 | { 20 | #pragma warning disable 612, 618 21 | modelBuilder 22 | .HasAnnotation("ProductVersion", "6.0.10") 23 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 24 | 25 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); 26 | 27 | modelBuilder.Entity("Invoice.Domain.InvoiceDetails", b => 28 | { 29 | b.Property("Id") 30 | .ValueGeneratedOnAdd() 31 | .HasColumnType("int"); 32 | 33 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 34 | 35 | b.Property("Description") 36 | .IsRequired() 37 | .HasColumnType("nvarchar(max)"); 38 | 39 | b.Property("GrandTotal") 40 | .HasColumnType("float"); 41 | 42 | b.Property("InvoiceInfoId") 43 | .HasColumnType("int"); 44 | 45 | b.Property("InvoiceNote") 46 | .IsRequired() 47 | .HasColumnType("nvarchar(max)"); 48 | 49 | b.Property("Price") 50 | .HasColumnType("float"); 51 | 52 | b.Property("ProductName") 53 | .IsRequired() 54 | .HasColumnType("nvarchar(max)"); 55 | 56 | b.Property("Qunatity") 57 | .HasColumnType("int"); 58 | 59 | b.Property("SubTotal") 60 | .HasColumnType("float"); 61 | 62 | b.Property("Tax") 63 | .HasColumnType("decimal(18,2)"); 64 | 65 | b.Property("Total") 66 | .HasColumnType("float"); 67 | 68 | b.Property("TotalTax") 69 | .HasColumnType("float"); 70 | 71 | b.HasKey("Id"); 72 | 73 | b.HasIndex("InvoiceInfoId"); 74 | 75 | b.ToTable("InvoiceDetails"); 76 | }); 77 | 78 | modelBuilder.Entity("Invoice.Domain.InvoiceInfo", b => 79 | { 80 | b.Property("Id") 81 | .ValueGeneratedOnAdd() 82 | .HasColumnType("int"); 83 | 84 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 85 | 86 | b.Property("BillTo") 87 | .HasColumnType("int"); 88 | 89 | b.Property("CreatedDate") 90 | .HasColumnType("datetime2"); 91 | 92 | b.Property("DueDate") 93 | .HasColumnType("datetime2"); 94 | 95 | b.Property("InvoiceDate") 96 | .HasColumnType("datetime2"); 97 | 98 | b.Property("InvoiceNo") 99 | .IsRequired() 100 | .HasColumnType("nvarchar(max)"); 101 | 102 | b.Property("Status") 103 | .IsRequired() 104 | .HasColumnType("nvarchar(max)"); 105 | 106 | b.HasKey("Id"); 107 | 108 | b.ToTable("InvoiceInfo"); 109 | }); 110 | 111 | modelBuilder.Entity("Invoice.Domain.Product", b => 112 | { 113 | b.Property("Id") 114 | .ValueGeneratedOnAdd() 115 | .HasColumnType("int"); 116 | 117 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 118 | 119 | b.Property("Name") 120 | .HasColumnType("nvarchar(max)"); 121 | 122 | b.Property("price") 123 | .HasColumnType("decimal(18,2)"); 124 | 125 | b.HasKey("Id"); 126 | 127 | b.ToTable("Products"); 128 | }); 129 | 130 | modelBuilder.Entity("Invoice.Domain.InvoiceDetails", b => 131 | { 132 | b.HasOne("Invoice.Domain.InvoiceInfo", null) 133 | .WithMany("invoiceDetails") 134 | .HasForeignKey("InvoiceInfoId") 135 | .OnDelete(DeleteBehavior.Cascade) 136 | .IsRequired(); 137 | }); 138 | 139 | modelBuilder.Entity("Invoice.Domain.InvoiceInfo", b => 140 | { 141 | b.Navigation("invoiceDetails"); 142 | }); 143 | #pragma warning restore 612, 618 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Migrations/20221202114309_addproduct.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace Invoice.Infra.Data.Migrations 6 | { 7 | public partial class addproduct : Migration 8 | { 9 | protected override void Up(MigrationBuilder migrationBuilder) 10 | { 11 | migrationBuilder.CreateTable( 12 | name: "Products", 13 | columns: table => new 14 | { 15 | Id = table.Column(type: "int", nullable: false) 16 | .Annotation("SqlServer:Identity", "1, 1"), 17 | Name = table.Column(type: "nvarchar(max)", nullable: true), 18 | price = table.Column(type: "decimal(18,2)", nullable: false) 19 | }, 20 | constraints: table => 21 | { 22 | table.PrimaryKey("PK_Products", x => x.Id); 23 | }); 24 | } 25 | 26 | protected override void Down(MigrationBuilder migrationBuilder) 27 | { 28 | migrationBuilder.DropTable( 29 | name: "Products"); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Migrations/20230109094723_add customer entity.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Invoice.Infra.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | #nullable disable 11 | 12 | namespace Invoice.Infra.Data.Migrations 13 | { 14 | [DbContext(typeof(AppDbContext))] 15 | [Migration("20230109094723_add customer entity")] 16 | partial class addcustomerentity 17 | { 18 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 19 | { 20 | #pragma warning disable 612, 618 21 | modelBuilder 22 | .HasAnnotation("ProductVersion", "6.0.10") 23 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 24 | 25 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); 26 | 27 | modelBuilder.Entity("Invoice.Domain.Customer", b => 28 | { 29 | b.Property("Id") 30 | .ValueGeneratedOnAdd() 31 | .HasColumnType("int"); 32 | 33 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 34 | 35 | b.Property("Address") 36 | .IsRequired() 37 | .HasColumnType("nvarchar(max)"); 38 | 39 | b.Property("Name") 40 | .IsRequired() 41 | .HasColumnType("nvarchar(max)"); 42 | 43 | b.HasKey("Id"); 44 | 45 | b.ToTable("Customers"); 46 | }); 47 | 48 | modelBuilder.Entity("Invoice.Domain.InvoiceDetails", b => 49 | { 50 | b.Property("Id") 51 | .ValueGeneratedOnAdd() 52 | .HasColumnType("int"); 53 | 54 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 55 | 56 | b.Property("Description") 57 | .IsRequired() 58 | .HasColumnType("nvarchar(max)"); 59 | 60 | b.Property("GrandTotal") 61 | .HasColumnType("float"); 62 | 63 | b.Property("InvoiceInfoId") 64 | .HasColumnType("int"); 65 | 66 | b.Property("InvoiceNote") 67 | .IsRequired() 68 | .HasColumnType("nvarchar(max)"); 69 | 70 | b.Property("Price") 71 | .HasColumnType("float"); 72 | 73 | b.Property("ProductName") 74 | .IsRequired() 75 | .HasColumnType("nvarchar(max)"); 76 | 77 | b.Property("Qunatity") 78 | .HasColumnType("int"); 79 | 80 | b.Property("SubTotal") 81 | .HasColumnType("float"); 82 | 83 | b.Property("Tax") 84 | .HasColumnType("decimal(18,2)"); 85 | 86 | b.Property("Total") 87 | .HasColumnType("float"); 88 | 89 | b.Property("TotalTax") 90 | .HasColumnType("float"); 91 | 92 | b.HasKey("Id"); 93 | 94 | b.HasIndex("InvoiceInfoId"); 95 | 96 | b.ToTable("InvoiceDetails"); 97 | }); 98 | 99 | modelBuilder.Entity("Invoice.Domain.InvoiceInfo", b => 100 | { 101 | b.Property("Id") 102 | .ValueGeneratedOnAdd() 103 | .HasColumnType("int"); 104 | 105 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 106 | 107 | b.Property("BillTo") 108 | .HasColumnType("int"); 109 | 110 | b.Property("CreatedDate") 111 | .HasColumnType("datetime2"); 112 | 113 | b.Property("DueDate") 114 | .HasColumnType("datetime2"); 115 | 116 | b.Property("InvoiceDate") 117 | .HasColumnType("datetime2"); 118 | 119 | b.Property("InvoiceNo") 120 | .IsRequired() 121 | .HasColumnType("nvarchar(max)"); 122 | 123 | b.Property("Status") 124 | .IsRequired() 125 | .HasColumnType("nvarchar(max)"); 126 | 127 | b.HasKey("Id"); 128 | 129 | b.ToTable("InvoiceInfo"); 130 | }); 131 | 132 | modelBuilder.Entity("Invoice.Domain.Product", b => 133 | { 134 | b.Property("Id") 135 | .ValueGeneratedOnAdd() 136 | .HasColumnType("int"); 137 | 138 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 139 | 140 | b.Property("Name") 141 | .HasColumnType("nvarchar(max)"); 142 | 143 | b.Property("price") 144 | .HasColumnType("decimal(18,2)"); 145 | 146 | b.HasKey("Id"); 147 | 148 | b.ToTable("Products"); 149 | }); 150 | 151 | modelBuilder.Entity("Invoice.Domain.InvoiceDetails", b => 152 | { 153 | b.HasOne("Invoice.Domain.InvoiceInfo", null) 154 | .WithMany("invoiceDetails") 155 | .HasForeignKey("InvoiceInfoId") 156 | .OnDelete(DeleteBehavior.Cascade) 157 | .IsRequired(); 158 | }); 159 | 160 | modelBuilder.Entity("Invoice.Domain.InvoiceInfo", b => 161 | { 162 | b.Navigation("invoiceDetails"); 163 | }); 164 | #pragma warning restore 612, 618 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Migrations/20230109094723_add customer entity.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace Invoice.Infra.Data.Migrations 6 | { 7 | public partial class addcustomerentity : Migration 8 | { 9 | protected override void Up(MigrationBuilder migrationBuilder) 10 | { 11 | migrationBuilder.CreateTable( 12 | name: "Customers", 13 | columns: table => new 14 | { 15 | Id = table.Column(type: "int", nullable: false) 16 | .Annotation("SqlServer:Identity", "1, 1"), 17 | Name = table.Column(type: "nvarchar(max)", nullable: false), 18 | Address = table.Column(type: "nvarchar(max)", nullable: false) 19 | }, 20 | constraints: table => 21 | { 22 | table.PrimaryKey("PK_Customers", x => x.Id); 23 | }); 24 | } 25 | 26 | protected override void Down(MigrationBuilder migrationBuilder) 27 | { 28 | migrationBuilder.DropTable( 29 | name: "Customers"); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Migrations/AppDbContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Invoice.Infra.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | 9 | #nullable disable 10 | 11 | namespace Invoice.Infra.Data.Migrations 12 | { 13 | [DbContext(typeof(AppDbContext))] 14 | partial class AppDbContextModelSnapshot : ModelSnapshot 15 | { 16 | protected override void BuildModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("ProductVersion", "6.0.10") 21 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 22 | 23 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); 24 | 25 | modelBuilder.Entity("Invoice.Domain.Customer", b => 26 | { 27 | b.Property("Id") 28 | .ValueGeneratedOnAdd() 29 | .HasColumnType("int"); 30 | 31 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 32 | 33 | b.Property("Address") 34 | .IsRequired() 35 | .HasColumnType("nvarchar(max)"); 36 | 37 | b.Property("Name") 38 | .IsRequired() 39 | .HasColumnType("nvarchar(max)"); 40 | 41 | b.HasKey("Id"); 42 | 43 | b.ToTable("Customers"); 44 | }); 45 | 46 | modelBuilder.Entity("Invoice.Domain.InvoiceDetails", b => 47 | { 48 | b.Property("Id") 49 | .ValueGeneratedOnAdd() 50 | .HasColumnType("int"); 51 | 52 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 53 | 54 | b.Property("Description") 55 | .IsRequired() 56 | .HasColumnType("nvarchar(max)"); 57 | 58 | b.Property("GrandTotal") 59 | .HasColumnType("float"); 60 | 61 | b.Property("InvoiceInfoId") 62 | .HasColumnType("int"); 63 | 64 | b.Property("InvoiceNote") 65 | .IsRequired() 66 | .HasColumnType("nvarchar(max)"); 67 | 68 | b.Property("Price") 69 | .HasColumnType("float"); 70 | 71 | b.Property("ProductName") 72 | .IsRequired() 73 | .HasColumnType("nvarchar(max)"); 74 | 75 | b.Property("Qunatity") 76 | .HasColumnType("int"); 77 | 78 | b.Property("SubTotal") 79 | .HasColumnType("float"); 80 | 81 | b.Property("Tax") 82 | .HasColumnType("decimal(18,2)"); 83 | 84 | b.Property("Total") 85 | .HasColumnType("float"); 86 | 87 | b.Property("TotalTax") 88 | .HasColumnType("float"); 89 | 90 | b.HasKey("Id"); 91 | 92 | b.HasIndex("InvoiceInfoId"); 93 | 94 | b.ToTable("InvoiceDetails"); 95 | }); 96 | 97 | modelBuilder.Entity("Invoice.Domain.InvoiceInfo", b => 98 | { 99 | b.Property("Id") 100 | .ValueGeneratedOnAdd() 101 | .HasColumnType("int"); 102 | 103 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 104 | 105 | b.Property("BillTo") 106 | .HasColumnType("int"); 107 | 108 | b.Property("CreatedDate") 109 | .HasColumnType("datetime2"); 110 | 111 | b.Property("DueDate") 112 | .HasColumnType("datetime2"); 113 | 114 | b.Property("InvoiceDate") 115 | .HasColumnType("datetime2"); 116 | 117 | b.Property("InvoiceNo") 118 | .IsRequired() 119 | .HasColumnType("nvarchar(max)"); 120 | 121 | b.Property("Status") 122 | .IsRequired() 123 | .HasColumnType("nvarchar(max)"); 124 | 125 | b.HasKey("Id"); 126 | 127 | b.ToTable("InvoiceInfo"); 128 | }); 129 | 130 | modelBuilder.Entity("Invoice.Domain.Product", b => 131 | { 132 | b.Property("Id") 133 | .ValueGeneratedOnAdd() 134 | .HasColumnType("int"); 135 | 136 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 137 | 138 | b.Property("Name") 139 | .HasColumnType("nvarchar(max)"); 140 | 141 | b.Property("price") 142 | .HasColumnType("decimal(18,2)"); 143 | 144 | b.HasKey("Id"); 145 | 146 | b.ToTable("Products"); 147 | }); 148 | 149 | modelBuilder.Entity("Invoice.Domain.InvoiceDetails", b => 150 | { 151 | b.HasOne("Invoice.Domain.InvoiceInfo", null) 152 | .WithMany("invoiceDetails") 153 | .HasForeignKey("InvoiceInfoId") 154 | .OnDelete(DeleteBehavior.Cascade) 155 | .IsRequired(); 156 | }); 157 | 158 | modelBuilder.Entity("Invoice.Domain.InvoiceInfo", b => 159 | { 160 | b.Navigation("invoiceDetails"); 161 | }); 162 | #pragma warning restore 612, 618 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/PagerExtension.cs: -------------------------------------------------------------------------------- 1 | //using Invoice.Domain; 2 | //using Microsoft.EntityFrameworkCore; 3 | //using System; 4 | //using System.Collections.Generic; 5 | //using System.Linq; 6 | //using System.Text; 7 | //using System.Threading.Tasks; 8 | 9 | //namespace Invoice.Infra.Data 10 | //{ 11 | // public static class PagerExtension 12 | // { 13 | // public static async Task> PaginateAsync( 14 | // this IQueryable query, 15 | // int page, 16 | // int limit, 17 | // CancellationToken cancellationToken) 18 | // where TModel : class 19 | // { 20 | 21 | // var paged = new PagedList(); 22 | 23 | // page = (page < 0) ? 1 : page; 24 | 25 | // //paged.CurrentPage = page; 26 | // paged.PageSize = limit; 27 | 28 | 29 | 30 | // var startRow = (page - 1) * limit; 31 | // paged.Items = await query 32 | // .Skip(startRow) 33 | // .Take(limit) 34 | // .ToListAsync(cancellationToken); 35 | 36 | // paged.TotalItems = await totalItemsCountTask; 37 | // paged.TotalPages = (int)Math.Ceiling(paged.TotalItems / (double)limit); 38 | 39 | // return paged; 40 | // } 41 | // } 42 | //} 43 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Repository/CustomerDapperRepository.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Infra.Data.Interfaces; 2 | using Microsoft.Extensions.Configuration; 3 | using Dapper; 4 | using Microsoft.Data.SqlClient; 5 | using Invoice.Domain.Entity; 6 | 7 | namespace Invoice.Infra.Data.Repository 8 | { 9 | public class CustomerDapperRepository : ICustomeDapperRepository 10 | { 11 | private IConfiguration _configuration; 12 | private readonly SqlConnection _sqlConnection; 13 | 14 | public CustomerDapperRepository(IConfiguration configuration) 15 | { 16 | _configuration = configuration; 17 | _sqlConnection = new SqlConnection(_configuration.GetConnectionString("InvoiceConnection")); 18 | } 19 | 20 | public List GetAll() 21 | { 22 | var query = "select * from Customers"; 23 | return _sqlConnection.Query(query).ToList(); 24 | } 25 | public void Insert(Customer customer) 26 | { 27 | var query = @"Insert into Customers(Name,Address) VALUES(@Name,@Address)"; 28 | _sqlConnection.Execute(query,new { Name = customer.Name, Address = customer.Address}); 29 | } 30 | public Customer Get(int id) 31 | { 32 | var query = "select * from Customers where Id=" + id; 33 | return _sqlConnection.QueryFirstOrDefault(query); 34 | } 35 | public void Delete(int id) 36 | { 37 | var query = "delete from Customers where Id ="+ id; 38 | _sqlConnection.Execute(query); 39 | } 40 | public void Update(Customer customer) 41 | { 42 | var query = "update Customers set Name="+ customer.Name +", Address="+ customer.Address + " where Id="+ customer.Id; 43 | _sqlConnection.Execute(query); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Repository/GenericRepository.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Infra.Data.Interfaces; 2 | using Microsoft.EntityFrameworkCore; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Invoice.Infra.Data.Repository 10 | { 11 | public class GenericRepository : IGenericRepository where T : class 12 | { 13 | protected readonly AppDbContext _appDbContext; 14 | 15 | public GenericRepository(AppDbContext appDbContext) 16 | { 17 | _appDbContext = appDbContext; 18 | } 19 | 20 | public Task Add(T entity) 21 | { 22 | _appDbContext.Set().Add(entity); 23 | return Task.CompletedTask; 24 | } 25 | 26 | public void Delete(T entity) 27 | { 28 | _appDbContext.Set().Remove(entity); 29 | } 30 | 31 | public IQueryable GetAll() 32 | { 33 | return _appDbContext.Set().AsNoTracking(); 34 | } 35 | 36 | public Task GetById(int id) 37 | { 38 | throw new NotImplementedException(); 39 | } 40 | 41 | public void Update(T entity) 42 | { 43 | throw new NotImplementedException(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Repository/InvoiceDetailsRepository.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Domain.Entity; 2 | using Invoice.Infra.Data.Interfaces; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Invoice.Infra.Data.Repository 10 | { 11 | public class InvoiceDetailsRepository : GenericRepository, IInvoiceDetailsRepository 12 | { 13 | private readonly AppDbContext appDb; 14 | public InvoiceDetailsRepository(AppDbContext appDbContext): base(appDbContext) 15 | { 16 | appDb = appDbContext; 17 | } 18 | 19 | public List GetByInvoiceId(int invoiceId) 20 | { 21 | return appDb.InvoiceDetails.Where(x => x.InvoiceInfoId == invoiceId).ToList(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Repository/InvoiceInfoRepository.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Domain; 2 | using Invoice.Infra.Data.Interfaces; 3 | using Microsoft.EntityFrameworkCore; 4 | using System.Linq.Expressions; 5 | using System.Reflection; 6 | using System.Linq; 7 | //using System.Linq.Dynamic.Core; 8 | using System.Text; 9 | using System.Security.Cryptography; 10 | using Invoice.Domain.DTO; 11 | using Invoice.Infra.Data.Extention; 12 | using static Microsoft.EntityFrameworkCore.DbLoggerCategory; 13 | using System.Threading; 14 | using Invoice.Domain.Entity; 15 | using System.Runtime.InteropServices; 16 | 17 | namespace Invoice.Infra.Data.Repository 18 | { 19 | public class InvoiceInfoRepository : GenericRepository,IInvoiceInfoRepository 20 | { 21 | private readonly AppDbContext appDb; 22 | public InvoiceInfoRepository(AppDbContext context) : base(context) 23 | { 24 | appDb = context; 25 | } 26 | 27 | public Task> GetInvoiceByCustomerID(int custId) 28 | { 29 | throw new NotImplementedException(); 30 | } 31 | 32 | public PagedList GetInvoiceWithPaging(PagingRequestModel paging) 33 | { 34 | IQueryable data = from invoice in appDb.InvoiceInfo 35 | join cust in appDb.Customers 36 | on invoice.BillTo equals cust.Id 37 | orderby invoice.InvoiceDate ascending 38 | select new InvoiceInfoDTO 39 | { 40 | Id = invoice.Id, 41 | Customer = cust.Name, 42 | InvoiceNo = invoice.InvoiceNo, 43 | InvoiceDate = invoice.InvoiceDate, 44 | DueDate = invoice.DueDate, 45 | Status = invoice.Status 46 | }; 47 | 48 | var result = data.OrderByDynamic(paging.orderBy, paging.direction).Paging(paging.PageSize, paging.PageNumber).ToList(); 49 | return new PagedList(result, data.Count(), paging.PageNumber, paging.PageSize); 50 | } 51 | 52 | private void ApplySort(ref IQueryable invoices, string orderbystring, string byOrder) 53 | { 54 | if (!invoices.Any()) 55 | return; 56 | 57 | if (string.IsNullOrWhiteSpace(orderbystring)) 58 | { 59 | invoices = invoices.OrderBy(x => x.InvoiceDate); 60 | } 61 | 62 | //var orderParams = orderbystring.Trim().Split(","); 63 | var queryBuilder = new StringBuilder(); 64 | //foreach(var param in orderParams) 65 | //{ 66 | // if (string.IsNullOrWhiteSpace(param)) 67 | // continue; 68 | 69 | var propertyInfos = typeof(InvoiceInfo).GetProperty(orderbystring); 70 | if (propertyInfos == null) 71 | return; 72 | 73 | queryBuilder.Append($"{propertyInfos.Name}"); 74 | //} 75 | 76 | var orderQuery = queryBuilder.ToString(); 77 | 78 | invoices.OrderBy(x => propertyInfos.Name); 79 | } 80 | 81 | private void ApplyPagination(ref IQueryable invoices, PagingRequestModel paging) 82 | { 83 | if (!invoices.Any()) 84 | return; 85 | 86 | invoices.Skip((paging.PageNumber -1) * paging.PageSize).Take(paging.PageSize).ToList(); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Repository/ProductRepository.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Domain.Entity; 2 | using Invoice.Infra.Data.Interfaces; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Invoice.Infra.Data.Repository 10 | { 11 | public class ProductRepository: GenericRepository, IProductRepository 12 | { 13 | protected readonly AppDbContext _appDbContext; 14 | public ProductRepository(AppDbContext context) : base(context) 15 | { 16 | _appDbContext = context; 17 | } 18 | 19 | public async Task CreateProduct(Product product) 20 | { 21 | _appDbContext.Products.Add(product); 22 | await _appDbContext.SaveChangesAsync(); 23 | return product; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Invoice.Infra.Data/Repository/UnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Infra.Data.Interfaces; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Invoice.Infra.Data.Repository 9 | { 10 | public class UnitOfWork : IUnitOfWork 11 | { 12 | private readonly AppDbContext _contex; 13 | public IInvoiceInfoRepository InvoiceInfo { get; } 14 | public IInvoiceDetailsRepository InvoiceDetails { get; } 15 | 16 | public UnitOfWork(AppDbContext appDbContext, IInvoiceInfoRepository invoiceInfoRepository, IInvoiceDetailsRepository invoiceDetailsRepository ) 17 | { 18 | _contex = appDbContext; 19 | InvoiceInfo = invoiceInfoRepository; 20 | InvoiceDetails = invoiceDetailsRepository; 21 | } 22 | 23 | public int complete() 24 | { 25 | return _contex.SaveChanges(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Invoice.Services.API/Controllers/CustomerController.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Applicaion.Interfaces; 2 | using Invoice.Domain.Entity; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.AspNetCore.Mvc; 5 | 6 | namespace Invoice.Services.API.Controllers 7 | { 8 | [ApiVersion("1.0")] 9 | [Route("api/v{version:apiVersion}/[controller]")] 10 | [ApiController] 11 | public class CustomerController : ControllerBase 12 | { 13 | private readonly ICustomerDapperService _customerDapperService; 14 | public CustomerController(ICustomerDapperService customerDapperService) 15 | { 16 | _customerDapperService = customerDapperService; 17 | } 18 | 19 | [HttpGet("GetAll")] 20 | public IActionResult GetAll() 21 | { 22 | var customers = _customerDapperService.GetAll(); 23 | return Ok(customers); 24 | } 25 | 26 | [HttpPost("SaveCustomer")] 27 | public IActionResult SaveCustomer(Customer customer) 28 | { 29 | _customerDapperService.Insert(customer); 30 | return Ok(); 31 | } 32 | 33 | [HttpGet("GetById")] 34 | public IActionResult GetById(int id) 35 | { 36 | var result = _customerDapperService.GetById(id); 37 | return Ok(result); 38 | } 39 | 40 | [HttpDelete] 41 | public IActionResult Delete(int id) 42 | { 43 | _customerDapperService.Delete(id); 44 | return Ok(); 45 | } 46 | 47 | [HttpPut] 48 | public IActionResult Update(Customer customer) 49 | { 50 | _customerDapperService.Update(customer); 51 | return Ok(); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Invoice.Services.API/Controllers/InvoiceController.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using FluentValidation; 3 | using FluentValidation.Results; 4 | using Invoice.Applicaion.Interface; 5 | using Invoice.Applicaion.Validations; 6 | using Invoice.Domain; 7 | using Invoice.Domain.DTO; 8 | using Invoice.Domain.Entity; 9 | using Invoice.Infra.Data.Interfaces; 10 | using Microsoft.AspNetCore.Cors; 11 | using Microsoft.AspNetCore.Mvc; 12 | using Microsoft.EntityFrameworkCore; 13 | using Serilog; 14 | 15 | namespace Invoice.Services.API.Controllers 16 | { 17 | //[Authorize] 18 | [Route("api/[controller]")] 19 | [ApiController] 20 | public class InvoiceController : ControllerBase 21 | { 22 | private readonly IUnitOfWork _unitOfWork; 23 | private readonly IInvoiceService _invoiceService; 24 | private IMapper _mapper; 25 | public InvoiceController(IInvoiceService invoiceService, IUnitOfWork unitOfWork, IMapper mapper) 26 | { 27 | _invoiceService = invoiceService; 28 | _unitOfWork = unitOfWork; 29 | _mapper = mapper; 30 | } 31 | 32 | [HttpGet] 33 | public async Task GetInvoice([FromQuery] PagingRequestModel pagingModel) 34 | { 35 | Log.Information("Get Invoice API call"); 36 | var invoices = _unitOfWork.InvoiceInfo.GetInvoiceWithPaging(pagingModel); 37 | //var invoiceInfo = await _unitOfWork.InvoiceInfo.GetAll().ToListAsync(); 38 | //foreach (var item in invoiceInfo) 39 | //{ 40 | // var detail = _unitOfWork.InvoiceDetails.GetByInvoiceId(item.Id); 41 | // item.invoiceDetails = detail; 42 | //} 43 | 44 | var metadata = new 45 | { 46 | invoices.TotalCount, 47 | invoices.PageSize, 48 | invoices.CurrentPage, 49 | invoices.TotalPages, 50 | invoices.hasPrivious, 51 | invoices.hasNext 52 | }; 53 | invoices[0].TotalRecords = invoices.TotalCount; 54 | Response.Headers.Add("X-Pagination", Newtonsoft.Json.JsonConvert.SerializeObject(metadata)); 55 | 56 | return Ok(invoices); 57 | } 58 | 59 | [HttpPost("SaveInvoice")] 60 | public async Task SaveInvoice(InvoiceDTO invoiceDTO) 61 | { 62 | var invoiceInfo = _mapper.Map(invoiceDTO); 63 | 64 | InvoiceInfoValidator validator = new InvoiceInfoValidator(); 65 | validator.ValidateAndThrow(invoiceInfo); 66 | 67 | 68 | //ValidationResult result = validator.Validate(invoiceInfo); 69 | //if (!result.IsValid) 70 | //{ 71 | // return BadRequest(result.Errors); 72 | //} 73 | 74 | await _invoiceService.SaveInvoice(invoiceInfo); 75 | return Ok(invoiceInfo); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Invoice.Services.API/Controllers/ProductController.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Applicaion.CQRS.Commands; 2 | using Invoice.Applicaion.CQRS.Notifications; 3 | using Invoice.Applicaion.CQRS.Queries; 4 | using MediatR; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.Extensions.Caching.Distributed; 8 | using System.Text; 9 | using Newtonsoft.Json; 10 | using Invoice.Domain.Entity; 11 | 12 | namespace Invoice.Services.API.Controllers 13 | { 14 | [Route("api/[controller]")] 15 | [ApiController] 16 | public class ProductController : ControllerBase 17 | { 18 | private readonly IMediator _mediator; 19 | private readonly IDistributedCache _distributedCache; 20 | public ProductController(IMediator mediator, IDistributedCache distributedCache) 21 | { 22 | _mediator = mediator; 23 | _distributedCache = distributedCache; 24 | } 25 | 26 | [HttpPost("AddProduct")] 27 | public async Task AddProduct(Product product) 28 | { 29 | var productCommand = new AddProductCommand() { product = product }; 30 | var productRetrun = await _mediator.Send(productCommand); 31 | return Ok(productRetrun); 32 | } 33 | 34 | [HttpGet("GetProduct")] 35 | public async Task GetProduct() 36 | { 37 | string serializedcustomerlist; 38 | //var redisProductList = await _distributedCache.GetAsync("productlist"); 39 | var products = new List(); 40 | //if (redisProductList != null) 41 | //{ 42 | // serializedcustomerlist = Encoding.UTF8.GetString(redisProductList); 43 | // products = JsonConvert.DeserializeObject>(serializedcustomerlist); 44 | //} 45 | //else { 46 | products = await _mediator.Send(new GetProductQuery()); 47 | serializedcustomerlist = JsonConvert.SerializeObject(products); 48 | //redisProductList = Encoding.UTF8.GetBytes(serializedcustomerlist); 49 | //var options = 50 | // new DistributedCacheEntryOptions() 51 | // .SetAbsoluteExpiration(DateTime.Now.AddMinutes(10)) 52 | // .SetSlidingExpiration(TimeSpan.FromMinutes(2)); 53 | //await _distributedCache.SetAsync("productlist", redisProductList, options); 54 | //} 55 | return Ok(products); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Invoice.Services.API/Controllers/UserController.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Applicaion.Interfaces; 2 | using Invoice.Domain.Entity; 3 | using Microsoft.AspNetCore.Authorization; 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace Invoice.Services.API.Controllers 8 | { 9 | [Route("api/[controller]")] 10 | [ApiController] 11 | public class UserController : ControllerBase 12 | { 13 | private readonly ITokenService _tokenService; 14 | private readonly IConfiguration _configuration; 15 | 16 | private string generatedToken = string.Empty; 17 | public UserController(ITokenService tokenService, IConfiguration configuration) 18 | { 19 | _tokenService = tokenService; 20 | _configuration = configuration; 21 | } 22 | 23 | [AllowAnonymous] 24 | [HttpPost("Login")] 25 | public IActionResult Login(UserModel userModel) 26 | { 27 | if(userModel.UserName == "username" && userModel.Password == "password") 28 | { 29 | generatedToken = _tokenService.BuildToken(_configuration["Jwt:key"], _configuration["Jwt:Issuer"], userModel); 30 | return Ok(new { token = generatedToken }); 31 | } 32 | return Unauthorized(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Invoice.Services.API/Controllers/WeatherForecastController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace Invoice.Services.API.Controllers 4 | { 5 | [ApiController] 6 | [Route("[controller]")] 7 | public class WeatherForecastController : ControllerBase 8 | { 9 | private static readonly string[] Summaries = new[] 10 | { 11 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" 12 | }; 13 | 14 | private readonly ILogger _logger; 15 | 16 | public WeatherForecastController(ILogger logger) 17 | { 18 | _logger = logger; 19 | } 20 | 21 | [HttpGet(Name = "GetWeatherForecast")] 22 | public IEnumerable Get() 23 | { 24 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast 25 | { 26 | Date = DateTime.Now.AddDays(index), 27 | TemperatureC = Random.Shared.Next(-20, 55), 28 | Summary = Summaries[Random.Shared.Next(Summaries.Length)] 29 | }) 30 | .ToArray(); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Invoice.Services.API/Dockerfile: -------------------------------------------------------------------------------- 1 | #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. 2 | 3 | FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base 4 | WORKDIR /app 5 | EXPOSE 80 6 | EXPOSE 443 7 | 8 | FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build 9 | WORKDIR /src 10 | COPY ["Invoice.Services.API/Invoice.Services.API.csproj", "Invoice.Services.API/"] 11 | RUN dotnet restore "Invoice.Services.API/Invoice.Services.API.csproj" 12 | COPY . . 13 | WORKDIR "/src/Invoice.Services.API" 14 | RUN dotnet build "Invoice.Services.API.csproj" -c Release -o /app/build 15 | 16 | FROM build AS publish 17 | RUN dotnet publish "Invoice.Services.API.csproj" -c Release -o /app/publish /p:UseAppHost=false 18 | 19 | FROM base AS final 20 | WORKDIR /app 21 | COPY --from=publish /app/publish . 22 | ENTRYPOINT ["dotnet", "Invoice.Services.API.dll"] -------------------------------------------------------------------------------- /Invoice.Services.API/ExceptionMiddleware.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Domain; 2 | using Serilog; 3 | using System.Net; 4 | 5 | namespace Invoice.Services.API 6 | { 7 | public class ExceptionMiddleware 8 | { 9 | private readonly RequestDelegate _next; 10 | private readonly ILogger _logger; 11 | public ExceptionMiddleware(RequestDelegate next,ILogger logger) 12 | { 13 | _next = next; 14 | _logger = logger; 15 | } 16 | 17 | public async Task Invoke(HttpContext httpContext) 18 | { 19 | try 20 | { 21 | await _next(httpContext); 22 | } 23 | catch (Exception ex) 24 | { 25 | _logger.LogError(ex , ex.Message); 26 | Log.Error(ex, ex.Message); 27 | await HandleExceptionAsync(httpContext, ex); 28 | } 29 | } 30 | private async Task HandleExceptionAsync(HttpContext context, Exception exception) 31 | { 32 | context.Response.ContentType = "application/json"; 33 | context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; 34 | await context.Response.WriteAsync(new ErrorDetails() 35 | { 36 | StatusCode = context.Response.StatusCode, 37 | Message = "Internal Server Error from the custom middleware." 38 | }.ToString()); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Invoice.Services.API/Invoice.Services.API.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 855d21aa-16bf-49a2-a59a-f3d12fae6a90 8 | Linux 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Invoice.Services.API/MappingProfiles.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Invoice.Domain.DTO; 3 | using Invoice.Domain.Entity; 4 | using System.Security.Cryptography.X509Certificates; 5 | 6 | namespace Invoice.Services.API 7 | { 8 | public class MappingProfiles: Profile 9 | { 10 | public MappingProfiles() 11 | { 12 | CreateMap(); 13 | CreateMap() 14 | .ForMember(dest => dest.Description , opt => opt.MapFrom(src => src.Desc)); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Invoice.Services.API/Program.cs: -------------------------------------------------------------------------------- 1 | using Invoice.Applicaion.CQRS.Behaviors; 2 | using Invoice.Applicaion.CQRS.Commands; 3 | using Invoice.Applicaion.Interface; 4 | using Invoice.Applicaion.Interfaces; 5 | using Invoice.Applicaion.Services; 6 | using Invoice.Infra.Data; 7 | using Invoice.Infra.Data.Interfaces; 8 | using Invoice.Infra.Data.Repository; 9 | using Invoice.Services.API; 10 | using MediatR; 11 | using Microsoft.AspNetCore.Authentication.JwtBearer; 12 | using Microsoft.AspNetCore.Mvc; 13 | using Microsoft.EntityFrameworkCore; 14 | using Microsoft.Extensions.Configuration; 15 | using Microsoft.IdentityModel.Tokens; 16 | using Serilog; 17 | using System.Reflection; 18 | using System.Text; 19 | 20 | var builder = WebApplication.CreateBuilder(args); 21 | 22 | //Option-1: Serilog on top of MEL(Microsoft Etension logging) 23 | //builder.Host.UseSerilog((ctx, lc) => lc 24 | // .WriteTo.Console() 25 | // //.WriteTo.File("log-.txt", rollingInterval: RollingInterval.Day) 26 | // .ReadFrom.Configuration(ctx.Configuration) 27 | // ); 28 | 29 | //Option-2: It will use pure serilog API without MEL 30 | //Log.Logger = new LoggerConfiguration() 31 | // .WriteTo.Console() 32 | // .WriteTo.File("log-.txt", rollingInterval: RollingInterval.Day) 33 | // .CreateLogger(); 34 | //Log.Information("Ah, there you are!"); 35 | 36 | 37 | //Option-3:var logger = new LoggerConfiguration() 38 | // .WriteTo.Console() 39 | // .WriteTo.File("log-.txt", rollingInterval: RollingInterval.Day) 40 | // .CreateLogger(); 41 | //builder.Logging.ClearProviders(); 42 | //builder.Logging.AddSerilog(logger); 43 | 44 | //Option-4: Create logger with read configuration 45 | var logger = new LoggerConfiguration() 46 | .ReadFrom.Configuration(builder.Configuration) 47 | .Enrich.FromLogContext() 48 | .CreateLogger(); 49 | builder.Logging.ClearProviders(); 50 | builder.Logging.AddSerilog(logger); 51 | 52 | // Add services to the container. 53 | 54 | builder.Services.AddControllers(); 55 | // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle 56 | builder.Services.AddEndpointsApiExplorer(); 57 | builder.Services.AddSwaggerGen(); 58 | 59 | builder.Services.AddScoped(); 60 | builder.Services.AddScoped(); 61 | builder.Services.AddScoped(); 62 | builder.Services.AddScoped(); 63 | builder.Services.AddSingleton(); 64 | builder.Services.AddTransient(); 65 | 66 | builder.Services.AddScoped(); 67 | builder.Services.AddTransient(); 68 | 69 | builder.Services.AddMediatR(typeof(Program)); 70 | builder.Services.AddMediatR(typeof(AddProductCommand)); 71 | 72 | builder.Services.AddSingleton(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>)); 73 | 74 | builder.Services.AddDbContext(options => 75 | options.UseSqlServer(builder.Configuration.GetConnectionString("InvoiceConnection")) 76 | ); 77 | 78 | builder.Services.AddAutoMapper(typeof(Program)); 79 | 80 | var Configuration = builder.Configuration; 81 | 82 | builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) 83 | .AddJwtBearer(options => 84 | { 85 | options.TokenValidationParameters = new TokenValidationParameters 86 | { 87 | ValidateIssuer = true, 88 | ValidateAudience = true, 89 | ValidateLifetime = true, 90 | ValidateIssuerSigningKey = true, 91 | ValidIssuer = Configuration["Jwt:Issuer"], 92 | ValidAudience = Configuration["Jwt:Issuer"], 93 | IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])) 94 | }; 95 | }); 96 | 97 | builder.Services.AddStackExchangeRedisCache(options => 98 | { 99 | options.Configuration = builder.Configuration["RedisconnectionString"].ToString(); 100 | }); 101 | 102 | var allowOrigins = "corsallow"; 103 | builder.Services.AddCors(option => 104 | { 105 | option.AddPolicy(name: "AllowOrigin", 106 | builder => { builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); 107 | }); 108 | }); 109 | 110 | builder.Services.AddApiVersioning(options => 111 | { 112 | options.AssumeDefaultVersionWhenUnspecified = true; 113 | options.DefaultApiVersion = new ApiVersion(1, 0); 114 | }); 115 | 116 | var app = builder.Build(); 117 | 118 | // Configure the HTTP request pipeline. 119 | if (app.Environment.IsDevelopment()) 120 | { 121 | app.UseSwagger(); 122 | app.UseSwaggerUI(); 123 | } 124 | //app.UseSerilogRequestLogging(); //use this with option-1 125 | 126 | app.UseAuthentication(); 127 | 128 | app.UseHttpsRedirection(); 129 | 130 | app.UseCors("AllowOrigin"); 131 | 132 | app.UseAuthorization(); 133 | 134 | app.MapControllers(); 135 | 136 | app.UseMiddleware(); 137 | 138 | app.Run(); 139 | -------------------------------------------------------------------------------- /Invoice.Services.API/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Invoice.Services.API": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "launchUrl": "swagger", 7 | "environmentVariables": { 8 | "ASPNETCORE_ENVIRONMENT": "Development" 9 | }, 10 | "dotnetRunMessages": true, 11 | "applicationUrl": "https://localhost:7013;http://localhost:5013" 12 | }, 13 | "IIS Express": { 14 | "commandName": "IISExpress", 15 | "launchBrowser": true, 16 | "launchUrl": "swagger", 17 | "environmentVariables": { 18 | "ASPNETCORE_ENVIRONMENT": "Development" 19 | } 20 | }, 21 | "Docker": { 22 | "commandName": "Docker", 23 | "launchBrowser": true, 24 | "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", 25 | "publishAllPorts": true, 26 | "useSSL": true 27 | } 28 | }, 29 | "$schema": "https://json.schemastore.org/launchsettings.json", 30 | "iisSettings": { 31 | "windowsAuthentication": false, 32 | "anonymousAuthentication": true, 33 | "iisExpress": { 34 | "applicationUrl": "http://localhost:3932", 35 | "sslPort": 44304 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Invoice.Services.API/WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | namespace Invoice.Services.API 2 | { 3 | public class WeatherForecast 4 | { 5 | public DateTime Date { get; set; } 6 | 7 | public int TemperatureC { get; set; } 8 | 9 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 10 | 11 | public string? Summary { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Invoice.Services.API/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Serilog": { 3 | "MinimumLevel": { 4 | "Default": "Information", 5 | "Override": { 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | }, 10 | "Filter": [ 11 | { 12 | "Name": "ByExcluding", 13 | "Args": { 14 | "expression": "@mt = 'An unhandled exception has occurred while executing the request.'" 15 | } 16 | } 17 | ], 18 | "WriteTo": [ 19 | { 20 | "Name": "File", 21 | "Args": { 22 | "path": "./logs/log-.txt", 23 | "rollingInterval": "Day" 24 | } 25 | }, 26 | { 27 | "Name": "Seq", 28 | "Args": { "serverUrl": "http://localhost:5341" } 29 | } 30 | ] 31 | }, 32 | "AllowedHosts": "*", 33 | "ConnectionStrings": { 34 | "InvoiceConnection": "Server=DESKTOP-DPB8QG9;Initial Catalog=InvoiceDB;MultipleActiveResultSets=true;User ID=sa;Password=sa123" 35 | }, 36 | "Jwt": { 37 | "Key": "ThisismySecretKey", 38 | "Issuer": "http://localhost:7013/", 39 | "Audience": "http://localhost:7013/" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Invoice.Services.API/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Serilog": { 3 | "MinimumLevel": { 4 | "Default": "Information", 5 | "Override": { 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | }, 10 | "Filter": [ 11 | { 12 | "Name": "ByExcluding", 13 | "Args": { 14 | "expression": "@mt = 'An unhandled exception has occurred while executing the request.'" 15 | } 16 | } 17 | ], 18 | "WriteTo": [ 19 | { 20 | "Name": "File", 21 | "Args": { 22 | "path": "./logs/log-.txt", 23 | "rollingInterval": "Day" 24 | } 25 | }, 26 | { 27 | "Name": "Seq", 28 | "Args": { "serverUrl": "http://localhost:5341" } 29 | } 30 | ] 31 | }, 32 | "AllowedHosts": "*", 33 | "ConnectionStrings": { 34 | "InvoiceConnection": "Server=DESKTOP-DPB8QG9;Initial Catalog=InvoiceDB;MultipleActiveResultSets=true;User ID=sa;Password=sa123" 35 | }, 36 | "Jwt": { 37 | "Key": "ThisismySecretKey", 38 | "Issuer": "http://localhost:7013/", 39 | "Audience": "http://localhost:7013/" 40 | }, 41 | "RedisconnectionString": "127.0.0.1:6379" 42 | } 43 | -------------------------------------------------------------------------------- /Invoice.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32825.248 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Invoice.Services.API", "Invoice.Services.API\Invoice.Services.API.csproj", "{845F1CDA-84D3-42BB-B289-45C05A9E8B0C}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Invoice.Applicaion", "Invoice.Applicaion\Invoice.Applicaion.csproj", "{49844AF0-DF38-4EE3-8E01-457C50A09BD9}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Invoice.Domain", "Invoice.Domain\Invoice.Domain.csproj", "{13643D87-C83C-4A9B-92AB-7845C0D0DCB6}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Invoice.Infra.Data", "Invoice.Infra.Data\Invoice.Infra.Data.csproj", "{6BB16D08-3583-435B-81DF-8EF62EF309F5}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EmailSendingService", "EmailSendingService\EmailSendingService.csproj", "{461801C0-0454-42C6-9064-0D249C23E2E2}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {845F1CDA-84D3-42BB-B289-45C05A9E8B0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {845F1CDA-84D3-42BB-B289-45C05A9E8B0C}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {845F1CDA-84D3-42BB-B289-45C05A9E8B0C}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {845F1CDA-84D3-42BB-B289-45C05A9E8B0C}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {49844AF0-DF38-4EE3-8E01-457C50A09BD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {49844AF0-DF38-4EE3-8E01-457C50A09BD9}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {49844AF0-DF38-4EE3-8E01-457C50A09BD9}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {49844AF0-DF38-4EE3-8E01-457C50A09BD9}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {13643D87-C83C-4A9B-92AB-7845C0D0DCB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {13643D87-C83C-4A9B-92AB-7845C0D0DCB6}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {13643D87-C83C-4A9B-92AB-7845C0D0DCB6}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {13643D87-C83C-4A9B-92AB-7845C0D0DCB6}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {6BB16D08-3583-435B-81DF-8EF62EF309F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {6BB16D08-3583-435B-81DF-8EF62EF309F5}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {6BB16D08-3583-435B-81DF-8EF62EF309F5}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {6BB16D08-3583-435B-81DF-8EF62EF309F5}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {461801C0-0454-42C6-9064-0D249C23E2E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {461801C0-0454-42C6-9064-0D249C23E2E2}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {461801C0-0454-42C6-9064-0D249C23E2E2}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {461801C0-0454-42C6-9064-0D249C23E2E2}.Release|Any CPU.Build.0 = Release|Any CPU 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | GlobalSection(ExtensibilityGlobals) = postSolution 47 | SolutionGuid = {2176CD5C-99F2-4042-9D26-E4F2F9B4E425} 48 | EndGlobalSection 49 | EndGlobal 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # InvoiceService 2 | --------------------------------------------------------------------------------