2025-12-29 15:20:32 +08:00
|
|
|
|
namespace WebApi.Controllers;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 周期性账单控制器
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[ApiController]
|
|
|
|
|
|
[Route("api/[controller]/[action]")]
|
|
|
|
|
|
public class TransactionPeriodicController(
|
|
|
|
|
|
ITransactionPeriodicRepository periodicRepository,
|
|
|
|
|
|
ITransactionPeriodicService periodicService,
|
|
|
|
|
|
ILogger<TransactionPeriodicController> logger
|
|
|
|
|
|
) : ControllerBase
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取周期性账单列表(分页)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[HttpGet]
|
|
|
|
|
|
public async Task<PagedResponse<TransactionPeriodic>> GetListAsync(
|
|
|
|
|
|
[FromQuery] int pageIndex = 1,
|
|
|
|
|
|
[FromQuery] int pageSize = 20,
|
|
|
|
|
|
[FromQuery] string? searchKeyword = null
|
|
|
|
|
|
)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var list = await periodicRepository.GetPagedListAsync(pageIndex, pageSize, searchKeyword);
|
|
|
|
|
|
var total = await periodicRepository.GetTotalCountAsync(searchKeyword);
|
|
|
|
|
|
|
|
|
|
|
|
return new PagedResponse<TransactionPeriodic>
|
|
|
|
|
|
{
|
|
|
|
|
|
Success = true,
|
|
|
|
|
|
Data = list.ToArray(),
|
|
|
|
|
|
Total = (int)total
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
logger.LogError(ex, "获取周期性账单列表失败");
|
|
|
|
|
|
return PagedResponse<TransactionPeriodic>.Fail($"获取列表失败: {ex.Message}");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 根据ID获取周期性账单详情
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[HttpGet("{id}")]
|
|
|
|
|
|
public async Task<BaseResponse<TransactionPeriodic>> GetByIdAsync(long id)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var periodic = await periodicRepository.GetByIdAsync(id);
|
|
|
|
|
|
if (periodic == null)
|
|
|
|
|
|
{
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return "周期性账单不存在".Fail<TransactionPeriodic>();
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return periodic.Ok();
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
logger.LogError(ex, "获取周期性账单详情失败,ID: {Id}", id);
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return $"获取详情失败: {ex.Message}".Fail<TransactionPeriodic>();
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建周期性账单
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[HttpPost]
|
|
|
|
|
|
public async Task<BaseResponse<TransactionPeriodic>> CreateAsync([FromBody] CreatePeriodicRequest request)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var periodic = new TransactionPeriodic
|
|
|
|
|
|
{
|
|
|
|
|
|
PeriodicType = request.PeriodicType,
|
|
|
|
|
|
PeriodicConfig = request.PeriodicConfig ?? string.Empty,
|
|
|
|
|
|
Amount = request.Amount,
|
|
|
|
|
|
Type = request.Type,
|
|
|
|
|
|
Classify = request.Classify ?? string.Empty,
|
|
|
|
|
|
Reason = request.Reason ?? string.Empty,
|
|
|
|
|
|
IsEnabled = true
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 计算下次执行时间
|
|
|
|
|
|
periodic.NextExecuteTime = periodicService.CalculateNextExecuteTime(periodic, DateTime.Now);
|
|
|
|
|
|
|
|
|
|
|
|
var success = await periodicRepository.AddAsync(periodic);
|
|
|
|
|
|
if (!success)
|
|
|
|
|
|
{
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return "创建周期性账单失败".Fail<TransactionPeriodic>();
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return periodic.Ok("创建成功");
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
logger.LogError(ex, "创建周期性账单失败");
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return $"创建失败: {ex.Message}".Fail<TransactionPeriodic>();
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 更新周期性账单
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[HttpPost]
|
2026-01-04 16:43:32 +08:00
|
|
|
|
public async Task<BaseResponse> UpdateAsync([FromBody] UpdatePeriodicRequest request)
|
2025-12-29 15:20:32 +08:00
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var periodic = await periodicRepository.GetByIdAsync(request.Id);
|
|
|
|
|
|
if (periodic == null)
|
|
|
|
|
|
{
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return "周期性账单不存在".Fail();
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
periodic.PeriodicType = request.PeriodicType;
|
|
|
|
|
|
periodic.PeriodicConfig = request.PeriodicConfig ?? string.Empty;
|
|
|
|
|
|
periodic.Amount = request.Amount;
|
|
|
|
|
|
periodic.Type = request.Type;
|
|
|
|
|
|
periodic.Classify = request.Classify ?? string.Empty;
|
|
|
|
|
|
periodic.Reason = request.Reason ?? string.Empty;
|
|
|
|
|
|
periodic.IsEnabled = request.IsEnabled;
|
|
|
|
|
|
periodic.UpdateTime = DateTime.Now;
|
|
|
|
|
|
|
|
|
|
|
|
// 重新计算下次执行时间
|
|
|
|
|
|
periodic.NextExecuteTime = periodicService.CalculateNextExecuteTime(periodic, DateTime.Now);
|
|
|
|
|
|
|
|
|
|
|
|
var success = await periodicRepository.UpdateAsync(periodic);
|
|
|
|
|
|
if (!success)
|
|
|
|
|
|
{
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return "更新周期性账单失败".Fail();
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return "更新成功".Ok();
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
logger.LogError(ex, "更新周期性账单失败,ID: {Id}", request.Id);
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return $"更新失败: {ex.Message}".Fail();
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 删除周期性账单
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[HttpPost]
|
2026-01-04 16:43:32 +08:00
|
|
|
|
public async Task<BaseResponse> DeleteByIdAsync([FromQuery] long id)
|
2025-12-29 15:20:32 +08:00
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var success = await periodicRepository.DeleteAsync(id);
|
|
|
|
|
|
if (!success)
|
|
|
|
|
|
{
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return "删除周期性账单失败".Fail();
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return "删除成功".Ok();
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
logger.LogError(ex, "删除周期性账单失败,ID: {Id}", id);
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return $"删除失败: {ex.Message}".Fail();
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 启用/禁用周期性账单
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[HttpPost]
|
2026-01-04 16:43:32 +08:00
|
|
|
|
public async Task<BaseResponse> ToggleEnabledAsync([FromQuery] long id, [FromQuery] bool enabled)
|
2025-12-29 15:20:32 +08:00
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var periodic = await periodicRepository.GetByIdAsync(id);
|
|
|
|
|
|
if (periodic == null)
|
|
|
|
|
|
{
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return "周期性账单不存在".Fail();
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
periodic.IsEnabled = enabled;
|
|
|
|
|
|
periodic.UpdateTime = DateTime.Now;
|
|
|
|
|
|
|
|
|
|
|
|
var success = await periodicRepository.UpdateAsync(periodic);
|
|
|
|
|
|
if (!success)
|
|
|
|
|
|
{
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return "操作失败".Fail();
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return (enabled ? "已启用" : "已禁用").Ok();
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
logger.LogError(ex, "启用/禁用周期性账单失败,ID: {Id}", id);
|
2026-01-04 16:43:32 +08:00
|
|
|
|
return $"操作失败: {ex.Message}".Fail();
|
2025-12-29 15:20:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建周期性账单请求
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class CreatePeriodicRequest
|
|
|
|
|
|
{
|
|
|
|
|
|
public PeriodicType PeriodicType { get; set; }
|
|
|
|
|
|
public string? PeriodicConfig { get; set; }
|
|
|
|
|
|
public decimal Amount { get; set; }
|
|
|
|
|
|
public TransactionType Type { get; set; }
|
|
|
|
|
|
public string? Classify { get; set; }
|
|
|
|
|
|
public string? Reason { get; set; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 更新周期性账单请求
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class UpdatePeriodicRequest
|
|
|
|
|
|
{
|
|
|
|
|
|
public long Id { get; set; }
|
|
|
|
|
|
public PeriodicType PeriodicType { get; set; }
|
|
|
|
|
|
public string? PeriodicConfig { get; set; }
|
|
|
|
|
|
public decimal Amount { get; set; }
|
|
|
|
|
|
public TransactionType Type { get; set; }
|
|
|
|
|
|
public string? Classify { get; set; }
|
|
|
|
|
|
public string? Reason { get; set; }
|
|
|
|
|
|
public bool IsEnabled { get; set; }
|
|
|
|
|
|
}
|