Skip to content

Commit b775fb7

Browse files
committed
orders.json added
1 parent 62d41f6 commit b775fb7

26 files changed

Lines changed: 11617 additions & 135 deletions

StarWars.API.sln

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StarWars.Common", "StarWars
77
EndProject
88
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StarWars.Model", "StarWars.Model\StarWars.Model.csproj", "{E2B1078A-3942-4148-A468-322935BDE2D7}"
99
EndProject
10-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StarWars.Interface", "StarWars.Interface\StarWars.Interface.csproj", "{C5BFE477-14D5-417C-A0FF-A53CAD82710D}"
11-
EndProject
1210
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StarWars.Repository", "StarWars.Repository\StarWars.Repository.csproj", "{4458030B-A58F-430C-9548-C0F7A967D843}"
1311
EndProject
1412
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StarWars.API", "StarWars.API\StarWars.API.csproj", "{6365F21C-B8F1-4559-B0E5-55FF85D079B4}"
1513
EndProject
14+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StarWars.UnitTesting", "StarWars.UnitTesting\StarWars.UnitTesting.csproj", "{C0C53F6C-4EBF-4F2D-B8D0-0BF20CAC36CE}"
15+
EndProject
1616
Global
1717
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1818
Debug|Any CPU = Debug|Any CPU
@@ -27,10 +27,6 @@ Global
2727
{E2B1078A-3942-4148-A468-322935BDE2D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
2828
{E2B1078A-3942-4148-A468-322935BDE2D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
2929
{E2B1078A-3942-4148-A468-322935BDE2D7}.Release|Any CPU.Build.0 = Release|Any CPU
30-
{C5BFE477-14D5-417C-A0FF-A53CAD82710D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31-
{C5BFE477-14D5-417C-A0FF-A53CAD82710D}.Debug|Any CPU.Build.0 = Debug|Any CPU
32-
{C5BFE477-14D5-417C-A0FF-A53CAD82710D}.Release|Any CPU.ActiveCfg = Release|Any CPU
33-
{C5BFE477-14D5-417C-A0FF-A53CAD82710D}.Release|Any CPU.Build.0 = Release|Any CPU
3430
{4458030B-A58F-430C-9548-C0F7A967D843}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
3531
{4458030B-A58F-430C-9548-C0F7A967D843}.Debug|Any CPU.Build.0 = Debug|Any CPU
3632
{4458030B-A58F-430C-9548-C0F7A967D843}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -39,6 +35,10 @@ Global
3935
{6365F21C-B8F1-4559-B0E5-55FF85D079B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
4036
{6365F21C-B8F1-4559-B0E5-55FF85D079B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
4137
{6365F21C-B8F1-4559-B0E5-55FF85D079B4}.Release|Any CPU.Build.0 = Release|Any CPU
38+
{C0C53F6C-4EBF-4F2D-B8D0-0BF20CAC36CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39+
{C0C53F6C-4EBF-4F2D-B8D0-0BF20CAC36CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
40+
{C0C53F6C-4EBF-4F2D-B8D0-0BF20CAC36CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
41+
{C0C53F6C-4EBF-4F2D-B8D0-0BF20CAC36CE}.Release|Any CPU.Build.0 = Release|Any CPU
4242
EndGlobalSection
4343
GlobalSection(SolutionProperties) = preSolution
4444
HideSolutionNode = FALSE

StarWars.API/Controllers/MoviesController.cs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using Microsoft.AspNetCore.Authorization;
33
using Microsoft.AspNetCore.Http;
44
using Microsoft.AspNetCore.Mvc;
5-
using StarWars.Interface;
5+
using StarWars.Api.Services;
66
using StarWars.Model;
77
using StarWars.Model.ViewModels;
88
using System;
@@ -14,18 +14,18 @@ namespace StarWars.Api.Controllers
1414
[Route("api/[controller]")]
1515
public class MoviesController : ControllerBase
1616
{
17-
private readonly IMovieService service;
17+
private readonly IMovieService _movieService;
1818

19-
public MoviesController(IMovieService service)
19+
public MoviesController(IMovieService movieService)
2020
{
21-
this.service = service;
21+
_movieService = movieService;
2222
}
2323

2424
[HttpGet]
2525
[ProducesResponseType(StatusCodes.Status200OK)]
2626
public async Task<IActionResult> AllAsync()
2727
{
28-
var items = await service.All();
28+
var items = await _movieService.AllAsync();
2929
return new OkObjectResult(items);
3030
}
3131

@@ -35,7 +35,7 @@ public async Task<IActionResult> AllAsync()
3535
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
3636
public async Task<IActionResult> AllProtectedAsync()
3737
{
38-
var items = await service.All();
38+
var items = await _movieService.AllAsync();
3939
return new OkObjectResult(items);
4040
}
4141

@@ -72,45 +72,45 @@ public async Task<IActionResult> AllSecuredAsync()
7272
}
7373

7474
[HttpGet("{id}")]
75-
public async Task<IActionResult> Get([FromRoute] string id)
75+
public async Task<IActionResult> GetAsync([FromRoute] string id)
7676
{
77-
var item = await service.Get(id);
77+
var item = await _movieService.GetAsync(id);
7878
if (item == null) return new NotFoundObjectResult(id);
7979

8080
return new OkObjectResult(item);
8181
}
8282

8383
[Authorize]
8484
[HttpPost()]
85-
public async Task<IActionResult> Create([FromBody] MovieView movieView)
85+
public async Task<IActionResult> CreateAsync([FromBody] MovieView movieView)
8686
{
8787
var movie = Mapper.Map<Movie>(movieView);
88-
var item = await service.Create(movie);
88+
var item = await _movieService.CreateAsync(movie);
8989
if (item == null) return new BadRequestObjectResult($"Movie with ID '{movieView.ID}' already exists in DB");
9090

9191
return new OkObjectResult(item);
9292
}
9393

9494
[Authorize]
9595
[HttpPut("{id}")]
96-
public async Task<IActionResult> Update([FromRoute] string id, [FromBody] MovieView movieView)
96+
public async Task<IActionResult> UpdateAsync([FromRoute] string id, [FromBody] MovieView movieView)
9797
{
98-
var existingItem = await service.Get(id);
98+
var existingItem = await _movieService.GetAsync(id);
9999
if (existingItem == null) return new NotFoundObjectResult(id);
100100
var movie = Mapper.Map<Movie>(movieView);
101-
var item = await service.Update(id, movie);
101+
var item = await _movieService.UpdateAsync(id, movie);
102102
if (item == null) return new BadRequestObjectResult($"Movie with ID '{id}' could not be updated");
103103
return new OkObjectResult(item);
104104
}
105105

106106
[Authorize]
107107
[HttpDelete("{id}")]
108-
public async Task<IActionResult> Delete([FromRoute] string id)
108+
public async Task<IActionResult> DeleteAsync([FromRoute] string id)
109109
{
110-
var item = await service.Get(id);
110+
var item = await _movieService.GetAsync(id);
111111
if (item == null) return new NotFoundObjectResult(id);
112112

113-
item = await service.Delete(id);
113+
item = await _movieService.DeleteAsync(id);
114114

115115
if (item == null) return new BadRequestObjectResult($"Movie with ID '{id}' could not be deleted");
116116

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using Microsoft.AspNetCore.Http;
2+
using Microsoft.AspNetCore.Mvc;
3+
using Microsoft.Extensions.Logging;
4+
using StarWars.API.Services;
5+
using StarWars.Model;
6+
using StarWars.Model.ViewModels;
7+
using System;
8+
using System.Collections.Generic;
9+
using System.Threading;
10+
using System.Threading.Tasks;
11+
12+
namespace StarWars.API.Controllers
13+
{
14+
[ApiController]
15+
[Route("[controller]")]
16+
public class OrdersController : ControllerBase
17+
{
18+
private readonly ILogger<OrdersController> _logger;
19+
private readonly IOrderService _orderService;
20+
21+
public OrdersController(ILogger<OrdersController> logger, IOrderService orderService)
22+
{
23+
_logger = logger;
24+
_orderService = orderService;
25+
}
26+
27+
[HttpGet]
28+
[ProducesResponseType(typeof(OrderResponseView), StatusCodes.Status200OK)]
29+
public async Task<IActionResult> GetAsync(
30+
[FromQuery] string pharmacyId,
31+
[FromQuery] List<Status> status,
32+
[FromQuery] DateTime? from,
33+
[FromQuery] DateTime? to,
34+
[FromQuery] string sort = Constants.DEFAULT_SORT_BY,
35+
[FromQuery] string dir = Constants.DEFAULT_DIRECTION,
36+
[FromQuery] int page = Constants.DEFAULT_PAGE_START,
37+
[FromQuery] int pageSize = Constants.DEFAULT_PAGE_SIZE,
38+
CancellationToken cancellationToken = default)
39+
{
40+
try
41+
{
42+
var query = new OrderQueryParams {
43+
PharmacyId = pharmacyId,
44+
Status = status,
45+
From = from,
46+
To = to,
47+
Sort = sort,
48+
Dir = dir,
49+
Page = page,
50+
PageSize = pageSize
51+
};
52+
var result = await _orderService.GetAsync(query, cancellationToken);
53+
54+
return Ok(result);
55+
}
56+
catch (Exception ex)
57+
{
58+
_logger.LogError(ex, "GetAsync: Something went wrong");
59+
return BadRequest(ex.Message);
60+
}
61+
}
62+
}
63+
}

StarWars.API/Controllers/WebJetController.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using Microsoft.AspNetCore.Mvc;
2-
using StarWars.Interface;
2+
using StarWars.Api.Services;
33
using System.Threading.Tasks;
44

55
namespace StarWars.Api.Controllers
@@ -8,34 +8,34 @@ namespace StarWars.Api.Controllers
88
[Route("api/[controller]")]
99
public class WebJetController : ControllerBase
1010
{
11-
private readonly IWebJetService service;
11+
private readonly IWebJetService _webJetService;
1212

13-
public WebJetController(IWebJetService service)
13+
public WebJetController(IWebJetService webJetService)
1414
{
15-
this.service = service;
15+
_webJetService = webJetService;
1616
}
1717

1818
[HttpGet("{provider}")]
19-
public async Task<IActionResult> GetAll([FromRoute] string provider)
19+
public async Task<IActionResult> GetAllAsync([FromRoute] string provider)
2020
{
2121
if (string.IsNullOrEmpty(provider))
2222
return BadRequest("Provider is required");
2323

24-
var items = await service.GetAll(provider);
24+
var items = await _webJetService.GetAllAsync(provider);
2525

2626
return new OkObjectResult(items);
2727
}
2828

2929
[HttpGet("{provider}/{id}")]
30-
public async Task<IActionResult> Get([FromRoute] string provider, [FromRoute] string id)
30+
public async Task<IActionResult> GetAsync([FromRoute] string provider, [FromRoute] string id)
3131
{
3232
if (string.IsNullOrEmpty(provider))
3333
return BadRequest("Provider is required");
3434

3535
if (string.IsNullOrEmpty(id))
3636
return BadRequest("Movie ID is required");
3737

38-
var item = await service.Get(provider, id);
38+
var item = await _webJetService.GetAsync(provider, id);
3939

4040
return new OkObjectResult(item);
4141
}

StarWars.API/DatabaseInitializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ private async Task SeedItems(string rootPath)
5353
var items = JsonSerializer.Deserialize<IEnumerable<Movie>>(json, _jsonOptions) ?? [];
5454

5555
await _context.Movies.AddRangeAsync(items);
56-
_logger.LogInformation("Seeded {Count} items successfully!", items.Count());
56+
_logger.LogDebug("Seeded {Count} items successfully!", items.Count());
5757
}
5858
}
5959
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using Microsoft.AspNetCore.Http;
2+
using Microsoft.Extensions.Logging;
3+
using StarWars.Model;
4+
using System;
5+
using System.Threading.Tasks;
6+
7+
namespace StarWars.API.Middleware
8+
{
9+
public class CorrelationIdMiddleware
10+
{
11+
private readonly RequestDelegate _next;
12+
private const string CorrelationHeader = Constants.X_CORRELATION_ID;
13+
14+
public CorrelationIdMiddleware(RequestDelegate next)
15+
{
16+
_next = next;
17+
}
18+
19+
public async Task InvokeAsync(HttpContext context, ILogger<CorrelationIdMiddleware> logger)
20+
{
21+
// Check for incoming correlation ID
22+
if (!context.Request.Headers.TryGetValue(CorrelationHeader, out var correlationId))
23+
{
24+
correlationId = Guid.NewGuid().ToString();
25+
}
26+
27+
// Store in HttpContext.Items for access in controllers/services
28+
context.Items[CorrelationHeader] = correlationId.ToString();
29+
30+
// Add to response headers so clients can see it
31+
context.Response.OnStarting(() =>
32+
{
33+
context.Response.Headers[CorrelationHeader] = correlationId.ToString();
34+
return Task.CompletedTask;
35+
});
36+
37+
using (logger.BeginScope("{CorrelationId}", correlationId!))
38+
{
39+
await _next(context);
40+
}
41+
}
42+
}
43+
}

StarWars.API/Program.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using Microsoft.EntityFrameworkCore;
99
using Microsoft.Extensions.DependencyInjection;
1010
using Microsoft.Extensions.Hosting;
11-
using Microsoft.Extensions.Options;
1211
using Microsoft.IdentityModel.Tokens;
1312
using Microsoft.OpenApi.Models;
1413
using Polly;
@@ -17,7 +16,8 @@
1716
using StarWars.Api.Authorization;
1817
using StarWars.Api.Services;
1918
using StarWars.Api.Settings;
20-
using StarWars.Interface;
19+
using StarWars.API.Middleware;
20+
using StarWars.API.Services;
2121
using StarWars.Model.ViewModels;
2222
using StarWars.Repository;
2323
using System;
@@ -74,6 +74,7 @@ public static async Task Main(string[] args)
7474
var webJetSettings = builder.Configuration.GetSection("WebJetSettings");
7575

7676
builder.Services.Configure<WebJetSettings>(webJetSettings);
77+
builder.Services.AddSingleton<IOrderService, OrderService>();
7778
builder.Services.AddTransient<IDatabaseInitializer, DatabaseInitializer>();
7879
builder.Services.AddTransient<IMoviesRepository, MovieRepository>();
7980
builder.Services.AddScoped<IMovieService, MovieService>();
@@ -89,7 +90,10 @@ public static async Task Main(string[] args)
8990
builder.Services
9091
.AddRouting(o => o.LowercaseUrls = true)
9192
.AddControllers()
92-
.AddJsonOptions(o => o.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull);
93+
.AddJsonOptions(options => {
94+
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
95+
options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
96+
});
9397

9498
builder.Services.AddFluentValidationAutoValidation();
9599
builder.Services.AddFluentValidationClientsideAdapters();
@@ -101,6 +105,16 @@ public static async Task Main(string[] args)
101105

102106
var app = builder.Build();
103107

108+
app.UseMiddleware<CorrelationIdMiddleware>();
109+
110+
// Load and cache orders at startup
111+
using (var scope = app.Services.CreateScope())
112+
{
113+
var orderService = scope.ServiceProvider.GetRequiredService<IOrderService>();
114+
var env = scope.ServiceProvider.GetRequiredService<IWebHostEnvironment>();
115+
await orderService.CacheOrdersAsync(env.ContentRootPath);
116+
}
117+
104118
// DB seeding from JSON file for soft startup
105119
using (var scope = app.Services.CreateScope())
106120
{

0 commit comments

Comments
 (0)