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

View File

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