{
  "title": "Currency Service",
  "slug": "team/backend/services/currency-service",
  "url": "/docs/team/backend/services/currency-service",
  "frontmatter": {
    "layout": "doc",
    "title": "Currency Service",
    "description": "تنها مرجع نرخ ارز و تبدیل مبلغ در پلتفرم",
    "version": "1.0.0",
    "status": "BLUEPRINT",
    "author": "xoxxel",
    "owner": "xoxxel",
    "created_at": "2026-06-11",
    "updated_at": "2026-06-11",
    "tags": "",
    "reviewers": ""
  },
  "sections": [
    {
      "level": 1,
      "heading": "Currency Service",
      "content": "> **Blueprint v1.0 — پیش از توسعه**\n\n---"
    },
    {
      "level": 2,
      "heading": "1. هدف سرویس",
      "content": "تنها مرجع نرخ ارز و تبدیل مبلغ در کل پلتفرم. هر سرویسی که نیاز به تبدیل ارز دارد فقط با این سرویس صحبت می‌کند. نرخ‌ها از منابع خارجی (Nobitex، fixer.io) دریافت و در Redis cache می‌شوند.\n\n---"
    },
    {
      "level": 2,
      "heading": "2. مسئولیت‌ها",
      "content": "- دریافت نرخ زنده از منابع خارجی (Nobitex برای IRR، fixer.io برای سایر ارزها) هر ۵ دقیقه\n- کش کردن نرخ‌ها در Redis\n- ارائه نرخ خام از طریق `GET /rates`\n- تبدیل مبلغ با rounding صحیح و مدیریت precision از طریق `POST /convert`\n- مدیریت fallback: در صورت عدم دسترسی به منبع خارجی، از آخرین نرخ کش شده استفاده کند\n\n---"
    },
    {
      "level": 2,
      "heading": "3. حوزه (Scope)",
      "content": "**در این سرویس:**\n- دریافت و کش نرخ ارز\n- تبدیل مبلغ با rounding صحیح\n- مدیریت precision/decimal rules به ازای هر ارز\n\n**نیست در این سرویس:**\n- منطق پرداخت\n- ذخیره تاریخچه نرخ (مسئولیت analytics-service)\n- نمایش قیمت به کاربر\n\n---"
    },
    {
      "level": 2,
      "heading": "3.۱. مرز مسئولیت با Pool Service",
      "content": "> **تصمیم معماری (C9):** هیچ همپوشانی مسئولیتی بین Currency Service و Pool Service وجود ندارد.\n\n- **Pool Service** مالک **Reference Data** ارز است: کدهای ISO 4217، نام ارزها، نماد (Symbol)، دقت اعشار (Precision) و نگاشت کشور (Country Mapping).\n- **Currency Service** مالک **نرخ** است: نرخ تبدیل، نرخ لحظه‌ای (Live Rate)، نرخ‌های تاریخی (Historical Rates) و داده‌های بازار (Market Data).\n\nCurrency Service برای نمایش لیست/انوم ارزها از Pool Service استفاده می‌کند؛ اما محاسبه و نگهداری نرخ زنده صرفاً در این سرویس انجام می‌شود.\n\n---"
    },
    {
      "level": 2,
      "heading": "4. تکنولوژی",
      "content": "| مؤلفه | فناوری |\n|---|---|\n| زبان | Node.js / NestJS |\n| کش | Redis (TTL: ۵ دقیقه) |\n| دیتابیس | ندارد |\n| منابع خارجی | Nobitex (IRR), fixer.io (سایر ارزها) |\n\n---"
    },
    {
      "level": 2,
      "heading": "5. API",
      "content": ""
    },
    {
      "level": 3,
      "heading": "`GET /rates`",
      "content": "دریافت نرخ تمام ارزهای پشتیبانی‌شده.\n\n```typescript\ninterface GetRatesResponse {\n  USD_IRR: number\n  USD_TRY: number\n  USD_EUR: number\n  updatedAt: string\n}\n```"
    },
    {
      "level": 3,
      "heading": "`POST /convert`",
      "content": "تبدیل مبلغ از یک ارز به ارز دیگر.\n\n```typescript\ninterface ConvertRequest {\n  amount: bigint        // integer — lowest unit (e.g. cents)\n  from: Currency\n  to: Currency\n}\n\ninterface ConvertResponse {\n  result: bigint        // converted amount — integer\n  rate: number          // applied rate\n  rateAt: string        // timestamp of the rate\n}\n```\n\n**خطاها:**\n\n| کد | وضعیت | توضیح |\n|---|---|---|\n| `UNSUPPORTED_PAIR` | 422 | جفت‌ارز پشتیبانی نمی‌شود |\n| `RATE_UNAVAILABLE` | 424 | نرخ در دسترس نیست |\n| `INVALID_AMOUNT` | 422 | مبلغ نامعتبر (صفر یا منفی) |\n\n---"
    },
    {
      "level": 2,
      "heading": "6. ارزهای پشتیبانی‌شده",
      "content": "| جفت | وضعیت |\n|---|---|\n| `USD/IRR` | فعلی |\n| `USD/TRY` | آینده |\n| `USD/EUR` | آینده |\n\n---"
    },
    {
      "level": 2,
      "heading": "7. مصرف‌کنندگان",
      "content": "| سرویس | دلیل |\n|---|---|\n| marketplace-service | تبدیل ارز فروشنده به USD هنگام ثبت قیمت |\n| payment-service | تبدیل USD به ارز gateway هنگام پرداخت |\n| search-service | فیلتر قیمت بر اساس ارز کاربر |\n| settlement-service | تبدیل مبلغ تسویه به ارز فروشنده |\n\n---"
    },
    {
      "level": 2,
      "heading": "8. وابستگی‌ها",
      "content": "| وابستگی | نوع |\n|---|---|\n| Redis | کش نرخ |\n| Nobitex API | منبع نرخ IRR |\n| fixer.io API | منبع نرخ سایر ارزها |\n\n---"
    },
    {
      "level": 2,
      "heading": "9. رویدادها",
      "content": "این سرویس **رویدادی منتشر نمی‌کند**. کاملاً synchronous API است.\n\n---"
    },
    {
      "level": 2,
      "heading": "10. خطا و Fallback",
      "content": "| سناریو | رفتار |\n|---|---|\n| سرویس در دسترس نیست، Redis کش دارد | استفاده از آخرین نرخ کش شده |\n| سرویس در دسترس نیست، Redis هم در دسترس نیست | **توقف پرداخت** — رویداد به DLQ |\n| کش منقضی شده (TTL) | تلاش مجدد برای نرخ جدید؛ در صورت失敗 → DLQ |\n| جفت‌ارز پشتیبانی نمی‌شود | خطای `UNSUPPORTED_PAIR` |\n\n**Retry policy:**\n\n| تلاش | تأخیر | اقدام |\n|---|---|---|\n| ۱ | ۱ ثانیه | درخواست مجدد به منبع خارجی |\n| ۲ | ۵ ثانیه | تلاش مجدد + استفاده از کش |\n| ۳ | ۳۰ ثانیه | اجبار به استفاده از کش |\n| پس از ۳ تلاش | — | اگر کش نبود → DLQ |\n\n---"
    },
    {
      "level": 2,
      "heading": "11. مسیر توسعه",
      "content": "| مرحله | وضعیت |\n|---|---|\n| Blueprint | ✅ تکمیل |\n| Demo | ⏳ در انتظار |\n| توسعه | ❌ شروع نشده |\n| تست | ❌ شروع نشده |\n| انتشار | ❌ شروع نشده |"
    }
  ]
}