Skip to content

Commit 1fddb0b

Browse files
Implement Order API with CRUD operations and documentation for GitHub Copilot (#23)
2 parents c9b8c7c + c9133b7 commit 1fddb0b

14 files changed

+315
-0
lines changed

.github/copilot-instructions.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Instructions for GitHub Copilot
2+
3+
## Source Control
4+
5+
- We use GitHub Issues for all work tracking.
6+
- We use Pull Requests to facilitate code reviews.
7+
- We use Trunk-based development and short term feature branches. Featur branches should start with `feat/`, for example a feature called "add login" would be `feat/add-login`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using Orders.Domain;
3+
4+
namespace Orders.Api.Controllers;
5+
6+
[ApiController]
7+
[Route("api/[controller]")]
8+
public class OrderController : ControllerBase
9+
{
10+
private readonly IOrderRepository _orderRepository;
11+
private readonly ILogger<OrderController> _logger;
12+
13+
public OrderController(IOrderRepository orderRepository, ILogger<OrderController> logger)
14+
{
15+
_orderRepository = orderRepository;
16+
_logger = logger;
17+
}
18+
19+
[HttpGet("{id}")]
20+
public async Task<IActionResult> GetOrderById(int id)
21+
{
22+
var order = await _orderRepository.GetOrderByIdAsync(id);
23+
if (order == null)
24+
{
25+
return NotFound();
26+
}
27+
return Ok(order);
28+
}
29+
30+
[HttpPost]
31+
public async Task<IActionResult> CreateOrder([FromBody] Order order)
32+
{
33+
await _orderRepository.AddOrderAsync(order);
34+
await _orderRepository.SaveChangesAsync();
35+
return CreatedAtAction(nameof(GetOrderById), new { id = order.Id }, order);
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
11+
<PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.3.0" />
12+
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.10.0" />
13+
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.0.0-rc9.9" />
14+
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.0.0-rc9.9" />
15+
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.2.0" />
16+
</ItemGroup>
17+
18+
<ItemGroup>
19+
<ProjectReference Include="..\Orders.Domain\Orders.Domain.csproj" />
20+
</ItemGroup>
21+
22+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@Orders.Api_HostAddress = http://localhost:5099
2+
3+
GET {{Orders.Api_HostAddress}}/weatherforecast/
4+
Accept: application/json
5+
6+
###

samples/Orders/Orders.Api/Program.cs

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using Orders.Domain;
2+
using Orders.Api.Repositories;
3+
using OpenTelemetry.Trace;
4+
5+
var builder = WebApplication.CreateBuilder(args);
6+
7+
// Add services to the container.
8+
builder.Services.AddControllers();
9+
builder.Services.AddScoped<IOrderRepository, OrderRepository>();
10+
builder.Services.AddOpenApi();
11+
12+
var app = builder.Build();
13+
14+
// Configure the HTTP request pipeline.
15+
if (app.Environment.IsDevelopment())
16+
{
17+
app.UseDeveloperExceptionPage();
18+
app.UseSwagger();
19+
app.UseSwaggerUI();
20+
app.MapOpenApi();
21+
}
22+
23+
app.UseHttpsRedirection();
24+
app.UseAuthorization();
25+
26+
app.MapControllers();
27+
28+
app.Run();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"$schema": "https://json.schemastore.org/launchsettings.json",
3+
"profiles": {
4+
"http": {
5+
"commandName": "Project",
6+
"dotnetRunMessages": true,
7+
"launchBrowser": false,
8+
"applicationUrl": "http://localhost:5099",
9+
"environmentVariables": {
10+
"ASPNETCORE_ENVIRONMENT": "Development"
11+
}
12+
},
13+
"https": {
14+
"commandName": "Project",
15+
"dotnetRunMessages": true,
16+
"launchBrowser": false,
17+
"applicationUrl": "https://localhost:7218;http://localhost:5099",
18+
"environmentVariables": {
19+
"ASPNETCORE_ENVIRONMENT": "Development"
20+
}
21+
}
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Orders.Domain;
2+
3+
namespace Orders.Api.Repositories;
4+
5+
public class OrderRepository : IOrderRepository
6+
{
7+
private readonly List<Order> _orders = new();
8+
9+
public Task<Order> GetOrderByIdAsync(int id)
10+
{
11+
var order = _orders.FirstOrDefault(o => o.Id == id);
12+
return Task.FromResult(order);
13+
}
14+
15+
public Task AddOrderAsync(Order order)
16+
{
17+
_orders.Add(order);
18+
return Task.CompletedTask;
19+
}
20+
21+
public Task SaveChangesAsync()
22+
{
23+
// In-memory implementation, no action needed
24+
return Task.CompletedTask;
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
}
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
},
8+
"AllowedHosts": "*"
9+
}

samples/Orders/Orders.Domain/Order.cs

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
namespace Orders.Domain;
2+
3+
public class Order
4+
{
5+
public int Id { get; set; }
6+
public DateTime OrderDate { get; set; }
7+
public string CustomerName { get; set; }
8+
public List<OrderItem> Items { get; set; } = new List<OrderItem>();
9+
10+
public void AddOrderItem(OrderItem item)
11+
{
12+
Items.Add(item);
13+
}
14+
15+
public decimal GetTotal()
16+
{
17+
return Items.Sum(item => item.Price * item.Quantity);
18+
}
19+
}
20+
21+
public class OrderItem
22+
{
23+
public int Id { get; set; }
24+
public string ProductName { get; set; }
25+
public decimal Price { get; set; }
26+
public int Quantity { get; set; }
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using Microsoft.Extensions.Logging;
2+
3+
namespace Orders.Domain;
4+
5+
public class OrderService
6+
{
7+
private readonly ILogger<Order> _logger;
8+
9+
public OrderService(ILogger<Order> logger)
10+
{
11+
_logger = logger;
12+
}
13+
14+
public int Id { get; set; }
15+
public DateTime OrderDate { get; set; }
16+
public string CustomerName { get; set; }
17+
public List<OrderItem> Items { get; set; } = new List<OrderItem>();
18+
19+
public static Order CreateOrder(ILogger<Order> logger, string customerName, List<OrderItem> items)
20+
{
21+
var order = new Order()
22+
{
23+
CustomerName = customerName,
24+
OrderDate = DateTime.UtcNow,
25+
Items = items
26+
};
27+
logger.LogInformation("Order created for customer: {CustomerName}", customerName);
28+
return order;
29+
}
30+
31+
public void AddOrderItem(OrderItem item)
32+
{
33+
Items.Add(item);
34+
_logger.LogInformation("Order item added: {ProductName}", item.ProductName);
35+
}
36+
37+
public decimal GetTotal()
38+
{
39+
return Items.Sum(item => item.Price * item.Quantity);
40+
}
41+
}
42+
43+
44+
public interface IOrderRepository
45+
{
46+
Task<Order> GetOrderByIdAsync(int id);
47+
Task AddOrderAsync(Order order);
48+
Task SaveChangesAsync();
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.0" />
11+
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
12+
</ItemGroup>
13+
14+
</Project>

samples/Orders/Orders.sln.sln

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.0.31903.59
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orders.Api", "Orders.Api\Orders.Api.csproj", "{7325FF68-A2DA-4F26-BFA6-260B98F11374}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orders.Domain", "Orders.Domain\Orders.Domain.csproj", "{CEB33049-A20A-434C-AC8C-2904E67C85A8}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
Release|Any CPU = Release|Any CPU
14+
EndGlobalSection
15+
GlobalSection(SolutionProperties) = preSolution
16+
HideSolutionNode = FALSE
17+
EndGlobalSection
18+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
19+
{7325FF68-A2DA-4F26-BFA6-260B98F11374}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
20+
{7325FF68-A2DA-4F26-BFA6-260B98F11374}.Debug|Any CPU.Build.0 = Debug|Any CPU
21+
{7325FF68-A2DA-4F26-BFA6-260B98F11374}.Release|Any CPU.ActiveCfg = Release|Any CPU
22+
{7325FF68-A2DA-4F26-BFA6-260B98F11374}.Release|Any CPU.Build.0 = Release|Any CPU
23+
{CEB33049-A20A-434C-AC8C-2904E67C85A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24+
{CEB33049-A20A-434C-AC8C-2904E67C85A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
25+
{CEB33049-A20A-434C-AC8C-2904E67C85A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
26+
{CEB33049-A20A-434C-AC8C-2904E67C85A8}.Release|Any CPU.Build.0 = Release|Any CPU
27+
EndGlobalSection
28+
EndGlobal

samples/Orders/README.md

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Generated with Edits
2+
3+
## Prompt 1
4+
5+
```markdown
6+
# Ordering Domain
7+
8+
## Context
9+
- The Ordering Domain uses DDD and Clean Architecture in an ecommerce web api.
10+
- Business logic is encapsulated for things like `AddOrder`
11+
12+
## Goal
13+
- generate the entities and aggregates for the Order Domain
14+
- use Entity Framework
15+
- use Logging
16+
```
17+
18+
## Prompt 2
19+
20+
```markdown
21+
# Ordering API
22+
23+
## Context
24+
- The Ordering Domain uses DDD and Clean Architecture in an ecommerce web api.
25+
- We follow REST standards and use OpenAPI spec
26+
27+
## Goal
28+
- generate the REST methods for Order domain
29+
- use Controllers, not minimal API
30+
- use Open Telemetry
31+
```

0 commit comments

Comments
 (0)