订单管理
This commit is contained in:
parent
a9a0ecf0d5
commit
daa5f7b973
@ -4,6 +4,7 @@ using Microsoft.Extensions.Logging;
|
||||
using YD_Event.Application.Client.Dtos;
|
||||
using YD_Event.Core.Entities;
|
||||
using YD_Event.Core.Enum;
|
||||
using YD_Event.Core.Utils;
|
||||
using YD_Event.Core.Infrastructure.WeChat;
|
||||
using YD_Event.Core.Infrastructure.WeChat.Dto;
|
||||
using YD_Event.Core.Options;
|
||||
@ -48,6 +49,7 @@ public class EventClientController : IDynamicApiController
|
||||
private readonly ISqlSugarRepository<SysDistrict> _districtRepository;
|
||||
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Order> _orderRepository;
|
||||
private readonly ISqlSugarRepository<MerchantCertification> _merchantCertificationRepository;
|
||||
private readonly ISqlSugarRepository<EventRegistrationPayment> _paymentRepository;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly IIdGenerator _idGenerator;
|
||||
private readonly WeChatPayService _weChatPayService;
|
||||
@ -79,6 +81,7 @@ public class EventClientController : IDynamicApiController
|
||||
ISqlSugarRepository<SysDistrict> districtRepository,
|
||||
ISqlSugarRepository<YD_Event.Core.Entities.Order> orderRepository,
|
||||
ISqlSugarRepository<MerchantCertification> merchantCertificationRepository,
|
||||
ISqlSugarRepository<EventRegistrationPayment> paymentRepository,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IIdGenerator idGenerator,
|
||||
WeChatPayService weChatPayService,
|
||||
@ -109,6 +112,7 @@ public class EventClientController : IDynamicApiController
|
||||
_districtRepository = districtRepository;
|
||||
_orderRepository = orderRepository;
|
||||
_merchantCertificationRepository = merchantCertificationRepository;
|
||||
_paymentRepository = paymentRepository;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_idGenerator = idGenerator;
|
||||
_weChatPayService = weChatPayService;
|
||||
@ -929,7 +933,7 @@ public class EventClientController : IDynamicApiController
|
||||
AppId = configOptions.AppId,
|
||||
Description = $"{evt.EventName} - 报名费",
|
||||
NotifyUrl = configOptions.NotifyUrl,
|
||||
TotalAmount = (int)(reg.TotalAmount * 100),
|
||||
TotalAmount = AmountHelper.YuanToFen(reg.TotalAmount),
|
||||
ExpireTime = DateTimeOffset.Now.AddMinutes(30),
|
||||
OpenId = input.OpenId
|
||||
};
|
||||
@ -1279,6 +1283,24 @@ public class EventClientController : IDynamicApiController
|
||||
await _registrationRepository.UpdateAsync(reg);
|
||||
_logger.LogInformation($"订单 {reg.OrderNo} 支付状态同步成功,微信交易号:{queryResult.TransactionId}");
|
||||
|
||||
// 创建支付记录
|
||||
var payment = new EventRegistrationPayment
|
||||
{
|
||||
Id = _idGenerator.NewLong(),
|
||||
RegistrationId = reg.Id,
|
||||
TransactionNo = queryResult.TransactionId ?? "",
|
||||
PaymentChannel = 1, // 微信支付
|
||||
PaymentAmount = reg.TotalAmount,
|
||||
PaymentTime = queryResult.SuccessTime?.DateTime ?? DateTime.Now,
|
||||
PaymentStatus = 1, // 已支付
|
||||
RefundStatus = 0, // 未退款
|
||||
PayeeAccount = "", // 收款账户
|
||||
CreatedUserId = userId,
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
await _paymentRepository.InsertAsync(payment);
|
||||
_logger.LogInformation($"支付记录创建成功,报名ID={reg.Id},交易号={queryResult.TransactionId}");
|
||||
|
||||
// 更新 Order 记录状态
|
||||
var order = await _orderRepository.GetFirstAsync(o => o.OrderNo == reg.OrderNo);
|
||||
if (order != null)
|
||||
@ -1412,6 +1434,24 @@ public class EventClientController : IDynamicApiController
|
||||
await _registrationRepository.UpdateAsync(reg);
|
||||
_logger.LogInformation($"订单 {reg.OrderNo} 支付成功,微信交易号:{notifyData.TransactionId}");
|
||||
|
||||
// 创建支付记录
|
||||
var payment = new EventRegistrationPayment
|
||||
{
|
||||
Id = _idGenerator.NewLong(),
|
||||
RegistrationId = reg.Id,
|
||||
TransactionNo = notifyData.TransactionId ?? "",
|
||||
PaymentChannel = 1, // 微信支付
|
||||
PaymentAmount = reg.TotalAmount,
|
||||
PaymentTime = notifyData.SuccessTime?.DateTime ?? DateTime.Now,
|
||||
PaymentStatus = 1, // 已支付
|
||||
RefundStatus = 0, // 未退款
|
||||
PayeeAccount = "", // 收款账户
|
||||
CreatedUserId = reg.CreatedUserId,
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
await _paymentRepository.InsertAsync(payment);
|
||||
_logger.LogInformation($"支付记录创建成功,报名ID={reg.Id},交易号={notifyData.TransactionId}");
|
||||
|
||||
// 更新 Order 记录状态
|
||||
var order = await _orderRepository.GetFirstAsync(o => o.OrderNo == reg.OrderNo);
|
||||
if (order != null)
|
||||
|
||||
@ -2,6 +2,7 @@ using YD_Event.Application.Event.Dtos;
|
||||
using YD_Event.Application.Project.Dtos;
|
||||
using YD_Event.Core.Entities;
|
||||
using YD_Event.Core.Enum;
|
||||
using YD_Event.Core.Utils;
|
||||
using MiniExcelLibs;
|
||||
using SqlSugar;
|
||||
using Mapster;
|
||||
@ -402,7 +403,7 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
EventId = eventInfo.Id,
|
||||
ProjectId = projInput.ProjectId,
|
||||
GenderType = projInput.GenderType,
|
||||
Price = (int)(projInput.Fee * 100),
|
||||
Price = AmountHelper.YuanToFen(projInput.Fee),
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
await _eventProjectRepository.InsertAsync(eventProject);
|
||||
@ -576,7 +577,7 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
EventId = eventInfo.Id,
|
||||
ProjectId = projInput.ProjectId,
|
||||
GenderType = projInput.GenderType,
|
||||
Price = (int)(projInput.Fee * 100),
|
||||
Price = AmountHelper.YuanToFen(projInput.Fee),
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
await _eventProjectRepository.InsertAsync(eventProject);
|
||||
@ -938,7 +939,7 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
EventId = input.EventId,
|
||||
ProjectId = projInput.ProjectId,
|
||||
GenderType = projInput.GenderType,
|
||||
Price = (int)(projInput.Fee * 100),
|
||||
Price = AmountHelper.YuanToFen(projInput.Fee),
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
await _eventProjectRepository.InsertAsync(eventProject);
|
||||
@ -1033,7 +1034,7 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
}
|
||||
|
||||
// 格式验证:最多保留两位小数
|
||||
if (Math.Round(input.FeeConfig.Price, 2) != input.FeeConfig.Price)
|
||||
if (!AmountHelper.IsValidAmount(input.FeeConfig.Price))
|
||||
{
|
||||
throw new InvalidOperationException("价格格式不正确,最多保留两位小数");
|
||||
}
|
||||
@ -1059,7 +1060,7 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
}
|
||||
|
||||
// 格式验证:最多保留两位小数
|
||||
if (Math.Round(feeInput.Fee, 2) != feeInput.Fee)
|
||||
if (!AmountHelper.IsValidAmount(feeInput.Fee))
|
||||
{
|
||||
throw new InvalidOperationException("项目单价格式不正确,最多保留两位小数");
|
||||
}
|
||||
@ -1067,7 +1068,7 @@ public class EventService : BaseService<EventInfo>, ITransient
|
||||
var proj = eventProjects.FirstOrDefault(p => p.Id == feeInput.ProjectId);
|
||||
if (proj != null)
|
||||
{
|
||||
proj.Price = (int)(feeInput.Fee * 100);
|
||||
proj.Price = AmountHelper.YuanToFen(feeInput.Fee);
|
||||
proj.UpdatedTime = DateTime.Now;
|
||||
await _eventProjectRepository.UpdateAsync(proj);
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ using System.Threading.Tasks;
|
||||
using YD_Event.Application.Event.Dtos;
|
||||
using YD_Event.Core.Entities;
|
||||
using YD_Event.Core.Enum;
|
||||
using YD_Event.Core.Utils;
|
||||
using SqlSugar;
|
||||
using Mapster;
|
||||
using YD_Event.Application.Auth;
|
||||
@ -519,8 +520,8 @@ public class UserEventRecordService : IDynamicApiController, ITransient
|
||||
{
|
||||
OutTradeNo = registration.OrderNo,
|
||||
OutRefundNo = outRefundNo,
|
||||
RefundAmount = (int)(registration.TotalAmount * 100), // 转分
|
||||
TotalAmount = (int)(registration.TotalAmount * 100),
|
||||
RefundAmount = AmountHelper.YuanToFen(registration.TotalAmount), // 转分
|
||||
TotalAmount = AmountHelper.YuanToFen(registration.TotalAmount),
|
||||
Reason = input.CancelReason
|
||||
};
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ using YD_Event.Application.Project;
|
||||
using YD_Event.Core.Entities;
|
||||
using YD_Event.Core.Enum;
|
||||
using YD_Event.Core.Domain.Pricing;
|
||||
using YD_Event.Core.Utils;
|
||||
using SqlSugar;
|
||||
using Mapster;
|
||||
using YD_Event.Application.Auth;
|
||||
@ -234,25 +235,16 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient
|
||||
.Where(t => !t.DeleteMark && t.Status == AvailabilityStatus.Enable)
|
||||
.ToListAsync();
|
||||
|
||||
var completionStats = await _projectService.GetProjectStatisticsBatchAsync(
|
||||
projectIds,
|
||||
ProjectService.ProjectStatisticType.CompletionCount);
|
||||
|
||||
output.Projects = eventProjects.Select(ep =>
|
||||
{
|
||||
var p = baseProjects.FirstOrDefault(b => b.Id == ep.ProjectId);
|
||||
var completionCount = 0;
|
||||
if (p != null && completionStats.TryGetValue(p.Id, out var count))
|
||||
{
|
||||
completionCount = count;
|
||||
}
|
||||
|
||||
var dto = new UserEventProjectListOutput
|
||||
{
|
||||
Id = ep.Id,
|
||||
Name = p?.Name ?? "",
|
||||
Fee = ep.Price / 100m,
|
||||
CompletionCount = completionCount
|
||||
CompletionCount = p?.CompletionCount ?? 0
|
||||
};
|
||||
|
||||
if (p != null)
|
||||
@ -330,18 +322,9 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient
|
||||
.Where(t => !t.DeleteMark && t.Status == AvailabilityStatus.Enable)
|
||||
.ToListAsync();
|
||||
|
||||
var completionStats = await _projectService.GetProjectStatisticsBatchAsync(
|
||||
projectIds,
|
||||
ProjectService.ProjectStatisticType.CompletionCount);
|
||||
|
||||
return eventProjects.Select(ep =>
|
||||
{
|
||||
var p = baseProjects.FirstOrDefault(b => b.Id == ep.ProjectId);
|
||||
var completionCount = 0;
|
||||
if (p != null && completionStats.TryGetValue(p.Id, out var count))
|
||||
{
|
||||
completionCount = count;
|
||||
}
|
||||
|
||||
var dto = new UserEventProjectListOutput
|
||||
{
|
||||
@ -349,7 +332,7 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient
|
||||
Name = p?.Name ?? "",
|
||||
Fee = ep.Price / 100m,
|
||||
TeamSize = 1,
|
||||
CompletionCount = completionCount
|
||||
CompletionCount = p?.CompletionCount ?? 0
|
||||
};
|
||||
|
||||
if (p != null)
|
||||
@ -939,7 +922,7 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient
|
||||
AppId = configOptions.AppId,
|
||||
Description = $"{eventInfo.EventName} - 报名费",
|
||||
NotifyUrl = configOptions.NotifyUrl,
|
||||
TotalAmount = (int)(finalAmount * 100), // 单位为分,使用优惠后的金额
|
||||
TotalAmount = AmountHelper.YuanToFen(finalAmount), // 单位为分,使用优惠后的金额
|
||||
ExpireTime = DateTimeOffset.Now.AddMinutes(5)
|
||||
};
|
||||
|
||||
|
||||
18
YD_Event.Application/Order/Dtos/UpdatePaymentStatusInput.cs
Normal file
18
YD_Event.Application/Order/Dtos/UpdatePaymentStatusInput.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace YD_Event.Application.Order.Dtos;
|
||||
|
||||
public class UpdatePaymentStatusInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 订单ID列表(批量更新)
|
||||
/// </summary>
|
||||
[Required]
|
||||
public List<long> Ids { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付状态:0-未支付,1-已支付,3-已退款
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int PaymentStatus { get; set; }
|
||||
}
|
||||
@ -136,7 +136,7 @@ public class OrderService : BaseService<YD_Event.Core.Entities.Order>, ITransien
|
||||
Id = _idGenerator.NextId(),
|
||||
OrderNo = entity.OrderNo,
|
||||
OrderType = 1, // 收入
|
||||
PaymentMethod = 1, // 默认线上支付
|
||||
PaymentMethod = 2, // 默认线上支付 (1=线下, 2=线上)
|
||||
RegistrationMode = 2, // 后台管理页面只做团队报名
|
||||
MerchantId = eventInfo?.MerchantId, // 设置商户ID(支付商户)
|
||||
MerchantCertificationId = certification?.Id, // 设置单位认证ID
|
||||
@ -202,7 +202,7 @@ public class OrderService : BaseService<YD_Event.Core.Entities.Order>, ITransien
|
||||
EventName = e.EventName,
|
||||
OrderType = o.OrderType == 1 ? "收入" : "退款",
|
||||
RelatedOrderNo = ro.OrderNo,
|
||||
PaymentMethod = o.PaymentMethod == 1 ? "线上" : "线下",
|
||||
PaymentMethod = o.PaymentMethod == 2 ? "线上" : "线下",
|
||||
PaymentProofUrl = o.PaymentProofUrl,
|
||||
RegistrationMode = o.RegistrationMode == 1 ? "个人" : "团队",
|
||||
ContactName = r.ContactName,
|
||||
@ -282,30 +282,60 @@ public class OrderService : BaseService<YD_Event.Core.Entities.Order>, ITransien
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新订单状态
|
||||
/// 批量更新订单支付状态
|
||||
/// </summary>
|
||||
[DisplayName("更新订单状态")]
|
||||
[HttpPut("status")]
|
||||
public async Task UpdateStatus(UpdateOrderStatusInput input)
|
||||
[DisplayName("批量更新订单支付状态")]
|
||||
[HttpPut("payment-status")]
|
||||
public async Task UpdatePaymentStatus(UpdatePaymentStatusInput input)
|
||||
{
|
||||
var order = await _orderRepository.GetByIdAsync(input.Id);
|
||||
if (order == null) throw Oops.Bah("订单不存在");
|
||||
|
||||
// 更新订单
|
||||
order.OrderStatus = input.PaymentStatus == 1 ? OrderStatus.Paid : OrderStatus.Pending; // 假设1表示支付成功
|
||||
if (input.PaymentStatus == 1)
|
||||
if (input.Ids == null || !input.Ids.Any())
|
||||
{
|
||||
order.PaymentTime = DateTime.Now;
|
||||
throw Oops.Bah("请选择要更新的订单");
|
||||
}
|
||||
await _orderRepository.UpdateAsync(order);
|
||||
|
||||
// 同步更新报名记录
|
||||
var reg = await _registrationRepository.GetByIdAsync(order.RegistrationId);
|
||||
if (reg != null)
|
||||
var orders = await _orderRepository.AsQueryable()
|
||||
.Where(o => input.Ids.Contains(o.Id))
|
||||
.ToListAsync();
|
||||
|
||||
if (!orders.Any())
|
||||
{
|
||||
reg.PaymentStatus = input.PaymentStatus;
|
||||
reg.PaymentTime = order.PaymentTime;
|
||||
await _registrationRepository.UpdateAsync(reg);
|
||||
throw Oops.Bah("未找到订单");
|
||||
}
|
||||
|
||||
var currentUserId = _authManager.UserId;
|
||||
var now = DateTime.Now;
|
||||
|
||||
foreach (var order in orders)
|
||||
{
|
||||
// 更新订单的 OrderStatus(以 EventRegistration 的支付状态为准)
|
||||
if (input.PaymentStatus == 1)
|
||||
{
|
||||
order.OrderStatus = OrderStatus.Paid;
|
||||
order.PaymentTime = now;
|
||||
}
|
||||
else if (input.PaymentStatus == 3)
|
||||
{
|
||||
order.OrderStatus = OrderStatus.Refunded;
|
||||
order.PaymentTime = now;
|
||||
}
|
||||
else
|
||||
{
|
||||
order.OrderStatus = OrderStatus.Pending;
|
||||
}
|
||||
order.UpdatedTime = now;
|
||||
order.UpdatedUserId = currentUserId;
|
||||
await _orderRepository.UpdateAsync(order);
|
||||
|
||||
// 同步更新报名记录的支付状态
|
||||
var reg = await _registrationRepository.GetByIdAsync(order.RegistrationId);
|
||||
if (reg != null)
|
||||
{
|
||||
reg.PaymentStatus = input.PaymentStatus;
|
||||
reg.PaymentTime = order.PaymentTime;
|
||||
reg.UpdatedTime = now;
|
||||
reg.UpdatedUserId = currentUserId;
|
||||
await _registrationRepository.UpdateAsync(reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -338,6 +368,9 @@ public class OrderService : BaseService<YD_Event.Core.Entities.Order>, ITransien
|
||||
|
||||
if (order.OrderStatus != OrderStatus.Paid) throw Oops.Bah("订单未支付,无法退款");
|
||||
|
||||
var currentUserId = _authManager.UserId;
|
||||
var now = DateTime.Now;
|
||||
|
||||
// 1. 创建退款订单
|
||||
var refundOrder = new YD_Event.Core.Entities.Order
|
||||
{
|
||||
@ -354,30 +387,66 @@ public class OrderService : BaseService<YD_Event.Core.Entities.Order>, ITransien
|
||||
OriginalAmount = order.ActualAmount,
|
||||
ActualAmount = input.RefundAmount, // 退款金额
|
||||
OrderStatus = OrderStatus.Refunded, // 退款成功
|
||||
PaymentTime = DateTime.Now,
|
||||
PaymentTime = now,
|
||||
Remark = input.Reason,
|
||||
CreatedTime = DateTime.Now,
|
||||
CreatedUserId = _idGenerator.NewLong() // 系统或当前用户
|
||||
CreatedTime = now,
|
||||
CreatedUserId = currentUserId
|
||||
};
|
||||
await _orderRepository.InsertAsync(refundOrder);
|
||||
|
||||
// 2. 更新报名状态
|
||||
// 2. 更新原订单状态
|
||||
order.OrderStatus = OrderStatus.Refunded;
|
||||
order.UpdatedTime = now;
|
||||
order.UpdatedUserId = currentUserId;
|
||||
await _orderRepository.UpdateAsync(order);
|
||||
|
||||
// 3. 更新报名状态
|
||||
var reg = await _registrationRepository.GetByIdAsync(order.RegistrationId);
|
||||
if (reg != null)
|
||||
{
|
||||
reg.PaymentStatus = 3; // 已退款
|
||||
reg.UpdatedTime = now;
|
||||
reg.UpdatedUserId = currentUserId;
|
||||
await _registrationRepository.UpdateAsync(reg);
|
||||
}
|
||||
|
||||
// 4. 更新支付记录(如果有)
|
||||
var payment = await _paymentRepository.GetFirstAsync(p => p.RegistrationId == order.RegistrationId);
|
||||
if (payment != null)
|
||||
{
|
||||
payment.RefundStatus = 1; // 已退款
|
||||
payment.UpdatedTime = now;
|
||||
payment.UpdatedUserId = currentUserId;
|
||||
await _paymentRepository.UpdateAsync(payment);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除订单
|
||||
/// 删除订单(软删除)
|
||||
/// </summary>
|
||||
[DisplayName("删除订单")]
|
||||
[HttpPost("delete")]
|
||||
public async Task Delete([FromBody] List<long> ids)
|
||||
{
|
||||
await _orderRepository.DeleteAsync(x => ids.Contains(x.Id));
|
||||
if (ids == null || !ids.Any())
|
||||
{
|
||||
throw Oops.Bah("请选择要删除的订单");
|
||||
}
|
||||
|
||||
var currentUserId = _authManager.UserId;
|
||||
var now = DateTime.Now;
|
||||
|
||||
var orders = await _orderRepository.AsQueryable()
|
||||
.Where(o => ids.Contains(o.Id))
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var order in orders)
|
||||
{
|
||||
order.DeleteMark = true;
|
||||
order.UpdatedTime = now;
|
||||
order.UpdatedUserId = currentUserId;
|
||||
await _orderRepository.UpdateAsync(order);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -415,7 +484,7 @@ public class OrderService : BaseService<YD_Event.Core.Entities.Order>, ITransien
|
||||
EventName = e.EventName,
|
||||
OrderType = o.OrderType == 1 ? "收入" : "退款",
|
||||
RelatedOrderNo = ro.OrderNo,
|
||||
PaymentMethod = o.PaymentMethod == 1 ? "线上" : "线下",
|
||||
PaymentMethod = o.PaymentMethod == 2 ? "线上" : "线下",
|
||||
RegistrationMode = o.RegistrationMode == 1 ? "个人" : "团队",
|
||||
ContactName = r.ContactName,
|
||||
ContactPhone = r.ContactPhone,
|
||||
|
||||
@ -70,19 +70,6 @@ public class ProjectService : BaseService<YD_Event.Core.Entities.Project>, ITran
|
||||
})
|
||||
.ToPagedListAsync(input);
|
||||
|
||||
var projectIds = result.Rows.Select(x => x.Id).ToList();
|
||||
if (projectIds.Any())
|
||||
{
|
||||
var stats = await GetProjectStatisticsBatchAsync(projectIds, ProjectStatisticType.CompletionCount);
|
||||
foreach (var item in result.Rows)
|
||||
{
|
||||
if (stats.TryGetValue(item.Id, out var count))
|
||||
{
|
||||
item.CompletionCount = count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -181,8 +168,6 @@ public class ProjectService : BaseService<YD_Event.Core.Entities.Project>, ITran
|
||||
|
||||
var groups = await _groupRepository.GetListAsync(x => x.ProjectId == id);
|
||||
dto.Groups = groups.Adapt<List<ProjectGroupDto>>();
|
||||
|
||||
dto.CompletionCount = await GetProjectStatisticAsync(id, ProjectStatisticType.CompletionCount);
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
@ -8,10 +8,13 @@
|
||||
<ItemGroup>
|
||||
<Compile Remove="Blog\**" />
|
||||
<Compile Remove="Config\**" />
|
||||
<Compile Remove="File\**" />
|
||||
<EmbeddedResource Remove="Blog\**" />
|
||||
<EmbeddedResource Remove="Config\**" />
|
||||
<EmbeddedResource Remove="File\**" />
|
||||
<None Remove="Blog\**" />
|
||||
<None Remove="Config\**" />
|
||||
<None Remove="File\**" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="applicationsettings.json" />
|
||||
@ -25,7 +28,6 @@
|
||||
<ItemGroup>
|
||||
<Folder Include="Auth\Dtos\" />
|
||||
<Folder Include="Certificate\Dtos\" />
|
||||
<Folder Include="File\Dtos\" />
|
||||
<Folder Include="Logging\Dtos\" />
|
||||
<Folder Include="Menu\Dtos\" />
|
||||
<Folder Include="Organization\Dtos\" />
|
||||
|
||||
79
YD_Event.Core/Utils/AmountHelper.cs
Normal file
79
YD_Event.Core/Utils/AmountHelper.cs
Normal file
@ -0,0 +1,79 @@
|
||||
namespace YD_Event.Core.Utils;
|
||||
|
||||
/// <summary>
|
||||
/// 金额处理工具类
|
||||
/// 统一处理货币单位转换、精度控制和四舍五入规则
|
||||
/// </summary>
|
||||
public static class AmountHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 金额精度小数位数
|
||||
/// </summary>
|
||||
private const int DecimalPlaces = 2;
|
||||
|
||||
/// <summary>
|
||||
/// 将元转换为分
|
||||
/// </summary>
|
||||
/// <param name="amount">金额(元)</param>
|
||||
/// <returns>金额(分)</returns>
|
||||
public static int YuanToFen(decimal amount)
|
||||
{
|
||||
// 使用四舍五入到最近的整数,使用银行家舍入法(四舍六入五成双)
|
||||
// 这里先确保精度,然后乘以100,再四舍五入
|
||||
var roundedAmount = Math.Round(amount, DecimalPlaces, MidpointRounding.AwayFromZero);
|
||||
return (int)Math.Round(roundedAmount * 100, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将分转换为元
|
||||
/// </summary>
|
||||
/// <param name="amount">金额(分)</param>
|
||||
/// <returns>金额(元)</returns>
|
||||
public static decimal FenToYuan(int amount)
|
||||
{
|
||||
return amount / 100m;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将分转换为元(可为空)
|
||||
/// </summary>
|
||||
/// <param name="amount">金额(分)</param>
|
||||
/// <returns>金额(元)</returns>
|
||||
public static decimal? FenToYuan(int? amount)
|
||||
{
|
||||
if (!amount.HasValue) return null;
|
||||
return amount.Value / 100m;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 四舍五入金额到指定小数位
|
||||
/// </summary>
|
||||
/// <param name="amount">金额</param>
|
||||
/// <param name="decimalPlaces">小数位数,默认2位</param>
|
||||
/// <returns>四舍五入后的金额</returns>
|
||||
public static decimal Round(decimal amount, int decimalPlaces = DecimalPlaces)
|
||||
{
|
||||
return Math.Round(amount, decimalPlaces, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证金额格式是否正确(最多保留2位小数)
|
||||
/// </summary>
|
||||
/// <param name="amount">金额</param>
|
||||
/// <returns>是否有效</returns>
|
||||
public static bool IsValidAmount(decimal amount)
|
||||
{
|
||||
var rounded = Math.Round(amount, DecimalPlaces, MidpointRounding.AwayFromZero);
|
||||
return rounded == amount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证金额是否大于0且格式正确
|
||||
/// </summary>
|
||||
/// <param name="amount">金额</param>
|
||||
/// <returns>是否有效</returns>
|
||||
public static bool IsValidPositiveAmount(decimal amount)
|
||||
{
|
||||
return amount > 0 && IsValidAmount(amount);
|
||||
}
|
||||
}
|
||||
@ -5811,6 +5811,60 @@
|
||||
子选项
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:YD_Event.Core.Utils.AmountHelper">
|
||||
<summary>
|
||||
金额处理工具类
|
||||
统一处理货币单位转换、精度控制和四舍五入规则
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:YD_Event.Core.Utils.AmountHelper.DecimalPlaces">
|
||||
<summary>
|
||||
金额精度小数位数
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:YD_Event.Core.Utils.AmountHelper.YuanToFen(System.Decimal)">
|
||||
<summary>
|
||||
将元转换为分
|
||||
</summary>
|
||||
<param name="amount">金额(元)</param>
|
||||
<returns>金额(分)</returns>
|
||||
</member>
|
||||
<member name="M:YD_Event.Core.Utils.AmountHelper.FenToYuan(System.Int32)">
|
||||
<summary>
|
||||
将分转换为元
|
||||
</summary>
|
||||
<param name="amount">金额(分)</param>
|
||||
<returns>金额(元)</returns>
|
||||
</member>
|
||||
<member name="M:YD_Event.Core.Utils.AmountHelper.FenToYuan(System.Nullable{System.Int32})">
|
||||
<summary>
|
||||
将分转换为元(可为空)
|
||||
</summary>
|
||||
<param name="amount">金额(分)</param>
|
||||
<returns>金额(元)</returns>
|
||||
</member>
|
||||
<member name="M:YD_Event.Core.Utils.AmountHelper.Round(System.Decimal,System.Int32)">
|
||||
<summary>
|
||||
四舍五入金额到指定小数位
|
||||
</summary>
|
||||
<param name="amount">金额</param>
|
||||
<param name="decimalPlaces">小数位数,默认2位</param>
|
||||
<returns>四舍五入后的金额</returns>
|
||||
</member>
|
||||
<member name="M:YD_Event.Core.Utils.AmountHelper.IsValidAmount(System.Decimal)">
|
||||
<summary>
|
||||
验证金额格式是否正确(最多保留2位小数)
|
||||
</summary>
|
||||
<param name="amount">金额</param>
|
||||
<returns>是否有效</returns>
|
||||
</member>
|
||||
<member name="M:YD_Event.Core.Utils.AmountHelper.IsValidPositiveAmount(System.Decimal)">
|
||||
<summary>
|
||||
验证金额是否大于0且格式正确
|
||||
</summary>
|
||||
<param name="amount">金额</param>
|
||||
<returns>是否有效</returns>
|
||||
</member>
|
||||
<member name="F:Easy.Core.EnumExtension.EnumDic">
|
||||
<summary>
|
||||
缓存
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user