The system manages supplier purchases, stock storage across multiple warehouses, inter-warehouse transfers, and simulates inventory audits by allowing manual stock adjustments due to surplus, damage, or missing items.
- Secured using JWT with refresh & revoke tokens
- Role information is embedded in tokens for protected route handling
- JWT-based access with roles (admin, Inventory Manager, Supplier, Sales Viewer)
- Admin can register and manage all users and their roles
- Suppliers can register themselves
- Support for viewing user details and updating profile information
- Roles:
Admin
,InventoryManager
,Supplier
,SalesViewer
- Admin has full access; in future updates, Inventory Managers will be restricted to their own warehouse
- Products are created by suppliers with base data (name, price, etc.), and extended by the inventory system (barcode, availability)
- Supports full product CRUD operations, bulk creation, and category-based queries
- Only verified suppliers can receive purchase orders or upload products
- A supplier cannot perform any action in the system until verified by an Admin.
- Inventory managers and Admin can create purchase orders with multiple products and send them to suppliers
- Purchase orders support multiple statuses:
Draft
,Sent
,PartiallyReceived
,Received
, andCancelled
- Multiple warehouses supported, each with individual inventory levels
- Products can be stored in multiple warehouses with separate stock quantities
- Enables transferring products between warehouses
- Automatically updates inventory records and logs the transfer as a stock movement
- Allows manual adjustments to stock quantities (e.g., for lost, damaged, or extra items)
- All adjustments are logged in the stock movement history
- Logs every inventory action (purchase, sale, transfer, manual adjustment) with quantity, date, product, and warehouse details
- Query stock movements by product or warehouse
- β Built using clean RESTful principles and SOLID architecture
- β EF Core with Code First approach, using Fluent API for full control over relationships and configurations
- β
Soft Delete supported in selected entities like
Category
andApplicationUser
, with automatic filtering - β
All key List endpoints support:
- π Search
- π§© Dynamic Filtering
βοΈ Sorting- π Pagination
- β
Middleware pipeline includes:
- π― Global Exception Handling
- πΌοΈ Image Validation
- π‘οΈ Request Lock Middleware (prevents duplicate Purchase Order submission within 1 minute)
- β FluentValidation integrated for all DTOs that require complex validation logic
- β
Fully implemented JWT Authentication with:
- Access & Refresh Tokens
- Token rotation and secure reissue endpoints
- β
Role-based access control (RBAC) with
[Authorize(Roles = "...")]
, supporting roles likeAdmin
,InventoryManager
,Supplier
, andSalesViewer
- β
All stock-related actions (Purchase, Transfer, Manual Adjustments) are logged via the
StockMovement
table - β Advanced entity mappings using Fluent API
InventoryManagement/
βββ API/
β βββ InventoryManagement/
β βββ wwwroot/
β βββ Controllers/
β βββ Filters/
β βββ Middleware/
β βββ Settings/
β βββ appsettings.json
β βββ InventoryManagement.http
β βββ Program.cs
β βββ ServiceCollectionExtensions.cs
β
βββ Application/
β βββ Application/
β βββ Constants/
β βββ DTO's/
β βββ Exceptions/
β βββ Interfaces/
β βββ Mappings/
β βββ ResponseDTO's/
β βββ Services/
β βββ Settings/
β βββ validations/
β βββ ServiceCollectionExtensions.cs
β
βββ Domain/
β βββ Domain/
β βββ Entity/
β βββ Enum/
β βββ Interface/
β
βββ Infrastructure/
βββ Infrastructure/
βββ Configurations/
βββ Context/
βββ Enum/
βββ Identity Models/
βββ Internal Interfaces/
βββ Mappings/
βββ Migrations/
βββ Repository/
βββ Seeds/
βββ Services/
βββ Settings/
βββ UnitOfWork/
βββ Views/
βββ ServiceCollectionExtensions.cs
β οΈ Note:
To follow clean architecture principles and separation of concerns, the Identity-related models likeApplicationUser
are not placed inside theDomain
layer.
Instead, they are defined in theInfrastructure
layer only, and the relationship (e.g., betweenSupplier
andApplicationUser
) is configured using Fluent API insideDbContext
.
- JWT-based authentication with Refresh Token support
- Role-based authorization using Claims (
Admin
,Supplier
,InventoryManager
,SalesViewer
) - Centralized user context extraction using custom middleware:
UserContextMiddleware
- Relies on
UserContextService
to accessUserId
,Roles
,IsSupplier
,Route
from any layer of the application - Custom
RequireVerifiedSupplierAttribute
is an IAsyncAuthorizationFilter that provides additional verification to ensure only verified suppliers can perform specific operations
- Clean Architecture applied with separation into: Domain, Application, Infrastructure, and API layers
- Uses Repository Pattern with Unit of Work for better data handling abstraction
- Dependency Injection is used across the project to manage services and repositories
- Middleware:
- Global Exception Handling
UserContextMiddleware
to extract and reuse authenticated user info- Request locking middleware to prevent duplicate purchase requests in the same minute (admin/inventory manager)
- Entity Framework Core as ORM
- Support for both Soft Delete (e.g., on Suppliers) and Hard Delete where needed
- All entity configurations done through Fluent API (example:
CategoryConfigurations
) - Includes SQL Views, such as
SupplierProfileView
, for optimized read access - Proper indexing and Check constraints applied to ensure data integrity (e.g.,
builder.HasCheckConstraint("CK_PurchaseOrder_TotalCost_Positive", "[TotalCost] > 0")
)
- Global Exception Handling with centralized logic
- Custom Action Filters:
ValidateImageAttribute
β Validates image file format and sizeValidateModelAttribute
β Automatically validates incoming DTOs using FluentValidation
- DTO Validation with FluentValidation
- Full API documentation via Swagger UI
- Dynamic configuration for image uploads using
IOptions<ImageSettings>
pattern: - Example:
"ImageSettings": { "MaxFileSize": 5242880, "AllowedExtensions": [ ".jpg", ".jpeg", ".png" ] }
- These settings are strongly typed using a custom
ImageSettings
class and injected using theIOptions<T>
interface, allowing seamless configuration changes per environment (e.g., development vs production)
- ORM: Entity Framework Core
- Type: Relational Database
- Approach: Code-First
- Features:
- Migrations
- Relationships (One-to-One, One-to-Many)
- Views
- Indexing
- Soft Delete
This project implements Clean Architecture principles where:
- Domain Layer: Contains core business entities like Supplier and cannot see any other layers
- Infrastructure Layer: Contains ApplicationUser (Identity tables) and can see the Domain Layer
- Cannot add ApplicationUser as a Navigation Property in Supplier because the Domain Layer cannot see the Infrastructure Layer
- However, we need access to user information related to the supplier
Database Views were created to retrieve complete supplier and related user information without violating Clean Architecture principles.
- β Maintains Clean Architecture principles
- β Does not violate dependency rules
- β Retrieves complete data in a single query
- β Improves performance
Parent Entity | Child Entity | Relationship Type | Foreign Key | Description |
---|---|---|---|---|
Category | Product | One-to-Many | CategoryId | One category can have multiple products |
Supplier | Product | One-to-Many | SupplierId | One supplier can provide multiple products |
ApplicationUser | Supplier | One-to-One | userid | One user is linked to one supplier |
Supplier | PurchaseOrder | One-to-Many | SupplierId | One supplier can create multiple purchase orders |
Warehouse | PurchaseOrder | One-to-Many | WarehouseId | One warehouse can receive multiple purchase orders |
PurchaseOrder | PurchaseOrderItem | One-to-Many | PurchaseOrderId | One purchase order contains multiple items |
Product | PurchaseOrderItem | One-to-Many | ProductId | One product can be in multiple purchase order items |
Warehouse | Inventory | One-to-Many | WarehouseId | One warehouse contains inventory of multiple products |
Product | Inventory | One-to-Many | ProductId | One product can have inventory in multiple warehouses |
Product | StockMovement | One-to-Many | ProductId | One product can have multiple stock movements |
Warehouse | StockMovement (Source) | One-to-Many | SourceWarehouseId | One warehouse can be source of multiple stock movements |
Warehouse | StockMovement (Destination) | One-to-Many | DestinationWarehouseId | One warehouse can be destination of multiple stock movements |
POST /api/auth/login
{
"email": "admin@Inventory.com",
"password": "P@ssword123"
}