Developed using .NET Core for my senior Software Engineering graduation project.
Our Warehouse and Accounting Management System offers multiple baseline ERP features, with 80+ apis for inventory and billing information management.
-
- Invoicing with multiple types including: Sales, Purchases, Returns, Imports, Exports.
- Making payments for invoices issued with debts.
- Discounting on invoices and integration with payments.
- Product conversions for splitting or aggregating multiple types of products.
- Product minimum level notifications.
- Inventory management, including extended set of filters, multiple groupings, and more.
-
- Journal Entries for adding billing relations over accounts.
- Account Statements for specific billing information over accounts including debts and credits.
-
- Offering different roles for each user, and policies on specified system resources.
See commit history for details about features implemented.
The system follows the principles of clean architecture, including:
- The dependency rule:
This can be witnessed with our packaging hierarchy; Domain -> Application -> Infrastructure and Presentation.
- Entities:
Our entities are objects with methods specifying the business rules, can be found under the Domain/Entities package.
- Use Cases:
Our application layer contains application specific business rules. It encapsulates and implements all of the use cases of the system. These use cases orchestrate the flow of data to and from the entities, and direct those entities to use their enterprise wide business rules to achieve the goals of the use case.
- Interface Adapters:
Repositories and Services under our Application layer follow this rule. The main reason for it is to converted from the form most convenient for entities and use cases, into the form most convenient for whatever persistence framework is being used. In our case; Entity Framework.
The system follows the CQRS pattern, all can be witnessed under our Application layer. The pattern states that:
-
Reads and writes are separated into different models, using commands to update data, and queries to read data.
-
Queries never modify the database. A query returns a DTO that does not encapsulate any domain knowledge.
-
Commands should be task-based, rather than data centric ("Close invoice", not "set InvoiceStatus to Closed").
-
Commands may be placed on a queue for asynchronous processing, rather than being processed synchronously. A mediator library such as MediatR helped us with this.
Our system uses classes called "Repositories" that encapsulate the logic required to access data sources.
They centralize common data access functionality, providing better maintainability and decoupling the infrastructure or technology used to access databases from the domain model layer.
This lets you focus on the data persistence logic rather than on data access plumbing.
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.
Contributors names and contact info