AutoStock is a full-stack automotive inventory management system for managing vehicles, stock movements, suppliers, customers, purchase orders, sales, inventory valuation, profitability, notifications, and audit history from one centralized platform.
The project combines an ASP.NET Core / .NET 8 Web API backend with a React + TypeScript + Vite frontend and SQL Server. It follows a layered, Clean Architecture-inspired structure to keep business rules, infrastructure concerns, API delivery, and UI responsibilities separated and maintainable.
- Project Overview
- Core Features
- Inventory Cost Accounting
- Architecture
- Tech Stack
- Project Structure
- Getting Started
- Backend Setup
- Frontend Setup
- API Overview
- Authentication and Authorization
- Testing and Validation
- Screenshots
- Important Business Rules
- Security and Local Configuration
- Development Notes
- Current Status
AutoStock provides an end-to-end workflow for automotive inventory operations.
The system supports:
- Vehicle inventory management
- Brands and categories
- Suppliers and customers
- Manual Stock In / Stock Out
- Purchase order workflow
- Sales processing
- Weighted-average inventory costing
- Cost of Goods Sold (COGS)
- Gross profit and gross margin reporting
- Legacy inventory cost-basis reconciliation
- Stock transaction history
- Low-stock and out-of-stock alerts
- Notifications
- Audit logging
- JWT authentication
- Role-based authorization
- Dashboard and business reports
- CSV exports
- VIN-related utilities
- Car image uploads
- Search, filtering, and pagination
- Responsive React administration interface
The accounting layer keeps historical sale values immutable. A completed sale stores the cost snapshot used at the time of sale instead of recalculating historical COGS from the car's current inventory cost.
Cars can be managed with information such as model, year, selling price, quantity, reorder level, color, fuel type, transmission, brand, category, supplier, active/archive status, average unit cost, and vehicle images.
AutoStock supports manual Stock In, manual Stock Out, filtered stock history, historical unit-cost snapshots, movement-value snapshots, movement-source tracking, and inventory validation to prevent invalid stock operations.
Stock history can identify movements created by manual operations, sales, purchase orders, and legacy records. When a related source entity exists, the frontend can navigate from a stock transaction to the related Sale or Purchase Order.
The purchasing workflow supports:
Draft → Submitted → Received
↘ Cancelled
Features include supplier selection, multiple purchase items, quantity and unit-cost validation, immutable totals, submission, receiving, cancellation, automatic inventory updates, weighted-average cost updates, notifications, audit logging, and duplicate-receive protection.
Partial receiving is not supported in the current version.
Sales support customer selection, multiple sale items, quantity validation, payment method, revenue calculation, historical unit-cost snapshot, COGS, gross profit, gross margin, stock reduction, stock-history creation, and sale-completed notifications.
The dashboard provides operational metrics for total units, brands, categories, suppliers, healthy inventory, low-stock vehicles, and out-of-stock vehicles. Reporting covers inventory, sales, purchasing, profitability, and stock movement, with CSV export where supported.
Notifications include Low Stock, Out of Stock, Sale Completed, and system events. Administrative and accounting-sensitive operations are recorded in the audit log for traceability.
AutoStock uses weighted-average inventory costing.
Existing inventory:
10 units × EGP 800,000 = EGP 8,000,000
New stock:
5 units × EGP 900,000 = EGP 4,500,000
New weighted-average unit cost:
(EGP 8,000,000 + EGP 4,500,000) / 15
= EGP 833,333.33
When a sale is created, AutoStock snapshots the current inventory cost into the sale item.
Quantity sold: 2
Selling price: EGP 1,000,000
Average unit cost: EGP 800,000
Revenue = EGP 2,000,000
COGS = EGP 1,600,000
Gross Profit = EGP 400,000
Gross Margin = 20%
The stored snapshot ensures later inventory-cost changes do not rewrite historical profit.
Older inventory may have a known quantity but no reliable historical acquisition cost. If:
Quantity > 0
AverageUnitCost = null
AutoStock does not fabricate an average cost for unknown historical units.
An administrator can use the dedicated one-time endpoint:
PUT /api/InventoryCost/{carId}/basisThis operation requires existing stock, requires the current cost to be unknown, does not change quantity, cannot overwrite an already-known basis, creates an audit entry, and affects future accounting only.
AutoStock uses a layered / Clean Architecture-inspired structure.
AutoStock.sln
│
├── AutoStock.API
│ ├── Controllers
│ ├── ExceptionHandling
│ ├── Services
│ ├── Authentication / Authorization
│ └── API startup configuration
│
├── AutoStock.Application
│ ├── DTOs
│ ├── Interfaces
│ ├── Settings
│ └── Common application contracts
│
├── AutoStock.Domain
│ ├── Entities
│ └── Enums
│
├── AutoStock.Infrastructure
│ ├── Data / Entity Framework Core
│ ├── Identity
│ ├── Services
│ └── Migrations
│
├── AutoStock.Tests
│ ├── Integration tests
│ ├── Service tests
│ ├── Accounting tests
│ ├── Concurrency tests
│ ├── Helpers
│ └── Fakes
│
└── AutoStock.Client
├── React
├── TypeScript
├── API integration
├── Services
├── Pages
├── Components
├── Context
└── Utilities
Domain
↑
Application
↑
Infrastructure
↑
API
React Client
↓ HTTP / JSON
API
Project references:
Application → Domain
Infrastructure → Domain + Application
API → Application + Infrastructure
Tests → Domain + Application + Infrastructure + API
| Layer | Responsibility |
|---|---|
| Domain | Business entities and enums |
| Application | DTOs, interfaces, contracts, settings, shared application models |
| Infrastructure | EF Core, SQL Server, Identity, service implementations |
| API | HTTP endpoints, JWT auth, authorization, exception handling |
| Client | React UI and API integration |
| Tests | Automated business, accounting, integration, and persistence validation |
- .NET 8
- ASP.NET Core Web API
- Entity Framework Core 8
- ASP.NET Core Identity
- JWT Bearer Authentication
- SQL Server
- Swagger / OpenAPI
- LINQ
- React
- TypeScript
- Vite
- React Router
- Axios
- Lucide React
- Responsive CSS
- xUnit
- Moq
- EF Core SQLite test database
- SQL Server concurrency coverage for inventory-sensitive scenarios
- ASP.NET Core integration testing
- Visual Studio
- SQL Server Management Studio
- npm
- Git
- GitHub
AutoStock/
│
├── AutoStock.API/
├── AutoStock.Application/
├── AutoStock.Client/
├── AutoStock.Domain/
├── AutoStock.Infrastructure/
├── AutoStock.Tests/
├── AutoStock.sln
├── .gitignore
└── README.md
Install:
- .NET 8 SDK
- SQL Server
- SQL Server Management Studio (recommended)
- Node.js + npm
- Visual Studio 2022 or newer
- Git
Verify:
dotnet --version
node --version
npm.cmd --version
git --versionClone the repository:
git clone https://github.com/mohamedelsayed31/AutoStock.git
cd AutoStockOpen:
AutoStock.sln
The default local development connection uses Windows Authentication:
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=AutoStockDB;Trusted_Connection=True;TrustServerCertificate=True"
}
}For another environment, update the connection string using local configuration, User Secrets, or environment variables as appropriate.
Do not commit real JWT signing keys or administrator passwords.
From the repository root:
dotnet user-secrets set "Jwt:Key" "YOUR_STRONG_JWT_KEY" --project .\AutoStock.API\AutoStock.API.csproj
dotnet user-secrets set "AdminUser:Email" "admin@example.com" --project .\AutoStock.API\AutoStock.API.csproj
dotnet user-secrets set "AdminUser:Password" "YOUR_STRONG_ADMIN_PASSWORD" --project .\AutoStock.API\AutoStock.API.csproj
dotnet user-secrets set "AdminUser:FullName" "AutoStock Administrator" --project .\AutoStock.API\AutoStock.API.csproj
AdminUser:Passwordis used by the current seeder when the configured administrator does not already exist in the database.
dotnet restore .\AutoStock.slnUsing Visual Studio Package Manager Console:
Update-Database -Project AutoStock.Infrastructure -StartupProject AutoStock.APIOr, when the EF CLI tool is installed:
dotnet ef database update --project .\AutoStock.Infrastructure --startup-project .\AutoStock.APIUsing the command line:
dotnet run --project .\AutoStock.API\AutoStock.API.csprojOr set AutoStock.API as the Startup Project in Visual Studio and run it.
Swagger can be used in the development environment to inspect and test API endpoints.
Frontend directory:
AutoStock.Client
Install dependencies:
cd .\AutoStock.Client
npm.cmd installCreate a local .env from .env.example if needed:
VITE_API_BASE_URL=https://localhost:7140/apiIf your API uses a different local port, update
VITE_API_BASE_URLto match the URL shown by the API/Visual Studio launch profile.
Start development mode:
npm.cmd run devVite normally displays a URL similar to:
http://localhost:5173
Production build:
npm.cmd run buildSwagger is the source of truth for the complete interactive API contract.
| Area | Example route / pattern | Purpose |
|---|---|---|
| Authentication | /api/Auth/... |
Login and authentication |
| Cars | /api/Cars |
Vehicle inventory CRUD and queries |
| Brands | /api/Brands |
Brand management |
| Categories | /api/Categories |
Category management |
| Suppliers | /api/Suppliers |
Supplier management |
| Customers | /api/Customers |
Customer management |
| Stock | /api/Stock/... |
Stock in, stock out, stock history |
| Sales | /api/Sales |
Sale creation and retrieval |
| Purchase Orders | /api/PurchaseOrders/... |
Purchase workflow and receiving |
| Inventory Cost | /api/InventoryCost/{carId}/basis |
One-time legacy cost-basis assignment |
| Profit Reports | /api/ProfitReports |
Revenue, COGS, and profit reporting |
| Notifications | /api/Notifications/... |
Notifications |
| Audit Logs | /api/AuditLogs/... |
Administrative audit history |
| Dashboard | /api/Dashboard/... |
Dashboard metrics |
| Reports | /api/Reports/... |
Operational reports |
| VIN | /api/Vin/... |
VIN-related utilities |
PUT /api/InventoryCost/12/basis
Authorization: Bearer <admin-jwt>
Content-Type: application/json{
"unitCost": 6200000,
"reason": "Opening inventory reconciliation"
}Example response shape:
{
"carId": 12,
"carModel": "X5",
"quantity": 4,
"previousAverageUnitCost": null,
"averageUnitCost": 6200000,
"inventoryValue": 24800000,
"effectiveAt": "2026-09-11T00:00:00Z",
"reason": "Opening inventory reconciliation"
}{
"id": 1,
"carId": 12,
"carModel": "X5",
"transactionType": "Stock Out",
"quantity": 2,
"transactionDate": "2026-09-11T00:00:00Z",
"unitCost": 6200000,
"inventoryValue": 12400000,
"sourceType": "Sale",
"sourceId": 3,
"notes": null
}inventoryValue represents the value of the movement, not the current total inventory balance.
AutoStock uses ASP.NET Core Identity with JWT Bearer authentication.
Role-based authorization protects administrative functionality. Examples include inventory cost-basis reconciliation, purchase-order administration, selected reporting functionality, and audit-log access.
The Inventory Cost endpoint is explicitly Admin-only.
Run the complete backend test suite:
dotnet test .\AutoStock.Tests\AutoStock.Tests.csprojCurrent verified result:
Total: 57
Succeeded: 57
Failed: 0
Skipped: 0
Major tested areas include manual stock operations, unit-cost validation, weighted-average cost, unknown legacy cost handling, stock accounting metadata, sale cost snapshots and COGS, purchase-order receiving, duplicate receive protection, concurrent inventory updates, legacy cost-basis assignment, cost-basis overwrite protection, and zero-stock cost-basis rejection.
From AutoStock.Client:
npm.cmd run buildThe current frontend production build completes successfully.
Security audit:
npm.cmd auditCurrent audit result:
found 0 vulnerabilities
- Stock quantity cannot become negative.
- Stock In requires a positive unit cost.
- Stock Out snapshots the inventory average cost available before the movement.
- Inventory-sensitive operations use transactional/concurrency-aware updates.
- Empty inventory + incoming stock → incoming cost starts the new cost basis.
- Known existing cost + incoming stock → weighted average is recalculated.
- Unknown legacy inventory cost + incoming stock → no fabricated average is created.
- A sale snapshots cost at creation time.
- Historical COGS is not recalculated later.
- Revenue with unknown historical cost remains distinguishable from revenue with known cost.
- Only valid status transitions are allowed.
- Receiving adds inventory once.
- Receiving the same purchase order twice is rejected.
- Purchase item cost is stored as the stock-movement cost.
- Requires current stock greater than zero.
- Requires unknown
AverageUnitCost. - Cannot overwrite a known basis.
- Does not rewrite historical sales.
- Crossing the reorder threshold can create a Low Stock alert.
- Reaching zero creates an Out of Stock alert.
- Completed sales can create Sale Completed notifications.
Sensitive values such as JWT signing keys and administrator passwords are not stored in the repository.
Use ASP.NET Core User Secrets for local backend secrets and environment variables or a production secret manager for deployed environments.
The repository .gitignore excludes local or generated content such as:
.vs/
**/bin/
**/obj/
**/node_modules/
**/dist/
**/.vite/
TestResults/
coverage/
*.trx
.env
.env.*
appsettings.Development.json
appsettings.Local.json
*.log
AutoStock.API/wwwroot/uploads/
AutoStock.Client/.env.example is intentionally safe to commit as a configuration template.
If PowerShell execution policy blocks the npm shim, use:
npm.cmd install
npm.cmd run dev
npm.cmd run build
npm.cmd auditCar images uploaded at runtime are stored under:
AutoStock.API/wwwroot/uploads/
This runtime upload directory is excluded from Git so user-uploaded files are not committed to source control.
The main branch is configured to track:
origin/main
Repository:
https://github.com/mohamedelsayed31/AutoStock
Verified locally:
Backend build ✅
Backend automated tests ✅ 57 / 57
Frontend TypeScript build ✅
Frontend Vite production build ✅
Frontend npm audit ✅ 0 vulnerabilities
Git repository cleanup ✅
Tracked-secret scan ✅
GitHub main branch ✅
Remaining release work:
Optional deployment configuration
Production environment configuration
This project was developed as an educational full-stack software engineering project.












