A comprehensive REST API for a vending machine system built with .NET 8, implementing Clean Architecture with CQRS pattern, Docker support, and PostgreSQL database.
- Complete CRUD Operations for users and products
- Role-based Authentication (buyer/seller) with JWT tokens
- Vending Machine Operations: deposit, buy, reset
- Coin System: Supports 5, 10, 20, 50, and 100 cent coins
- Change Calculation: Optimal change distribution
- CQRS Pattern with MediatR
- Clean Architecture with separated layers
- Docker Support with PostgreSQL
- Comprehensive Testing (Unit & Integration tests)
- Exception Handling with custom middleware
- Logging with Serilog
- API Documentation with Swagger/OpenAPI
โโโโโโโโโโโโโโโโโโโ
โ API Layer โ โ Controllers, Middleware
โโโโโโโโโโโโโโโโโโโค
โ Application โ โ Commands, Queries, Handlers, Services
โโโโโโโโโโโโโโโโโโโค
โ Domain โ โ Entities, DTOs, Interfaces, Exceptions
โโโโโโโโโโโโโโโโโโโค
โ Infrastructure โ โ Database, Repositories, External Services
โโโโโโโโโโโโโโโโโโโ
- .NET 8 - Framework
- ASP.NET Core - Web API
- Entity Framework Core - ORM
- PostgreSQL - Database
- JWT - Authentication
- MediatR - CQRS implementation
- Serilog - Logging
- Docker - Containerization
- xUnit - Testing framework
- FluentAssertions - Test assertions
- Swagger - API documentation
- .NET 8 SDK
- Docker & Docker Compose
- Git
-
Clone the repository
git clone <repository-url> cd VendingMachine
-
Start the application
docker-compose up --build
-
Access the API
- API: http://localhost:8080
- Swagger UI: http://localhost:8080/swagger
-
Install PostgreSQL and create database
CREATE DATABASE vendingmachine;
-
Update connection string in
appsettings.json -
Install dependencies and run
dotnet restore dotnet ef database update --project src/VendingMachine.Infrastructure --startup-project src/VendingMachine.API dotnet run --project src/VendingMachine.API
POST /api/users/register # Register new user
POST /api/users/login # Login userGET /api/users/{id} # Get user by ID (authenticated)
PUT /api/users/{id} # Update user (owner only)
DELETE /api/users/{id} # Delete user (owner only)GET /api/products # Get all products (public)
GET /api/products/{id} # Get product by ID (public)
POST /api/products # Create product (seller only)
PUT /api/products/{id} # Update product (owner only)
DELETE /api/products/{id} # Delete product (owner only)
GET /api/products/seller/{sellerId} # Get products by sellerPOST /api/vending/deposit # Deposit coins
POST /api/vending/buy # Buy products
POST /api/vending/reset # Reset depositcurl -X POST "http://localhost:8080/api/users/register" \
-H "Content-Type: application/json" \
-d '{
"username": "buyer1",
"password": "Buyer123!",
"role": "buyer"
}'curl -X POST "http://localhost:8080/api/users/login" \
-H "Content-Type: application/json" \
-d '{
"username": "buyer1",
"password": "Buyer123!"
}'curl -X POST "http://localhost:8080/api/products" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"productName": "Coca Cola",
"amountAvailable": 10,
"cost": 100
}'curl -X POST "http://localhost:8080/api/vending/deposit" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"coins": {
"100": 2,
"50": 1
}
}'curl -X POST "http://localhost:8080/api/vending/buy" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"productId": 1,
"amount": 1
}'dotnet testdotnet test --filter "Category=Unit"
dotnet test --filter "Category=Integration"The solution includes comprehensive tests:
- Unit Tests: Services, handlers, utilities
- Integration Tests: Controllers, database operations
- End-to-End Tests: Complete user workflows
- JWT Authentication with configurable expiration
- Role-based Authorization (buyer/seller)
- Password Hashing with BCrypt
- Input Validation and sanitization
- SQL Injection Protection via Entity Framework
- CORS Configuration for cross-origin requests
- Structured logging with Serilog
- Console and file outputs
- Configurable log levels
- Request/response logging
- Global exception middleware
- Domain-specific exceptions
- Consistent error responses
- Error tracking and monitoring
- Connection pooling
- Migration support
- Seed data for testing
- Index optimization
- Async/await throughout
- Efficient queries with EF Core
- Caching considerations
- Resource cleanup
- API: .NET 8 web application
- Database: PostgreSQL 15
ASPNETCORE_ENVIRONMENT=Development
ConnectionStrings__DefaultConnection=Host=postgres;Database=vendingmachine;Username=postgres;Password=postgres123- Id (string, PK)
- Username (string, unique)
- Email (string)
- Deposit (int, cents)
- Password (hashed)
- Id (int, PK)
- ProductName (string)
- AmountAvailable (int)
- Cost (int, cents)
- SellerId (string, FK)
- buyer: Can deposit coins and buy products
- seller: Can manage products
{
"Jwt": {
"Key": "your-secret-key",
"Issuer": "VendingMachineAPI",
"Audience": "VendingMachineUsers",
"ExpireMinutes": 60
}
}{
"ConnectionStrings": {
"DefaultConnection": "Host=localhost;Database=vendingmachine;Username=postgres;Password=yourpassword"
}
}The API returns consistent error responses:
{
"statusCode": 400,
"message": "Invalid coin denomination: 15. Valid denominations are: 5, 10, 20, 50, 100 cents.",
"timestamp": "2024-01-15T10:30:00Z"
}- 400: Bad Request (validation errors, business rule violations)
- 401: Unauthorized (invalid credentials, missing token)
- 403: Forbidden (insufficient permissions)
- 404: Not Found (resource doesn't exist)
- 500: Internal Server Error (unexpected errors)
- Application logs in
/logsdirectory - Structured JSON format
- Different log levels (Debug, Info, Warning, Error)
- Request correlation IDs
- Database connectivity
- Application status
- Available at
/healthendpoint
# Add migration
dotnet ef migrations add <MigrationName> --project src/VendingMachine.Infrastructure --startup-project src/VendingMachine.API
# Update database
dotnet ef database update --project src/VendingMachine.Infrastructure --startup-project src/VendingMachine.API- Clean Architecture principles
- SOLID principles
- Dependency Injection
- Separation of Concerns
- Domain-Driven Design concepts
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
The application comes with sample data:
- Seller: username:
seller1, password:Seller123! - Buyer: username:
buyer1, password:Buyer123! - Products: Coca Cola, Pepsi, Water, Snickers, Chips
- Product categories and filtering
- Purchase history and analytics
- Multiple vending machines support
- Real-time notifications
- Admin dashboard
- Payment gateway integration
- Inventory management alerts
- Multi-language support
This project is licensed under the MIT License - see the LICENSE file for details.
For questions and support:
- Check the documentation
- Review test cases for usage examples
- Open an issue for bugs or feature requests
Generative AI Usage: This solution was developed by me and with assistance from Claude AI to implement Clean Architecture patterns, CQRS design, comprehensive testing, and production-ready features.
Built with โค๏ธ using .NET 8 and Clean Architecture