Skip to content

Conversation

@xinquiry
Copy link
Collaborator

@xinquiry xinquiry commented Jan 21, 2026

Summary

  • Fix 404 error when fetching user wallet by correcting API path from /redemption/ to /business/
  • Fix React Query cache invalidation by using correct query key ["userWallet"] instead of ["wallet"]

Test plan

  • Verify points (积分) display shows actual value instead of "--"
  • Verify check-in refreshes wallet balance correctly
  • Verify no 404 errors in browser console for wallet endpoint

🤖 Generated with Claude Code

Summary by Sourcery

更新与钱包相关的 API 端点以及查询缓存失效逻辑,以使用正确的业务路径和查询键。

Bug 修复:

  • 将钱包和兑换相关的 API URL 从 /redemption 更正为使用 /business 命名空间,以防止出现 404 错误。
  • 修复 React Query 中钱包缓存失效的问题,在成功签到后正确地针对 userWallet 查询键进行失效处理。
Original summary in English

Summary by Sourcery

Update wallet-related API endpoints and query cache invalidation to use the correct business paths and query key.

Bug Fixes:

  • Correct wallet and redemption API URLs to use the /business namespace instead of /redemption to prevent 404 errors.
  • Fix React Query wallet cache invalidation by targeting the userWallet query key after successful check-in.

- Update redemptionService.ts to use /business/ instead of /redemption/
  (backend mounts the router at /business prefix)
- Fix query key mismatch in CheckInCalendar.tsx for wallet invalidation

Co-Authored-By: Claude <noreply@anthropic.com>
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Jan 21, 2026

审阅者指南(在较小 PR 上折叠)

审阅者指南

将与兑换相关的 API 端点从已弃用的 /redemption/ 命名空间调整为 /business/,并通过在签到操作后使用正确的钱包查询键来修复 React Query 的缓存失效问题。

使用已更正查询键的签到与钱包刷新时序图

sequenceDiagram
  actor User
  participant CheckInCalendar
  participant QueryClient
  participant RedemptionService
  participant BackendBusinessApi

  User->>CheckInCalendar: clickCheckIn()
  CheckInCalendar->>RedemptionService: redeemCode(code)
  RedemptionService->>BackendBusinessApi: POST /xyzen/api/v1/business/redeem
  BackendBusinessApi-->>RedemptionService: RedeemCodeResponse
  RedemptionService-->>CheckInCalendar: RedeemCodeResponse

  CheckInCalendar->>QueryClient: invalidateQueries([check-in])
  CheckInCalendar->>QueryClient: invalidateQueries([userWallet])

  QueryClient->>RedemptionService: getUserWallet()
  RedemptionService->>BackendBusinessApi: GET /xyzen/api/v1/business/wallet
  BackendBusinessApi-->>RedemptionService: UserWalletResponse
  RedemptionService-->>QueryClient: UserWalletResponse
  QueryClient-->>CheckInCalendar: updated userWallet data
  CheckInCalendar-->>User: updated points display
Loading

更新后的 RedemptionService 业务端点类图

classDiagram
  class RedemptionService {
    +redeemCode(code string) RedeemCodeResponse
    +getUserWallet() UserWalletResponse
    +getRedemptionHistory(limit number, offset number) RedemptionHistoryResponse[]
    +getDailyTokenStats(date string, tz string) DailyTokenStatsResponse
    +getTopUsers(limit number) UserConsumptionResponse[]
    +getConsumeRecords(startDate string, endDate string, limit number, offset number) ConsumeRecordResponse[]
    +getDailyUserActivity(startDate string, endDate string, limit number, offset number, tz string) DailyUserActivityResponse[]
  }

  class BackendBusinessApi {
    +POST_xyzen_api_v1_business_redeem()
    +GET_xyzen_api_v1_business_wallet()
    +GET_xyzen_api_v1_business_history()
    +GET_xyzen_api_v1_business_admin_stats_daily_tokens()
    +GET_xyzen_api_v1_business_admin_stats_top_users()
    +GET_xyzen_api_v1_business_admin_stats_consume_records()
    +GET_xyzen_api_v1_business_admin_stats_user_activity()
  }

  RedemptionService --> BackendBusinessApi
Loading

文件级变更

变更 详情 文件
将所有与兑换相关的 API 调用更新为使用 /business/ 后端路径,而不是 /redemption/。
  • 将兑换码 POST 端点路径更改为使用 /business/redeem 路由。
  • 将用户钱包 GET 端点路径更改为使用 /business/wallet 路由。
  • 将兑换历史 GET 端点路径更改为使用 /business/history 路由。
  • 将多个管理员统计端点(每日代币、顶级用户、消费记录、用户活动)更改为使用 /business/admin/stats/* 路由。
web/src/service/redemptionService.ts
通过使正确的 React Query 缓存键失效来修复签到后的钱包刷新。
  • 在成功签到之后,将用于查询失效的键从 ["wallet"] 更新为 ["userWallet"],从而确保钱包数据被正确重新获取。
web/src/components/features/CheckInCalendar.tsx

技巧与命令

与 Sourcery 交互

  • 触发新审阅: 在 pull request 中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审阅评论。
  • 从审阅评论生成一个 GitHub issue: 在某条审阅评论下回复,要求 Sourcery 根据该评论创建一个 issue。你也可以在审阅评论下回复 @sourcery-ai issue,以此从该评论创建一个 issue。
  • 生成 pull request 标题: 在 pull request 标题中的任意位置写上 @sourcery-ai,即可随时生成标题。你也可以在 pull request 中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成 pull request 摘要: 在 pull request 正文中的任意位置写上 @sourcery-ai summary,即可在你想要的位置随时生成 PR 摘要。你也可以在 pull request 中评论 @sourcery-ai summary 来(重新)生成摘要。
  • 生成审阅者指南: 在 pull request 中评论 @sourcery-ai guide,即可随时(重新)生成审阅者指南。
  • 将所有 Sourcery 评论标记为已解决: 在 pull request 中评论 @sourcery-ai resolve,即可将所有 Sourcery 评论标记为已解决。如果你已经处理了所有评论且不想再看到它们,这会很有用。
  • 忽略所有 Sourcery 审阅: 在 pull request 中评论 @sourcery-ai dismiss,即可忽略所有现有的 Sourcery 审阅。尤其适用于你想从头开始新的审阅时——别忘了再评论 @sourcery-ai review 来触发新的审阅!

自定义你的体验

访问你的 控制面板 以:

  • 启用或禁用审阅功能,例如 Sourcery 生成的 pull request 摘要、审阅者指南等。
  • 更改审阅语言。
  • 添加、移除或编辑自定义审阅指令。
  • 调整其他审阅设置。

获取帮助

Original review guide in English
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adjusts redemption-related API endpoints from the deprecated /redemption/ namespace to /business/ and fixes React Query cache invalidation by using the correct wallet query key after check-in operations.

Sequence diagram for check-in and wallet refresh with corrected query key

sequenceDiagram
  actor User
  participant CheckInCalendar
  participant QueryClient
  participant RedemptionService
  participant BackendBusinessApi

  User->>CheckInCalendar: clickCheckIn()
  CheckInCalendar->>RedemptionService: redeemCode(code)
  RedemptionService->>BackendBusinessApi: POST /xyzen/api/v1/business/redeem
  BackendBusinessApi-->>RedemptionService: RedeemCodeResponse
  RedemptionService-->>CheckInCalendar: RedeemCodeResponse

  CheckInCalendar->>QueryClient: invalidateQueries([check-in])
  CheckInCalendar->>QueryClient: invalidateQueries([userWallet])

  QueryClient->>RedemptionService: getUserWallet()
  RedemptionService->>BackendBusinessApi: GET /xyzen/api/v1/business/wallet
  BackendBusinessApi-->>RedemptionService: UserWalletResponse
  RedemptionService-->>QueryClient: UserWalletResponse
  QueryClient-->>CheckInCalendar: updated userWallet data
  CheckInCalendar-->>User: updated points display
Loading

Updated class diagram for RedemptionService business endpoints

classDiagram
  class RedemptionService {
    +redeemCode(code string) RedeemCodeResponse
    +getUserWallet() UserWalletResponse
    +getRedemptionHistory(limit number, offset number) RedemptionHistoryResponse[]
    +getDailyTokenStats(date string, tz string) DailyTokenStatsResponse
    +getTopUsers(limit number) UserConsumptionResponse[]
    +getConsumeRecords(startDate string, endDate string, limit number, offset number) ConsumeRecordResponse[]
    +getDailyUserActivity(startDate string, endDate string, limit number, offset number, tz string) DailyUserActivityResponse[]
  }

  class BackendBusinessApi {
    +POST_xyzen_api_v1_business_redeem()
    +GET_xyzen_api_v1_business_wallet()
    +GET_xyzen_api_v1_business_history()
    +GET_xyzen_api_v1_business_admin_stats_daily_tokens()
    +GET_xyzen_api_v1_business_admin_stats_top_users()
    +GET_xyzen_api_v1_business_admin_stats_consume_records()
    +GET_xyzen_api_v1_business_admin_stats_user_activity()
  }

  RedemptionService --> BackendBusinessApi
Loading

File-Level Changes

Change Details Files
Update all redemption-related API calls to use the /business/ backend path instead of /redemption/.
  • Change redeem code POST endpoint path to use the /business/redeem route.
  • Change user wallet GET endpoint path to use the /business/wallet route.
  • Change redemption history GET endpoint path to use the /business/history route.
  • Change multiple admin stats endpoints (daily tokens, top users, consume records, user activity) to use the /business/admin/stats/* routes.
web/src/service/redemptionService.ts
Fix wallet refresh after check-in by invalidating the correct React Query cache key.
  • Update the query invalidation key used after a successful check-in from ["wallet"] to ["userWallet"] so the wallet data is refetched correctly.
web/src/components/features/CheckInCalendar.tsx

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了 1 个问题,并给出了一些总体性反馈:

  • 现在有多个方法使用 /xyzen/api/v1/business 作为基础路径,建议把这段路径提取为一个共享常量或辅助方法,这样当端点再次变更时可以避免出现不一致。
  • React Query 的 key "userWallet" 目前只是一个普通字符串;将其定义为一个共享常量(并在定义查询的地方重复使用)可以降低因为拼写错误或不一致而导致缓存失效问题的风险。
给 AI 智能体的提示
Please address the comments from this code review:

## Overall Comments
- 现在有多个方法使用 `/xyzen/api/v1/business` 作为基础路径,建议把这段路径提取为一个共享常量或辅助方法,这样当端点再次变更时可以避免出现不一致。
- React Query 的 key `"userWallet"` 目前只是一个普通字符串;将其定义为一个共享常量(并在定义查询的地方重复使用)可以降低因为拼写错误或不一致而导致缓存失效问题的风险。

## Individual Comments

### Comment 1
<location> `web/src/service/redemptionService.ts:98-101` </location>
<code_context>
   async redeemCode(code: string): Promise<RedeemCodeResponse> {
     const response = await fetch(
-      `${this.getBackendUrl()}/xyzen/api/v1/redemption/redeem`,
+      `${this.getBackendUrl()}/xyzen/api/v1/business/redeem`,
       {
         method: "POST",
</code_context>

<issue_to_address>
**suggestion:** 建议为 `/xyzen/api/v1/business` 这个前缀提取一个共享的基础路径,以减少重复代码,并降低未来路由变更时的风险。

由于这些调用都使用相同的 `${this.getBackendUrl()}/xyzen/api/v1/business` 前缀(其中一些还会追加 `admin/stats`),可以考虑将这些片段统一定义一次(例如作为类属性或辅助方法)并复用。这样可以让后续的路由变更更加安全,避免遗漏单独的调用点。

建议实现方式:

```typescript
export class RedemptionService {
  private getBusinessBaseUrl(): string {
    return `${this.getBackendUrl()}/xyzen/api/v1/business`;
  }

```

```typescript
  async redeemCode(code: string): Promise<RedeemCodeResponse> {
    const response = await fetch(
      `${this.getBusinessBaseUrl()}/redeem`,
      {

```

```typescript
  async getUserWallet(): Promise<UserWalletResponse> {
    const response = await fetch(
      `${this.getBusinessBaseUrl()}/wallet`,
      {

```
</issue_to_address>

Sourcery 对开源项目免费——如果你觉得我们的评审有帮助,欢迎分享给更多人 ✨
帮我变得更有用!请在每条评论上点击 👍 或 👎,我会根据你的反馈改进后续的代码评审。
Original comment in English

Hey - I've found 1 issue, and left some high level feedback:

  • Now that multiple methods use the /xyzen/api/v1/business base path, consider extracting this segment into a shared constant or helper to avoid future inconsistencies when endpoints change again.
  • The React Query key "userWallet" is currently a bare string; defining it as a shared constant (and reusing it where the query is defined) would reduce the risk of subtle cache invalidation bugs from typos or mismatches.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Now that multiple methods use the `/xyzen/api/v1/business` base path, consider extracting this segment into a shared constant or helper to avoid future inconsistencies when endpoints change again.
- The React Query key `"userWallet"` is currently a bare string; defining it as a shared constant (and reusing it where the query is defined) would reduce the risk of subtle cache invalidation bugs from typos or mismatches.

## Individual Comments

### Comment 1
<location> `web/src/service/redemptionService.ts:98-101` </location>
<code_context>
   async redeemCode(code: string): Promise<RedeemCodeResponse> {
     const response = await fetch(
-      `${this.getBackendUrl()}/xyzen/api/v1/redemption/redeem`,
+      `${this.getBackendUrl()}/xyzen/api/v1/business/redeem`,
       {
         method: "POST",
</code_context>

<issue_to_address>
**suggestion:** Consider extracting a shared base path for the `/xyzen/api/v1/business` prefix to reduce duplication and risk on future route changes.

Since all these calls use the same `${this.getBackendUrl()}/xyzen/api/v1/business` prefix (and some also add `admin/stats`), consider defining these segments once (e.g., as class properties or helper methods) and reusing them. This will make future route changes safer and avoid missing individual call sites.

Suggested implementation:

```typescript
export class RedemptionService {
  private getBusinessBaseUrl(): string {
    return `${this.getBackendUrl()}/xyzen/api/v1/business`;
  }

```

```typescript
  async redeemCode(code: string): Promise<RedeemCodeResponse> {
    const response = await fetch(
      `${this.getBusinessBaseUrl()}/redeem`,
      {

```

```typescript
  async getUserWallet(): Promise<UserWalletResponse> {
    const response = await fetch(
      `${this.getBusinessBaseUrl()}/wallet`,
      {

```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@Mile-Away Mile-Away merged commit eae25d5 into main Jan 21, 2026
6 checks passed
@Mile-Away Mile-Away deleted the fix/redemption-wallet-not-found branch January 21, 2026 11:54
Mile-Away pushed a commit that referenced this pull request Jan 21, 2026
## [1.0.5](v1.0.4...v1.0.5) (2026-01-21)

### 🐛 Bug Fixes

* correct redemption API path and wallet query key ([#190](#190)) ([eae25d5](eae25d5))
@Mile-Away
Copy link
Contributor

🎉 This PR is included in version 1.0.5 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants