fix: 地址簿管理端可查全部,修复 SqlSugar 条件翻译
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
9a48ec1a63
commit
1cf55b2669
@ -13,6 +13,12 @@ public class CustomerSenderAddressPaginatedInput
|
|||||||
[Newtonsoft.Json.JsonProperty("pageSize")]
|
[Newtonsoft.Json.JsonProperty("pageSize")]
|
||||||
public int PageSize { get; set; } = 30;
|
public int PageSize { get; set; } = 30;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 客户 ID(管理端可选;不传则查全部)。
|
||||||
|
/// </summary>
|
||||||
|
[Newtonsoft.Json.JsonProperty("customerId")]
|
||||||
|
public int? CustomerId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 地址类型:all / sender / return / receiver。
|
/// 地址类型:all / sender / return / receiver。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -31,6 +37,11 @@ public class CustomerSenderAddressPaginatedInput
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CreateCustomerSenderAddressInput
|
public class CreateCustomerSenderAddressInput
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 客户 ID(管理端代操作必传;客户门户可省略)。
|
||||||
|
/// </summary>
|
||||||
|
public int? CustomerId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 地址类型:sender 发件 / return 退件 / receiver 收件。
|
/// 地址类型:sender 发件 / return 退件 / receiver 收件。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -17,26 +17,27 @@ public partial class OrderService
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 客户地址分页列表(发件/退件/收件)。
|
/// 客户地址分页列表(发件/退件/收件)。
|
||||||
|
/// 管理端未传 customerId 时查询全部;客户门户仅查自身。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HttpPost("/order/sender-address/list")]
|
[HttpPost("/order/sender-address/list")]
|
||||||
public async Task<OmsPageResult<CustomerSenderAddressOutput>> GetSenderAddressListAsync(
|
public async Task<OmsPageResult<CustomerSenderAddressOutput>> GetSenderAddressListAsync(
|
||||||
[FromBody] CustomerSenderAddressPaginatedInput input)
|
[FromBody] CustomerSenderAddressPaginatedInput input)
|
||||||
{
|
{
|
||||||
var customer = await OmsSessionHelper.ResolveSessionCustomerAsync(CustomerRepository, CurrentUser);
|
var customerId = await WarehouseCustomerHelper.ResolveListCustomerIdAsync(
|
||||||
|
CustomerRepository,
|
||||||
|
CurrentUser,
|
||||||
|
input.CustomerId);
|
||||||
var pageIndex = OmsDocHelper.NormalizePage(input.Page);
|
var pageIndex = OmsDocHelper.NormalizePage(input.Page);
|
||||||
var pageSize = OmsDocHelper.NormalizePageSize(input.PageSize);
|
var pageSize = OmsDocHelper.NormalizePageSize(input.PageSize);
|
||||||
var predicate = BuildSenderAddressPredicate(customer.Id, input);
|
var predicate = BuildSenderAddressPredicate(customerId, input);
|
||||||
|
|
||||||
var entities = await CustomerSenderAddressRepository.GetPagedListAsync(
|
// 避免 Fake GetPagedListAsync(sorting) 丢失 Where / SqlSugar 错误翻译表达式
|
||||||
|
var (entities, total) = await RepositoryPageHelper.GetPageAsync(
|
||||||
|
CustomerSenderAddressRepository,
|
||||||
predicate,
|
predicate,
|
||||||
pageIndex,
|
pageIndex,
|
||||||
pageSize,
|
pageSize,
|
||||||
new Dictionary<string, bool>
|
q => q.OrderByDescending(x => x.IsDefault).ThenByDescending(x => x.Id));
|
||||||
{
|
|
||||||
[nameof(CustomerSenderAddress.IsDefault)] = false,
|
|
||||||
[nameof(CustomerSenderAddress.Id)] = false
|
|
||||||
});
|
|
||||||
var total = await CustomerSenderAddressRepository.CountAsync(predicate);
|
|
||||||
var countryMap = await LoadCountryCodeMapAsync(entities.Select(x => x.Country).Where(x => x.HasValue).Select(x => x!.Value));
|
var countryMap = await LoadCountryCodeMapAsync(entities.Select(x => x.Country).Where(x => x.HasValue).Select(x => x!.Value));
|
||||||
|
|
||||||
return new OmsPageResult<CustomerSenderAddressOutput>
|
return new OmsPageResult<CustomerSenderAddressOutput>
|
||||||
@ -50,9 +51,11 @@ public partial class OrderService
|
|||||||
/// 客户地址详情。
|
/// 客户地址详情。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HttpGet("/order/sender-address/detail")]
|
[HttpGet("/order/sender-address/detail")]
|
||||||
public async Task<CustomerSenderAddressOutput> GetSenderAddressDetailAsync([FromQuery] int id)
|
public async Task<CustomerSenderAddressOutput> GetSenderAddressDetailAsync(
|
||||||
|
[FromQuery] int id,
|
||||||
|
[FromQuery] int? customerId = null)
|
||||||
{
|
{
|
||||||
var entity = await GetOwnedSenderAddressOrThrowAsync(id);
|
var entity = await GetOwnedSenderAddressOrThrowAsync(id, customerId);
|
||||||
var countryMap = await LoadCountryCodeMapAsync(entity.Country.HasValue ? [entity.Country.Value] : []);
|
var countryMap = await LoadCountryCodeMapAsync(entity.Country.HasValue ? [entity.Country.Value] : []);
|
||||||
return MapSenderAddressOutput(entity, countryMap);
|
return MapSenderAddressOutput(entity, countryMap);
|
||||||
}
|
}
|
||||||
@ -63,19 +66,22 @@ public partial class OrderService
|
|||||||
[HttpPost("/order/sender-address/create")]
|
[HttpPost("/order/sender-address/create")]
|
||||||
public async Task<object> CreateSenderAddressAsync([FromBody] CreateCustomerSenderAddressInput input)
|
public async Task<object> CreateSenderAddressAsync([FromBody] CreateCustomerSenderAddressInput input)
|
||||||
{
|
{
|
||||||
var customer = await OmsSessionHelper.ResolveSessionCustomerAsync(CustomerRepository, CurrentUser);
|
var customerId = await WarehouseCustomerHelper.ResolveRequiredCustomerIdAsync(
|
||||||
|
CustomerRepository,
|
||||||
|
CurrentUser,
|
||||||
|
input.CustomerId);
|
||||||
var addressType = NormalizeAddressTypeOrThrow(input.AddressType);
|
var addressType = NormalizeAddressTypeOrThrow(input.AddressType);
|
||||||
ValidateSenderAddressInput(input);
|
ValidateSenderAddressInput(input);
|
||||||
var countryId = await ResolveSenderCountryIdAsync(input.CountryCode);
|
var countryId = await ResolveSenderCountryIdAsync(input.CountryCode);
|
||||||
|
|
||||||
if (input.IsDefault)
|
if (input.IsDefault)
|
||||||
{
|
{
|
||||||
await CustomerSenderAddressRepository.ClearDefaultAsync(customer.Id, addressType);
|
await CustomerSenderAddressRepository.ClearDefaultAsync(customerId, addressType);
|
||||||
}
|
}
|
||||||
|
|
||||||
var entity = new CustomerSenderAddress
|
var entity = new CustomerSenderAddress
|
||||||
{
|
{
|
||||||
CustomerId = customer.Id,
|
CustomerId = customerId,
|
||||||
AddressType = addressType,
|
AddressType = addressType,
|
||||||
AddressName = TrimOrNull(input.AddressName),
|
AddressName = TrimOrNull(input.AddressName),
|
||||||
SenderName = input.SenderName.Trim(),
|
SenderName = input.SenderName.Trim(),
|
||||||
@ -104,7 +110,7 @@ public partial class OrderService
|
|||||||
[HttpPost("/order/sender-address/update")]
|
[HttpPost("/order/sender-address/update")]
|
||||||
public async Task UpdateSenderAddressAsync([FromBody] UpdateCustomerSenderAddressInput input)
|
public async Task UpdateSenderAddressAsync([FromBody] UpdateCustomerSenderAddressInput input)
|
||||||
{
|
{
|
||||||
var entity = await GetOwnedSenderAddressOrThrowAsync(input.Id);
|
var entity = await GetOwnedSenderAddressOrThrowAsync(input.Id, input.CustomerId);
|
||||||
var addressType = NormalizeAddressTypeOrThrow(input.AddressType);
|
var addressType = NormalizeAddressTypeOrThrow(input.AddressType);
|
||||||
ValidateSenderAddressInput(input);
|
ValidateSenderAddressInput(input);
|
||||||
var countryId = await ResolveSenderCountryIdAsync(input.CountryCode);
|
var countryId = await ResolveSenderCountryIdAsync(input.CountryCode);
|
||||||
@ -140,7 +146,7 @@ public partial class OrderService
|
|||||||
[HttpPost("/order/sender-address/delete")]
|
[HttpPost("/order/sender-address/delete")]
|
||||||
public async Task DeleteSenderAddressAsync([FromBody] IdInput input)
|
public async Task DeleteSenderAddressAsync([FromBody] IdInput input)
|
||||||
{
|
{
|
||||||
var entity = await GetOwnedSenderAddressOrThrowAsync(input.Id);
|
var entity = await GetOwnedSenderAddressOrThrowAsync(input.Id, null);
|
||||||
await CustomerSenderAddressRepository.DeleteAsync(entity);
|
await CustomerSenderAddressRepository.DeleteAsync(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +156,7 @@ public partial class OrderService
|
|||||||
[HttpPost("/order/sender-address/set-default")]
|
[HttpPost("/order/sender-address/set-default")]
|
||||||
public async Task SetDefaultSenderAddressAsync([FromBody] IdInput input)
|
public async Task SetDefaultSenderAddressAsync([FromBody] IdInput input)
|
||||||
{
|
{
|
||||||
var entity = await GetOwnedSenderAddressOrThrowAsync(input.Id);
|
var entity = await GetOwnedSenderAddressOrThrowAsync(input.Id, null);
|
||||||
var addressType = string.IsNullOrWhiteSpace(entity.AddressType)
|
var addressType = string.IsNullOrWhiteSpace(entity.AddressType)
|
||||||
? CustomerAddressTypeCodes.Sender
|
? CustomerAddressTypeCodes.Sender
|
||||||
: entity.AddressType;
|
: entity.AddressType;
|
||||||
@ -159,10 +165,17 @@ public partial class OrderService
|
|||||||
await CustomerSenderAddressRepository.UpdateAsync(entity);
|
await CustomerSenderAddressRepository.UpdateAsync(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<CustomerSenderAddress> GetOwnedSenderAddressOrThrowAsync(int id)
|
private async Task<CustomerSenderAddress> GetOwnedSenderAddressOrThrowAsync(int id, int? requestedCustomerId)
|
||||||
{
|
{
|
||||||
var customer = await OmsSessionHelper.ResolveSessionCustomerAsync(CustomerRepository, CurrentUser);
|
var customerId = await WarehouseCustomerHelper.ResolveListCustomerIdAsync(
|
||||||
var entity = await CustomerSenderAddressRepository.GetOwnedAsync(id, customer.Id);
|
CustomerRepository,
|
||||||
|
CurrentUser,
|
||||||
|
requestedCustomerId);
|
||||||
|
var (hasCustomerFilter, customerIdValue) = WarehouseCustomerHelper.ToCustomerFilter(customerId);
|
||||||
|
|
||||||
|
var entity = hasCustomerFilter
|
||||||
|
? await CustomerSenderAddressRepository.GetOwnedAsync(id, customerIdValue)
|
||||||
|
: await CustomerSenderAddressRepository.FirstOrDefaultAsync(x => x.Id == id);
|
||||||
if (entity == null)
|
if (entity == null)
|
||||||
{
|
{
|
||||||
throw new BusinessException("地址不存在");
|
throw new BusinessException("地址不存在");
|
||||||
@ -204,24 +217,28 @@ public partial class OrderService
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Expression<Func<CustomerSenderAddress, bool>> BuildSenderAddressPredicate(
|
private static Expression<Func<CustomerSenderAddress, bool>> BuildSenderAddressPredicate(
|
||||||
int customerId,
|
int? customerId,
|
||||||
CustomerSenderAddressPaginatedInput input)
|
CustomerSenderAddressPaginatedInput input)
|
||||||
{
|
{
|
||||||
|
var (hasCustomerFilter, customerIdValue) = WarehouseCustomerHelper.ToCustomerFilter(customerId);
|
||||||
var keyword = input.Keyword?.Trim();
|
var keyword = input.Keyword?.Trim();
|
||||||
|
var hasKeyword = !string.IsNullOrWhiteSpace(keyword);
|
||||||
var onlyDefault = input.OnlyDefault;
|
var onlyDefault = input.OnlyDefault;
|
||||||
var addressType = input.AddressType?.Trim();
|
var addressType = input.AddressType?.Trim();
|
||||||
var filterByType = !string.IsNullOrWhiteSpace(addressType)
|
var filterByType = !string.IsNullOrWhiteSpace(addressType)
|
||||||
&& !string.Equals(addressType, "all", StringComparison.OrdinalIgnoreCase);
|
&& !string.Equals(addressType, "all", StringComparison.OrdinalIgnoreCase);
|
||||||
|
var addressTypeValue = filterByType ? addressType! : string.Empty;
|
||||||
|
|
||||||
|
// 布尔/关键字先算成局部变量;避免 SqlSugar 翻译 IsNullOrWhiteSpace / ?? / HasValue 生成非法 SQL
|
||||||
return x =>
|
return x =>
|
||||||
x.CustomerId == customerId
|
(!hasCustomerFilter || x.CustomerId == customerIdValue)
|
||||||
&& (!filterByType || x.AddressType == addressType)
|
&& (!filterByType || x.AddressType == addressTypeValue)
|
||||||
&& (!onlyDefault || x.IsDefault == 1)
|
&& (!onlyDefault || x.IsDefault == 1)
|
||||||
&& (string.IsNullOrWhiteSpace(keyword)
|
&& (!hasKeyword
|
||||||
|| (x.AddressName ?? string.Empty).Contains(keyword)
|
|| (x.AddressName != null && x.AddressName.Contains(keyword!))
|
||||||
|| x.SenderName.Contains(keyword)
|
|| x.SenderName.Contains(keyword!)
|
||||||
|| (x.Phone ?? string.Empty).Contains(keyword)
|
|| (x.Phone != null && x.Phone.Contains(keyword!))
|
||||||
|| x.StreetAddress1.Contains(keyword));
|
|| x.StreetAddress1.Contains(keyword!));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Dictionary<int, string>> LoadCountryCodeMapAsync(IEnumerable<int> countryIds)
|
private async Task<Dictionary<int, string>> LoadCountryCodeMapAsync(IEnumerable<int> countryIds)
|
||||||
|
|||||||
@ -19,11 +19,13 @@ public class CustomerSenderAddressRepository : OmsSqlSugarRepository<CustomerSen
|
|||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var type = addressType.Trim();
|
var type = addressType.Trim();
|
||||||
|
var hasExcludeId = excludeId.HasValue;
|
||||||
|
var excludeIdValue = excludeId.GetValueOrDefault();
|
||||||
var list = await GetListAsync(
|
var list = await GetListAsync(
|
||||||
x => x.CustomerId == customerId
|
x => x.CustomerId == customerId
|
||||||
&& x.AddressType == type
|
&& x.AddressType == type
|
||||||
&& x.IsDefault == 1
|
&& x.IsDefault == 1
|
||||||
&& (!excludeId.HasValue || x.Id != excludeId.Value),
|
&& (!hasExcludeId || x.Id != excludeIdValue),
|
||||||
cancellationToken: cancellationToken);
|
cancellationToken: cancellationToken);
|
||||||
if (list.Count == 0)
|
if (list.Count == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user