محمدرضا و تیمش مشغول طراحی سامانه‌ای برای مدیریت کیف پول دیجیتال به‌نام دیجی‌والِت هستند. در نسخه‌ی اولیه‌ی این سامانه قرار است قابلیت‌های زیر وجود داشته باشد:

  • امکان ایجاد تراکنش و تغییر وضعیت آن
  • امکان مشاهده‌ی لیست تراکنش‌ها
  • امکان تسویه‌حساب
  • امکان مشاهده‌ی موجودی کیف پول

تیم محمدرضا ساختار برنامه را طراحی کرده‌اند و از شما می‌خواهند تا پیاده‌سازی آن را انجام دهید.

جزئیات پروژه

پروژه‌ی اولیه را از این لینک دانلود کنید.

ساختار فایل‌ها

src
└── ir
    └── digipay
        └── digiwallet
            ├── model
            │   ├── AdminWallet.java
            │   ├── Transaction.java
            │   ├── TransactionStatus.java
            │   ├── TransactionType.java
            │   └── Wallet.java
            ├── repository
            │   ├── CrudRepository.java
            │   ├── TransactionRepository.java
            │   └── TransactionRepositoryImpl.java
            ├── service
            │   ├── AdminWalletService.java
            │   └── WalletService.java
            ├── Application.java
            └── DigiWalletSampleTest.java
Plain text

مدل‌ها

  • کیف پول (Wallet)
    • این مدل تنها شامل یک شناسه از نوع String است.
  • کیف پول مربوط به ادمین‌های برنامه (AdminWallet)
    • این مدل از کلاس Wallet ارث‌بری می‌کند و هیچ پیاده‌سازی اضافه‌ای نسبت به مدل Wallet ندارد.
  • نوع تراکنش (TransactionType): این کلاس یک enum است که به‌ترتیب شامل دو مقدار DEPOSIT و WITHDRAWAL است.
    • تراکنش‌هایی که از نوع DEPOSIT هستند، بیانگر واریزهایی هستند که مقصد آن‌ها، کیف پول فعلی است.
    • تراکنش‌هایی که از نوع WITHDRAWAL هستند، بیانگر برداشت‌هایی هستند که از کیف پول به حساب بانکی صاحب کیف پول منتقل می‌شوند.
  • وضعیت تراکنش (TransactionStatus): این کلاس یک enum است که به‌ترتیب شامل سه مقدار CANCELED، PENDING و ACCEPTED است.
  • تراکنش (Transaction)
    • این مدل به‌ترتیب شامل پراپرتی‌های زیر است:
      • long id: شناسه‌ی تراکنش
      • Wallet wallet: کیف پول مربوط به تراکنش
      • TransactionType type: نوع تراکنش
      • BigDecimal amount: مبلغ تراکنش
      • Date createdAt: زمان ایجاد تراکنش
      • TransactionStatus status: وضعیت تراکنش با مقدار اولیه‌ی PENDING
      • Date updatedAt: زمان تغییر وضعیت تراکنش
    • همه‌ی پراپرتی‌ها به‌جز پراپرتی updatedAt در کانستراکتور مقداردهی می‌شوند.
    • متد setStatus را طوری پیاده‌سازی کنید که با دریافت یک TransactionStatus، وضعیت تراکنش را به وضعیت واردشده تغییر داده و مقدار پراپرتی updatedAt را برابر با یک آبجکت جدید از نوع Date قرار دهد.

مخزن‌ها

  • اینترفیس CrudRepository<T, ID>
    • این اینترفیس شامل دو پارامتر جنریک T (نوع مدل) و ID (نوع شناسه‌ی مدل) است.
    • این اینترفیس شامل تعریف متدهای زیر است:
      • boolean add(T t): این متد، مدل را به مخزن اضافه می‌کند؛ به شرط آن که مدل از قبل در مخزن وجود نداشته باشد. اگر مدل از قبل در مخزن موجود باشد، مقدار false و در غیر این‌صورت، مقدار true را برمی‌گرداند.
      • List<T> getAll(): این متد، لیست همه‌ی مدل‌های ذخیره‌شده را به‌ترتیب درج برمی‌گرداند.
      • T get(ID id): این متد، مدلی که شناسه‌ی آن برابر با id است را برمی‌گرداند. اگر چنین مدلی یافت نشود، مقدار null را برمی‌گرداند.
      • List<T> get(Predicate<T> predicate): این متد، لیست مدل‌هایی که شرایط داده‌شده در predicate را دارند به‌ترتیب درج برمی‌گرداند.
  • اینترفیس TransactionRepository
    • این اینترفیس از اینترفیس CrudRepository ارث‌بری می‌کند و صرفاً نوع تراکنش‌ها (که Transaction است) و نوع شناسه‌ی آن‌ها (که Long است) را مشخص می‌کند.
  • کلاس TransactionRepositoryImpl
    • این کلاس، اینترفیس TransactionRepository را پیاده‌سازی می‌کند و تراکنش‌های مربوط به همه‌ی کیف پول‌ها در آن ذخیره می‌شود.
    • متدهای این کلاس را مطابق توضیحات اینترفیس CrudRepository پیاده‌سازی کنید.
    • در متد add اگر مبلغ تراکنش کوچک‌تر یا مساوی صفر باشد، یک IllegalArgumentException باید پرتاب شود.

سرویس‌ها

  • سرویس WalletService
    • از این کلاس برای مدیریت کیف پول‌ها استفاده می‌شود.
    • متد addTransaction را طوری پیاده‌سازی کنید که با دریافت یک تراکنش، با فراخوانی متد add از transactionRepository، آن را به لیست تراکنش‌ها اضافه کند. این متد در صورتی که تراکنش از قبل موجود باشد، باید مقدار false و در غیر این‌صورت، باید مقدار true را برگرداند.
    • متد getTransactions(Wallet wallet) را طوری پیاده‌سازی کنید که لیست همه‌ی تراکنش‌هایی که مربوط به کیف پول ورودی هستند را به‌ترتیب درج برگرداند.
    • متد getTransactions(Wallet wallet, Predicate<Transaction> predicate) را طوری پیاده‌سازی کنید که لیست همه‌ی تراکنش‌هایی که مربوط به کیف پول ورودی هستند و شرایط داده‌شده در predicate را دارند به‌ترتیب درج برگرداند.
    • متد getBalance را طوری پیاده‌سازی کنید که با دریافت یک کیف پول، موجودی حساب کیف پول را در قالب یک BigDecimal برگرداند. موجودی حساب برابر با مجموع مبلغ DEPOSITهای ACCEPTED منهای مجموع مبلغ WITHDRAWALهای ACCEPTED است.
    • متد setTransactionStatus را طوری پیاده‌سازی کنید که با دریافت یک تراکنش و وضعیت جدید، در صورتی که وضعیت تراکنش PENDING نبود یا وضعیت جدید برابر با PENDING بود، مقدار false را برگرداند. در غیر این‌صورت، اگر تراکنش از نوع WITHDRAWAL بود و موجودی کیف پول به اندازه‌ی مبلغ تراکنش نبود، یک IllegalArgumentException پرتاب شود. در غیر این‌صورت، وضعیت تراکنش به وضعیت جدید تغییر کند، مقدار پراپرتی updatedAt تراکنش به‌روز شود و مقدار true برگردانده شود.
  • سرویس AdminWalletService
    • این کلاس از کلاس WalletService ارث‌بری می‌کند.
    • متد getTransactions(Predicate<Transaction> predicate) را طوری پیاده‌سازی کنید که لیست همه‌ی تراکنش‌های مربوط به همه‌ی کیف پول‌ها که شرایط داده‌شده در predicate را دارند به‌ترتیب درج برگرداند.
    • متد getAllTransactions را طوری پیاده‌سازی کنید که لیست همه‌ی تراکنش‌های مربوط به همه‌ی کیف پول‌ها (همه‌ی تراکنش‌های موجود در مخزن) را به‌ترتیب درج برگرداند.

نکات

  • لازم نیست که ذخیره‌سازی مقدار مدل‌ها persistent باشد (تنها یک بار اجرای برنامه را در نظر بگیرید).
  • هر نمونه از مخزن باید داده‌ها را به‌صورت جداگانه در خودش ذخیره کند.
  • در صورت نیاز، می‌توانید پراپرتی‌ها و متدهای جدیدی به کلاس‌ها (به‌جز کلاس Application) اضافه کنید.

مثال

با اجرای متد main موجود در کلاس Application، خروجی زیر مورد انتظار است:

true
1000
[[Id: 1, Wallet Id: x-y-z, Type: DEPOSIT, Amount: 1000, Status: ACCEPTED]]
[[Id: 1, Wallet Id: x-y-z, Type: DEPOSIT, Amount: 1000, Status: ACCEPTED]]
Plain text

آن‌چه باید آپلود کنید

پس از پیاده‌سازی موارد خواسته‌شده، یک فایل زیر آپلود کنید که وقتی آن را باز می‌کنیم، با ساختار زیر مواجه شویم (از سایر فایل‌ها صرف‌نظر می‌شود):

.
└── ir
    └── digipay
        └── digiwallet
            ├── model
            │   └── Transaction.java
            ├── repository
            │   └── TransactionRepositoryImpl.java
            ├── service
            │   ├── AdminWalletService.java
            └── └── WalletService.java
Plain text

ارسال پاسخ برای این سؤال
فایلی انتخاب نشده است.