https://github.com/rnelson/fetch-receipt_processor-dotnet
Fetch Receipt Processor
https://github.com/rnelson/fetch-receipt_processor-dotnet
Last synced: over 1 year ago
JSON representation
Fetch Receipt Processor
- Host: GitHub
- URL: https://github.com/rnelson/fetch-receipt_processor-dotnet
- Owner: rnelson
- License: mit
- Created: 2025-01-10T15:28:44.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-01-11T03:46:35.000Z (over 1 year ago)
- Last Synced: 2025-01-30T15:51:31.848Z (over 1 year ago)
- Language: C#
- Size: 116 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Fetch Receipt Processor (.NET)
 
A solution for Fetch's [Receipt Processor challenge][fetch-rpc].
### About
While Fetch's preferred language is Go, I am currently most comfortable in C#. As someone who has been
doing this for a while, I understand that any senior developer is often going to be able to read and
understand code even in a language they don't use, and doing this in the language I've most heavily
used for the last 6 years gives the best representation of how I attack the problem and architect a
complete project.
#### Architecture
Other than unit tests, the solution is split into the following projects:
1. `Libexec.FetchReceiptProcessor`, the ASP.NET Core Web API project providing the API.
2. `Libexec.FetchReceiptProcessor.Data`, a combination of shared models, abstractions, and my data access layer (DAL).
3. `Libexec.FetchReceiptProcessor.Extensions`, a project for just [extension methods][dotnet-ext].
The Extensions project only has a single extension. I have been meaning to take all the random helper
extension classes that I've written and shoving them into a single NuGet package for easier reuse, but
since I haven't gotten around to that yet the helper I wrote is in its own project.
There isn't a lot to say about the Data project. The one thing I feel I should point out is that I wrote
`IDatabase` and `Database`, an interface and concrete class, to act as my in-memory database. In the startup
file ([Program.cs][program-cs]), I add a singleton mapping `IDatabase` to `Database` in ASP.NET Core's
dependency injection framework. In a more realistic example, I would have an object that actually hits a
database through whatever means, and then be able to use that same DI container to mock a database for
unit tests, so I'm not ruining real data or adding unnecessary stress to the DBMS.
With .NET 9, Microsoft released a new OpenAPI package. I've used Swashbuckle, a popular .NET Swagger package,
for years and took this as an opportunity to play with the new package. You can see the generated result by
requesting `/openapi/v1.json` from a running instance of the API.
For the person(s) reviewing this code, these are the important files:
+ [src/Libexec.FetchReceiptProcessor/Program.cs](https://github.com/rnelson/fetch-receipt_processor-dotnet/blob/main/src/Libexec.FetchReceiptProcessor/Program.cs): startup code that configures the API and causes it to run
+ [src/Libexec.FetchReceiptProcessor/Controllers/ReceiptsController.cs](https://github.com/rnelson/fetch-receipt_processor-dotnet/blob/main/src/Libexec.FetchReceiptProcessor/Controllers/ReceiptsController.cs): the controller handling the `/receipts` requests
+ [src/Libexec.FetchReceiptProcessor.Data/Receipt.cs](https://github.com/rnelson/fetch-receipt_processor-dotnet/blob/main/src/Libexec.FetchReceiptProcessor.Data/Receipt.cs): model that contains the point calculation rules
#### Tests
Since I had no time constraint for this project, I chose to go beyond the 2-3 hour mark to set *everything*
up the way that I would for a personal project. That includes doing sufficient testing of the application.
First and foremost, there are three unit tests projects:

Between these three projects, the solution has 100% code coverage:

Additionally, using [JetBrains' HTTP client][jb-http], I built simple integration tests that run all of the
Fetch-provided JSON through the live application:

(To run these, open the sln file in [Rider][rider], start the "Libexec.FetchReceiptProcessor: http" project, open
the Services explorer, and run the HTTP Requests.)
## Requirements
* .NET 9
* ASP.NET Core
* Docker (optional)
## Container Usage
The container is [available on Docker Hub][hub-link] and can be run without having to build anything
yourself: `docker run -d -p 12345:8080 rossnelson84/fetchreceiptprocessor:1.0.0`
To build the container from source, run `docker build -t fetchreceiptprocessor:1.0.0 .`
You can `docker run -d -p 12345:8080 fetchreceiptprocessor:1.0.0`, substituting your local port of choice
for `12345` (e.g., `-p 9090:8080` to run on port 9090 on the host).
## License
This program is licensed under the [MIT license][license].
[license]: https://rnelson.mit-license.org
[fetch-rpc]: https://github.com/fetch-rewards/receipt-processor-challenge
[hub-link]: https://hub.docker.com/repository/docker/rossnelson84/fetchreceiptprocessor/general
[jb-http]: https://www.jetbrains.com/help/idea/http-client-in-product-code-editor.html
[rider]: https://www.jetbrains.com/rider
[dotnet-ext]: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods
[program-cs]: https://github.com/rnelson/fetch-receipt_processor-dotnet/blob/main/src/Libexec.FetchReceiptProcessor/Program.cs