292 lines
11 KiB
C#
292 lines
11 KiB
C#
using System.Linq.Expressions;
|
|
using Fake.Application;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Oms.Application.Dtos.Channels;
|
|
using Oms.Application.Dtos.Shared;
|
|
using Oms.Application.Shared;
|
|
using Oms.Domain.ChannelsAggregate.Entities;
|
|
using Oms.Domain.ChannelsAggregate.Repositories;
|
|
|
|
namespace Oms.Application.Services.Channels;
|
|
|
|
[ApiExplorerSettings(GroupName = "OMS-Channel")]
|
|
public partial class ServiceChannelService : ApplicationService
|
|
{
|
|
private const string PriceOperatorType = "price";
|
|
private const string RulesOperatorType = "rules";
|
|
|
|
private IServiceChannelRepository ServiceChannelRepository => LazyServiceProvider.GetRequiredService<IServiceChannelRepository>();
|
|
|
|
/// <summary>
|
|
/// 获取服务渠道分页列表。
|
|
/// </summary>
|
|
[HttpGet("/channel/service-channel/list")]
|
|
public async Task<OmsPageResult<ServiceChannelListOutput>> GetListAsync([FromQuery] ServiceChannelListInput input)
|
|
{
|
|
var predicate = BuildListPredicate(input);
|
|
var pageIndex = OmsDocHelper.NormalizePage(input.Page);
|
|
var pageSize = OmsDocHelper.NormalizePageSize(input.PageSize);
|
|
var entities = await ServiceChannelRepository.GetPagedListAsync(
|
|
predicate,
|
|
pageIndex,
|
|
pageSize,
|
|
new Dictionary<string, bool> { [nameof(ServiceChannel.UpdateTime)] = false, [nameof(ServiceChannel.Id)] = false });
|
|
var total = await ServiceChannelRepository.CountAsync(predicate);
|
|
var groupMap = await GetGroupMapAsync();
|
|
return new OmsPageResult<ServiceChannelListOutput>
|
|
{
|
|
Items = entities.Select(entity => MapListOutput(entity, groupMap)).ToList(),
|
|
Total = total
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取服务渠道详情。
|
|
/// </summary>
|
|
[HttpGet("/channel/service-channel/detail")]
|
|
public async Task<ServiceChannelDetailOutput> GetDetailAsync([FromQuery] long id)
|
|
{
|
|
var entity = await GetEntityOrThrowAsync(id);
|
|
return MapDetailOutput(entity, await GetGroupMapAsync());
|
|
}
|
|
|
|
/// <summary>
|
|
/// 新增服务渠道。
|
|
/// </summary>
|
|
[HttpPost("/channel/service-channel/create")]
|
|
public async Task CreateAsync(ServiceChannelSaveInput input)
|
|
{
|
|
await ValidateChannelCodeAsync(input.ChannelCode, null);
|
|
var entity = new ServiceChannel
|
|
{
|
|
IsDeleted = false,
|
|
CreateTime = DateTime.Now,
|
|
CreateUserId = CurrentUser.GetId<int>()
|
|
};
|
|
ApplyInput(entity, input);
|
|
await ServiceChannelRepository.InsertAsync(entity);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 更新服务渠道。
|
|
/// </summary>
|
|
[HttpPost("/channel/service-channel/update")]
|
|
public async Task UpdateAsync(ServiceChannelSaveInput input)
|
|
{
|
|
var entity = await GetEntityOrThrowAsync(input.Id);
|
|
await ValidateChannelCodeAsync(input.ChannelCode, entity.Id);
|
|
ApplyInput(entity, input);
|
|
entity.UpdateTime = DateTime.Now;
|
|
entity.UpdateUserId = CurrentUser.GetId<int>();
|
|
await ServiceChannelRepository.UpdateAsync(entity);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 删除服务渠道。
|
|
/// </summary>
|
|
[HttpPost("/channel/service-channel/delete")]
|
|
public async Task DeleteAsync(IdInput input)
|
|
{
|
|
var entity = await GetEntityOrThrowAsync(input.Id);
|
|
entity.IsDeleted = true;
|
|
entity.UpdateTime = DateTime.Now;
|
|
entity.UpdateUserId = CurrentUser.GetId<int>();
|
|
await ServiceChannelRepository.UpdateAsync(entity);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 保存服务渠道配置。
|
|
/// </summary>
|
|
[HttpPost("/channel/service-channel/config/save")]
|
|
public async Task SaveConfigAsync(ServiceChannelSaveInput input)
|
|
{
|
|
var entity = await GetEntityOrThrowAsync(input.Id);
|
|
await ValidateChannelCodeAsync(input.ChannelCode, entity.Id);
|
|
ApplyInput(entity, input);
|
|
entity.UpdateTime = DateTime.Now;
|
|
entity.UpdateUserId = CurrentUser.GetId<int>();
|
|
await ServiceChannelRepository.UpdateAsync(entity);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取服务渠道买价项列表。
|
|
/// </summary>
|
|
[HttpGet("/channel/service-channel/price/list")]
|
|
public async Task<OmsItemsResult<ServiceChannelPriceListOutput>> GetPriceListAsync([FromQuery] long serviceChannelId)
|
|
{
|
|
await GetEntityOrThrowAsync(serviceChannelId);
|
|
return new OmsItemsResult<ServiceChannelPriceListOutput>
|
|
{
|
|
Items = await GetPriceOutputsAsync(serviceChannelId)
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 新增服务渠道买价项。
|
|
/// </summary>
|
|
[HttpPost("/channel/service-channel/price/create")]
|
|
public async Task CreatePriceAsync(ServiceChannelPriceSaveInput input)
|
|
{
|
|
await GetEntityOrThrowAsync(input.ServiceChannelId);
|
|
var now = DateTime.Now;
|
|
var userId = CurrentUser.GetId<int>();
|
|
await ServiceChannelRepository.InsertPriceAsync(
|
|
new ServiceChannelPrice
|
|
{
|
|
ServiceChannelId = input.ServiceChannelId,
|
|
SerialNumber = input.SerialNumber,
|
|
Status = input.Status,
|
|
PriceName = input.PriceName,
|
|
CostItem = input.CostItem,
|
|
CostUnit = input.CostUnit,
|
|
Currency = input.Currency,
|
|
ChargingTime = input.ChargingTime,
|
|
ChargingCondition = input.ChargingCondition,
|
|
IsDeleted = false,
|
|
CreateTime = now,
|
|
CreateUserId = userId
|
|
},
|
|
BuildPriceFactors(input.Factors, now, userId),
|
|
BuildPriceDetails(input.Details, now, userId));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 更新服务渠道买价项。
|
|
/// </summary>
|
|
[HttpPost("/channel/service-channel/price/update")]
|
|
public async Task UpdatePriceAsync(ServiceChannelPriceSaveInput input)
|
|
{
|
|
var price = await GetPriceOrThrowAsync(input.Id);
|
|
if (price.ServiceChannelId != input.ServiceChannelId)
|
|
{
|
|
throw new BusinessException("买价项归属不匹配");
|
|
}
|
|
|
|
price.SerialNumber = input.SerialNumber;
|
|
price.Status = input.Status;
|
|
price.PriceName = input.PriceName;
|
|
price.CostItem = input.CostItem;
|
|
price.CostUnit = input.CostUnit;
|
|
price.Currency = input.Currency;
|
|
price.ChargingTime = input.ChargingTime;
|
|
price.ChargingCondition = input.ChargingCondition;
|
|
price.UpdateTime = DateTime.Now;
|
|
price.UpdateUserId = CurrentUser.GetId<int>();
|
|
await ServiceChannelRepository.UpdatePriceAsync(
|
|
price,
|
|
BuildPriceFactors(input.Factors, DateTime.Now, CurrentUser.GetId<int>()),
|
|
BuildPriceDetails(input.Details, DateTime.Now, CurrentUser.GetId<int>()));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 删除服务渠道买价项。
|
|
/// </summary>
|
|
[HttpPost("/channel/service-channel/price/delete")]
|
|
public async Task DeletePriceAsync(IdInput input)
|
|
{
|
|
await GetPriceOrThrowAsync(input.Id);
|
|
await ServiceChannelRepository.DeletePriceAsync(input.Id);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 切换服务渠道买价项状态。
|
|
/// </summary>
|
|
[HttpPost("/channel/service-channel/price/toggleStatus")]
|
|
public async Task TogglePriceStatusAsync(ToggleStatusInput input)
|
|
{
|
|
await GetPriceOrThrowAsync(input.Id);
|
|
await ServiceChannelRepository.UpdatePriceStatusAsync(input.Id, input.Status);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 批量保存服务渠道买价项。
|
|
/// </summary>
|
|
[HttpPost("/channel/service-channel/price/save")]
|
|
public async Task SavePriceAsync(ServiceChannelPriceSaveAllInput input)
|
|
{
|
|
await GetEntityOrThrowAsync(input.ServiceChannelId);
|
|
var now = DateTime.Now;
|
|
var userId = CurrentUser.GetId<int>();
|
|
var prices = new List<ServiceChannelPrice>();
|
|
var factors = new List<ServiceChannelPriceFactor>();
|
|
var details = new List<ServiceChannelPriceDetail>();
|
|
var tempId = -1L;
|
|
|
|
// 使用临时负数 Id 保持买价项与子表数据在批量替换时的关联关系。
|
|
foreach (var priceInput in input.Prices.OrderBy(x => x.SerialNumber))
|
|
{
|
|
var currentTempId = tempId--;
|
|
prices.Add(new ServiceChannelPrice
|
|
{
|
|
Id = currentTempId,
|
|
ServiceChannelId = input.ServiceChannelId,
|
|
SerialNumber = priceInput.SerialNumber,
|
|
Status = priceInput.Status,
|
|
PriceName = priceInput.PriceName,
|
|
CostItem = priceInput.CostItem,
|
|
CostUnit = priceInput.CostUnit,
|
|
Currency = priceInput.Currency,
|
|
ChargingTime = priceInput.ChargingTime,
|
|
ChargingCondition = priceInput.ChargingCondition,
|
|
IsDeleted = false,
|
|
CreateTime = now,
|
|
CreateUserId = userId
|
|
});
|
|
factors.AddRange(BuildPriceFactors(priceInput.Factors, now, userId, currentTempId));
|
|
details.AddRange(BuildPriceDetails(priceInput.Details, now, userId, currentTempId));
|
|
}
|
|
|
|
await ServiceChannelRepository.ReplacePricesAsync(input.ServiceChannelId, prices, factors, details);
|
|
if (input.Publish)
|
|
{
|
|
await CreatePublishRecordAsync(input.ServiceChannelId, PriceOperatorType, "保存并发布买价");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取服务渠道价格发布记录。
|
|
/// </summary>
|
|
[HttpGet("/channel/service-channel/publish/price/list")]
|
|
public Task<OmsPageResult<ServiceChannelPublishRecordOutput>> GetPricePublishListAsync([FromQuery] ServiceChannelPublishListInput input)
|
|
{
|
|
return GetPublishListAsync(input, PriceOperatorType);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取服务渠道规则发布记录。
|
|
/// </summary>
|
|
[HttpGet("/channel/service-channel/publish/rules/list")]
|
|
public Task<OmsPageResult<ServiceChannelPublishRecordOutput>> GetRulesPublishListAsync([FromQuery] ServiceChannelPublishListInput input)
|
|
{
|
|
return GetPublishListAsync(input, RulesOperatorType);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 发布当前服务渠道配置。
|
|
/// </summary>
|
|
[HttpPost("/channel/service-channel/publish")]
|
|
public async Task PublishAsync(ServiceChannelPublishInput input)
|
|
{
|
|
await CreatePublishRecordAsync(input.ServiceChannelId, NormalizeOperatorType(input.OperatorType), input.Description);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 按发布记录回滚服务渠道配置。
|
|
/// </summary>
|
|
[HttpPost("/channel/service-channel/publish/rollback")]
|
|
public Task RollbackAsync(ServiceChannelRollbackInput input)
|
|
{
|
|
return RollbackCoreAsync(input);
|
|
}
|
|
|
|
private static Expression<Func<ServiceChannel, bool>> BuildListPredicate(ServiceChannelListInput input)
|
|
{
|
|
var keyword = input.Keyword?.Trim();
|
|
return entity =>
|
|
!entity.IsDeleted &&
|
|
(!input.GroupId.HasValue || entity.GroupId == input.GroupId.Value) &&
|
|
(string.IsNullOrWhiteSpace(keyword) || entity.ChannelCode.Contains(keyword) || entity.ChannelName.Contains(keyword)) &&
|
|
(!input.IsActive.HasValue || entity.IsActive == input.IsActive.Value);
|
|
}
|
|
}
|