A modern, scalable REST API for pharmacy delivery and e-commerce operations built with Clean Architecture principles.
- About The Project
- Architecture & Design Patterns
- Tech Stack
- Project Structure
- Prerequisites
- Getting Started
- Configuration
- Running the Application
- API Documentation
- Testing
- Key Features
- Best Practices Implemented
PharmaGO API is a robust backend service designed for pharmacy delivery systems. The project demonstrates professional software engineering practices including Domain-Driven Design (DDD), Clean Architecture, Test-Driven Development (TDD), and SOLID principles using C# with .NET 10.0.
- π Authentication & Authorization - JWT-based secure authentication
- π Product Management - CRUD operations for pharmaceutical products
- π₯ Pharmacy Management - Multi-pharmacy support system
- π₯ Client Management - User registration and profile management
- π API Documentation - Interactive API documentation with Scalar
The project follows Clean Architecture principles with clear separation of concerns across four main layers:
βββββββββββββββββββββββββββββββββββββββββββ
β PharmaGO.Api (Presentation) β
β Controllers, Middleware, Mapping β
βββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββ
β PharmaGO.Application (Use Cases) β
β Commands, Queries, Validators β
βββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββ
β PharmaGO.Core (Domain/Business) β
β Entities, Interfaces, Errors β
βββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββ
β PharmaGO.Infrastructure (Data/External)β
β Repositories, DbContext, JWT, Servicesβ
βββββββββββββββββββββββββββββββββββββββββββ
- Commands: Handle write operations (Create, Update, Delete)
- Queries: Handle read operations (Get, List)
- Implemented using MediatR for clean command/query handling
- Abstracts data access logic
- Interfaces defined in
Corelayer - Implementations in
Infrastructurelayer - Enables easy testing and swapping of data sources
- Each layer registers its dependencies via extension methods
- Clean, maintainable service registration
- Follows Dependency Inversion Principle
- Functional error handling without exceptions
- Returns
ErrorOr<T>for explicit error handling - Better error visibility and handling at compile time
- Cross-cutting concerns handled via MediatR behaviors
- Validation behavior automatically validates all commands
- Extensible for logging, caching, etc.
- Configuration strongly-typed using Options pattern
- JWT settings, connection strings configured via
appsettings.json
| Technology | Purpose |
|---|---|
| .NET 10.0 | Runtime framework |
| C# 13 | Programming language |
| ASP.NET Core | Web framework |
| Entity Framework Core 10 | ORM |
| PostgreSQL | Database |
- MediatR (v14.0.0) - CQRS implementation
- FluentValidation (v12.1.1) - Input validation
- BCrypt.Net-Core (v1.6.0) - Password hashing
- Mapster (v9.0.0) - Object mapping
- Scalar.AspNetCore (v2.11.1) - API documentation
- Microsoft.AspNetCore.OpenApi - OpenAPI support
- Npgsql.EntityFrameworkCore.PostgreSQL (v10.0.0) - PostgreSQL provider
- System.IdentityModel.Tokens.Jwt (v8.15.0) - JWT generation
- xUnit (v2.9.3) - Testing framework
- Moq (v4.20.72) - Mocking framework
- FluentAssertions (v8.8.0) - Assertion library
pharmago.server.api/
βββ src/
β βββ PharmaGO.Api/ # Presentation Layer
β β βββ Controllers/ # API Controllers
β β βββ Errors/ # Error handling
β β βββ Http/ # HTTP context helpers
β β βββ Mapping/ # DTO mappings
β β βββ Program.cs # Application entry point
β β
β βββ PharmaGO.Application/ # Application Layer
β β βββ Authentication/ # Auth use cases
β β β βββ Commands/ # Auth commands
β β β βββ Queries/ # Auth queries
β β β βββ Common/ # Shared auth models
β β βββ Pharmacies/ # Pharmacy use cases
β β βββ Products/ # Product use cases
β β βββ Common/
β β βββ Behaviors/ # MediatR behaviors (validation)
β β
β βββ PharmaGO.Core/ # Domain Layer
β β βββ Entities/ # Domain entities
β β β βββ Base/ # Base entity classes
β β β βββ Client.cs
β β β βββ Pharmacy.cs
β β β βββ Product.cs
β β βββ Interfaces/ # Contracts/Abstractions
β β β βββ Authentication/ # Auth interfaces
β β β βββ Persistence/ # Repository interfaces
β β β βββ Services/ # Service interfaces
β β βββ Common/
β β βββ Constants/ # Application constants
β β βββ Errors/ # Domain errors
β β
β βββ PharmaGO.Infrastructure/ # Infrastructure Layer
β β βββ Authentication/ # JWT implementation
β β βββ Persistence/ # EF Core implementation
β β β βββ Base/ # Base repository
β β β βββ PharmaGOContext.cs # DbContext
β β β βββ *Repository.cs # Repository implementations
β β βββ Services/ # External services
β β
β βββ PharmaGO.Contract/ # API Contracts (DTOs)
β βββ Authentication/ # Auth DTOs
β βββ Pharmacy/ # Pharmacy DTOs
β βββ Product/ # Product DTOs
β
βββ tests/
βββ PharmaGO.UnitTests/ # Unit Tests
βββ Systems/ # Test organization
βββ Helpers/ # Test helpers
Before running this project, ensure you have the following installed:
- .NET 10.0 SDK or later
- PostgreSQL 15+
- Git
- IDE: Visual Studio 2022, JetBrains Rider, or VS Code
- pgAdmin 4 - PostgreSQL GUI
- Postman or Insomnia - API testing
- Docker - For containerized PostgreSQL (optional)
git clone https://github.com/Gildofj/pharmago.server.api.git
cd pharmago.server.apiCreate a new database:
# Connect to PostgreSQL
psql -U postgres
# Create database
CREATE DATABASE pharmago;
# Create user (if needed)
CREATE USER 'your_username' WITH PASSWORD 'your_password';
# Grant privileges
GRANT ALL PRIVILEGES ON DATABASE pharmago TO 'your_username';docker run --name pharmago-postgres \
-e POSTGRES_DB=pharmago \
-e POSTGRES_USER='your_username' \
-e POSTGRES_PASSWORD=your_password \
-p 5432:5432 \
-d postgres:18dotnet restoredotnet buildUpdate src/PharmaGO.Api/appsettings.json or create appsettings.Development.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"JwtSettings": {
"Secret": "your-secret-key-at-least-32-characters-long",
"ExpiryMinutes": 60,
"Issuer": "PharmaGO",
"Audience": "PharmaGO"
},
"LicenseKeys": {
"MediatR": "your-mediatr-license-key-if-needed"
},
"ConnectionStrings": {
"PharmaGOContext": "Server=127.0.0.1;Port=5432;Database=pharmago;User Id=your_username;Password=your_password;"
}
}For production, generate a secure secret key:
# Using PowerShell
$bytes = New-Object byte[] 32
[System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)
[Convert]::ToBase64String($bytes)
# Using OpenSSL (Linux/Mac)
openssl rand -base64 32# Navigate to the API project
cd src/PharmaGO.Api
# Create initial migration (if not exists)
dotnet ef migrations add InitialCreate --project ../PharmaGO.Infrastructure
# Apply migrations to database
dotnet ef database update# From solution root
dotnet run --project src/PharmaGO.Api/PharmaGO.Api.csproj
# Or navigate to API project
cd src/PharmaGO.Api
dotnet runThe API will start on:
- HTTPS:
https://localhost:5001 - HTTP:
http://localhost:5000
cd src/PharmaGO.Api
dotnet watch rundotnet publish -c Release -o ./publish
cd publish
dotnet PharmaGO.Api.dllOnce the application is running in development mode, access the interactive API documentation:
Scalar UI: Navigate to https://localhost:5001/scalar/v1
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/auth/Register |
Register new client |
| POST | /api/auth/Login |
Login and get JWT token |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/pharmacies |
Create new pharmacy |
| GET | /api/pharmacies/{id} |
Get pharmacy by ID |
| GET | /api/pharmacies |
List all pharmacies |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/products |
Create new product |
| GET | /api/products/{id} |
Get product by ID |
| GET | /api/products |
List all products |
Register Client:
curl -X POST https://localhost:5001/api/auth/Register?pharmacyId=<pharmacy-guid> \
-H "Content-Type: application/json" \
-d '{
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"password": "SecurePassword123!"
}'Response:
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}# From solution root
dotnet test
# With detailed output
dotnet test --verbosity detailed
# With coverage
dotnet test /p:CollectCoverage=truedotnet test tests/PharmaGO.UnitTests/PharmaGO.UnitTests.csproj- Unit Tests: Testing individual components in isolation
- Mocking: Using Moq for dependency mocking
- Assertions: FluentAssertions for readable test assertions
- Custom error types using ErrorOr pattern
- Centralized error handling with ProblemDetails
- Consistent error responses across the API
- FluentValidation validators for all commands
- Validation pipeline behavior intercepts invalid requests
- Clear validation error messages
- JWT token-based authentication
- BCrypt password hashing with salt
- Configurable token expiration
- Entity Framework Core with code-first approach
- Repository pattern for data access
- PostgreSQL with async operations
- Structured for easy API versioning
- OpenAPI documentation generation
- Scalar UI for beautiful API docs
- Single Responsibility: Each class has one reason to change
- Open/Closed: Open for extension, closed for modification
- Liskov Substitution: Proper abstraction usage
- Interface Segregation: Focused interfaces
- Dependency Inversion: Depend on abstractions, not concretions
- Meaningful names for classes, methods, and variables
- Small, focused methods
- Proper commenting where necessary
- Consistent code formatting
- Password hashing with BCrypt
- JWT token-based authentication
- Sensitive data in configuration (not hardcoded)
- CORS configuration for controlled access
- Unit test coverage for business logic
- Mocking for external dependencies
- Arrange-Act-Assert pattern
- Descriptive test names
- Environment-specific configurations
- User secrets for development
- Options pattern for strongly-typed settings
- Clear layer boundaries
- DTOs for API contracts
- Entities for domain models
- Mappers for transformations
- Asynchronous operations throughout
- Proper cancellation token usage
- Non-blocking I/O operations
- Constructor injection
- Service lifetime management
- Testable code through DI
Docker support is planned for future releases. The application will be containerized for easy deployment.
This project is licensed under the MIT License - see the LICENSE file for details.
Gildo Junior
- Email: 1gildojunior@gmail.com
- Portfolio: https://gildofj.github.io/portfolio
- Clean Architecture principles by Robert C. Martin
- MediatR library by Jimmy Bogard
- ErrorOr pattern for functional error handling
- The .NET community for excellent tools and libraries
Note: This project is under active development. Features and documentation may change.