+ محدودیت زمان: ۱ ثانیه
+ محدودیت حافظه: ۲۵۶ مگابایت
----------
علی که خیلی به کسب و کار اهمیت میدهد به تازگی در دو بانک کار میکند. او باید روزهای زوج به بانک «پرسپولیس» و روزهای فرد به بانک «بهمن» برود.
میدانیم روزهای «شنبه»، «دوشنبه» و «چهارشنبه» یک روز **زوج** و روزهای «یکشنبه»، «سهشنبه» و «پنجشنبه» یک روز **فرد** است. همچنین روز «جمعه» **تعطیل** است.
به شما یک رشته داده میشود که یکی از روزهای هفته را نشان میدهد. از شما میخواهیم نام بانکی که علی باید در آن روز، آنجا کار کند را چاپ کنید یا اینکه اعلام کنید این روز تعطیل است.
+ شنبه (`shanbe`) یک روز زوج است، پس باید در بانک پرسپولیس (`perspolis`) کار کند.
+ یکشنبه (`yekshanbe`) یک روز فرد است، پس باید در بانک بهمن (`bahman`) کار کند.
+ دوشنبه (`doshanbe`) یک روز زوج است، پس باید در بانک پرسپولیس (`perspolis`) کار کند.
+ سهشنبه (`seshanbe`) یک روز فرد است، پس باید در بانک بهمن (`bahman`) کار کند.
+ چهارشنبه (`chaharshanbe`) یک روز زوج است، پس باید در بانک پرسپولیس (`perspolis`) کار کند.
+ پنجشنبه (`panjshanbe`) یک روز فرد است، پس باید در بانک بهمن (`bahman`) کار کند.
+ جمعه (`jome`) یک روز تعطیل (`tatil`) است و لازم نیست جایی کار کند.
# ورودی
در تنها سطر ورودی یکی از ۷ رشته `shanbe`، `yekshanbe`، `doshanbe`، `seshanbe`، `chaharshanbe`، `panjshanbe` یا `jome` داده میشود.
# خروجی
در تنها سطر خروجی در صورتی که روز کار در بانک پرسپولیس است `perspolis` و در صورتی که روز کار در بانک بهمن است `bahman` و در صورت تعطیل بودن `tatil` را چاپ کنید.
# مثال
## ورودی نمونه ۱
```
shanbe
```
## خروجی نمونه ۱
```
perspolis
```
شنبه یک روز زوج است، پس باید در بانک «پرسپولیس» کار کند.
## ورودی نمونه ۲
```
seshanbe
```
## خروجی نمونه ۲
```
bahman
```
سهشنبه یک روز فرد است، پس باید در بانک «بهمن» کار کند.
## ورودی نمونه ۳
```
jome
```
## خروجی نمونه ۳
```
tatil
```
جمعه یک روز تعطیل است و نیازی نیست جایی کار کند.
دو شغله
+ محدودیت زمان: ۱ ثانیه
+ محدودیت حافظه: ۲۵۶ مگابایت
----------
علی به سه کشور امارات، فرانسه و آمریکا سفر کرده و به تازگی به ایران برگشته است.
او برای هزینههای این سفر از دوستش محمد $n$ ریال قرض گرفته بود و حالا که از سفر برگشته میخواهد این قرض را به محمد پس بدهد.
علی با خود $x$ اسکناس یک درهمی از امارات، $y$ اسکناس یک یورویی از فرانسه و $z$ اسکناس یک دلاری از آمریکا آورده است.
میدانیم در روز پرداخت، قیمت یک درهم $a$ ریال، قیمت یک یورو $b$ ریال و قیمت یک دلار $c$ ریال است.
علی میخواهد بداند به چند طریق میتواند $x'$ اسکناس یک درهمی، $y'$ اسکناس یک یورویی، $z'$ اسکناس یک دلاری به محمد بدهد به طوری که ارزش آنها دقیقاً $n$ ریال باشد.
به عبارت دیگر تعداد راههای مشخص کردن سه عدد صحیح $x'$، $y'$ و $z'$ به طوری که:
$$x' \times a + y' \times b + z' \times c = n$$
$$0 \le x' \le x, \quad 0 \le y' \le y, \quad 0 \le z' \le z$$
چقدر است؟
# ورودی
در سطر اول ورودی تنها عدد صحیح $n$ آمده که نشاندهنده مبلغی (به ریال) است که علی باید به محمد پرداخت کند.
$$1 \le n \le 100\,000$$
در سطر دوم ورودی سه عدد صحیح $x$، $y$ و $z$ با فاصله آمده که به ترتیب نشاندهنده تعداد اسکانسهای درهم، یورو و دلار است.
$$0 \le x, y, z \le 5000$$
در سطر سوم ورودی سه عدد صحیح $a$، $b$ و $c$ با فاصله آمده که به ترتیب نشاندهنده قیمت یک درهم، یورو و دلار بر حسب ریال است.
$$1 \le a, b, c \le 100\,000$$
# خروجی
در تنها سطر خروجی یک عدد صحیح که نشاندهنده پاسخ مسئله یعنی تعداد روشهای پرداخت $n$ ریال به محمد است را چاپ کنید.
# مثال
## ورودی نمونه ۱
```
100000
2 1 1
50000 70000 30000
```
## خروجی نمونه ۱
```
2
```
دو روش برای پرداخت ممکن است:
+ دو اسکناس یک درهمی بدهد.
$$2 \times 50\,000 + 0 \times 70\,000 + 0 \times 30\,000 = 100\,000$$
+ یک اسکناس یک یورویی و یک اسکناس یک دلاری بدهد.
$$0 \times 50\,000 + 1 \times 70\,000 + 1 \times 30\,000 = 100\,000$$
## ورودی نمونه ۲
```
60000
3 3 3
30000 20000 30000
```
## خروجی نمونه ۲
```
4
```
چهار روش برای پرداخت ممکن است:
+ دو اسکناس یک درهمی بدهد.
$$2 \times 30\,000 + 0 \times 20\,000 + 0 \times 30\,000 = 60\,000$$
+ دو اسکناس یک دلاری بدهد.
$$0 \times 30\,000 + 0 \times 20\,000 + 2 \times 30\,000 = 60\,000$$
+ یک اسکناس یک درهمی و یک اسکناس یک دلاری بدهد.
$$1 \times 30\,000 + 0 \times 20\,000 + 1 \times 30\,000 = 60\,000$$
+ سه اسکناس یک یورویی بدهد.
$$0 \times 30\,000 + 3 \times 20\,000 + 0 \times 30\,000 = 60\,000$$
## ورودی نمونه ۳
```
32000
2 1 1
4200 7500 3600
```
## خروجی نمونه ۳
```
0
```
مجموع ارزش پولی که علی دارد کمتر از پولی است که باید به محمد بدهد.
$$2 \times 4\,200 + 1 \times 7\,500 + 1 \times 3\,600 = 19\,500 < 32\,000$$
پس هیچ راهی برای پرداخت ندارد.
تبدیل ارز
محمدرضا و تیمش مشغول طراحی سامانهای برای مدیریت کیف پول دیجیتال بهنام *دیجیوالِت* هستند. در نسخهی اولیهی این سامانه قرار است قابلیتهای زیر وجود داشته باشد:
+ امکان ایجاد تراکنش و تغییر وضعیت آن
+ امکان مشاهدهی لیست تراکنشها
+ امکان تسویهحساب
+ امکان مشاهدهی موجودی کیف پول
تیم محمدرضا ساختار برنامه را طراحی کردهاند و از شما میخواهند تا پیادهسازی آن را انجام دهید.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/33037/download_problem_initial_project/111752/) دانلود کنید.
<details class="grey">
<summary>ساختار فایلها</summary>
```
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
```
</details>
## مدلها
+ کیف پول (`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]]
```
# آنچه باید آپلود کنید
پس از پیادهسازی موارد خواستهشده، یک فایل زیر آپلود کنید که وقتی آن را باز میکنیم، با ساختار زیر مواجه شویم (از سایر فایلها صرفنظر میشود):
```
.
└── ir
└── digipay
└── digiwallet
├── model
│ └── Transaction.java
├── repository
│ └── TransactionRepositoryImpl.java
├── service
│ ├── AdminWalletService.java
└── └── WalletService.java
```
دیجیوالِت
چند ماهی است که احمد یک وبسرویس پرداخت با نام *بپرداز* پیادهسازی کرده است. این وبسرویس اخیراً شاهد ترافیک سنگین درخواستها بوده است. احمد برای رفع این مشکل، تصمیم گرفت تا از چند سرور مختلف برای پردازش درخواستها استفاده کند. این سرورها با یکدیگر *sync* هستند؛ اما هماکنون برخی از آنها همچنان به دلیل ترافیک بالای درخواستها کند شدهاند. از آنجایی که احمد هنوز راهحل درستی برای این مسئله پیدا نکرده، میخواهد یک تغییر موقتی روی *SDK* ای که در اختیار توسعهدهندگان قرار داده است اعمال کند.
احمد میخواهد *SDK* جاوای وبسرویسش را طوری پیادهسازی کند که درخواست تأیید یک تراکنش بهصورت همزمان به همهی سرورهای موجود ارسال شود و به محض اولین پاسخی که از یکی از سرورها دریافت میشود، این پاسخ برگردانده شود. همچنین، او میخواهد قابلیت ست کردن *timeout* وجود داشته باشد تا اگر پس از $n$ واحد زمانی هیچ پاسخی دریافت نشد، برنامه یک `Exception` پرتاب کند.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/33037/download_problem_initial_project/111751/) دانلود کنید.
## کلاس `TransactionVerifier`
این کلاس در کانستراکتور خود لیستی از `URL`های مربوط به درخواست تأیید تراکنش را دریافت میکند.
+ بدنهی کانستراکتور را بهگونهای تغییر دهید که اگر لیست `URL`ها خالی بود، یک `IllegalArgumentException` پرتاب شود.
+ متد `setTimeout` را طوری پیادهسازی کنید که با دریافت یک واحد زمانی از نوع `Duration`، حداکثر زمان انتظار برای دریافت پاسخ را مشخص کند. همچنین، مقدار پیشفرض *timeout* را برابر با ۳ ثانیه قرار دهید.
+ متد `verify` را طوری پیادهسازی کنید که با دریافت شناسهی یک تراکنش (که از نوع `String` است)، درخواست تأیید تراکنش را بهصورت همروند به همهی آدرسها ارسال کند و به محض دریافت اولین پاسخ، آن را در قالب یک رشته برگرداند. این متد باید حداکثر به اندازهی *timeout* ست شده منتظر پاسخ بماند. اگر *timeout* رخ دهد، این متد باید یک `TimeoutException` پرتاب کند. درخواستها باید از نوع `POST` باشند و مقدار پارامتر `transaction_id` باید برابر با شناسهی تراکنش قرار داده شود. بدنهی درخواست باید از نوع *JSON* باشد.
+ متد `getFastestServer` را طوری پیادهسازی کنید که `URL` سروری که تاکنون بیشترین پاسخها از آن دریافت شده است را برگرداند. اگر تعداد دفعات دریافت زودترین پاسخ از چند سرور یکسان بود، `URL` یکی از آنها را به دلخواه برگردانید.
# مثال
با اجرای متد `main`، یکی از سه خروجی زیر مورد انتظار است:
```json
{
"sever_id": 1,
"status": true
}
```
```json
{
"sever_id": 2,
"status": true
}
```
```json
{
"sever_id": 3,
"status": true
}
```
**توجه:** برنامهی شما نباید *resource leak* داشته باشد.
# آنچه باید آپلود کنید
پس از پیادهسازی کلاس `TransactionVerifier`، فایل `TransactionVerifier.java` را آپلود کنید.
تأیید همروند
تیم *انبوهفروشان مشرقزمین* قصد دارد سامانهای تحتوب برای مدیریت آسانتر فروشگاهشان راهاندازی کند. آنها تصمیم گرفتهاند تا وبسرویسشان را با استفاده از *Spring Boot* پیادهسازی کنند. نیازمندیها از قبل بهطور دقیق مشخص شدهاند، اما هنوز برنامهنویسی به تیم آنها اضافه نشده است. از شما میخواهیم تا نسخهی اولیهی این وبسرویس را پیادهسازی کنید.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/33037/download_problem_initial_project/111750/) دانلود کنید.
+ این پروژه از *Maven* استفاده میکند و وابستگیها در *POM* تعریف شدهاند. امکان تغییر این وابستگیها وجود ندارد.
+ از *[Liquibase](https://www.liquibase.org/)* برای مدیریت *schema* دیتابیس استفاده شده است.
+ برای اجرای تستها، از دیتابیس *[H2](https://www.h2database.com/)* استفاده میشود.
+ در این پروژه، وابستگی *[Project Lombok](https://projectlombok.org/)* تعریف شده و قابل استفاده است.
+ بستهی `ir.digipay.bulkshop` شامل موجودیتهای *JPA* برنامه است که مطابق با *schema* دیتابیس طراحی شدهاند. شناسه (`id`) موجودیتها بهصورت خودکار توسط *Hibernate* تولید میشود.
+ کلاس `CustomerEntity`: از این کلاس برای نگهداری اطلاعات هر مشتری استفاده میشود.
+ کلاس `ProductEntity`: از این کلاس برای نگهداری اطلاعات هر محصول استفاده میشود.
+ کلاس `OrderEntity`: از این کلاس برای نگهداری اطلاعات هر سفارش استفاده میشود.
+ بستهی `ir.digipay.bulkshop.api` شامل کلاسهایی برای مدیریت ورودیها و خروجیهای *API* است.
+ بستهی `ir.digipay.bulkshop.rest` شامل *REST controller* های برنامه است. کنترلر مربوط به آدرس `/` برای تست برنامه در کلاس `IndexRestEnpoint` پیادهسازی شده است. سایر کنترلرها را در این بسته پیادهسازی کنید.
+ از آنجا که این برنامه اولین نسخهی سامانه است، هر سفارش میتواند شامل یک نوع محصول باشد، اما تعداد آن را میتوان در سفارش تعیین کرد.
## سرویسها
تعدادی وبسرویس *REST* مطابق نیازمندیهای زیر باید پیادهسازی شود:
| آدرس | عنوان |
| :------------------------ | ----------------------: |
| `GET /api/products` | دریافت اطلاعات محصولات |
| `POST /api/products` | ایجاد محصول |
| `GET /api/products/{id}` | دریافت اطلاعات یک محصول |
| `PUT /api/products` | ویرایش اطلاعات یک محصول |
| `GET /api/customers` | دریافت اطلاعات مشتریان |
| `POST /api/customers` | ایجاد مشتری |
| `GET /api/customers/{id}` | دریافت اطلاعات یک مشتری |
| `PUT /api/customers` | ویرایش اطلاعات یک مشتری |
| `GET /api/orders` | دریافت اطلاعات سفارشات |
| `POST /api/orders` | ایجاد سفارش |
| `GET /api/orders/{id}` | دریافت اطلاعات یک سفارش |
### دریافت اطلاعات محصولات
اطلاعات همهی محصولات در قالب یک آرایه برگردانده میشود:
```yml
URL: "GET /api/products"
http-code: 200
content-type: "application/json"
response: {
"products": [ # Array of ProductModel or ProductEntity
{
"id": "some_uuid",
"name": "x",
"price": 50000,
"availableCount": 100
},
{
"id": "some_uuid",
"name": "y",
"price": 75000,
"availableCount": 50
}
]
}
```
### ایجاد محصول
یک محصول با اطلاعات اولیهی دادهشده ایجاد میشود و شناسهی آن برگردانده میشود:
```yml
URL: "POST /api/products"
request: { # ProductCreateParam
"name": "x",
"price": 40000,
"initialAvailableCount": 100
}
http-code: 201
content-type: "application/json"
response: { # ProductCreateResult
"productId": "some_uuid"
}
```
### دریافت اطلاعات یک محصول
شناسهی محصول بهعنوان ورودی داده میشود و اطلاعات محصول برگردانده میشود:
```yml
URL: "GET /api/products/1234"
http-code: 200
content-type: "application/json"
response: { # ProductModel or ProductEntity
"id": "some_uuid",
"name": "z",
"price": 40000,
"availableCount": 150
}
```
اگر محصولی با شناسهی واردشده موجود نباشد، پاسخ باید بهصورت زیر باشد:
```yml
http-code: 404
content-type: "application/json"
response: {
"message": "Entity not found"
}
```
### ویرایش اطلاعات یک محصول
اطلاعات جدید محصول داده میشود و پس از بهروزرسانی اطلاعات محصول، پاسخی با کد `204` برگردانده میشود:
```yml
URL: "PUT /api/products"
request: { # ProductUpdateParam
"id": "some_uuid",
"name": "x2",
"price": 51000,
"availableCount": 200
}
http-code: 204
```
اگر محصولی با شناسهی واردشده موجود نباشد، پاسخ باید بهصورت زیر باشد:
```yml
http-code: 404
content-type: "application/json"
response: {
"message": "Entity not found"
}
```
### دریافت اطلاعات مشتریان
اطلاعات همهی مشتریان در قالب یک آرایه برگردانده میشود:
```yml
URL: "GET /api/customers"
http-code: 200
content-type: "application/json"
response: {
"customers": [ # Array of CustomerModel or CustomerEntity
{
"id": "some_uuid",
"username": "x",
"firstName": "x",
"lastName": "x"
},
{
"id": "some_uuid",
"username": "y",
"firstName": "y",
"lastName": "y"
}
]
}
```
### ایجاد مشتری
یک مشتری با اطلاعات اولیهی دادهشده ایجاد میشود و شناسهی آن برگردانده میشود:
```yml
URL: "POST /api/customers"
request: { # CustomerCreateParam
"username": "z",
"firstName": "Z",
"lastName": "z"
}
http-code: 201
content-type: "application/json"
response: { # CustomerCreateResult
"customerId": "some_uuid"
}
```
اگر مشتریای با نام کاربری دادهشده از قبل موجود باشد، پاسخ باید بهصورت زیر باشد:
```yml
http-code: 409
content-type: "application/json"
response: {
"message": "Username already taken"
}
```
### دریافت اطلاعات یک مشتری
شناسهی مشتری بهعنوان ورودی داده میشود و اطلاعات مشتری برگردانده میشود:
```yml
URL: "GET /api/customers/1"
http-code: 200
content-type: "application/json"
response: { # CustomerModel or CustomerEntity
"id": "some_uuid",
"username": "x",
"firstName": "x",
"lastName": "x"
}
```
اگر مشتریای با شناسهی واردشده موجود نباشد، پاسخ باید بهصورت زیر باشد:
```yml
http-code: 404
content-type: "application/json"
response: {
"message": "Entity not found"
}
```
### ویرایش اطلاعات یک مشتری
اطلاعات جدید مشتری داده میشود و پس از بهروزرسانی اطلاعات مشتری، پاسخی با کد `204` برگردانده میشود:
```yml
URL: "PUT /api/customers"
request: { # CustomerUpdateParam
"id": "some_uuid",
"username": "x2",
"firstName": "x2",
"lastName": "x2"
}
http-code: 204
```
اگر مشتریای با شناسهی واردشده موجود نباشد، پاسخ باید بهصورت زیر باشد:
```yml
http-code: 404
content-type: "application/json"
response: {
"message": "Entity not found"
}
```
### دریافت اطلاعات سفارشات
اطلاعات همهی محصولات در قالب یک آرایه برگردانده میشود:
```yml
URL: "GET /api/orders"
http-code: 200
content-type: "application/json"
response: {
"orders": [ # Array of OrderModel or OrderEntity
{
"id": "some_uuid",
"customerId": "some_uuid",
"productId": "some_uuid",
"count": 4
},
{
"id": "some_uuid",
"customerId": "some_uuid",
"productId": "some_uuid",
"count": 3
}
]
}
```
### ایجاد سفارش
یک سفارش با اطلاعات دادهشده ایجاد میشود، مقدار موجودی محصول به اندازهی تعداد واردشده کم میشود و شناسهی سفارش برگردانده میشود:
```yml
URL: "POST /api/orders"
request: { # OrderCreateParam
"customerId": "some_uuid",
"productId": "some_uuid",
"count": 6
}
http-code: 201
content-type: "application/json"
response: { # OrderCreateResult
"orderId": "some_uuid"
}
```
اگر مشتری یا محصولی با شناسهی واردشده موجود نباشد، پاسخ باید بهصورت زیر باشد:
```yml
http-code: 404
content-type: "application/json"
response: {
"message": "Entity not found"
}
```
اگر مقدار فیلد `count` کوچکتر یا مساوی صفر باشد، پاسخ باید بهصورت زیر باشد:
```yml
http-code: 400
content-type: "application/json"
response: {
"message": "Invalid count"
}
```
اگر مقدار `count` بزرگتر از موجودی فعلی محصول باشد، پاسخ باید بهصورت زیر باشد:
```yml
http-code: 400
content-type: "application/json"
response: {
"message": "Not enough available count"
}
```
### دریافت اطلاعات یک سفارش
شناسهی سفارش بهعنوان ورودی داده میشود و اطلاعات سفارش برگردانده میشود:
```yml
URL: "GET /api/orders/1234"
http-code: 200
content-type: "application/json"
response: { # OrderModel or OrderEntity
"id": "some_uuid",
"customerId": "some_uuid",
"productId": "some_uuid",
"count": 5
}
```
اگر سفارشی با شناسهی واردشده موجود نباشد، پاسخ باید بهصورت زیر باشد:
```yml
http-code: 404
content-type: "application/json"
response: {
"message": "Entity not found"
}
```
# نکات
+ ممکن است چند درخواست همزمان برای خرید یک محصول به برنامه ارسال شود. این درخواستها باید بهدرستی مدیریت شوند.
+ شما تنها مجاز به اعمال تغییرات در بستهی `ir.digipay.bulkshop` هستید.
# آنچه باید آپلود کنید
پس از پیادهسازی موارد خواستهشده، پوشهی `src` پروژه را زیپ کرده و ارسال کنید. توجه داشته باشید که فقط تغییرات اعمالشده در پوشهی `src/main/java/ir.digipay.bulkshop` در نظر گرفته میشوند.