میخواهیم یک سایت خرید اینترنتی محصولات مختلف بزنیم.
در این سایت کاربران میتوانند محصولات مختلف را مشاهده کرده و پس از انتخاب چند محصول فاکتور نهایی خرید خود را بینند.
بخشی از این پروژه نوشته شده است. از شما میخواهیم این پروژه را تکمیل کنید.
## پروژه اولیه
پروژه اولیه را از [این لینک](/problemset/assignments/4367/download_problem_initial_project/21211/) دانلود کنید. ساختار این پروژه به شرح زیر است:
```
shop
├── app
│ ├── migrations
│ │ ├── __init__.py
│ │ └── 0001_initial.py
| ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── <mark class="yellow" title="شما مجاز به تغییر این فایل هستید."> > models.py < </mark>
│ ├── urls.py
│ └── <mark class="yellow" title="شما مجاز به تغییر این فایل هستید."> > views.py < </mark>
| └── <mark class="yellow" title="شما مجاز به تغییر این فایل هستید."> > forms.py < </mark>
├── Shop
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
└── requirements.txt
```
## جزئیات
در فایل `models.py` چهار مدل به شرح زیر وجود دارد:
<details class="blue">
<summary> **۱. مدل** `Category` </summary>
این مدل شامل فیلد زیر است:
+ نام : `name`
</details>
<details class="blue">
<summary> **۲. مدل** `Product` </summary>
این مدل شامل فیلدهای زیر است:
+ نام محصول : `name`
+ دسته محصول : `category`
+ توضیحات : `description`
+ قیمت محصول : `price`
+ موجودی انبار : `stock`
</details>
<details class="blue">
<summary> **۳. مدل** `Order` </summary>
این مدل شامل فیلدهای زیر است:
+ ایمیل سفارشدهنده : `email`
+ آدرس سفارشدهنده : `address`
</details>
<details class="blue">
<summary> **۴. مدل** `OrderItem` </summary>
این مدل شامل فیلدهای زیر است:
+ سفارش مربوطه : `order`
+ محصول سفارشداده شده : `product`
+ تعداد : `quantity`
</details>
مواردی که باید انجام دهید:
<details class="green">
<summary> **۱. نوشتن منیجر** </summary>
یک منیجر جدید به نام `available` برای مدل `Product` بنویسید به طوری که فقط کالاهایی را که در انبار موجودند برگرداند.
+ منیجر (objects) باید همانند سابق منیجر پیشفرض باقی بماند.
``` shell terminal terminal
>>> Product.objects.all()
<QuerySet [<Product: pc>, <Product: mouse>, ...]>
>>> Product.available.all()
<QuerySet [<Product: pc>, ...]>
>>> Product.available.filter(price__gt=20)
<QuerySet [<Product: pc>, <Product: keyboard>, ...>
```
</details>
<details class="green">
<summary> **۲. نوشتن فرم** </summary>
در این قسمت باید یک مدلفرم برای مدل `Product` بنویسید. برای این کار، فایل `apps/forms.py` دارای یک کلاس `ProductForm` است که باید آن را پیادهسازی کنید. کالاهایی که به وسیلهی این فرم ساخته میشوند باید ویژگیهای زیر را دارا باشند:
* قیمت کالا از 1000 نباید بیشتر باشد. در صورت بیشتر بودن این قیمت از 1000، باید یک `ValidationError` با پیام `Product is too expensive` پرتاب شود.
* طول توضیحات کالا باید از 20 کاراکتر بیشتر باشد. در صورتی که این طول کمتر یا مساوی 20 باشد، باید یک `ValidationError` با پیام `Product must have a good description` پرتاب شود.
</details>
<details class="green">
<summary> **۳. نمایش قیمت نهایی یک** `order` </summary>
در این قسمت باید view محاسبه قیمت نهایی `order` را (`checkout`) طوری تغییر دهید که قیمت نهایی یک `order` مشخص (`int:pk`) را به صورت یک خروجی JSON به شکل زیر برگرداند.
```json
{"total_price": "12.31"}
```
+ این مقدار از نوع `Decimal` می باشد و باید تا دو رقم اعشار مقدار آن حفظ شود.
+ نیازی به تغییر stock پس از checkout نمیباشد و تضمین میشود که در تستها تعداد کالای سفارشداده شده برابر و یا کمتر از موجودی کالا باشد.
+ اگر فاکتوری با ID مورد نظر موجود نبود، خطایی با استاتوسکد `404` برگردانید.
</details>
## تست نمونه
در فایلهای اولیهای که دانلود کردید یکسری داده اولیه به عنوان نمونه قرار داده شده است. میتوانید قبل از فرستادن سوال در سایت، این تستها را ببینید تا با نحوه داوری ما آشنا شوید و از پاسخ خود اطمینان حاصل نمایید.
تستها را میتوانید با دستور زیر اجرا کنید:
```shell terminal terminal
python manage.py test
```
## نکات
+ شما تنها مجاز به تغییر در `app/views.py`، `app/models.py` و `app/forms.py` هستید.
اگر تغییری در سایر فایلها ایجاد کنید، این تغییرات نادیده گرفته خواهد شد.
+ فراموش نکنید که میتوانید با مطالعهی `testsample.py` با روش تست کردن آشنا شوید.
## نحوه ارسال
یک فایل _ZIP_ حاوی همهی فایلهای پروژه، آپلود کنید. نام فایل _ZIP_ اهمیتی ندارد.