*فرهاد* که به تازگی در کوئرا استخدام شده، تصمیم گرفته برای کمک به بخش [Careers کوئرا](https://talent.quera.ir/) تعدادی دستور طراحی کند. او که تسلط کمی به خط فرمان دارد و فقط توانسته مدل شرکت را تکمیل کند و به علت همزمان شدن امتحاناتش با زمان تحویل، به کمک شما برای تکمیل دستورات نیاز دارد.
## پروژه اولیه
پروژه اولیه را از [این لینک](/contest/assignments/30822/download_problem_initial_project/102170/) دریافت کنید.
ساختار فایلهای این پروژه به صورت زیر است.
<details class="green">
<summary> **ساختار درختی پروژه** </summary>
```
CLI
├── career
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── management
│ │ ├── commands
│ │ │ ├── <mark class="yellow" title="این فایل را تغییر دهید"> > addCompany.py < </mark>
│ │ │ ├── <mark class="yellow" title="این فایل را تغییر دهید"> > collectCompany.py < </mark>
│ │ │ ├── <mark class="yellow" title="این فایل را تغییر دهید"> > editCompany.py < </mark>
│ │ │ ├── __init__.py
│ │ │ └── <mark class="yellow" title="این فایل را تغییر دهید"> > rmCompany.py < </mark>
│ │ └── __init__.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ ├── utils.py
│ └── views.py
├── config
│ ├── asgi.py
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
├── requirements.txt
└── tests
├── __init__.py
└── testssample.py
```
</details>
برای کمک به *فرهاد*، دستورات خواسته شده را در فایلهای خواسته شده پیادهسازی کنید.
<details class="blue">
<summary> **دستور** `addCompany` </summary>
میخواهیم درون فایل `addCompany.py`، دستوری برای جنگو بنویسیم که با اجرای آن، به ترتیب مقادیر *name*, *email*, *phone*, *description* (از چپ به راست) را از کاربر دریافت کند و با این مقادیر، یک نمونه از کلاس *Company* بسازد.
+ برای فیلدهايی که دارای ویژگی `null=False` هستند، کاربر حتما باید مقداری را وارد کند. در صورتی که کاربر بدون وارد کردن مقداری *Enter* زد باید خطای `Error: This field cannot be blank.` نمایش داده شود و برای فیلدهایی که دارای ویژگی `null=True` هستند، با زدن *Enter* به مرحله بعد رفته و مقدار آن فیلد *None* شود.
### اعتبارسنجی مخصوص هر فیلد:
<details class="grey">
<summary> **name** </summary>
فیلد `name` باید حداکثر ۵۰ کاراکتر باشد؛ در غیر اینصورت، عبارت
`Error: Ensure this value has at most 50 characters (it has COUNT).`
نمایش داده شود که به جای کلمهی *COUNT*، تعداد کاراکترهای عبارت شما قرار میگیرد.
همچنین این فیلد باید یکتا باشد؛ در غیر اینصورت، عبارت
`Error: That name is already taken.`
نمایش داده شود.
</details>
<details class="grey">
<summary> **email** </summary>
آدرس وارد شده باید یک ایمیل معتبر باشد، در غیر اینصورت باید عبارت
`Error: Enter a valid email address.`
نمایش داده شود.
</details>
<details class="grey">
<summary> **phone** </summary>
یک شماره موبایل در صورتی معتبر است که یکی از حالتهای زیر را دارا باشد:
* شامل ۱۱ رقم باشد و با 09 آغاز شود.
* شامل ۱۳ رقم باشد و با 98+ آغاز شود.
* شامل ۱۴ رقم باشد و با 0098 آغاز شود.
در غیر این صورت باید عبارت
`Error: Phone number format is not valid.`
نمایش داده شود.
</details>
<details class="grey">
<summary> **description** </summary>
این فیلد محدودیتی ندارد.
</details>
### نکات مهم
* در صورت وارد شدن مقدار غیر قابل قبول برای هر فیلد، خط فرمان همچنان منتظر وارد شدن مقدار قابل قبول برای همان فیلد میماند.
* برای چاپ خطاها، حتماً از دستور `self.stderr.write(error_msg)` استفاده کنید.
### نمونه
![توضیح تصویر](https://s4.uupload.ir/files/contest1_pdos.png)
</details>
</details>
<details class="blue">
<summary> **دستور** `editCompany` </summary>
میخواهیم درون فایل `editCompany.py`، دستوری برای جنگو بنویسیم که یک *positional arguments* به عنوان نام شرکت و همچنین چهار *optional arguments* (`--description` ,`--phone` ,`--email` ,`--name`) دریافت و فیلدهای مربوط به آن شرکت را بروز کند.
+ برای فیلدهايی که دارای ویژگی `null=False` هستند، اگر آرگومان آنها برابر `''` بود؛ استثنای *CommandError* با پیام `Field cannot be blank.` رخ دهد (به جای کلمهی `Field`، نام فیلد با حرف ابتدای **بزرگ** قرار میگیرد.) اما برای فیلدهایی که دارای ویژگی `null=True` هستند، میتواند برابر `''` باشد؛ ولی مقدار فیلد تغییری نمیکند.
+ در هر مرحله از اعتبار سنجی که در ادامه اشاره میشود، اگر مقادیر، معتبر نبودند باید استثنای *CommandError* با پیام خطای مربوط رخ دهد.
+ موارد، به ترتیب نوشتهشده باید بررسی شوند.
<details class="grey">
<summary> **positional arguments** </summary>
در صورتی که شرکتی با این نام وجود نداشت؛ باید یک `Exception` با پیام
`Company matching query does not exist.`
رخ دهد.
</details>
<details class="grey">
<summary> **optional arguments** </summary>
<details class="yellow">
<summary> **name** </summary>
آرگومان `name` باید حداکثر ۵۰ کاراکتر باشد؛ در غیر اینصورت، یک `Exception` با پیام
`Error: Ensure this value has at most 50 characters (it has NUM).`
رخ دهد که به جای *NUM* تعداد کاراکترهای عبارت شما قرار میگیرد.
همچنین این فیلد باید یکتا باشد، در غیر اینصورت، باید یک `Exception` با پیام
`Error: That name is already taken.`
رخ دهد.
</details>
<details class="yellow">
<summary> **email** </summary>
آدرس وارد شده باید یک ایمیل معتبر باشد در غیر این صورت باید یک `Exception` با پیام
`Error: Enter a valid email address.`
رخ دهد.
</details>
<details class="yellow">
<summary> **phone** </summary>
یک شماره موبایل در صورتی معتبر است که یکی از حالتهای زیر را دارا باشد:
* شامل ۱۱ رقم باشد و با 09 آغاز شود.
* شامل ۱۳ رقم باشد و با 98+ آغاز شود.
* شامل ۱۴ رقم باشد و با 0098 آغاز شود.
در غیر این صورت باید یک `Exception` با پیام
`Error: Phone number format is not valid.`
رخ دهد.
</details>
<details class="yellow">
<summary> **description** </summary>
این آرگومان محدودیتی ندارد.
</details>
</details>
### نمونه
![توضیح تصویر](https://s4.uupload.ir/files/contest2_xqbo.png)
</details>
</details>
<details class="blue">
<summary> **دستور** `rmCompany` </summary>
میخواهیم درون فایل `rmCompany.py`، برای جنگو بنویسیم که نام تعدادی (صفر یا بیشتر) شرکت را دریافت کند و درصورتی که شرکتی با آن نامها وجود داشت آن را از پایگاه داده حذف کند.
<details class="grey">
<summary> **positional argument** </summary>
در صورتی که شرکتی با این نامها وجود نداشت، به ازای هر نام غیرمعتبر باید عبارت
`COMPANY matching query does not exist.`
نمایش داده شود، که به جای *COMPANY* نام شرکت وارد شده قرار میگیرد.
</details>
<details class="grey">
<summary> **optional argument** </summary>
در صورت وجود `--all` در دستور، بدون توجه به نام شرکتهای وارد شده (در صورت وجود)، تمام شرکتها حذف میشوند.
</details>
### نکات مهم
+ برای چاپ خطا، حتماً از دستور `self.stderr.write(error_msg)` استفاده کنید.
### نمونه
![توضیح تصویر](https://s4.uupload.ir/files/contest3_7vly.png)
</details>
<details class="blue">
<summary> **دستور** `collectCompany` </summary>
میخواهیم درون فایل `collectCompany.py`، دستوری برای جنگو بنویسیم که با اجرای آن، یک فایل *CSV* به نام `company.csv` شامل اطلاعات تماس شرکتها، در ریشهی پروژه ایجاد شود.
+ ستونهای فایل *CSV* به ترتیب (از چپ به راست) نام، ایمیل و تلفن شرکت است.
</details>
## نکات
+ توجه کنید که در قسمتهایی که گفته شده عبارت مورد نظر نمایش داده شود، باید از دستور `self.stderr.write(error_msg)` و در قسمتهایی که گفته شده یک `Exception` رخ دهد، از دستور `raise` استفاده کنید.
+ شما تنها مجوز ایجاد تغییرات در فایلهای زیر را دارید و **تمامی تغییرات دیگر شما** در فایلهای پروژه **نادیده گرفته خواهند شد.**
+ فایل `career/management/commands/addCompany.py`
+ فایل `career/management/commands/collectCompany.py`
+ فایل `career/management/commands/editCompany.py`
+ فایل `career/management/commands/rmCompany.py`
## آنچه باید آپلود کنید
این سوال از نوع سوالات چندفایلی است. برای حل سوال میتوانید پروژه را در قالب یک فایل *ZIP* که شامل کلیه فایلهای موجود در پروژه است، ارسال کنید.
ارسال پاسخ برای این سؤال
در حال حاضر شما دسترسی ندارید.