Skip to content

Commit c6691f2

Browse files
feat: Initial .NET Core 8 solution structure
- Create solution with 5 projects: - OrderMonitor.Api (ASP.NET Core Web API) - OrderMonitor.Core (domain entities, interfaces, models) - OrderMonitor.Infrastructure (data access, email, jobs) - OrderMonitor.UnitTests (xUnit) - OrderMonitor.IntegrationTests (xUnit) - Add project references and NuGet packages: - Dapper, Microsoft.Data.SqlClient (database) - MailKit (email) - Serilog.AspNetCore (logging) - Swashbuckle.AspNetCore (Swagger) - Moq, FluentAssertions (testing) - Create Core entities: Order, OrderStatus - Create Core interfaces: IOrderRepository, IStuckOrderService, IAlertService - Create Core models: StuckOrderDto, StuckOrdersResponse, StuckOrdersSummary, etc. - Add Dockerfile for containerized deployment - Add README with project overview and API docs JIRA: BD-690 Epic: BD-689 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
0 parents  commit c6691f2

26 files changed

Lines changed: 752 additions & 0 deletions

.gitignore

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Build results
2+
[Dd]ebug/
3+
[Rr]elease/
4+
x64/
5+
x86/
6+
[Aa][Rr][Mm]/
7+
[Aa][Rr][Mm]64/
8+
bld/
9+
[Bb]in/
10+
[Oo]bj/
11+
[Ll]og/
12+
[Ll]ogs/
13+
14+
# Visual Studio
15+
.vs/
16+
*.user
17+
*.userosscache
18+
*.sln.docstates
19+
*.suo
20+
*.cache
21+
*.vspscc
22+
*.vssscc
23+
.builds
24+
*.pidb
25+
*.svclog
26+
*.scc
27+
28+
# JetBrains Rider
29+
.idea/
30+
*.sln.iml
31+
32+
# Visual Studio Code
33+
.vscode/
34+
*.code-workspace
35+
36+
# NuGet
37+
*.nupkg
38+
*.snupkg
39+
**/[Pp]ackages/*
40+
!**/[Pp]ackages/build/
41+
*.nuget.props
42+
*.nuget.targets
43+
project.lock.json
44+
project.fragment.lock.json
45+
artifacts/
46+
47+
# ASP.NET
48+
ScaffoldingReadMe.txt
49+
50+
# Windows
51+
Thumbs.db
52+
ehthumbs.db
53+
Desktop.ini
54+
$RECYCLE.BIN/
55+
56+
# macOS
57+
.DS_Store
58+
.AppleDouble
59+
.LSOverride
60+
._*
61+
62+
# Test Results
63+
[Tt]est[Rr]esult*/
64+
[Bb]uild[Ll]og.*
65+
*.trx
66+
TestResult.xml
67+
coverage*.json
68+
coverage*.xml
69+
*.coverage
70+
*.coveragexml
71+
72+
# Docker
73+
**/docker-compose*.yml.override
74+
75+
# Environment
76+
.env
77+
.env.*
78+
!.env.example
79+
appsettings.*.json
80+
!appsettings.json
81+
!appsettings.Development.json
82+
83+
# Secrets
84+
*.pem
85+
*.key
86+
*.pfx
87+
credentials.json

Dockerfile

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Build stage
2+
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
3+
WORKDIR /src
4+
5+
# Copy solution and project files
6+
COPY OrderMonitor.sln .
7+
COPY nuget.config .
8+
COPY src/OrderMonitor.Api/OrderMonitor.Api.csproj src/OrderMonitor.Api/
9+
COPY src/OrderMonitor.Core/OrderMonitor.Core.csproj src/OrderMonitor.Core/
10+
COPY src/OrderMonitor.Infrastructure/OrderMonitor.Infrastructure.csproj src/OrderMonitor.Infrastructure/
11+
12+
# Restore dependencies
13+
RUN dotnet restore
14+
15+
# Copy source code
16+
COPY src/ src/
17+
18+
# Build
19+
RUN dotnet build -c Release --no-restore
20+
21+
# Publish
22+
RUN dotnet publish src/OrderMonitor.Api/OrderMonitor.Api.csproj -c Release -o /app/publish --no-build
23+
24+
# Runtime stage
25+
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
26+
WORKDIR /app
27+
28+
# Copy published app
29+
COPY --from=build /app/publish .
30+
31+
# Set environment
32+
ENV ASPNETCORE_URLS=http://+:8080
33+
ENV ASPNETCORE_ENVIRONMENT=Production
34+
35+
# Expose port
36+
EXPOSE 8080
37+
38+
# Health check
39+
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
40+
CMD curl -f http://localhost:8080/api/health || exit 1
41+
42+
# Run
43+
ENTRYPOINT ["dotnet", "OrderMonitor.Api.dll"]

OrderMonitor.sln

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OrderMonitor.Api", "src\OrderMonitor.Api\OrderMonitor.Api.csproj", "{5D6AB4D5-D22D-4909-B371-E3865C2C1FF5}"
9+
EndProject
10+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OrderMonitor.Core", "src\OrderMonitor.Core\OrderMonitor.Core.csproj", "{A0B6461F-7455-4990-A589-C6534A91FD38}"
11+
EndProject
12+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OrderMonitor.Infrastructure", "src\OrderMonitor.Infrastructure\OrderMonitor.Infrastructure.csproj", "{5F7D3601-198F-44C1-90E3-EDF8E2EADD13}"
13+
EndProject
14+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}"
15+
EndProject
16+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OrderMonitor.UnitTests", "tests\OrderMonitor.UnitTests\OrderMonitor.UnitTests.csproj", "{7BFD018D-5B55-4C58-B217-38050D971F3B}"
17+
EndProject
18+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OrderMonitor.IntegrationTests", "tests\OrderMonitor.IntegrationTests\OrderMonitor.IntegrationTests.csproj", "{29171804-9539-4FDC-92DF-E0D177490710}"
19+
EndProject
20+
Global
21+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
22+
Debug|Any CPU = Debug|Any CPU
23+
Debug|x64 = Debug|x64
24+
Debug|x86 = Debug|x86
25+
Release|Any CPU = Release|Any CPU
26+
Release|x64 = Release|x64
27+
Release|x86 = Release|x86
28+
EndGlobalSection
29+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
30+
{5D6AB4D5-D22D-4909-B371-E3865C2C1FF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31+
{5D6AB4D5-D22D-4909-B371-E3865C2C1FF5}.Debug|Any CPU.Build.0 = Debug|Any CPU
32+
{5D6AB4D5-D22D-4909-B371-E3865C2C1FF5}.Debug|x64.ActiveCfg = Debug|Any CPU
33+
{5D6AB4D5-D22D-4909-B371-E3865C2C1FF5}.Debug|x64.Build.0 = Debug|Any CPU
34+
{5D6AB4D5-D22D-4909-B371-E3865C2C1FF5}.Debug|x86.ActiveCfg = Debug|Any CPU
35+
{5D6AB4D5-D22D-4909-B371-E3865C2C1FF5}.Debug|x86.Build.0 = Debug|Any CPU
36+
{5D6AB4D5-D22D-4909-B371-E3865C2C1FF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
37+
{5D6AB4D5-D22D-4909-B371-E3865C2C1FF5}.Release|Any CPU.Build.0 = Release|Any CPU
38+
{5D6AB4D5-D22D-4909-B371-E3865C2C1FF5}.Release|x64.ActiveCfg = Release|Any CPU
39+
{5D6AB4D5-D22D-4909-B371-E3865C2C1FF5}.Release|x64.Build.0 = Release|Any CPU
40+
{5D6AB4D5-D22D-4909-B371-E3865C2C1FF5}.Release|x86.ActiveCfg = Release|Any CPU
41+
{5D6AB4D5-D22D-4909-B371-E3865C2C1FF5}.Release|x86.Build.0 = Release|Any CPU
42+
{A0B6461F-7455-4990-A589-C6534A91FD38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43+
{A0B6461F-7455-4990-A589-C6534A91FD38}.Debug|Any CPU.Build.0 = Debug|Any CPU
44+
{A0B6461F-7455-4990-A589-C6534A91FD38}.Debug|x64.ActiveCfg = Debug|Any CPU
45+
{A0B6461F-7455-4990-A589-C6534A91FD38}.Debug|x64.Build.0 = Debug|Any CPU
46+
{A0B6461F-7455-4990-A589-C6534A91FD38}.Debug|x86.ActiveCfg = Debug|Any CPU
47+
{A0B6461F-7455-4990-A589-C6534A91FD38}.Debug|x86.Build.0 = Debug|Any CPU
48+
{A0B6461F-7455-4990-A589-C6534A91FD38}.Release|Any CPU.ActiveCfg = Release|Any CPU
49+
{A0B6461F-7455-4990-A589-C6534A91FD38}.Release|Any CPU.Build.0 = Release|Any CPU
50+
{A0B6461F-7455-4990-A589-C6534A91FD38}.Release|x64.ActiveCfg = Release|Any CPU
51+
{A0B6461F-7455-4990-A589-C6534A91FD38}.Release|x64.Build.0 = Release|Any CPU
52+
{A0B6461F-7455-4990-A589-C6534A91FD38}.Release|x86.ActiveCfg = Release|Any CPU
53+
{A0B6461F-7455-4990-A589-C6534A91FD38}.Release|x86.Build.0 = Release|Any CPU
54+
{5F7D3601-198F-44C1-90E3-EDF8E2EADD13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
55+
{5F7D3601-198F-44C1-90E3-EDF8E2EADD13}.Debug|Any CPU.Build.0 = Debug|Any CPU
56+
{5F7D3601-198F-44C1-90E3-EDF8E2EADD13}.Debug|x64.ActiveCfg = Debug|Any CPU
57+
{5F7D3601-198F-44C1-90E3-EDF8E2EADD13}.Debug|x64.Build.0 = Debug|Any CPU
58+
{5F7D3601-198F-44C1-90E3-EDF8E2EADD13}.Debug|x86.ActiveCfg = Debug|Any CPU
59+
{5F7D3601-198F-44C1-90E3-EDF8E2EADD13}.Debug|x86.Build.0 = Debug|Any CPU
60+
{5F7D3601-198F-44C1-90E3-EDF8E2EADD13}.Release|Any CPU.ActiveCfg = Release|Any CPU
61+
{5F7D3601-198F-44C1-90E3-EDF8E2EADD13}.Release|Any CPU.Build.0 = Release|Any CPU
62+
{5F7D3601-198F-44C1-90E3-EDF8E2EADD13}.Release|x64.ActiveCfg = Release|Any CPU
63+
{5F7D3601-198F-44C1-90E3-EDF8E2EADD13}.Release|x64.Build.0 = Release|Any CPU
64+
{5F7D3601-198F-44C1-90E3-EDF8E2EADD13}.Release|x86.ActiveCfg = Release|Any CPU
65+
{5F7D3601-198F-44C1-90E3-EDF8E2EADD13}.Release|x86.Build.0 = Release|Any CPU
66+
{7BFD018D-5B55-4C58-B217-38050D971F3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
67+
{7BFD018D-5B55-4C58-B217-38050D971F3B}.Debug|Any CPU.Build.0 = Debug|Any CPU
68+
{7BFD018D-5B55-4C58-B217-38050D971F3B}.Debug|x64.ActiveCfg = Debug|Any CPU
69+
{7BFD018D-5B55-4C58-B217-38050D971F3B}.Debug|x64.Build.0 = Debug|Any CPU
70+
{7BFD018D-5B55-4C58-B217-38050D971F3B}.Debug|x86.ActiveCfg = Debug|Any CPU
71+
{7BFD018D-5B55-4C58-B217-38050D971F3B}.Debug|x86.Build.0 = Debug|Any CPU
72+
{7BFD018D-5B55-4C58-B217-38050D971F3B}.Release|Any CPU.ActiveCfg = Release|Any CPU
73+
{7BFD018D-5B55-4C58-B217-38050D971F3B}.Release|Any CPU.Build.0 = Release|Any CPU
74+
{7BFD018D-5B55-4C58-B217-38050D971F3B}.Release|x64.ActiveCfg = Release|Any CPU
75+
{7BFD018D-5B55-4C58-B217-38050D971F3B}.Release|x64.Build.0 = Release|Any CPU
76+
{7BFD018D-5B55-4C58-B217-38050D971F3B}.Release|x86.ActiveCfg = Release|Any CPU
77+
{7BFD018D-5B55-4C58-B217-38050D971F3B}.Release|x86.Build.0 = Release|Any CPU
78+
{29171804-9539-4FDC-92DF-E0D177490710}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
79+
{29171804-9539-4FDC-92DF-E0D177490710}.Debug|Any CPU.Build.0 = Debug|Any CPU
80+
{29171804-9539-4FDC-92DF-E0D177490710}.Debug|x64.ActiveCfg = Debug|Any CPU
81+
{29171804-9539-4FDC-92DF-E0D177490710}.Debug|x64.Build.0 = Debug|Any CPU
82+
{29171804-9539-4FDC-92DF-E0D177490710}.Debug|x86.ActiveCfg = Debug|Any CPU
83+
{29171804-9539-4FDC-92DF-E0D177490710}.Debug|x86.Build.0 = Debug|Any CPU
84+
{29171804-9539-4FDC-92DF-E0D177490710}.Release|Any CPU.ActiveCfg = Release|Any CPU
85+
{29171804-9539-4FDC-92DF-E0D177490710}.Release|Any CPU.Build.0 = Release|Any CPU
86+
{29171804-9539-4FDC-92DF-E0D177490710}.Release|x64.ActiveCfg = Release|Any CPU
87+
{29171804-9539-4FDC-92DF-E0D177490710}.Release|x64.Build.0 = Release|Any CPU
88+
{29171804-9539-4FDC-92DF-E0D177490710}.Release|x86.ActiveCfg = Release|Any CPU
89+
{29171804-9539-4FDC-92DF-E0D177490710}.Release|x86.Build.0 = Release|Any CPU
90+
EndGlobalSection
91+
GlobalSection(SolutionProperties) = preSolution
92+
HideSolutionNode = FALSE
93+
EndGlobalSection
94+
GlobalSection(NestedProjects) = preSolution
95+
{5D6AB4D5-D22D-4909-B371-E3865C2C1FF5} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
96+
{A0B6461F-7455-4990-A589-C6534A91FD38} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
97+
{5F7D3601-198F-44C1-90E3-EDF8E2EADD13} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
98+
{7BFD018D-5B55-4C58-B217-38050D971F3B} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
99+
{29171804-9539-4FDC-92DF-E0D177490710} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
100+
EndGlobalSection
101+
EndGlobal

README.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Order Monitor API
2+
3+
.NET Core 8 API service for monitoring stuck orders in the Printerpix Backoffice database.
4+
5+
## Overview
6+
7+
This service:
8+
- Monitors 152 order statuses for stuck orders
9+
- Detects orders exceeding configurable thresholds (6h for prep, 48h for facility)
10+
- Sends email alerts to operations team
11+
- Provides REST API for querying stuck orders
12+
13+
## Project Structure
14+
15+
```
16+
printerpix-backoffice-ordermonitor-api/
17+
├── src/
18+
│ ├── OrderMonitor.Api/ # ASP.NET Core Web API
19+
│ ├── OrderMonitor.Core/ # Domain entities, interfaces, services
20+
│ └── OrderMonitor.Infrastructure/ # Data access, email, background jobs
21+
├── tests/
22+
│ ├── OrderMonitor.UnitTests/ # Unit tests (xUnit)
23+
│ └── OrderMonitor.IntegrationTests/ # Integration tests
24+
├── docs/ # Documentation
25+
└── .github/workflows/ # CI/CD pipelines
26+
```
27+
28+
## Prerequisites
29+
30+
- .NET 8.0 SDK
31+
- SQL Server (read-only access to Backoffice database)
32+
- SMTP server access (pod51017.outlook.com)
33+
34+
## Configuration
35+
36+
### Environment Variables
37+
38+
```bash
39+
# Required
40+
SMTP_PASSWORD=<your-smtp-password>
41+
42+
# Optional (can also be in appsettings.json)
43+
ConnectionStrings__BackofficeDb=<connection-string>
44+
```
45+
46+
### appsettings.json
47+
48+
See `src/OrderMonitor.Api/appsettings.json` for full configuration options.
49+
50+
## Running Locally
51+
52+
```bash
53+
# Restore dependencies
54+
dotnet restore
55+
56+
# Build
57+
dotnet build
58+
59+
# Run tests
60+
dotnet test
61+
62+
# Run API
63+
dotnet run --project src/OrderMonitor.Api
64+
```
65+
66+
## API Endpoints
67+
68+
| Endpoint | Method | Description |
69+
|----------|--------|-------------|
70+
| `/api/orders/stuck` | GET | Get all stuck orders |
71+
| `/api/orders/{id}/status-history` | GET | Get order status history |
72+
| `/api/orders/stuck/summary` | GET | Get stuck orders summary |
73+
| `/api/health` | GET | Health check |
74+
| `/api/metrics` | GET | Service metrics |
75+
| `/api/alerts/test` | POST | Test email alert |
76+
77+
## Status Thresholds
78+
79+
| Status Range | Threshold |
80+
|--------------|-----------|
81+
| 3001-3910 (Prep) | 6 hours |
82+
| 4001-5830 (Facility) | 48 hours |
83+
84+
## JIRA
85+
86+
- Epic: [BD-689](https://printerpix.atlassian.net/browse/BD-689)
87+
- Related: [BD-411](https://printerpix.atlassian.net/browse/BD-411)
88+
89+
## License
90+
91+
Proprietary - Printerpix

nuget.config

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<packageSources>
4+
<clear />
5+
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
6+
</packageSources>
7+
</configuration>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.13" />
11+
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
12+
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.0" />
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<ProjectReference Include="..\OrderMonitor.Core\OrderMonitor.Core.csproj" />
17+
<ProjectReference Include="..\OrderMonitor.Infrastructure\OrderMonitor.Infrastructure.csproj" />
18+
</ItemGroup>
19+
20+
</Project>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@OrderMonitor.Api_HostAddress = http://localhost:5214
2+
3+
GET {{OrderMonitor.Api_HostAddress}}/weatherforecast/
4+
Accept: application/json
5+
6+
###

0 commit comments

Comments
 (0)