653 lines
24 KiB
Markdown
653 lines
24 KiB
Markdown
# 订单日志管理系统设计方案
|
||
|
||
## 1. 需求分析
|
||
|
||
### 1.1 业务背景
|
||
|
||
label_replace_requests 是一个换单请求的订单表,用于存储标签替换请求的相关信息。为了更好地追踪和管理订单的操作历史,需要建立一个订单日志管理表,用于记录订单所有的操作和操作结果。
|
||
|
||
### 1.2 功能需求
|
||
|
||
- 记录订单的所有操作,包括换单、集包、数据更新、下单、取消订单等
|
||
- 记录操作结果,如成功、失败
|
||
- 记录详细的操作说明,如每次集包的关联袋牌信息、数据更新的具体内容等
|
||
- 支持按订单号、尾程单号、操作类型、操作结果等条件查询日志
|
||
- 支持日志的分页查询和管理
|
||
|
||
## 2. 技术方案
|
||
|
||
### 2.1 数据库设计
|
||
|
||
#### 2.1.1 表结构设计
|
||
|
||
**表名:order_logs**
|
||
|
||
| 字段名 | 数据类型 | 约束 | 描述 |
|
||
|--------|----------|------|------|
|
||
| Id | BIGINT UNSIGNED | PRIMARY KEY, AUTO_INCREMENT | 主键ID,自增 |
|
||
| NeutralWaybillNumber | VARCHAR(100) | NOT NULL | 中性面单单号(必填) |
|
||
| FinalMileTrackingNumber | VARCHAR(100) | NULL | 尾程跟踪单号 |
|
||
| OperationType | VARCHAR(50) | NOT NULL | 操作类型(换单、集包、数据更新、下单、取消订单等) |
|
||
| OperationResult | VARCHAR(20) | NOT NULL | 操作结果(成功、失败) |
|
||
| OperationDescription | TEXT | NOT NULL | 操作说明(详细描述操作内容) |
|
||
| Operator | VARCHAR(100) | NULL | 操作人 |
|
||
| CreatedAt | DATETIME | NOT NULL | 操作时间 |
|
||
|
||
#### 2.1.2 索引设计
|
||
|
||
- `idx_neutral_waybill_number`:中性面单单号索引,用于快速查询特定订单的所有操作日志
|
||
- `idx_final_mile_tracking_number`:尾程跟踪单号索引,用于通过尾程单号查询日志
|
||
- `idx_operation_type`:操作类型索引,用于按操作类型查询日志
|
||
- `idx_operation_result`:操作结果索引,用于按操作结果查询日志
|
||
- `idx_created_at`:操作时间索引,用于按时间范围查询日志和排序
|
||
|
||
#### 2.1.3 关联关系
|
||
|
||
- 移除了与 `label_replace_requests` 表的外键关联
|
||
- 通过 `NeutralWaybillNumber` 或 `FinalMileTrackingNumber` 与订单表建立逻辑关联
|
||
|
||
### 2.2 代码实现
|
||
|
||
#### 2.2.1 枚举定义
|
||
|
||
```csharp
|
||
// MDL/Enums/OrderLogEnums.cs
|
||
using System;
|
||
|
||
namespace MDL.Enums
|
||
{
|
||
/// <summary>
|
||
/// 订单日志操作类型枚举
|
||
/// </summary>
|
||
public static class OrderLogOperationType
|
||
{
|
||
/// <summary>
|
||
/// 换单
|
||
/// </summary>
|
||
public const string REPLACE = "换单";
|
||
|
||
/// <summary>
|
||
/// 集包
|
||
/// </summary>
|
||
public const string PACK = "集包";
|
||
|
||
/// <summary>
|
||
/// 数据更新
|
||
/// </summary>
|
||
public const string UPDATE = "数据更新";
|
||
|
||
/// <summary>
|
||
/// 下单
|
||
/// </summary>
|
||
public const string CREATE_ORDER = "下单";
|
||
|
||
/// <summary>
|
||
/// 取消订单
|
||
/// </summary>
|
||
public const string CANCEL_ORDER = "取消订单";
|
||
}
|
||
|
||
/// <summary>
|
||
/// 订单日志操作结果枚举
|
||
/// </summary>
|
||
public static class OrderLogOperationResult
|
||
{
|
||
/// <summary>
|
||
/// 成功
|
||
/// </summary>
|
||
public const string SUCCESS = "成功";
|
||
|
||
/// <summary>
|
||
/// 失败
|
||
/// </summary>
|
||
public const string FAILED = "失败";
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2.2.2 实体类
|
||
|
||
```csharp
|
||
// MDL/Models/OrderLogEntity.cs
|
||
using System;
|
||
|
||
namespace MDL.Models
|
||
{
|
||
/// <summary>
|
||
/// 订单日志实体类
|
||
/// </summary>
|
||
public class OrderLogEntity
|
||
{
|
||
/// <summary>
|
||
/// 主键ID,自增
|
||
/// </summary>
|
||
public long Id { get; set; }
|
||
|
||
/// <summary>
|
||
/// 中性面单单号
|
||
/// </summary>
|
||
public string NeutralWaybillNumber { get; set; }
|
||
|
||
/// <summary>
|
||
/// 尾程跟踪单号
|
||
/// </summary>
|
||
public string FinalMileTrackingNumber { get; set; }
|
||
|
||
/// <summary>
|
||
/// 操作类型(换单、集包、数据更新、下单、取消订单等)
|
||
/// </summary>
|
||
public string OperationType { get; set; }
|
||
|
||
/// <summary>
|
||
/// 操作结果(成功、失败)
|
||
/// </summary>
|
||
public string OperationResult { get; set; }
|
||
|
||
/// <summary>
|
||
/// 操作说明(详细描述操作内容)
|
||
/// </summary>
|
||
public string OperationDescription { get; set; }
|
||
|
||
/// <summary>
|
||
/// 操作人
|
||
/// </summary>
|
||
public string Operator { get; set; }
|
||
|
||
/// <summary>
|
||
/// 操作时间
|
||
/// </summary>
|
||
public DateTime CreatedAt { get; set; }
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2.2.3 仓储接口
|
||
|
||
```csharp
|
||
// DAL/Interfaces/IOrderLogRepository.cs
|
||
using System.Collections.Generic;
|
||
using System.Threading.Tasks;
|
||
using MDL.Models;
|
||
|
||
namespace DAL.Interfaces
|
||
{
|
||
/// <summary>
|
||
/// 订单日志仓储接口
|
||
/// </summary>
|
||
public interface IOrderLogRepository
|
||
{
|
||
/// <summary>
|
||
/// 插入订单日志
|
||
/// </summary>
|
||
/// <param name="log">订单日志实体</param>
|
||
/// <returns>插入是否成功</returns>
|
||
Task<bool> InsertOrderLogAsync(OrderLogEntity log);
|
||
|
||
/// <summary>
|
||
/// 根据中性面单单号获取订单日志列表
|
||
/// </summary>
|
||
/// <param name="neutralWaybillNumber">中性面单单号</param>
|
||
/// <returns>订单日志实体列表</returns>
|
||
Task<List<OrderLogEntity>> GetOrderLogsByWaybillNumberAsync(string neutralWaybillNumber);
|
||
|
||
/// <summary>
|
||
/// 根据尾程跟踪单号获取订单日志列表
|
||
/// </summary>
|
||
/// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
|
||
/// <returns>订单日志实体列表</returns>
|
||
Task<List<OrderLogEntity>> GetOrderLogsByTrackingNumberAsync(string finalMileTrackingNumber);
|
||
|
||
/// <summary>
|
||
/// 获取所有订单日志列表(分页)
|
||
/// </summary>
|
||
/// <param name="pageIndex">页码</param>
|
||
/// <param name="pageSize">每页大小</param>
|
||
/// <returns>订单日志实体列表</returns>
|
||
Task<List<OrderLogEntity>> GetAllOrderLogsAsync(int pageIndex, int pageSize);
|
||
|
||
/// <summary>
|
||
/// 根据操作类型和操作结果获取订单日志列表
|
||
/// </summary>
|
||
/// <param name="operationType">操作类型</param>
|
||
/// <param name="operationResult">操作结果</param>
|
||
/// <param name="pageIndex">页码</param>
|
||
/// <param name="pageSize">每页大小</param>
|
||
/// <returns>订单日志实体列表</returns>
|
||
Task<List<OrderLogEntity>> GetOrderLogsByOperationAsync(string operationType, string operationResult, int pageIndex, int pageSize);
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2.2.4 仓储实现
|
||
|
||
```csharp
|
||
// DAL/Repositories/OrderLogRepository.cs
|
||
using System.Collections.Generic;
|
||
using System.Threading.Tasks;
|
||
using MDL.Models;
|
||
using DAL.Interfaces;
|
||
using SqlSugar;
|
||
|
||
namespace DAL.Repositories
|
||
{
|
||
/// <summary>
|
||
/// 订单日志仓储实现类
|
||
/// </summary>
|
||
public class OrderLogRepository : IOrderLogRepository
|
||
{
|
||
private readonly ISqlSugarClient _db;
|
||
|
||
/// <summary>
|
||
/// 构造函数
|
||
/// </summary>
|
||
/// <param name="db">SqlSugar客户端</param>
|
||
public OrderLogRepository(ISqlSugarClient db)
|
||
{
|
||
_db = db;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 插入订单日志
|
||
/// </summary>
|
||
/// <param name="log">订单日志实体</param>
|
||
/// <returns>插入是否成功</returns>
|
||
public async Task<bool> InsertOrderLogAsync(OrderLogEntity log)
|
||
{
|
||
var result = await _db.Insertable(log).ExecuteCommandAsync();
|
||
return result > 0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据中性面单单号获取订单日志列表
|
||
/// </summary>
|
||
/// <param name="neutralWaybillNumber">中性面单单号</param>
|
||
/// <returns>订单日志实体列表</returns>
|
||
public async Task<List<OrderLogEntity>> GetOrderLogsByWaybillNumberAsync(string neutralWaybillNumber)
|
||
{
|
||
return await _db.Queryable<OrderLogEntity>()
|
||
.Where(x => x.NeutralWaybillNumber == neutralWaybillNumber)
|
||
.OrderBy(x => x.CreatedAt)
|
||
.ToListAsync();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据尾程跟踪单号获取订单日志列表
|
||
/// </summary>
|
||
/// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
|
||
/// <returns>订单日志实体列表</returns>
|
||
public async Task<List<OrderLogEntity>> GetOrderLogsByTrackingNumberAsync(string finalMileTrackingNumber)
|
||
{
|
||
return await _db.Queryable<OrderLogEntity>()
|
||
.Where(x => x.FinalMileTrackingNumber == finalMileTrackingNumber)
|
||
.OrderBy(x => x.CreatedAt)
|
||
.ToListAsync();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取所有订单日志列表(分页)
|
||
/// </summary>
|
||
/// <param name="pageIndex">页码</param>
|
||
/// <param name="pageSize">每页大小</param>
|
||
/// <returns>订单日志实体列表</returns>
|
||
public async Task<List<OrderLogEntity>> GetAllOrderLogsAsync(int pageIndex, int pageSize)
|
||
{
|
||
return await _db.Queryable<OrderLogEntity>()
|
||
.OrderBy(x => x.CreatedAt, OrderByType.Desc)
|
||
.ToPageListAsync(pageIndex, pageSize);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据操作类型和操作结果获取订单日志列表
|
||
/// </summary>
|
||
/// <param name="operationType">操作类型</param>
|
||
/// <param name="operationResult">操作结果</param>
|
||
/// <param name="pageIndex">页码</param>
|
||
/// <param name="pageSize">每页大小</param>
|
||
/// <returns>订单日志实体列表</returns>
|
||
public async Task<List<OrderLogEntity>> GetOrderLogsByOperationAsync(string operationType, string operationResult, int pageIndex, int pageSize)
|
||
{
|
||
var query = _db.Queryable<OrderLogEntity>();
|
||
|
||
if (!string.IsNullOrEmpty(operationType))
|
||
{
|
||
query = query.Where(x => x.OperationType == operationType);
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(operationResult))
|
||
{
|
||
query = query.Where(x => x.OperationResult == operationResult);
|
||
}
|
||
|
||
return await query
|
||
.OrderBy(x => x.CreatedAt, OrderByType.Desc)
|
||
.ToPageListAsync(pageIndex, pageSize);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2.2.5 服务接口
|
||
|
||
```csharp
|
||
// BLL/Interfaces/IOrderLogService.cs
|
||
using System.Collections.Generic;
|
||
using System.Threading.Tasks;
|
||
using MDL.Models;
|
||
|
||
namespace BLL.Interfaces
|
||
{
|
||
/// <summary>
|
||
/// 订单日志服务接口
|
||
/// </summary>
|
||
public interface IOrderLogService
|
||
{
|
||
/// <summary>
|
||
/// 记录订单操作日志
|
||
/// </summary>
|
||
/// <param name="neutralWaybillNumber">中性面单单号</param>
|
||
/// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
|
||
/// <param name="operationType">操作类型</param>
|
||
/// <param name="operationResult">操作结果</param>
|
||
/// <param name="operationDescription">操作说明</param>
|
||
/// <param name="operator">操作人</param>
|
||
/// <returns>记录是否成功</returns>
|
||
Task<bool> RecordOrderLogAsync(string neutralWaybillNumber, string finalMileTrackingNumber, string operationType, string operationResult, string operationDescription, string @operator = null);
|
||
|
||
/// <summary>
|
||
/// 根据中性面单单号获取订单日志列表
|
||
/// </summary>
|
||
/// <param name="neutralWaybillNumber">中性面单单号</param>
|
||
/// <returns>订单日志实体列表</returns>
|
||
Task<List<OrderLogEntity>> GetOrderLogsByWaybillNumberAsync(string neutralWaybillNumber);
|
||
|
||
/// <summary>
|
||
/// 根据尾程跟踪单号获取订单日志列表
|
||
/// </summary>
|
||
/// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
|
||
/// <returns>订单日志实体列表</returns>
|
||
Task<List<OrderLogEntity>> GetOrderLogsByTrackingNumberAsync(string finalMileTrackingNumber);
|
||
|
||
/// <summary>
|
||
/// 获取所有订单日志列表(分页)
|
||
/// </summary>
|
||
/// <param name="pageIndex">页码</param>
|
||
/// <param name="pageSize">每页大小</param>
|
||
/// <returns>订单日志实体列表</returns>
|
||
Task<List<OrderLogEntity>> GetAllOrderLogsAsync(int pageIndex, int pageSize);
|
||
|
||
/// <summary>
|
||
/// 根据操作类型和操作结果获取订单日志列表
|
||
/// </summary>
|
||
/// <param name="operationType">操作类型</param>
|
||
/// <param name="operationResult">操作结果</param>
|
||
/// <param name="pageIndex">页码</param>
|
||
/// <param name="pageSize">每页大小</param>
|
||
/// <returns>订单日志实体列表</returns>
|
||
Task<List<OrderLogEntity>> GetOrderLogsByOperationAsync(string operationType, string operationResult, int pageIndex, int pageSize);
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2.2.6 服务实现
|
||
|
||
```csharp
|
||
// BLL/Services/OrderLogService.cs
|
||
using System.Collections.Generic;
|
||
using System.Threading.Tasks;
|
||
using MDL.Models;
|
||
using BLL.Interfaces;
|
||
using DAL.Interfaces;
|
||
|
||
namespace BLL.Services
|
||
{
|
||
/// <summary>
|
||
/// 订单日志服务实现类
|
||
/// </summary>
|
||
public class OrderLogService : IOrderLogService
|
||
{
|
||
private readonly IOrderLogRepository _orderLogRepository;
|
||
|
||
/// <summary>
|
||
/// 构造函数
|
||
/// </summary>
|
||
/// <param name="orderLogRepository">订单日志仓储</param>
|
||
public OrderLogService(IOrderLogRepository orderLogRepository)
|
||
{
|
||
_orderLogRepository = orderLogRepository;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 记录订单操作日志
|
||
/// </summary>
|
||
/// <param name="neutralWaybillNumber">中性面单单号</param>
|
||
/// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
|
||
/// <param name="operationType">操作类型</param>
|
||
/// <param name="operationResult">操作结果</param>
|
||
/// <param name="operationDescription">操作说明</param>
|
||
/// <param name="operator">操作人</param>
|
||
/// <returns>记录是否成功</returns>
|
||
public async Task<bool> RecordOrderLogAsync(string neutralWaybillNumber, string finalMileTrackingNumber, string operationType, string operationResult, string operationDescription, string @operator = null)
|
||
{
|
||
var log = new OrderLogEntity
|
||
{
|
||
NeutralWaybillNumber = neutralWaybillNumber,
|
||
FinalMileTrackingNumber = finalMileTrackingNumber,
|
||
OperationType = operationType,
|
||
OperationResult = operationResult,
|
||
OperationDescription = operationDescription,
|
||
Operator = @operator,
|
||
CreatedAt = System.DateTime.Now
|
||
};
|
||
|
||
return await _orderLogRepository.InsertOrderLogAsync(log);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据中性面单单号获取订单日志列表
|
||
/// </summary>
|
||
/// <param name="neutralWaybillNumber">中性面单单号</param>
|
||
/// <returns>订单日志实体列表</returns>
|
||
public async Task<List<OrderLogEntity>> GetOrderLogsByWaybillNumberAsync(string neutralWaybillNumber)
|
||
{
|
||
return await _orderLogRepository.GetOrderLogsByWaybillNumberAsync(neutralWaybillNumber);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据尾程跟踪单号获取订单日志列表
|
||
/// </summary>
|
||
/// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
|
||
/// <returns>订单日志实体列表</returns>
|
||
public async Task<List<OrderLogEntity>> GetOrderLogsByTrackingNumberAsync(string finalMileTrackingNumber)
|
||
{
|
||
return await _orderLogRepository.GetOrderLogsByTrackingNumberAsync(finalMileTrackingNumber);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取所有订单日志列表(分页)
|
||
/// </summary>
|
||
/// <param name="pageIndex">页码</param>
|
||
/// <param name="pageSize">每页大小</param>
|
||
/// <returns>订单日志实体列表</returns>
|
||
public async Task<List<OrderLogEntity>> GetAllOrderLogsAsync(int pageIndex, int pageSize)
|
||
{
|
||
return await _orderLogRepository.GetAllOrderLogsAsync(pageIndex, pageSize);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据操作类型和操作结果获取订单日志列表
|
||
/// </summary>
|
||
/// <param name="operationType">操作类型</param>
|
||
/// <param name="operationResult">操作结果</param>
|
||
/// <param name="pageIndex">页码</param>
|
||
/// <param name="pageSize">每页大小</param>
|
||
/// <returns>订单日志实体列表</returns>
|
||
public async Task<List<OrderLogEntity>> GetOrderLogsByOperationAsync(string operationType, string operationResult, int pageIndex, int pageSize)
|
||
{
|
||
return await _orderLogRepository.GetOrderLogsByOperationAsync(operationType, operationResult, pageIndex, pageSize);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2.3 依赖注入配置
|
||
|
||
需要在依赖注入容器中注册订单日志相关的服务和仓储:
|
||
|
||
```csharp
|
||
// 注册订单日志仓储
|
||
services.AddScoped<IOrderLogRepository, OrderLogRepository>();
|
||
|
||
// 注册订单日志服务
|
||
services.AddScoped<IOrderLogService, OrderLogService>();
|
||
```
|
||
|
||
## 3. 使用示例
|
||
|
||
### 3.1 记录下单操作日志
|
||
|
||
```csharp
|
||
// 注入订单日志服务
|
||
private readonly IOrderLogService _orderLogService;
|
||
|
||
public async Task CreateOrderAsync(string neutralWaybillNumber, string finalMileTrackingNumber)
|
||
{
|
||
// 处理下单逻辑
|
||
bool success = await ProcessCreateOrder(neutralWaybillNumber, finalMileTrackingNumber);
|
||
|
||
// 记录下单操作日志
|
||
await _orderLogService.RecordOrderLogAsync(
|
||
neutralWaybillNumber: neutralWaybillNumber,
|
||
finalMileTrackingNumber: finalMileTrackingNumber,
|
||
operationType: OrderLogOperationType.CREATE_ORDER,
|
||
operationResult: success ? OrderLogOperationResult.SUCCESS : OrderLogOperationResult.FAILED,
|
||
operationDescription: success ? $"客户在 {DateTime.Now} 下单成功" : $"客户在 {DateTime.Now} 下单失败",
|
||
@operator: "Customer"
|
||
);
|
||
}
|
||
```
|
||
|
||
### 3.2 记录取消订单操作日志
|
||
|
||
```csharp
|
||
public async Task CancelOrderAsync(string neutralWaybillNumber, string finalMileTrackingNumber)
|
||
{
|
||
// 处理取消订单逻辑
|
||
bool success = await ProcessCancelOrder(neutralWaybillNumber, finalMileTrackingNumber);
|
||
|
||
// 记录取消订单操作日志
|
||
await _orderLogService.RecordOrderLogAsync(
|
||
neutralWaybillNumber: neutralWaybillNumber,
|
||
finalMileTrackingNumber: finalMileTrackingNumber,
|
||
operationType: OrderLogOperationType.CANCEL_ORDER,
|
||
operationResult: success ? OrderLogOperationResult.SUCCESS : OrderLogOperationResult.FAILED,
|
||
operationDescription: success ? $"客户在 {DateTime.Now} 取消订单成功" : $"客户在 {DateTime.Now} 取消订单失败",
|
||
@operator: "Customer"
|
||
);
|
||
}
|
||
```
|
||
|
||
### 3.3 记录换单操作日志
|
||
|
||
```csharp
|
||
public async Task ProcessLabelReplaceAsync(string neutralWaybillNumber, string finalMileTrackingNumber)
|
||
{
|
||
// 处理换单逻辑
|
||
bool success = await ProcessReplace(neutralWaybillNumber, finalMileTrackingNumber);
|
||
|
||
// 记录换单操作日志
|
||
await _orderLogService.RecordOrderLogAsync(
|
||
neutralWaybillNumber: neutralWaybillNumber,
|
||
finalMileTrackingNumber: finalMileTrackingNumber,
|
||
operationType: OrderLogOperationType.REPLACE,
|
||
operationResult: success ? OrderLogOperationResult.SUCCESS : OrderLogOperationResult.FAILED,
|
||
operationDescription: success ? "换单成功" : "换单失败",
|
||
@operator: "System"
|
||
);
|
||
}
|
||
```
|
||
|
||
### 3.4 记录集包操作日志
|
||
|
||
```csharp
|
||
public async Task ProcessPackAsync(string neutralWaybillNumber, string bagTag)
|
||
{
|
||
// 处理集包逻辑
|
||
bool success = await ProcessPacking(neutralWaybillNumber, bagTag);
|
||
|
||
// 记录集包操作日志
|
||
await _orderLogService.RecordOrderLogAsync(
|
||
neutralWaybillNumber: neutralWaybillNumber,
|
||
finalMileTrackingNumber: null, // 可能没有尾程单号
|
||
operationType: OrderLogOperationType.PACK,
|
||
operationResult: success ? OrderLogOperationResult.SUCCESS : OrderLogOperationResult.FAILED,
|
||
operationDescription: success ? $"关联袋牌 {bagTag} 成功" : $"关联袋牌 {bagTag} 失败",
|
||
@operator: "System"
|
||
);
|
||
}
|
||
```
|
||
|
||
### 3.5 记录数据更新操作日志
|
||
|
||
```csharp
|
||
public async Task UpdateBillOfLadingAsync(string neutralWaybillNumber, string billOfLadingNumber)
|
||
{
|
||
// 处理数据更新逻辑
|
||
bool success = await UpdateBillOfLading(neutralWaybillNumber, billOfLadingNumber);
|
||
|
||
// 记录数据更新操作日志
|
||
await _orderLogService.RecordOrderLogAsync(
|
||
neutralWaybillNumber: neutralWaybillNumber,
|
||
finalMileTrackingNumber: null, // 可能没有尾程单号
|
||
operationType: OrderLogOperationType.UPDATE,
|
||
operationResult: success ? OrderLogOperationResult.SUCCESS : OrderLogOperationResult.FAILED,
|
||
operationDescription: success ? "更新提单号成功" : "更新提单号失败",
|
||
@operator: "System"
|
||
);
|
||
}
|
||
```
|
||
|
||
### 3.6 查询订单日志
|
||
|
||
```csharp
|
||
// 根据中性面单单号查询订单日志
|
||
var logs = await _orderLogService.GetOrderLogsByWaybillNumberAsync("NW1234567890");
|
||
|
||
// 根据尾程跟踪单号查询订单日志
|
||
var logs = await _orderLogService.GetOrderLogsByTrackingNumberAsync("FM1234567890");
|
||
|
||
// 分页查询所有订单日志
|
||
var logs = await _orderLogService.GetAllOrderLogsAsync(pageIndex: 1, pageSize: 20);
|
||
|
||
// 根据操作类型和操作结果查询订单日志
|
||
var logs = await _orderLogService.GetOrderLogsByOperationAsync(
|
||
operationType: OrderLogOperationType.CREATE_ORDER,
|
||
operationResult: OrderLogOperationResult.SUCCESS,
|
||
pageIndex: 1,
|
||
pageSize: 20
|
||
);
|
||
```
|
||
|
||
## 4. 性能优化
|
||
|
||
### 4.1 索引优化
|
||
|
||
- 已在表结构中定义了必要的索引,包括关联ID、中性面单单号、操作类型、操作结果和操作时间的索引
|
||
- 这些索引将提高查询性能,特别是在按中性面单单号、操作类型和操作结果查询时
|
||
|
||
### 4.2 分页查询
|
||
|
||
- 实现了分页查询功能,避免一次性加载大量日志数据
|
||
- 建议在前端展示时使用分页,提高用户体验
|
||
|
||
### 4.3 日志清理策略
|
||
|
||
- 考虑到日志数据会随着时间增长而变得庞大,建议制定日志清理策略
|
||
- 可以定期清理 older 日志数据,或者将 older 日志数据归档到历史表中
|
||
|
||
## 5. 总结
|
||
|
||
本设计方案实现了订单日志管理系统,用于记录订单的所有操作和操作结果。通过建立独立的订单日志表,并提供完整的日志记录和查询功能,可以更好地追踪和管理订单的操作历史,提高系统的可追溯性和可维护性。
|
||
|
||
系统支持记录换单、集包、数据更新等操作类型,以及成功、失败等操作结果,并提供详细的操作说明。同时,系统提供了多种查询方式,包括按中性面单单号、标签替换请求ID、操作类型和操作结果等条件查询,以及分页查询功能。
|
||
|
||
通过合理的索引设计和性能优化,系统可以高效地处理大量的日志数据,为业务运营提供有力的支持。 |