内容
# BrewUpErp
BrewUpErp 是一个端到端的 ERP 样板,旨在演示:
- 领域驱动设计(DDD)
- 模块化/有界上下文架构
- 函数式领域建模
- 清洁、可测试的应用层
该解决方案故意设计得现实但仍然足够小,以便于研究。它由以下部分组成:
- **BrewApi** – 后端 HTTP API(ASP.NET Core,.NET 10)
- **BrewSpa** – Blazor 网页前端
- **BrewApp** – .NET MAUI 移动应用程序
> 注意:此仓库是一个正在进行的工作。预计会有破坏性更改和不完整的特性,尤其是在较少使用的流程中。
## 解决方案结构
高级别的文件夹布局:
```
src/
├── BrewApi/ # 后端 API、领域和基础设施
├── BrewSpa/ # Blazor 网页前端
└── BrewApp/ # .NET MAUI 移动应用程序
BrewDocs/ # Bruno API 合同和示例有效载荷
docker/ # docker-compose.yml 和辅助脚本
```
### BrewApi
后端解决方案(`src/BrewApi/BrewUp.slnx`)托管所有领域逻辑和 HTTP 端点。
**基础设施和跨切面项目:**
| 项目 | 目的 |
|---|---|
| `BrewUp.Rest` | ASP.NET Core Web API 主机 – 具有显式模块注册的组合根 |
| `BrewUp.Shared` | 共享抽象:值对象、领域 ID、消息(命令/事件)、读取模型合同、验证器、帮助程序 |
| `BrewUp.Infrastructure` | 跨切面基础设施:MongoDB 帮助程序、RabbitMQ 设置、读取模型基础 |
| `BrewUp.AppHost` | .NET Aspire 应用主机,用于本地编排 |
| `BrewUp.ServiceDefaults` | .NET Aspire 服务默认值(OpenTelemetry、健康检查等) |
| `BrewUp.Mediator` | 自定义轻量级中介者 |
| `BrewUp.Warehouse.Entities` | 跨层共享的 Warehouse DTO/实体类型 |
**有界上下文**(每个包含 `Domain`、`Facade`、`Infrastructure`、`ReadModel`、`SharedKernel`、`Tests`):
| 上下文 | 描述 |
|---|---|
| `MasterData/` | 啤酒目录、客户和核心参考数据(也有一个 `.Entities` 项目) |
| `Sales/` | 销售订单和相关工作流 |
| `Purchases/` | 采购订单 |
| `Warehouse/` | 仓库和库存管理 |
| `Dashboards/` | 跨上下文仪表盘聚合(也有一个 `.Entities` 项目) |
| `Sagas/` | 长时间运行的过程管理器/ saga |
**AI 和 MCP 集成:**
| 项目 | 目的 |
|---|---|
| `Mcp/BrewUp.Mcp.McpServer` | 独立的 MCP(模型上下文协议)服务器,通过 HTTP 公开 ERP 工具 |
| `Mcp/BrewUp.Mcp.Facade` | AI 聊天服务、MCP 工具外观、Azure OpenAI 集成端点 |
| `Mcp/BrewUp.Mcp.SharedKernel` | MCP 层的共享类型 |
| `AI/BrewUp.AI.Facade` | AI 外观合同 |
| `AI/BrewUp.AI.SharedKernel` | AI 共享内核类型 |
**`BrewUp.Rest` 中的模块组成:**
`Program.cs` 使用显式组合根模式 – 每个功能都注册为 `IModule`:
```
CorsModule · LoggingModule · InfrastructureModule · OpenApiModule
MasterDataModule · PurchasesModule · SalesModule · WarehouseModule
DashboardsModule · SagasModule · ChatModule
```
### BrewSpa
Blazor 前端解决方案(`src/BrewSpa/BrewSpa.slnx`)镜像了 API 的有界上下文分解:
| 项目 | 目的 |
|---|---|
| `BrewSpa/BrewSpa` | 主要 Blazor 应用 – 外壳、布局、页面(`Home`、`NotFound`)、`wwwroot` |
| `BrewSpa/BrewSpa.Shared` | 共享客户端模型、帮助程序和共享测试 |
| `BrewSpa/BrewSpa.Shared.Components` | 可重用的 Razor 组件、自定义类型、JS 互操作、消息 |
| `Dashboards/` | `BrewSpa.Dashboards.ApplicationServices`、`BrewSpa.Dashboards.Facade`、`BrewSpa.Dashboards.Tests` |
| `MasterData/` | `BrewSpa.MasterData.Application`、`BrewSpa.MasterData.Facade` |
| `Sales/` | `BrewSpa.Sales.Application`、`BrewSpa.Sales.Facade` |
### BrewApp
.NET MAUI 移动解决方案位于 `src/BrewApp/mobile/`:
| 文件夹 | 目的 |
|---|---|
| `mobile/src/` | `BrewApp.Mobile` – `AppShell`、功能、组件、服务、模型、平台目标 |
| `mobile/tests/` | 移动 UI / 集成测试 |
| `specs/` | 规范/验收测试(`.specify`) |
### 有界上下文层布局
每个有界上下文都遵循相同的分层结构:
| 层 | 责任 |
|---|---|
| `*.Domain` | 聚合体、值对象、领域事件、领域服务 |
| `*.SharedKernel` | 仅在有界上下文内共享的类型 |
| `*.Infrastructure` | 持久化和集成(MongoDB、事件存储、消息传递) |
| `*.ReadModel` | 规范化的读取模型和投影 |
| `*.Facade` | 应用服务/用例编排 |
## 技术栈
- **运行时**:.NET 10(`net10.0`)
- **API**:ASP.NET Core Web API
- OpenAPI via Scalar
- OpenTelemetry 和 Azure Monitor 导出器进行可观察性
- Serilog 进行日志记录(控制台 + 文件接收器)
- 显式模块组成根模式
- **架构**:
- 具有显式领域和应用层的 DDD
- 模块化单体风格,按有界上下文分组
- CQRS 和消息驱动模式,由 **Muflone** 支持
- 自定义轻量级中介者(`BrewUp.Mediator`)
- .NET Aspire 进行本地编排
- **持久化和消息传递**:
- MongoDB – 读取模型文档存储(每个上下文的独立实例)
- KurrentDB(EventStoreDB)– 领域事件和 saga 的事件存储
- RabbitMQ 4.x with Stream 插件 – 消息总线
- **AI / MCP**:
- Azure OpenAI 集成(聊天补全)
- 模型上下文协议(MCP)服务器,通过 ERP 工具公开 AI 代理
- **网页 UI**:Blazor(服务端,`net10.0`)
- **移动端**:.NET MAUI(Android / iOS / Windows)
> 查看各个 `*.csproj` 文件和 `docker/docker-compose.yml` 以获取确切的包版本和外部依赖项。
## 入门指南
### 先决条件
- **.NET 10 SDK**
- **Docker Desktop** – 用于本地支持服务(MongoDB、RabbitMQ、KurrentDB)
- 最近的 IDE:Visual Studio 2022+、JetBrains Rider 或带有 C# Dev Kit 的 VS Code
可选(但推荐):
- `git` 用于源代码控制
- **Bruno** (API 客户端)用于运行 `BrewDocs/` 中的合同
- 现代浏览器用于 Blazor 调试工具
## 运行基础设施(Docker)
`docker` 文件夹包含 `docker-compose.yml` 和辅助脚本。
从仓库根目录:
```powershell
cd docker
.\run-docker-compose.bat
```
这启动了所有必需的支持服务:
| 服务 | 容器 | 主机端口 |
|---|---|---|
| KurrentDB(EventStoreDB) | `sales-eventstore` | `4113`(gRPC/HTTP) |
| MongoDB(saga) | `sagas-mongodb` | `27017` |
| MongoDB(销售读取模型) | `sales-mongodb` | `37017` |
| RabbitMQ(+ 流插件) | `rabbitmq` | `5672` AMQP · `5552` 流 · `15672` 管理 UI |
检查 `docker/docker-compose.yml` 以获取完整的配置详细信息。
## 运行后端 API(BrewApi)
后端 API 主机位于 `src/BrewApi/BrewUp.Rest`。
```powershell
cd src/BrewApi
dotnet run --project BrewUp.Rest/BrewUp.Rest.csproj
```
默认情况下,API 公开:
- 所有已注册模块的 REST 端点(MasterData、Sales、Purchases、Warehouse、Dashboards、Sagas、Chat/AI)
- 用于交互式探索的 Scalar OpenAPI UI
- AI 聊天端点(`ChatModule`)
配置位于 `BrewUp.Rest/appsettings.json`(和 `appsettings.Development.json`)。配置前需要配置的关键部分:
```json
"BrewUp": {
"MongoDbSettings": { "ConnectionString": "...", "DatabaseName": "BrewUp" },
"EventStore": { "ConnectionString": "esdb://localhost:4113?tls=false" },
"RabbitMQ": { "Host": "localhost", "Username": "guest", "Password": "guest", ... }
},
"AzureOpenAI": {
"Endpoint": "...",
"ApiKey": "...",
"DeploymentName": "..."
}
```
## 运行 MCP 服务器
独立的模型上下文协议服务器位于 `src/BrewApi/Mcp/BrewUp.Mcp.McpServer`。
```powershell
cd src/BrewApi/Mcp/BrewUp.Mcp.McpServer
dotnet run
```
它在 `/mcp` 处公开了一个无状态的 HTTP MCP 端点,具有以下工具:
| 工具 | 描述 |
|---|---|
| `get_catalog_beers` | 返回目录中的活跃啤酒 |
| `get_open_sales_orders` | 返回当前开放的销售订单 |
| `get_orders_by_customer` | 返回按客户名称筛选的销售订单 |
| `get_late_sales_orders` | 返回给定业务日期的延迟订单 |
## 运行网页前端(BrewSpa)
Blazor 应用位于 `src/BrewSpa/BrewSpa`。
```powershell
cd src/BrewSpa/BrewSpa
dotnet run
```
导航到控制台中打印的 URL(通常为 `https://localhost:xxxx`)。
SPA 消耗 BrewApi 端点,并分解为功能模块:
仪表盘、MasterData 和 Sales — 每个都有自己的 `Application` 和 `Facade` 层。
## 运行移动应用(BrewApp)
.NET MAUI 应用程序位于 `src/BrewApp/mobile/src/`。
1. 在 Visual Studio 2022+ 或 JetBrains Rider 中打开解决方案。
2. 选择所需的目标(Android、iOS、Windows)。
3. 从 IDE 构建和运行。
移动应用(`BrewApp.Mobile`)使用 `AppShell` 导航结构,包含功能模块、服务、组件和平台特定配置。
## 测试
测试项目分布在整个解决方案中:
| 项目 | 范围 |
|---|---|
| `BrewUp.MasterData.Tests` | MasterData 领域和架构 |
| `BrewUp.Rest.Tests` | API 集成和架构 |
| `BrewUp.Shared.Tests` | 共享实用程序 |
| `Sales/BrewUp.Sales.Tests` | Sales 领域 |
| `Purchases/BrewUp.Purchases.Tests` | Purchases 领域 |
| `Warehouse/BrewUp.Warehouse.Tests` | Warehouse 领域 |
| `Dashboards/BrewUp.Dashboards.Tests` | 仪表盘 |
| `Sagas/BrewUp.Sagas.Tests` | Saga |
| `BrewSpa/Dashboards/BrewSpa.Dashboards.Tests` | Blazor 仪表盘 |
| `BrewApp/mobile/tests/` | 移动 UI / 集成 |
运行所有后端测试:
```powershell
cd src/BrewApi
dotnet test
```
## 架构笔记
### DDD 和层
- **领域层**
- 封装业务规则、不变性和通用语言。
- 使用聚合体、值对象和领域事件。
- 纯 C# 代码,无基础设施依赖。
- **应用/外观层**
- 实现用例并协调领域操作。
- 在领域、读取模型和基础设施之间进行协调。
- **基础设施层**
- 持久化实现、消息传递和外部服务。
- 存储库、事件存储、消息发布器的实现。
### 模块化单体
- 每个有界上下文都生活在自己的文件夹树和程序集中。
- 跨上下文通信通过显式合同和消息(命令/事件在 `BrewUp.Shared/Messages/` 中)进行,而不是通过共享表或隐式耦合。
- 共享代码被推送到
- `BrewUp.Shared` 用于真正的跨切面问题,或
- `*.SharedKernel` 用于在单个上下文内共享类型。
- `BrewUp.Rest` 组合根在 `Program.cs` 中显式注册模块,使功能表面立即可见。
### 函数式建模
虽然用 C# 编写,但许多领域和应用程序组件都是以函数式思维构建的:
- 强调不可变值对象
- 用例的清晰输入/输出合同
- 减少副作用,IO 推送到基础设施层
### AI 和 MCP
- `ChatModule` 在 `BrewUp.Rest` 中公开了由 Azure OpenAI 支持的 AI 聊天端点。
- `BrewUp.Mcp.McpServer` 是一个单独的、独立部署的 ASP.NET Core 应用程序,它封装了 ERP 查询作为 MCP 工具,使 AI 代理能够通过模型上下文协议与 ERP 系统交互。
## 路线图和状态
该仓库正在积极开发中。一些计划或正在进行的工作包括:
- 完成所有有界上下文的端到端流程
- 扩展测试覆盖范围(单元、集成和合同测试)
- 加强可观察性(分布式跟踪、指标仪表盘)
- 改进每个有界上下文和模块的文档
欢迎以问题报告、想法和拉取请求的形式进行贡献,但请将此视为学习/参考项目,而不是生产就绪的软件。
## 许可证
请参阅仓库根目录下的 `LICENSE` 文件以获取完整的许可证文本。