diff --git a/sql/migrate_user_wecom_kf_url.sql b/sql/migrate_user_wecom_kf_url.sql
new file mode 100644
index 0000000..29d1e8a
--- /dev/null
+++ b/sql/migrate_user_wecom_kf_url.sql
@@ -0,0 +1,20 @@
+-- user 表:企业微信客服接入链接(幂等;列已存在则跳过)
+-- MySQL 5.7+ / 8.0
+
+SET @db := DATABASE();
+
+SET @col := (
+ SELECT COUNT(*)
+ FROM information_schema.COLUMNS
+ WHERE TABLE_SCHEMA = @db
+ AND TABLE_NAME = 'user'
+ AND COLUMN_NAME = 'WecomKfUrl'
+);
+SET @sql := IF(
+ @col = 0,
+ 'ALTER TABLE `user` ADD COLUMN `WecomKfUrl` VARCHAR(512) NULL COMMENT ''企业微信客服接入链接''',
+ 'SELECT ''skip WecomKfUrl'' AS msg'
+);
+PREPARE stmt FROM @sql;
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
diff --git a/src/Oms.Application/Dtos/Customers/CustomerServiceAdvisorOutput.cs b/src/Oms.Application/Dtos/Customers/CustomerServiceAdvisorOutput.cs
index d73be89..752220e 100644
--- a/src/Oms.Application/Dtos/Customers/CustomerServiceAdvisorOutput.cs
+++ b/src/Oms.Application/Dtos/Customers/CustomerServiceAdvisorOutput.cs
@@ -19,4 +19,9 @@ public class CustomerServiceAdvisorOutput
/// 微信二维码(URL 或 Base64)。
///
public string? WechatQrCode { get; set; }
+
+ ///
+ /// 企业微信客服接入链接。
+ ///
+ public string? WecomKfUrl { get; set; }
}
diff --git a/src/Oms.Application/Dtos/Orders/OrderUploadInput.cs b/src/Oms.Application/Dtos/Orders/OrderUploadInput.cs
index ee4028b..fcf70ef 100644
--- a/src/Oms.Application/Dtos/Orders/OrderUploadInput.cs
+++ b/src/Oms.Application/Dtos/Orders/OrderUploadInput.cs
@@ -21,4 +21,9 @@ public class OrderUploadInput
/// 默认发件地址 ID(地址管理中的发件人地址)。
///
public int? SenderAddressId { get; set; }
+
+ ///
+ /// 客户主键(管理端代客下单时必传)。
+ ///
+ public int? CustomerId { get; set; }
}
diff --git a/src/Oms.Application/Dtos/Rbac/OmsUserProfileDtos.cs b/src/Oms.Application/Dtos/Rbac/OmsUserProfileDtos.cs
index 9ea1153..903a8f2 100644
--- a/src/Oms.Application/Dtos/Rbac/OmsUserProfileDtos.cs
+++ b/src/Oms.Application/Dtos/Rbac/OmsUserProfileDtos.cs
@@ -11,6 +11,11 @@ public class UserProfileData
public string? WechatId { get; set; }
public string? WechatQrCode { get; set; }
+
+ ///
+ /// 企业微信客服接入链接(微信外接入)。
+ ///
+ public string? WecomKfUrl { get; set; }
}
public class OmsUserCreateInput : UserCreateDto
@@ -22,6 +27,8 @@ public class OmsUserCreateInput : UserCreateDto
public string? WechatId { get; set; }
public string? WechatQrCode { get; set; }
+
+ public string? WecomKfUrl { get; set; }
}
public class OmsUserUpdateInput : UserUpdateDto
@@ -31,6 +38,8 @@ public class OmsUserUpdateInput : UserUpdateDto
public string? WechatId { get; set; }
public string? WechatQrCode { get; set; }
+
+ public string? WecomKfUrl { get; set; }
}
public class OmsUserDetailDto : UserDto
@@ -42,4 +51,6 @@ public class OmsUserDetailDto : UserDto
public string? WechatId { get; set; }
public string? WechatQrCode { get; set; }
+
+ public string? WecomKfUrl { get; set; }
}
diff --git a/src/Oms.Application/Rbac/CustomerServiceAdvisorResolver.cs b/src/Oms.Application/Rbac/CustomerServiceAdvisorResolver.cs
index 7d11d34..ea7f768 100644
--- a/src/Oms.Application/Rbac/CustomerServiceAdvisorResolver.cs
+++ b/src/Oms.Application/Rbac/CustomerServiceAdvisorResolver.cs
@@ -30,6 +30,7 @@ public class CustomerServiceAdvisorResolver(FakeRbacDbContext dbContext) : IScop
Name = row.Name,
WechatId = row.WechatId,
WechatQrCode = row.WechatQrCode,
+ WecomKfUrl = row.WecomKfUrl,
};
}
@@ -44,7 +45,8 @@ public class CustomerServiceAdvisorResolver(FakeRbacDbContext dbContext) : IScop
SELECT
u.`Name` AS `Name`,
u.`WechatId` AS `WechatId`,
- u.`WechatQrCode` AS `WechatQrCode`
+ u.`WechatQrCode` AS `WechatQrCode`,
+ u.`WecomKfUrl` AS `WecomKfUrl`
FROM `user` u
WHERE u.`IsDeleted` = 0
AND u.`userid` = {0}
@@ -62,7 +64,8 @@ public class CustomerServiceAdvisorResolver(FakeRbacDbContext dbContext) : IScop
SELECT
u.`Name` AS `Name`,
u.`WechatId` AS `WechatId`,
- u.`WechatQrCode` AS `WechatQrCode`
+ u.`WechatQrCode` AS `WechatQrCode`,
+ u.`WecomKfUrl` AS `WecomKfUrl`
FROM `user` u
WHERE u.`IsDeleted` = 0
AND (u.`Name` = {0} OR u.`Account` = {0})
@@ -82,5 +85,7 @@ public class CustomerServiceAdvisorResolver(FakeRbacDbContext dbContext) : IScop
public string? WechatId { get; set; }
public string? WechatQrCode { get; set; }
+
+ public string? WecomKfUrl { get; set; }
}
}
diff --git a/src/Oms.Application/Rbac/OmsUserProfileMapper.cs b/src/Oms.Application/Rbac/OmsUserProfileMapper.cs
index 84d7761..463a194 100644
--- a/src/Oms.Application/Rbac/OmsUserProfileMapper.cs
+++ b/src/Oms.Application/Rbac/OmsUserProfileMapper.cs
@@ -32,6 +32,7 @@ internal static class OmsUserProfileMapper
detail.EmployeeNo = profile.EmployeeNo;
detail.WechatId = profile.WechatId;
detail.WechatQrCode = profile.WechatQrCode;
+ detail.WecomKfUrl = profile.WecomKfUrl;
return detail;
}
}
diff --git a/src/Oms.Application/Rbac/UserProfileRepository.cs b/src/Oms.Application/Rbac/UserProfileRepository.cs
index a90da01..73f75a3 100644
--- a/src/Oms.Application/Rbac/UserProfileRepository.cs
+++ b/src/Oms.Application/Rbac/UserProfileRepository.cs
@@ -20,7 +20,8 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
u.`Phone` AS `Phone`,
u.`EmployeeNo` AS `EmployeeNo`,
u.`WechatId` AS `WechatId`,
- u.`WechatQrCode` AS `WechatQrCode`
+ u.`WechatQrCode` AS `WechatQrCode`,
+ u.`WecomKfUrl` AS `WecomKfUrl`
FROM `user` u
WHERE u.`Id` = {0} AND u.`IsDeleted` = 0
LIMIT 1
@@ -41,6 +42,7 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
EmployeeNo = row.EmployeeNo,
WechatId = row.WechatId,
WechatQrCode = row.WechatQrCode,
+ WecomKfUrl = row.WecomKfUrl,
};
}
@@ -60,7 +62,8 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
u.`Phone` AS `Phone`,
u.`EmployeeNo` AS `EmployeeNo`,
u.`WechatId` AS `WechatId`,
- u.`WechatQrCode` AS `WechatQrCode`
+ u.`WechatQrCode` AS `WechatQrCode`,
+ u.`WecomKfUrl` AS `WecomKfUrl`
FROM `user` u
WHERE u.`Id` IN ({inClause}) AND u.`IsDeleted` = 0
""";
@@ -74,6 +77,7 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
EmployeeNo = x.EmployeeNo,
WechatId = x.WechatId,
WechatQrCode = x.WechatQrCode,
+ WecomKfUrl = x.WecomKfUrl,
});
}
@@ -85,7 +89,8 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
`Phone` = {1},
`EmployeeNo` = {2},
`WechatId` = {3},
- `WechatQrCode` = {4}
+ `WechatQrCode` = {4},
+ `WecomKfUrl` = {5}
WHERE `Id` = {0} AND `IsDeleted` = 0
""";
@@ -98,6 +103,7 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
(object?)NormalizeOptional(profile.EmployeeNo),
(object?)NormalizeOptional(profile.WechatId),
(object?)NormalizeOptional(profile.WechatQrCode),
+ (object?)NormalizeOptional(profile.WecomKfUrl),
],
cancellationToken);
}
@@ -112,7 +118,8 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
SET
`Phone` = {1},
`WechatId` = {2},
- `WechatQrCode` = {3}
+ `WechatQrCode` = {3},
+ `WecomKfUrl` = {4}
WHERE `Id` = {0} AND `IsDeleted` = 0
""";
@@ -123,6 +130,7 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
(object?)NormalizeOptional(profile.Phone),
(object?)NormalizeOptional(profile.WechatId),
(object?)NormalizeOptional(profile.WechatQrCode),
+ (object?)NormalizeOptional(profile.WecomKfUrl),
],
cancellationToken);
}
@@ -208,6 +216,8 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
public string? WechatId { get; set; }
public string? WechatQrCode { get; set; }
+
+ public string? WecomKfUrl { get; set; }
}
private sealed class UserProfileListRow
@@ -221,6 +231,8 @@ public class UserProfileRepository(FakeRbacDbContext dbContext) : IScopedDepende
public string? WechatId { get; set; }
public string? WechatQrCode { get; set; }
+
+ public string? WecomKfUrl { get; set; }
}
private sealed class EmployeeNoRow
diff --git a/src/Oms.Application/Services/Orders/OrderService.Helpers.cs b/src/Oms.Application/Services/Orders/OrderService.Helpers.cs
index 8b5ea91..8b14ed7 100644
--- a/src/Oms.Application/Services/Orders/OrderService.Helpers.cs
+++ b/src/Oms.Application/Services/Orders/OrderService.Helpers.cs
@@ -543,7 +543,7 @@ public partial class OrderService
var template = await OrderTemplateRepository.FirstOrDefaultAsync(x => x.Id == input.TemplateId)
?? throw new BusinessException("模板不存在");
- var effectiveCustomer = await ResolveEffectiveCustomerAsync();
+ var effectiveCustomer = await ResolveEffectiveCustomerAsync(input.CustomerId);
EnsureTemplateAccessible(template, effectiveCustomer.Id);
OrderTemplateImportMapping.EnsureTemplateReadyForImport(template);
diff --git a/src/Oms.Application/Services/Rbac/OmsUserService.cs b/src/Oms.Application/Services/Rbac/OmsUserService.cs
index 106a20e..27f8eb6 100644
--- a/src/Oms.Application/Services/Rbac/OmsUserService.cs
+++ b/src/Oms.Application/Services/Rbac/OmsUserService.cs
@@ -109,6 +109,7 @@ public class OmsUserService(
EmployeeNo = employeeNo,
WechatId = input.WechatId,
WechatQrCode = input.WechatQrCode,
+ WecomKfUrl = input.WecomKfUrl,
},
cancellationToken);
@@ -145,6 +146,7 @@ public class OmsUserService(
Phone = input.Phone,
WechatId = input.WechatId,
WechatQrCode = input.WechatQrCode,
+ WecomKfUrl = input.WecomKfUrl,
},
cancellationToken);