fix(reward): 修复调用 authorization-service 时传递 userId 而非 accountSequence 的问题

- IAuthorizationServiceClient 接口参数类型从 userId: bigint 改为 accountSequence: string
- authorization-service.client.ts 调用时使用正确的 accountSequence 格式
- calculateCommunityRight/calculateProvinceTeamRight/calculateCityTeamRight 方法增加 sourceAccountSequence 参数

此修复确保 reward-service 调用 authorization-service 时传递正确的用户标识格式(如 D25121400006),
而不是数字形式的 userId(如 7),使 authorization-service 能正确查找社区授权记录。

🤖 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 2025-12-14 06:48:58 -08:00
parent c9f944355c
commit c7d54da49f
2 changed files with 47 additions and 43 deletions

View File

@ -30,13 +30,13 @@ export interface AreaRewardDistribution {
}
export interface IAuthorizationServiceClient {
findNearestAuthorizedProvince(userId: bigint, provinceCode: string): Promise<bigint | null>;
findNearestAuthorizedCity(userId: bigint, cityCode: string): Promise<bigint | null>;
findNearestCommunity(userId: bigint): Promise<bigint | null>;
getCommunityRewardDistribution(userId: bigint, treeCount: number): Promise<RewardDistribution>;
getProvinceTeamRewardDistribution(userId: bigint, provinceCode: string, treeCount: number): Promise<RewardDistribution>;
findNearestAuthorizedProvince(accountSequence: string, provinceCode: string): Promise<string | null>;
findNearestAuthorizedCity(accountSequence: string, cityCode: string): Promise<string | null>;
findNearestCommunity(accountSequence: string): Promise<string | null>;
getCommunityRewardDistribution(accountSequence: string, treeCount: number): Promise<RewardDistribution>;
getProvinceTeamRewardDistribution(accountSequence: string, provinceCode: string, treeCount: number): Promise<RewardDistribution>;
getProvinceAreaRewardDistribution(provinceCode: string, treeCount: number): Promise<AreaRewardDistribution>;
getCityTeamRewardDistribution(userId: bigint, cityCode: string, treeCount: number): Promise<RewardDistribution>;
getCityTeamRewardDistribution(accountSequence: string, cityCode: string, treeCount: number): Promise<RewardDistribution>;
getCityAreaRewardDistribution(cityCode: string, treeCount: number): Promise<AreaRewardDistribution>;
}
@ -145,6 +145,7 @@ export class RewardCalculationService {
const provinceTeamRewards = await this.calculateProvinceTeamRight(
params.sourceOrderNo,
params.sourceUserId,
params.sourceAccountSequence!,
params.provinceCode,
params.treeCount,
);
@ -163,6 +164,7 @@ export class RewardCalculationService {
const cityTeamRewards = await this.calculateCityTeamRight(
params.sourceOrderNo,
params.sourceUserId,
params.sourceAccountSequence!,
params.cityCode,
params.treeCount,
);
@ -181,6 +183,7 @@ export class RewardCalculationService {
const communityRewards = await this.calculateCommunityRight(
params.sourceOrderNo,
params.sourceUserId,
params.sourceAccountSequence!,
params.treeCount,
);
rewards.push(...communityRewards);
@ -393,18 +396,19 @@ export class RewardCalculationService {
private async calculateProvinceTeamRight(
sourceOrderNo: string,
sourceUserId: bigint,
sourceAccountSequence: string,
provinceCode: string,
treeCount: number,
): Promise<RewardLedgerEntry[]> {
this.logger.debug(
`[calculateProvinceTeamRight] userId=${sourceUserId}, province=${provinceCode}, treeCount=${treeCount}`,
`[calculateProvinceTeamRight] accountSequence=${sourceAccountSequence}, province=${provinceCode}, treeCount=${treeCount}`,
);
const { usdt, hashpowerPercent } = RIGHT_AMOUNTS[RightType.PROVINCE_TEAM_RIGHT];
// 调用 authorization-service 获取省团队权益分配方案
const distribution = await this.authorizationService.getProvinceTeamRewardDistribution(
sourceUserId,
sourceAccountSequence,
provinceCode,
treeCount,
);
@ -504,18 +508,19 @@ export class RewardCalculationService {
private async calculateCityTeamRight(
sourceOrderNo: string,
sourceUserId: bigint,
sourceAccountSequence: string,
cityCode: string,
treeCount: number,
): Promise<RewardLedgerEntry[]> {
this.logger.debug(
`[calculateCityTeamRight] userId=${sourceUserId}, city=${cityCode}, treeCount=${treeCount}`,
`[calculateCityTeamRight] accountSequence=${sourceAccountSequence}, city=${cityCode}, treeCount=${treeCount}`,
);
const { usdt, hashpowerPercent } = RIGHT_AMOUNTS[RightType.CITY_TEAM_RIGHT];
// 调用 authorization-service 获取市团队权益分配方案
const distribution = await this.authorizationService.getCityTeamRewardDistribution(
sourceUserId,
sourceAccountSequence,
cityCode,
treeCount,
);
@ -617,17 +622,18 @@ export class RewardCalculationService {
private async calculateCommunityRight(
sourceOrderNo: string,
sourceUserId: bigint,
sourceAccountSequence: string,
treeCount: number,
): Promise<RewardLedgerEntry[]> {
this.logger.debug(
`[calculateCommunityRight] userId=${sourceUserId}, treeCount=${treeCount}`,
`[calculateCommunityRight] accountSequence=${sourceAccountSequence}, treeCount=${treeCount}`,
);
const { usdt, hashpowerPercent } = RIGHT_AMOUNTS[RightType.COMMUNITY_RIGHT];
// 调用 authorization-service 获取社区权益分配方案
const distribution = await this.authorizationService.getCommunityRewardDistribution(
sourceUserId,
sourceAccountSequence,
treeCount,
);

View File

@ -39,71 +39,69 @@ export class AuthorizationServiceClient implements IAuthorizationServiceClient {
this.baseUrl = this.configService.get<string>('AUTHORIZATION_SERVICE_URL', 'http://localhost:3006');
}
async findNearestAuthorizedProvince(userId: bigint, provinceCode: string): Promise<bigint | null> {
async findNearestAuthorizedProvince(accountSequence: string, provinceCode: string): Promise<string | null> {
try {
const response = await fetch(
`${this.baseUrl}/api/v1/authorization/nearest-province?accountSequence=${userId}&provinceCode=${provinceCode}`,
`${this.baseUrl}/api/v1/authorization/nearest-province?accountSequence=${accountSequence}&provinceCode=${provinceCode}`,
);
if (!response.ok) {
this.logger.warn(`No authorized province found for user ${userId}, province ${provinceCode}`);
this.logger.warn(`No authorized province found for accountSequence ${accountSequence}, province ${provinceCode}`);
return null;
}
// authorization-service 返回格式: { success, data: { accountSequence }, timestamp }
const result: AuthorizationServiceResponse<NearestAuthorizationResult> = await response.json();
const accountSeq = result.data?.accountSequence;
return accountSeq ? BigInt(accountSeq) : null;
return result.data?.accountSequence || null;
} catch (error) {
this.logger.error(`Error finding nearest authorized province:`, error);
return null;
}
}
async findNearestAuthorizedCity(userId: bigint, cityCode: string): Promise<bigint | null> {
async findNearestAuthorizedCity(accountSequence: string, cityCode: string): Promise<string | null> {
try {
const response = await fetch(
`${this.baseUrl}/api/v1/authorization/nearest-city?accountSequence=${userId}&cityCode=${cityCode}`,
`${this.baseUrl}/api/v1/authorization/nearest-city?accountSequence=${accountSequence}&cityCode=${cityCode}`,
);
if (!response.ok) {
this.logger.warn(`No authorized city found for user ${userId}, city ${cityCode}`);
this.logger.warn(`No authorized city found for accountSequence ${accountSequence}, city ${cityCode}`);
return null;
}
// authorization-service 返回格式: { success, data: { accountSequence }, timestamp }
const result: AuthorizationServiceResponse<NearestAuthorizationResult> = await response.json();
const accountSeq = result.data?.accountSequence;
return accountSeq ? BigInt(accountSeq) : null;
return result.data?.accountSequence || null;
} catch (error) {
this.logger.error(`Error finding nearest authorized city:`, error);
return null;
}
}
async findNearestCommunity(userId: bigint): Promise<bigint | null> {
async findNearestCommunity(accountSequence: string): Promise<string | null> {
try {
const response = await fetch(
`${this.baseUrl}/api/v1/authorization/nearest-community?accountSequence=${userId}`,
`${this.baseUrl}/api/v1/authorization/nearest-community?accountSequence=${accountSequence}`,
);
if (!response.ok) {
this.logger.warn(`No community found for user ${userId}`);
this.logger.warn(`No community found for accountSequence ${accountSequence}`);
return null;
}
// authorization-service 返回格式: { success, data: { accountSequence }, timestamp }
const result: AuthorizationServiceResponse<NearestAuthorizationResult> = await response.json();
const accountSeq = result.data?.accountSequence;
this.logger.debug(`findNearestCommunity for userId=${userId}: result=${accountSeq}`);
return accountSeq ? BigInt(accountSeq) : null;
const resultAccountSeq = result.data?.accountSequence;
this.logger.debug(`findNearestCommunity for accountSequence=${accountSequence}: result=${resultAccountSeq}`);
return resultAccountSeq || null;
} catch (error) {
this.logger.error(`Error finding nearest community:`, error);
return null;
}
}
async getCommunityRewardDistribution(userId: bigint, treeCount: number): Promise<RewardDistribution> {
async getCommunityRewardDistribution(accountSequence: string, treeCount: number): Promise<RewardDistribution> {
const HEADQUARTERS_ACCOUNT_SEQUENCE = 'S0000000001';
const defaultDistribution: RewardDistribution = {
distributions: [
@ -117,11 +115,11 @@ export class AuthorizationServiceClient implements IAuthorizationServiceClient {
try {
const response = await fetch(
`${this.baseUrl}/api/v1/authorization/community-reward-distribution?accountSequence=${userId}&treeCount=${treeCount}`,
`${this.baseUrl}/api/v1/authorization/community-reward-distribution?accountSequence=${accountSequence}&treeCount=${treeCount}`,
);
if (!response.ok) {
this.logger.warn(`Failed to get community reward distribution for user ${userId}, treeCount ${treeCount}`);
this.logger.warn(`Failed to get community reward distribution for accountSequence ${accountSequence}, treeCount ${treeCount}`);
return defaultDistribution;
}
@ -129,12 +127,12 @@ export class AuthorizationServiceClient implements IAuthorizationServiceClient {
const result: AuthorizationServiceResponse<RewardDistributionResult> = await response.json();
if (!result.data?.distributions || result.data.distributions.length === 0) {
this.logger.warn(`Empty distributions returned for user ${userId}`);
this.logger.warn(`Empty distributions returned for accountSequence ${accountSequence}`);
return defaultDistribution;
}
this.logger.debug(
`getCommunityRewardDistribution for userId=${userId}, treeCount=${treeCount}: ` +
`getCommunityRewardDistribution for accountSequence=${accountSequence}, treeCount=${treeCount}: ` +
`distributions=${JSON.stringify(result.data.distributions)}`,
);
@ -145,7 +143,7 @@ export class AuthorizationServiceClient implements IAuthorizationServiceClient {
}
}
async getProvinceTeamRewardDistribution(userId: bigint, provinceCode: string, treeCount: number): Promise<RewardDistribution> {
async getProvinceTeamRewardDistribution(accountSequence: string, provinceCode: string, treeCount: number): Promise<RewardDistribution> {
const HEADQUARTERS_ACCOUNT_SEQUENCE = 'S0000000001';
const defaultDistribution: RewardDistribution = {
distributions: [
@ -159,23 +157,23 @@ export class AuthorizationServiceClient implements IAuthorizationServiceClient {
try {
const response = await fetch(
`${this.baseUrl}/api/v1/authorization/province-team-reward-distribution?accountSequence=${userId}&provinceCode=${provinceCode}&treeCount=${treeCount}`,
`${this.baseUrl}/api/v1/authorization/province-team-reward-distribution?accountSequence=${accountSequence}&provinceCode=${provinceCode}&treeCount=${treeCount}`,
);
if (!response.ok) {
this.logger.warn(`Failed to get province team reward distribution for user ${userId}, province ${provinceCode}`);
this.logger.warn(`Failed to get province team reward distribution for accountSequence ${accountSequence}, province ${provinceCode}`);
return defaultDistribution;
}
const result: AuthorizationServiceResponse<RewardDistributionResult> = await response.json();
if (!result.data?.distributions || result.data.distributions.length === 0) {
this.logger.warn(`Empty province team distributions returned for user ${userId}`);
this.logger.warn(`Empty province team distributions returned for accountSequence ${accountSequence}`);
return defaultDistribution;
}
this.logger.debug(
`getProvinceTeamRewardDistribution for userId=${userId}, provinceCode=${provinceCode}, treeCount=${treeCount}: ` +
`getProvinceTeamRewardDistribution for accountSequence=${accountSequence}, provinceCode=${provinceCode}, treeCount=${treeCount}: ` +
`distributions=${JSON.stringify(result.data.distributions)}`,
);
@ -229,7 +227,7 @@ export class AuthorizationServiceClient implements IAuthorizationServiceClient {
}
}
async getCityTeamRewardDistribution(userId: bigint, cityCode: string, treeCount: number): Promise<RewardDistribution> {
async getCityTeamRewardDistribution(accountSequence: string, cityCode: string, treeCount: number): Promise<RewardDistribution> {
const HEADQUARTERS_ACCOUNT_SEQUENCE = 'S0000000001';
const defaultDistribution: RewardDistribution = {
distributions: [
@ -243,23 +241,23 @@ export class AuthorizationServiceClient implements IAuthorizationServiceClient {
try {
const response = await fetch(
`${this.baseUrl}/api/v1/authorization/city-team-reward-distribution?accountSequence=${userId}&cityCode=${cityCode}&treeCount=${treeCount}`,
`${this.baseUrl}/api/v1/authorization/city-team-reward-distribution?accountSequence=${accountSequence}&cityCode=${cityCode}&treeCount=${treeCount}`,
);
if (!response.ok) {
this.logger.warn(`Failed to get city team reward distribution for user ${userId}, city ${cityCode}`);
this.logger.warn(`Failed to get city team reward distribution for accountSequence ${accountSequence}, city ${cityCode}`);
return defaultDistribution;
}
const result: AuthorizationServiceResponse<RewardDistributionResult> = await response.json();
if (!result.data?.distributions || result.data.distributions.length === 0) {
this.logger.warn(`Empty city team distributions returned for user ${userId}`);
this.logger.warn(`Empty city team distributions returned for accountSequence ${accountSequence}`);
return defaultDistribution;
}
this.logger.debug(
`getCityTeamRewardDistribution for userId=${userId}, cityCode=${cityCode}, treeCount=${treeCount}: ` +
`getCityTeamRewardDistribution for accountSequence=${accountSequence}, cityCode=${cityCode}, treeCount=${treeCount}: ` +
`distributions=${JSON.stringify(result.data.distributions)}`,
);