commit
7d458cbecd
@ -398,11 +398,13 @@ public partial class OrderService
|
|||||||
}
|
}
|
||||||
|
|
||||||
var currencyDict = await DictRepository.GetListAsync(x => x.DictType == "currency");
|
var currencyDict = await DictRepository.GetListAsync(x => x.DictType == "currency");
|
||||||
var firstCurrency = currencyDict.OrderBy(x => x.DictSort).FirstOrDefault();
|
var defaultCurrency = currencyDict.FirstOrDefault(x =>
|
||||||
if (firstCurrency != null)
|
string.Equals(x.DictCode, "USD", StringComparison.OrdinalIgnoreCase))
|
||||||
|
?? currencyDict.OrderBy(x => x.DictSort).FirstOrDefault();
|
||||||
|
if (defaultCurrency != null)
|
||||||
{
|
{
|
||||||
overrides["declaredCurrency"] = firstCurrency.DictCode;
|
overrides["declaredCurrency"] = defaultCurrency.DictCode;
|
||||||
overrides["codCurrency"] = firstCurrency.DictCode;
|
overrides["codCurrency"] = defaultCurrency.DictCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
var exportDict = await DictRepository.GetListAsync(x => x.DictType == "export_customs_mode");
|
var exportDict = await DictRepository.GetListAsync(x => x.DictType == "export_customs_mode");
|
||||||
|
|||||||
@ -81,8 +81,6 @@ public static class OrderTemplateFieldRegistry
|
|||||||
Add("isCod", "是否COD", false, "boolean", example: "false");
|
Add("isCod", "是否COD", false, "boolean", example: "false");
|
||||||
Add("codCurrency", "COD币种", false, "select", "currency", example: "USD");
|
Add("codCurrency", "COD币种", false, "select", "currency", example: "USD");
|
||||||
Add("codSum", "COD金额", false, "number", example: "0");
|
Add("codSum", "COD金额", false, "number", example: "0");
|
||||||
Add("declaredCurrency", "申报币种", true, "select", "currency", example: "USD");
|
|
||||||
Add("declaredSum", "申报金额", false, "number");
|
|
||||||
Add("quantity", "包裹数量", true, "number", example: "1");
|
Add("quantity", "包裹数量", true, "number", example: "1");
|
||||||
|
|
||||||
Add("receiver.recipientsName", "收件人名称", true, group: "receiver", example: "Demo Receiver");
|
Add("receiver.recipientsName", "收件人名称", true, group: "receiver", example: "Demo Receiver");
|
||||||
@ -119,15 +117,17 @@ public static class OrderTemplateFieldRegistry
|
|||||||
Add("sender.streetAddress3", "发件地址3", false, group: "sender");
|
Add("sender.streetAddress3", "发件地址3", false, group: "sender");
|
||||||
Add("sender.houseNumber", "发件门牌号", false, group: "sender", example: "88");
|
Add("sender.houseNumber", "发件门牌号", false, group: "sender", example: "88");
|
||||||
|
|
||||||
|
Add("declaredCurrency", "申报币种", true, "select", "currency", "declaration", "USD");
|
||||||
|
Add("declaredSum", "申报总金额", false, "number", group: "declaration", example: "可选,不填自动汇总");
|
||||||
Add("items[0].cnName", "申报品名(中)", false, group: "declaration", example: "手机壳");
|
Add("items[0].cnName", "申报品名(中)", false, group: "declaration", example: "手机壳");
|
||||||
Add("items[0].enName", "申报品名(英)", true, group: "declaration", example: "Phone Case");
|
Add("items[0].enName", "申报品名(英)", true, group: "declaration", example: "Phone Case");
|
||||||
Add("items[0].sku", "SKU", false, group: "declaration", example: "SKU001");
|
Add("items[0].sku", "SKU", false, group: "declaration", example: "SKU001");
|
||||||
Add("items[0].unit", "单位", false, group: "declaration", example: "pcs");
|
Add("items[0].unit", "单位", false, group: "declaration", example: "pcs");
|
||||||
Add("items[0].unitPrice", "单价", true, "number", group: "declaration", example: "12.5");
|
Add("items[0].unitPrice", "单价(元)", true, "number", group: "declaration", example: "12.5");
|
||||||
Add("items[0].unitWeight", "单重", true, "number", group: "declaration", example: "0.3");
|
Add("items[0].unitWeight", "单重(kg)", true, "number", group: "declaration", example: "0.3");
|
||||||
Add("items[0].quantity", "申报数量", true, "number", group: "declaration", example: "1");
|
Add("items[0].quantity", "申报数量", true, "number", group: "declaration", example: "1");
|
||||||
Add("items[0].amount", "总金额", false, "number", group: "declaration", example: "12.5");
|
Add("items[0].amount", "总金额(元)", false, "number", group: "declaration", example: "自动计算=单价×数量");
|
||||||
Add("items[0].weight", "总重量", false, "number", group: "declaration", example: "0.3");
|
Add("items[0].weight", "总重量(kg)", false, "number", group: "declaration", example: "自动计算=单重×数量");
|
||||||
Add("items[0].imHsCode", "进口HsCode", false, group: "declaration");
|
Add("items[0].imHsCode", "进口HsCode", false, group: "declaration");
|
||||||
Add("items[0].exHsCode", "出口HsCode", false, group: "declaration");
|
Add("items[0].exHsCode", "出口HsCode", false, group: "declaration");
|
||||||
Add("items[0].skuImage", "商品图片URL", false, group: "declaration");
|
Add("items[0].skuImage", "商品图片URL", false, group: "declaration");
|
||||||
|
|||||||
@ -31,6 +31,8 @@ public static class OrderTemplateHeaderMatcher
|
|||||||
["实重kg"] = "actualWeight",
|
["实重kg"] = "actualWeight",
|
||||||
["实重"] = "actualWeight",
|
["实重"] = "actualWeight",
|
||||||
["申报币种"] = "declaredCurrency",
|
["申报币种"] = "declaredCurrency",
|
||||||
|
["申报金额"] = "declaredSum",
|
||||||
|
["申报总金额"] = "declaredSum",
|
||||||
["包裹数量"] = "quantity",
|
["包裹数量"] = "quantity",
|
||||||
["收件人名称"] = "receiver.recipientsName",
|
["收件人名称"] = "receiver.recipientsName",
|
||||||
["收件姓名"] = "receiver.recipientsName",
|
["收件姓名"] = "receiver.recipientsName",
|
||||||
@ -44,8 +46,14 @@ public static class OrderTemplateHeaderMatcher
|
|||||||
["品名英"] = "items[0].enName",
|
["品名英"] = "items[0].enName",
|
||||||
["申报品名中"] = "items[0].cnName",
|
["申报品名中"] = "items[0].cnName",
|
||||||
["单价"] = "items[0].unitPrice",
|
["单价"] = "items[0].unitPrice",
|
||||||
|
["单价元"] = "items[0].unitPrice",
|
||||||
["单重"] = "items[0].unitWeight",
|
["单重"] = "items[0].unitWeight",
|
||||||
|
["单重kg"] = "items[0].unitWeight",
|
||||||
["申报数量"] = "items[0].quantity",
|
["申报数量"] = "items[0].quantity",
|
||||||
|
["总金额"] = "items[0].amount",
|
||||||
|
["总金额元"] = "items[0].amount",
|
||||||
|
["总重量"] = "items[0].weight",
|
||||||
|
["总重量kg"] = "items[0].weight",
|
||||||
};
|
};
|
||||||
|
|
||||||
public static string? MatchStandardFieldKey(string? sourceHeader, string? templateKey)
|
public static string? MatchStandardFieldKey(string? sourceHeader, string? templateKey)
|
||||||
|
|||||||
@ -74,9 +74,51 @@ public static class OrderTemplateRowMapper
|
|||||||
SetFieldValue(input, fieldKey, coerced);
|
SetFieldValue(input, fieldKey, coerced);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ApplyDerivedDeclarationFields(input);
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ApplyDerivedDeclarationFields(OrderParcelCreateInput input)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(input.DeclaredCurrency))
|
||||||
|
{
|
||||||
|
input.DeclaredCurrency = "USD";
|
||||||
|
}
|
||||||
|
|
||||||
|
decimal declaredTotal = 0;
|
||||||
|
var hasDeclaredTotal = false;
|
||||||
|
|
||||||
|
foreach (var item in input.Items)
|
||||||
|
{
|
||||||
|
if (!item.Amount.HasValue && item.UnitPrice.HasValue && item.Quantity.HasValue)
|
||||||
|
{
|
||||||
|
item.Amount = Math.Round(
|
||||||
|
item.UnitPrice.Value * item.Quantity.Value,
|
||||||
|
4,
|
||||||
|
MidpointRounding.AwayFromZero);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!item.Weight.HasValue && item.UnitWeight.HasValue && item.Quantity.HasValue)
|
||||||
|
{
|
||||||
|
item.Weight = Math.Round(
|
||||||
|
item.UnitWeight.Value * item.Quantity.Value,
|
||||||
|
4,
|
||||||
|
MidpointRounding.AwayFromZero);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.Amount.HasValue)
|
||||||
|
{
|
||||||
|
declaredTotal += item.Amount.Value;
|
||||||
|
hasDeclaredTotal = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!input.DeclaredSum.HasValue && hasDeclaredTotal)
|
||||||
|
{
|
||||||
|
input.DeclaredSum = declaredTotal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static bool TryGetMappedValue(
|
private static bool TryGetMappedValue(
|
||||||
IReadOnlyDictionary<string, object> sourceValues,
|
IReadOnlyDictionary<string, object> sourceValues,
|
||||||
string sourceColumn,
|
string sourceColumn,
|
||||||
|
|||||||
@ -77,9 +77,10 @@ public static class OmsRbacRegistrationGuard
|
|||||||
string account,
|
string account,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// 唯一索引不按 IsDeleted 区分,软删除账号仍会触发 Duplicate entry。
|
||||||
var hit = await rbacDbContext.Database
|
var hit = await rbacDbContext.Database
|
||||||
.SqlQuery<int?>(
|
.SqlQuery<int?>(
|
||||||
$"SELECT 1 AS Value FROM `user` WHERE `IsDeleted` = 0 AND `Account` = {account} LIMIT 1")
|
$"SELECT 1 AS Value FROM `user` WHERE `Account` = {account} LIMIT 1")
|
||||||
.FirstOrDefaultAsync(cancellationToken);
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
return hit.HasValue;
|
return hit.HasValue;
|
||||||
}
|
}
|
||||||
@ -91,7 +92,7 @@ public static class OmsRbacRegistrationGuard
|
|||||||
{
|
{
|
||||||
var hit = await rbacDbContext.Database
|
var hit = await rbacDbContext.Database
|
||||||
.SqlQuery<int?>(
|
.SqlQuery<int?>(
|
||||||
$"SELECT 1 AS Value FROM `user` WHERE `IsDeleted` = 0 AND `Email` = {email} LIMIT 1")
|
$"SELECT 1 AS Value FROM `user` WHERE `Email` = {email} LIMIT 1")
|
||||||
.FirstOrDefaultAsync(cancellationToken);
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
return hit.HasValue;
|
return hit.HasValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,18 +100,19 @@ public class WeChatCustomerService(
|
|||||||
await OmsRbacRegistrationGuard.EnsureLoginIdentityAvailableAsync(rbacDbContext, phone, email, cancellationToken);
|
await OmsRbacRegistrationGuard.EnsureLoginIdentityAvailableAsync(rbacDbContext, phone, email, cancellationToken);
|
||||||
|
|
||||||
var customerRoleId = await GetCustomerRoleIdOrThrowAsync(cancellationToken);
|
var customerRoleId = await GetCustomerRoleIdOrThrowAsync(cancellationToken);
|
||||||
var user = await userService.CreateAsync(new UserCreateDto
|
UserDto? user = null;
|
||||||
{
|
|
||||||
Name = customerName,
|
|
||||||
Account = phone,
|
|
||||||
Password = password,
|
|
||||||
Email = email,
|
|
||||||
Avatar = NormalizeOptional(input.Wechat.Avatar),
|
|
||||||
RoleIds = []
|
|
||||||
});
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
user = await userService.CreateAsync(new UserCreateDto
|
||||||
|
{
|
||||||
|
Name = customerName,
|
||||||
|
Account = phone,
|
||||||
|
Password = password,
|
||||||
|
Email = email,
|
||||||
|
Avatar = NormalizeOptional(input.Wechat.Avatar),
|
||||||
|
RoleIds = []
|
||||||
|
});
|
||||||
|
|
||||||
await userService.AssignRolesAsync(user.Id, [customerRoleId]);
|
await userService.AssignRolesAsync(user.Id, [customerRoleId]);
|
||||||
var userId = await GetRbacUserMapIdOrThrowAsync(user.Id, cancellationToken);
|
var userId = await GetRbacUserMapIdOrThrowAsync(user.Id, cancellationToken);
|
||||||
var entity = new Customer
|
var entity = new Customer
|
||||||
@ -131,7 +132,11 @@ public class WeChatCustomerService(
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await TryRollbackRbacUserAsync(user.Id);
|
if (user != null)
|
||||||
|
{
|
||||||
|
await TryRollbackRbacUserAsync(user.Id);
|
||||||
|
}
|
||||||
|
|
||||||
throw ex is BusinessException ? ex : OmsRbacRegistrationGuard.ToSaveBusinessException(ex);
|
throw ex is BusinessException ? ex : OmsRbacRegistrationGuard.ToSaveBusinessException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user