fix(pending-actions): support accountSequence for user lookup

Allow admin to create pending actions using accountSequence (e.g.,
D25122700022) instead of requiring numeric userId.

- Add findUserByIdOrSequence helper method
- Update createAction to use helper
- Update batchCreateActions to use helper
- Update queryActions to support accountSequence filter

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-01-02 20:39:54 -08:00
parent 47a7e4a4da
commit 789d921fd7
1 changed files with 42 additions and 17 deletions

View File

@ -103,6 +103,7 @@ export class PendingActionService {
/**
* ()
* userId () accountSequence ( D25122700022)
*/
async createAction(
dto: CreatePendingActionDto,
@ -110,11 +111,8 @@ export class PendingActionService {
): Promise<PendingActionResponseDto> {
this.logger.log(`[PendingAction] Creating action for user: ${dto.userId}, code: ${dto.actionCode}`);
// 验证用户是否存在
const user = await this.prisma.userAccount.findUnique({
where: { userId: BigInt(dto.userId) },
select: { userId: true },
});
// 查找用户:支持 userId (纯数字) 或 accountSequence (如 D25122700022)
const user = await this.findUserByIdOrSequence(dto.userId);
if (!user) {
throw new ApplicationError('用户不存在');
@ -122,7 +120,7 @@ export class PendingActionService {
const action = await this.prisma.userPendingAction.create({
data: {
userId: BigInt(dto.userId),
userId: user.userId,
actionCode: dto.actionCode,
actionParams: dto.actionParams ?? undefined,
priority: dto.priority ?? 0,
@ -138,6 +136,7 @@ export class PendingActionService {
/**
* ()
* userId () accountSequence ( D25122700022)
*/
async batchCreateActions(
dto: BatchCreatePendingActionDto,
@ -148,22 +147,19 @@ export class PendingActionService {
let successCount = 0;
const failedUserIds: string[] = [];
for (const userId of dto.userIds) {
for (const userIdOrSequence of dto.userIds) {
try {
// 验证用户是否存在
const user = await this.prisma.userAccount.findUnique({
where: { userId: BigInt(userId) },
select: { userId: true },
});
// 查找用户:支持 userId 或 accountSequence
const user = await this.findUserByIdOrSequence(userIdOrSequence);
if (!user) {
failedUserIds.push(userId);
failedUserIds.push(userIdOrSequence);
continue;
}
await this.prisma.userPendingAction.create({
data: {
userId: BigInt(userId),
userId: user.userId,
actionCode: dto.actionCode,
actionParams: dto.actionParams ?? undefined,
priority: dto.priority ?? 0,
@ -174,8 +170,8 @@ export class PendingActionService {
successCount++;
} catch (error) {
this.logger.warn(`[PendingAction] Failed to create action for user: ${userId}, error: ${error.message}`);
failedUserIds.push(userId);
this.logger.warn(`[PendingAction] Failed to create action for user: ${userIdOrSequence}, error: ${error.message}`);
failedUserIds.push(userIdOrSequence);
}
}
@ -190,6 +186,7 @@ export class PendingActionService {
/**
* ()
* userId () accountSequence ( D25122700022)
*/
async queryActions(dto: QueryPendingActionsDto): Promise<PendingActionListResponseDto> {
const page = dto.page ?? 1;
@ -199,7 +196,14 @@ export class PendingActionService {
const where: any = {};
if (dto.userId) {
where.userId = BigInt(dto.userId);
// 支持 userId 或 accountSequence 筛选
const user = await this.findUserByIdOrSequence(dto.userId);
if (user) {
where.userId = user.userId;
} else {
// 用户不存在,返回空结果
return { items: [], total: 0, page, limit };
}
}
if (dto.actionCode) {
where.actionCode = dto.actionCode;
@ -342,6 +346,27 @@ export class PendingActionService {
// ==================== Helper Methods ====================
/**
* userId () accountSequence ( D25122700022)
*/
private async findUserByIdOrSequence(
userIdOrSequence: string,
): Promise<{ userId: bigint } | null> {
// 检查是否是纯数字 (userId)
if (/^\d+$/.test(userIdOrSequence)) {
return this.prisma.userAccount.findUnique({
where: { userId: BigInt(userIdOrSequence) },
select: { userId: true },
});
}
// 否则尝试通过 accountSequence 查找
return this.prisma.userAccount.findUnique({
where: { accountSequence: userIdOrSequence },
select: { userId: true },
});
}
private toResponseDto(action: any): PendingActionResponseDto {
return {
id: action.id.toString(),