Modernised replacement for the legacy .NET Framework 4.7 OrderProcessor
order flow. See MIGRATION.md for the zero-downtime migration
plan.
src/OrderHub.Orders/
Models.cs Typed request/result (replaces "FAIL: ..." strings)
Abstractions.cs Seams: school, catalog, stock, payment, notification
Pricing/PricingService.cs Tier discount + embroidery rules (pure, unit-tested)
OrderProcessor.cs Async orchestration
Infrastructure/ Parameterised SQL, HttpClientFactory payment, SMTP
tests/OrderHub.Orders.Tests/
PricingServiceTests.cs Characterisation tests pinning the pricing rule
| Legacy problem | Why it hurts in August | Fix |
|---|---|---|
| SQL built by string concatenation | Injectable from the public order form | Parameterised queries (Infrastructure/SqlStores.cs) |
.PostAsync(...).Result |
Sync-over-async → thread-pool starvation at peak | async end-to-end |
new HttpClient() per order |
Socket exhaustion under load | IHttpClientFactory-managed client |
catch { /* swallow */ } on email |
Parents pay, never hear back, nobody knows | Logged, alertable — still never fails a paid order |
"OK" / "FAIL: ..." strings |
Callers parse prose; typos become logic bugs | OrderResult with typed failure reasons |
| Pricing buried in if/else mid-method | Untestable; the rule most likely to drift in a rewrite | Extracted pure PricingService |
| No rounding on money | Sub-penny amounts sent to payment provider | Round per unit, 2 dp, away from zero |
- Stock reservation vs. stock check. The legacy code only checks stock, so two simultaneous orders can both pass and oversell. Preserved for behavioural parity; fixing it is an inventory-service concern (see Q4 decomposition) and changes business behaviour, so it needs a product decision, not a silent fix.
- EF Core / Dapper. ADO.NET kept close to the legacy queries makes the diff reviewable during migration. ORM adoption is a later, low-risk phase.
- Transactions / outbox. Arrives with the Q4 decomposition where the order gets persisted state.
dotnet testThe shipped test pins the rule I consider most important: tier discount is applied before the embroidery surcharge, and embroidery is never discounted. It's the money calculation, it's boundary-heavy (the 3-character embroidery threshold), and it's exactly the kind of rule that silently drifts during a rewrite.