175 lines
5.6 KiB
C#
175 lines
5.6 KiB
C#
|
|
namespace Repository;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 交易分类仓储接口
|
|||
|
|
/// </summary>
|
|||
|
|
public interface ITransactionCategoryRepository : IBaseRepository<TransactionCategory>
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 根据类型获取所有顶级分类(Level=2,即类型下的分类)
|
|||
|
|
/// </summary>
|
|||
|
|
Task<List<TransactionCategory>> GetTopLevelCategoriesByTypeAsync(TransactionType type);
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 根据父分类ID获取子分类
|
|||
|
|
/// </summary>
|
|||
|
|
Task<List<TransactionCategory>> GetChildCategoriesAsync(long parentId);
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取完整的分类树(按类型)
|
|||
|
|
/// </summary>
|
|||
|
|
Task<List<TransactionCategoryTreeDto>> GetCategoryTreeAsync(TransactionType? type = null);
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 根据名称和父ID查找分类(防止重复)
|
|||
|
|
/// </summary>
|
|||
|
|
Task<TransactionCategory?> GetByNameAndParentAsync(string name, long parentId, TransactionType type);
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 检查分类是否被使用
|
|||
|
|
/// </summary>
|
|||
|
|
Task<bool> IsCategoryInUseAsync(long categoryId);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 交易分类仓储实现
|
|||
|
|
/// </summary>
|
|||
|
|
public class TransactionCategoryRepository(IFreeSql freeSql) : BaseRepository<TransactionCategory>(freeSql), ITransactionCategoryRepository
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 根据类型获取所有顶级分类(Level=2)
|
|||
|
|
/// </summary>
|
|||
|
|
public async Task<List<TransactionCategory>> GetTopLevelCategoriesByTypeAsync(TransactionType type)
|
|||
|
|
{
|
|||
|
|
return await FreeSql.Select<TransactionCategory>()
|
|||
|
|
.Where(c => c.Type == type && c.Level == 2 && c.IsEnabled)
|
|||
|
|
.OrderBy(c => c.SortOrder)
|
|||
|
|
.OrderBy(c => c.Name)
|
|||
|
|
.ToListAsync();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 根据父分类ID获取子分类
|
|||
|
|
/// </summary>
|
|||
|
|
public async Task<List<TransactionCategory>> GetChildCategoriesAsync(long parentId)
|
|||
|
|
{
|
|||
|
|
return await FreeSql.Select<TransactionCategory>()
|
|||
|
|
.Where(c => c.ParentId == parentId && c.IsEnabled)
|
|||
|
|
.OrderBy(c => c.SortOrder)
|
|||
|
|
.OrderBy(c => c.Name)
|
|||
|
|
.ToListAsync();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取完整的分类树
|
|||
|
|
/// </summary>
|
|||
|
|
public async Task<List<TransactionCategoryTreeDto>> GetCategoryTreeAsync(TransactionType? type = null)
|
|||
|
|
{
|
|||
|
|
var query = FreeSql.Select<TransactionCategory>()
|
|||
|
|
.Where(c => c.IsEnabled);
|
|||
|
|
|
|||
|
|
if (type.HasValue)
|
|||
|
|
{
|
|||
|
|
query = query.Where(c => c.Type == type.Value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var allCategories = await query
|
|||
|
|
.OrderBy(c => c.Type)
|
|||
|
|
.OrderBy(c => c.SortOrder)
|
|||
|
|
.OrderBy(c => c.Name)
|
|||
|
|
.ToListAsync();
|
|||
|
|
|
|||
|
|
// 构建树形结构(Level 2为根节点,即各个分类)
|
|||
|
|
var result = new List<TransactionCategoryTreeDto>();
|
|||
|
|
var level2Categories = allCategories.Where(c => c.Level == 2).ToList();
|
|||
|
|
|
|||
|
|
foreach (var category in level2Categories)
|
|||
|
|
{
|
|||
|
|
var treeNode = new TransactionCategoryTreeDto
|
|||
|
|
{
|
|||
|
|
Id = category.Id,
|
|||
|
|
Name = category.Name,
|
|||
|
|
Type = category.Type,
|
|||
|
|
Level = category.Level,
|
|||
|
|
Icon = category.Icon,
|
|||
|
|
Children = BuildChildrenTree(category.Id, allCategories)
|
|||
|
|
};
|
|||
|
|
result.Add(treeNode);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 递归构建子分类树
|
|||
|
|
/// </summary>
|
|||
|
|
private List<TransactionCategoryTreeDto> BuildChildrenTree(long parentId, List<TransactionCategory> allCategories)
|
|||
|
|
{
|
|||
|
|
var children = allCategories.Where(c => c.ParentId == parentId).ToList();
|
|||
|
|
var result = new List<TransactionCategoryTreeDto>();
|
|||
|
|
|
|||
|
|
foreach (var child in children)
|
|||
|
|
{
|
|||
|
|
var treeNode = new TransactionCategoryTreeDto
|
|||
|
|
{
|
|||
|
|
Id = child.Id,
|
|||
|
|
Name = child.Name,
|
|||
|
|
Type = child.Type,
|
|||
|
|
Level = child.Level,
|
|||
|
|
Icon = child.Icon,
|
|||
|
|
Children = BuildChildrenTree(child.Id, allCategories)
|
|||
|
|
};
|
|||
|
|
result.Add(treeNode);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 根据名称和父ID查找分类
|
|||
|
|
/// </summary>
|
|||
|
|
public async Task<TransactionCategory?> GetByNameAndParentAsync(string name, long parentId, TransactionType type)
|
|||
|
|
{
|
|||
|
|
return await FreeSql.Select<TransactionCategory>()
|
|||
|
|
.Where(c => c.Name == name && c.ParentId == parentId && c.Type == type)
|
|||
|
|
.FirstAsync();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 检查分类是否被使用
|
|||
|
|
/// </summary>
|
|||
|
|
public async Task<bool> IsCategoryInUseAsync(long categoryId)
|
|||
|
|
{
|
|||
|
|
// 检查是否有交易记录使用此分类
|
|||
|
|
var category = await GetByIdAsync(categoryId);
|
|||
|
|
if (category == null) return false;
|
|||
|
|
|
|||
|
|
// 根据层级检查不同的字段
|
|||
|
|
var count = category.Level switch
|
|||
|
|
{
|
|||
|
|
2 => await FreeSql.Select<TransactionRecord>()
|
|||
|
|
.Where(r => r.Classify == category.Name && r.Type == category.Type)
|
|||
|
|
.CountAsync(),
|
|||
|
|
3 => await FreeSql.Select<TransactionRecord>()
|
|||
|
|
.Where(r => r.SubClassify == category.Name && r.Type == category.Type)
|
|||
|
|
.CountAsync(),
|
|||
|
|
_ => 0
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return count > 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 分类树DTO
|
|||
|
|
/// </summary>
|
|||
|
|
public class TransactionCategoryTreeDto
|
|||
|
|
{
|
|||
|
|
public long Id { get; set; }
|
|||
|
|
public string Name { get; set; } = string.Empty;
|
|||
|
|
public TransactionType Type { get; set; }
|
|||
|
|
public int Level { get; set; }
|
|||
|
|
public string? Icon { get; set; }
|
|||
|
|
public List<TransactionCategoryTreeDto> Children { get; set; } = new();
|
|||
|
|
}
|