Files
EmailBill/Repository/TransactionRecordRepository.cs

253 lines
8.9 KiB
C#
Raw Permalink Normal View History

2026-01-27 15:29:25 +08:00
namespace Repository;
2025-12-25 11:20:56 +08:00
public interface ITransactionRecordRepository : IBaseRepository<TransactionRecord>
{
Task<TransactionRecord?> ExistsByEmailMessageIdAsync(long emailMessageId, DateTime occurredAt);
Task<TransactionRecord?> ExistsByImportNoAsync(string importNo, string importFrom);
2026-01-28 10:58:15 +08:00
Task<List<TransactionRecord>> QueryAsync(
2025-12-26 17:56:08 +08:00
int? year = null,
2025-12-27 22:05:50 +08:00
int? month = null,
DateTime? startDate = null,
DateTime? endDate = null,
2026-01-28 10:58:15 +08:00
TransactionType? type = null,
string[]? classifies = null,
string? searchKeyword = null,
2025-12-30 17:02:30 +08:00
string? reason = null,
2026-01-28 10:58:15 +08:00
int pageIndex = 1,
int pageSize = int.MaxValue,
2025-12-27 22:05:50 +08:00
bool sortByAmount = false);
2025-12-25 11:20:56 +08:00
2026-01-28 10:58:15 +08:00
Task<long> CountAsync(
2025-12-27 22:05:50 +08:00
int? year = null,
2025-12-30 17:02:30 +08:00
int? month = null,
DateTime? startDate = null,
DateTime? endDate = null,
2026-01-28 10:58:15 +08:00
TransactionType? type = null,
string[]? classifies = null,
string? searchKeyword = null,
2025-12-30 17:02:30 +08:00
string? reason = null);
2025-12-25 11:20:56 +08:00
Task<List<string>> GetDistinctClassifyAsync();
Task<List<TransactionRecord>> GetByEmailIdAsync(long emailMessageId);
2026-01-28 10:58:15 +08:00
Task<int> GetCountByEmailIdAsync(long emailMessageId);
2025-12-26 15:21:31 +08:00
2026-01-28 10:58:15 +08:00
Task<List<TransactionRecord>> GetUnclassifiedAsync(int pageSize = 10);
2025-12-26 15:21:31 +08:00
2025-12-29 20:30:15 +08:00
Task<List<TransactionRecord>> GetClassifiedByKeywordsAsync(List<string> keywords, int limit = 10);
Task<List<TransactionRecord>> GetUnconfirmedRecordsAsync();
2026-01-28 10:58:15 +08:00
Task<int> BatchUpdateByReasonAsync(string reason, TransactionType type, string classify);
Task<int> UpdateCategoryNameAsync(string oldName, string newName, TransactionType type);
2026-01-20 19:11:05 +08:00
2026-01-28 10:58:15 +08:00
Task<int> ConfirmAllUnconfirmedAsync(long[] ids);
2025-12-25 11:20:56 +08:00
}
public class TransactionRecordRepository(IFreeSql freeSql) : BaseRepository<TransactionRecord>(freeSql), ITransactionRecordRepository
{
2026-01-28 10:58:15 +08:00
private ISelect<TransactionRecord> BuildQuery(
2025-12-26 17:56:08 +08:00
int? year = null,
2025-12-27 22:05:50 +08:00
int? month = null,
DateTime? startDate = null,
DateTime? endDate = null,
2026-01-28 10:58:15 +08:00
TransactionType? type = null,
string[]? classifies = null,
string? searchKeyword = null,
string? reason = null)
2025-12-25 11:20:56 +08:00
{
var query = FreeSql.Select<TransactionRecord>();
2025-12-27 11:50:12 +08:00
query = query.WhereIf(!string.IsNullOrWhiteSpace(searchKeyword),
t => t.Reason.Contains(searchKeyword!) ||
t.Classify.Contains(searchKeyword!) ||
t.Card.Contains(searchKeyword!) ||
2025-12-30 17:02:30 +08:00
t.ImportFrom.Contains(searchKeyword!))
.WhereIf(!string.IsNullOrWhiteSpace(reason),
t => t.Reason == reason);
2025-12-25 11:20:56 +08:00
2026-01-18 22:04:56 +08:00
if (classifies is { Length: > 0 })
2025-12-26 17:56:08 +08:00
{
var filterClassifies = classifies.Select(c => c == "未分类" ? string.Empty : c).ToList();
query = query.Where(t => filterClassifies.Contains(t.Classify));
2025-12-26 17:56:08 +08:00
}
2025-12-27 11:50:12 +08:00
query = query.WhereIf(type.HasValue, t => t.Type == type!.Value);
2025-12-26 17:56:08 +08:00
2026-01-28 17:00:58 +08:00
if (year.HasValue)
2025-12-26 17:56:08 +08:00
{
2026-01-28 17:00:58 +08:00
if (month.HasValue && month.Value > 0)
{
// 查询指定年月
var dateStart = new DateTime(year.Value, month.Value, 1);
var dateEnd = dateStart.AddMonths(1);
query = query.Where(t => t.OccurredAt >= dateStart && t.OccurredAt < dateEnd);
}
else
{
// 查询整年数据1月1日到下年1月1日
var dateStart = new DateTime(year.Value, 1, 1);
var dateEnd = new DateTime(year.Value + 1, 1, 1);
query = query.Where(t => t.OccurredAt >= dateStart && t.OccurredAt < dateEnd);
}
2025-12-26 17:56:08 +08:00
}
2026-01-20 19:11:05 +08:00
query = query.WhereIf(startDate.HasValue, t => t.OccurredAt >= startDate!.Value)
.WhereIf(endDate.HasValue, t => t.OccurredAt <= endDate!.Value);
2025-12-26 17:56:08 +08:00
2026-01-28 10:58:15 +08:00
return query;
}
public async Task<TransactionRecord?> ExistsByEmailMessageIdAsync(long emailMessageId, DateTime occurredAt)
{
return await FreeSql.Select<TransactionRecord>()
.Where(t => t.EmailMessageId == emailMessageId && t.OccurredAt == occurredAt)
.FirstAsync();
}
public async Task<TransactionRecord?> ExistsByImportNoAsync(string importNo, string importFrom)
{
return await FreeSql.Select<TransactionRecord>()
.Where(t => t.ImportNo == importNo && t.ImportFrom == importFrom)
.FirstAsync();
}
public async Task<List<TransactionRecord>> QueryAsync(
int? year = null,
int? month = null,
DateTime? startDate = null,
DateTime? endDate = null,
TransactionType? type = null,
string[]? classifies = null,
string? searchKeyword = null,
string? reason = null,
int pageIndex = 1,
int pageSize = int.MaxValue,
bool sortByAmount = false)
{
var query = BuildQuery(year, month, startDate, endDate, type, classifies, searchKeyword, reason);
2025-12-27 22:05:50 +08:00
if (sortByAmount)
2025-12-25 11:20:56 +08:00
{
2025-12-27 22:05:50 +08:00
return await query
.OrderByDescending(t => t.Amount)
.OrderByDescending(t => t.Id)
.Page(pageIndex, pageSize)
.ToListAsync();
}
2026-01-18 22:04:56 +08:00
return await query
.OrderByDescending(t => t.OccurredAt)
.OrderByDescending(t => t.Id)
.Page(pageIndex, pageSize)
.ToListAsync();
2025-12-25 11:20:56 +08:00
}
2026-01-28 10:58:15 +08:00
public async Task<long> CountAsync(
2025-12-27 22:05:50 +08:00
int? year = null,
2025-12-30 17:02:30 +08:00
int? month = null,
DateTime? startDate = null,
DateTime? endDate = null,
2026-01-28 10:58:15 +08:00
TransactionType? type = null,
string[]? classifies = null,
string? searchKeyword = null,
2025-12-30 17:02:30 +08:00
string? reason = null)
2025-12-25 11:20:56 +08:00
{
2026-01-28 10:58:15 +08:00
var query = BuildQuery(year, month, startDate, endDate, type, classifies, searchKeyword, reason);
2025-12-27 22:05:50 +08:00
return await query.CountAsync();
2025-12-25 11:20:56 +08:00
}
public async Task<List<string>> GetDistinctClassifyAsync()
{
return await FreeSql.Select<TransactionRecord>()
.Where(t => !string.IsNullOrEmpty(t.Classify))
.Distinct()
.ToListAsync(t => t.Classify);
}
public async Task<List<TransactionRecord>> GetByEmailIdAsync(long emailMessageId)
{
return await FreeSql.Select<TransactionRecord>()
.Where(t => t.EmailMessageId == emailMessageId)
.OrderBy(t => t.OccurredAt)
.ToListAsync();
}
2026-01-28 10:58:15 +08:00
public async Task<int> GetCountByEmailIdAsync(long emailMessageId)
{
return (int)await FreeSql.Select<TransactionRecord>()
2026-01-28 10:58:15 +08:00
.Where(t => t.EmailMessageId == emailMessageId)
.CountAsync();
}
public async Task<List<TransactionRecord>> GetUnclassifiedAsync(int pageSize = 10)
{
return await FreeSql.Select<TransactionRecord>()
.Where(t => string.IsNullOrEmpty(t.Classify))
.OrderByDescending(t => t.OccurredAt)
.Page(1, pageSize)
.ToListAsync();
}
2025-12-26 15:21:31 +08:00
2025-12-29 20:30:15 +08:00
public async Task<List<TransactionRecord>> GetClassifiedByKeywordsAsync(List<string> keywords, int limit = 10)
{
2026-01-18 22:04:56 +08:00
if (keywords.Count == 0)
2025-12-29 20:30:15 +08:00
{
2026-01-18 22:04:56 +08:00
return [];
2025-12-29 20:30:15 +08:00
}
var query = FreeSql.Select<TransactionRecord>()
2026-01-28 10:58:15 +08:00
.Where(t => t.Classify != "");
2025-12-29 20:30:15 +08:00
if (keywords.Count > 0)
{
query = query.Where(t => keywords.Any(keyword => t.Reason.Contains(keyword)));
}
return await query
.OrderByDescending(t => t.OccurredAt)
.Limit(limit)
.ToListAsync();
}
2026-01-28 10:58:15 +08:00
public async Task<List<TransactionRecord>> GetUnconfirmedRecordsAsync()
2025-12-29 20:30:15 +08:00
{
2026-01-28 10:58:15 +08:00
return await FreeSql.Select<TransactionRecord>()
.Where(t => t.UnconfirmedClassify != null && t.UnconfirmedClassify != "")
.OrderByDescending(t => t.OccurredAt)
2025-12-29 20:30:15 +08:00
.ToListAsync();
2026-01-28 10:58:15 +08:00
}
2025-12-29 20:30:15 +08:00
2026-01-28 10:58:15 +08:00
public async Task<int> BatchUpdateByReasonAsync(string reason, TransactionType type, string classify)
{
return await FreeSql.Update<TransactionRecord>()
.Set(t => t.Type, type)
.Set(t => t.Classify, classify)
.Where(t => t.Reason == reason)
.ExecuteAffrowsAsync();
}
public async Task<int> UpdateCategoryNameAsync(string oldName, string newName, TransactionType type)
{
return await FreeSql.Update<TransactionRecord>()
.Set(a => a.Classify, newName)
.Where(a => a.Classify == oldName && a.Type == type)
.ExecuteAffrowsAsync();
}
public async Task<int> ConfirmAllUnconfirmedAsync(long[] ids)
{
return await FreeSql.Update<TransactionRecord>()
.Set(t => t.Classify == t.UnconfirmedClassify)
.Set(t => t.Type == (t.UnconfirmedType ?? t.Type))
.Set(t => t.UnconfirmedClassify, null)
.Set(t => t.UnconfirmedType, null)
.Where(t => t.UnconfirmedClassify != null && t.UnconfirmedClassify != "")
.Where(t => ids.Contains(t.Id))
.ExecuteAffrowsAsync();
}
2025-12-25 11:20:56 +08:00
}