init
Some checks failed
CI/CD / Backend & Frontend Checks (push) Has been cancelled
CI/CD / Deploy to Production (push) Has been cancelled

This commit is contained in:
2026-05-18 11:34:07 +03:30
commit 7a8ddeabed
279 changed files with 37390 additions and 0 deletions

85
backend/utils/admin.py Normal file
View File

@@ -0,0 +1,85 @@
from django.contrib import admin, messages
from django.utils.translation import gettext_lazy as _
from django.db import transaction
from django.db.models.deletion import ProtectedError
from unfold.admin import ModelAdmin
class SoftDeleteListFilter(admin.SimpleListFilter):
title = _('Soft Delete Status')
parameter_name = 'is_deleted'
def lookups(self, request, model_admin):
return [
('0', _('Active')),
('1', _('Deleted')),
]
def queryset(self, request, queryset):
if self.value() == '0':
return queryset.filter(is_deleted=False)
if self.value() == '1':
return queryset.model.deleted_objects.all()
return queryset
class BaseModelAdmin(ModelAdmin):
actions = ["hard_delete_selected", "restore_selected"]
def get_queryset(self, request):
return self.model.all_objects.all()
@admin.action(description=_('Hard delete selected (permanent)'))
def hard_delete_selected(self, request, queryset):
"""
حذف فیزیکی رکوردهای انتخاب‌شده (دورزدن SoftDelete).
"""
count = queryset.count()
try:
with transaction.atomic():
queryset.hard_delete()
self.message_user(
request,
_('%(count)d record(s) permanently deleted.') % {'count': count},
level=messages.SUCCESS
)
except ProtectedError:
self.message_user(
request,
_('Cannot hard delete because related protected objects exist.'),
level=messages.ERROR
)
except Exception as e:
self.message_user(request, str(e), level=messages.ERROR)
@admin.action(description=_('Restore selected (undo soft delete)'))
def restore_selected(self, request, queryset):
"""
بازگردانی رکوردهای soft-deleted.
"""
restored = 0
for obj in queryset:
if getattr(obj, "is_deleted", False):
obj.restore()
restored += 1
self.message_user(
request,
_('%(count)d record(s) restored.') % {'count': restored},
level=messages.SUCCESS
)
def get_actions(self, request):
actions = super().get_actions(request)
if not request.user.is_superuser:
actions.pop("hard_delete_selected", None)
is_deleted_filter = request.GET.get('is_deleted')
should_show_restore_actions = is_deleted_filter == '1'
if not should_show_restore_actions:
actions.pop('restore_selected', None)
actions.pop('hard_delete_selected', None)
return actions

293
backend/utils/choices.py Normal file
View File

@@ -0,0 +1,293 @@
from enum import Enum
from django.db import models
class MajorChoices(models.TextChoices):
# مهندسی و کامپیوتر
CE = 'CE', 'مهندسی کامپیوتر'
CS = 'CS', 'علوم کامپیوتر'
SE = 'SE', 'مهندسی نرم‌افزار'
IT = 'IT', 'فناوری اطلاعات'
AI = 'AI', 'هوش مصنوعی و رباتیک'
DATA = 'DATA', 'علم داده'
EE = 'EE', 'مهندسی برق'
ME = 'ME', 'مهندسی مکانیک'
CIV = 'CIV', 'مهندسی عمران'
CHE = 'CHE', 'مهندسی شیمی'
IE = 'IE', 'مهندسی صنایع'
MSE = 'MSE', 'مهندسی مواد و متالورژی'
BME = 'BME', 'مهندسی پزشکی'
ARCH = 'ARCH', 'معماری'
AERO = 'AERO', 'مهندسی هوافضا'
PET = 'PET', 'مهندسی نفت'
MIN = 'MIN', 'مهندسی معدن'
ENV = 'ENV', 'مهندسی محیط‌زیست'
URP = 'URP', 'برنامه‌ریزی شهری و منطقه‌ای'
# علوم پایه
MATH = 'MATH', 'ریاضیات'
STAT = 'STAT', 'آمار'
PHYS = 'PHYS', 'فیزیک'
CHEM = 'CHEM', 'شیمی'
BIO = 'BIO', 'زیست‌شناسی'
GEO = 'GEO', 'زمین‌شناسی'
# پزشکی و پیراپزشکی (در صورت داشتن دانشکده‌های مربوط)
MED = 'MED', 'پزشکی'
DEN = 'DEN', 'دندان‌پزشکی'
PHARM= 'PHARM','داروسازی'
NURS = 'NURS', 'پرستاری'
MID = 'MID', 'مامایی'
LAB = 'LAB', 'علوم آزمایشگاهی'
RAD = 'RAD', 'رادیولوژی'
ANES = 'ANES', 'بیهوشی'
PUBH = 'PUBH', 'بهداشت'
# کشاورزی و دامپزشکی (اگر دارید)
AGRI = 'AGRI', 'کشاورزی (عمومی)'
HORT = 'HORT', 'باغبانی'
PLP = 'PLP', 'گیاه‌پزشکی'
SOIL = 'SOIL', 'علوم خاک'
VET = 'VET', 'دامپزشکی'
# مدیریت و اقتصاد
MGT = 'MGT', 'مدیریت'
ACC = 'ACC', 'حسابداری'
FIN = 'FIN', 'مالی'
ECO = 'ECO', 'اقتصاد'
BA = 'BA', 'مدیریت بازرگانی'
# علوم انسانی و هنر
LAW = 'LAW', 'حقوق'
POL = 'POL', 'علوم سیاسی'
SOC = 'SOC', 'جامعه‌شناسی'
PSY = 'PSY', 'روان‌شناسی'
PHIL = 'PHIL', 'فلسفه'
HIST = 'HIST', 'تاریخ'
GEOG = 'GEOG', 'جغرافیا'
EDU = 'EDU', 'علوم تربیتی'
PEd = 'PEd', 'تربیت بدنی'
LIT_FA = 'LIT_FA', 'زبان و ادبیات فارسی'
LIT_EN = 'LIT_EN', 'زبان و ادبیات انگلیسی'
LIT_AR = 'LIT_AR', 'زبان و ادبیات عربی'
TRAN_EN= 'TRAN_EN','مترجمی زبان انگلیسی'
ART = 'ART', 'هنرهای تجسمی'
GRAPH= 'GRAPH','گرافیک'
MUSIC= 'MUSIC','موسیقی'
THEAT= 'THEAT','نمایش و تئاتر'
from django.db import models
class UniversityChoices(models.TextChoices):
"""University codes preserving legacy constant names for backward compatibility."""
# ========= دولتی (وزارت علوم) =========
# موارد قبلی شما (بدون تغییر کدها)
GILAN = 'GILAN', 'دانشگاه گیلان'
UT = 'UT', 'دانشگاه تهران'
AUT = 'AUT', 'دانشگاه صنعتی امیرکبیر'
SHARIF = 'SHARIF', 'دانشگاه صنعتی شریف'
SBU = 'SBU', 'دانشگاه شهید بهشتی'
IUST = 'IUST', 'دانشگاه علم و صنعت ایران'
KNTU = 'KNTU', 'دانشگاه صنعتی خواجه‌نصیر'
MODARES = 'MODARES', 'دانشگاه تربیت مدرس'
ALLAMEH = 'ALLAMEH', 'دانشگاه علامه طباطبایی'
KHARAZMI = 'KHARAZMI', 'دانشگاه خوارزمی'
ISFAHAN_UNI = 'ISFAHAN_UNI', 'دانشگاه اصفهان'
IUT = 'IUT', 'دانشگاه صنعتی اصفهان'
SHIRAZ_UNI = 'SHIRAZ_UNI', 'دانشگاه شیراز'
SHIRAZ_TECH = 'SHIRAZ_TECH', 'دانشگاه صنعتی شیراز'
TABRIZ_UNI = 'TABRIZ_UNI', 'دانشگاه تبریز'
FERDOWSI = 'FERDOWSI', 'دانشگاه فردوسی مشهد'
IMAMREZA = 'IMAMREZA', 'دانشگاه بین المللی امام رضا مشهد'
RAZI = 'RAZI', 'دانشگاه رازی'
SHAHRKORD = 'SHAHRKORD', 'دانشگاه شهرکرد'
BUALI = 'BUALI', 'دانشگاه بوعلی‌سینا'
KURDISTAN = 'KURDISTAN', 'دانشگاه کردستان'
YAZD_UNI = 'YAZD_UNI', 'دانشگاه یزد'
KERMAN_UNI = 'KERMAN_UNI', 'دانشگاه شهید باهنر کرمان'
MAZANDARAN = 'MAZANDARAN', 'دانشگاه مازندران'
GOLESTAN = 'GOLESTAN', 'دانشگاه گلستان'
URMIA = 'URMIA', 'دانشگاه ارومیه'
ZANJAN = 'ZANJAN', 'دانشگاه زنجان'
ARDABIL = 'ARDABIL', 'دانشگاه محقق اردبیلی'
ARak_UNI = 'ARAK_UNI', 'دانشگاه اراک'
SEMNAN = 'SEMNAN', 'دانشگاه سمنان'
SHAHROOD = 'SHAHROOD', 'دانشگاه صنعتی شاهرود'
QOM_UNI = 'QOM_UNI', 'دانشگاه قم'
QOM_TECH = 'QOM_TECH', 'دانشگاه صنعتی قم'
IKIU = 'IKIU', 'دانشگاه بین‌المللی امام خمینی قزوین'
MAL_ASHTAR = 'MAL_ASHTAR', 'دانشگاه صنعتی مالک‌اشتر'
SAHAND = 'SAHAND', 'دانشگاه صنعتی سهند'
BABOL_NOSH = 'BABOL_NOSH', 'دانشگاه صنعتی نوشیروانی بابل'
BIRGAND = 'BIRGAND', 'دانشگاه بیرجند'
# ======= افزودنی‌های دولتی (نمونه‌های شاخص و پرتکرار) =======
ALZAHRA = 'ALZAHRA', 'دانشگاه الزهرا'
TAFRESH = 'TAFRESH', 'دانشگاه تفرش'
JAHROM = 'JAHROM', 'دانشگاه جهرم'
HAKIM_SABZ = 'HAKIM_SABZ', 'دانشگاه حکیم سبزواری'
PERSIAN_GULF = 'PERSIAN_GULF', 'دانشگاه خلیج فارس'
DAMGHAN = 'DAMGHAN', 'دانشگاه دامغان'
ILAM = 'ILAM', 'دانشگاه ایلام'
BOJNORD = 'BOJNORD', 'دانشگاه بجنورد'
KASHAN = 'KASHAN', 'دانشگاه کاشان'
LORESTAN = 'LORESTAN', 'دانشگاه لرستان'
MARAGHEH = 'MARAGHEH', 'دانشگاه مراغه'
MALAYER = 'MALAYER', 'دانشگاه ملایر'
NEYSHABUR = 'NEYSHABUR', 'دانشگاه نیشابور'
HORMOZGAN = 'HORMOZGAN', 'دانشگاه هرمزگان'
HONAR = 'HONAR', 'دانشگاه هنر'
# ========= علوم پزشکی =========
TUMS = 'TUMS', 'دانشگاه علوم پزشکی تهران'
SBMU_MED = 'SBMU_MED', 'دانشگاه علوم پزشکی شهید بهشتی'
IUMS_MED = 'IUMS_MED', 'دانشگاه علوم پزشکی ایران'
MUMS_MED = 'MUMS_MED', 'دانشگاه علوم پزشکی مشهد'
SUMS_MED = 'SUMS_MED', 'دانشگاه علوم پزشکی شیراز'
TBZ_MED = 'TBZ_MED', 'دانشگاه علوم پزشکی تبریز'
ISF_MED = 'ISF_MED', 'دانشگاه علوم پزشکی اصفهان'
AJUMS_MED = 'AJUMS_MED', 'دانشگاه علوم پزشکی اهواز'
AJA_MED = 'AJA_MED', 'دانشگاه علوم پزشکی ارتش'
KUMS_MED = 'KUMS_MED', 'دانشگاه علوم پزشکی کرمانشاه'
KER_MED = 'KER_MED', 'دانشگاه علوم پزشکی کرمان'
MED_QOM = 'MED_QOM', 'دانشگاه علوم پزشکی قم'
MED_QAZVIN = 'MED_QAZVIN', 'دانشگاه علوم پزشکی قزوین'
MED_ALBORZ = 'MED_ALBORZ', 'دانشگاه علوم پزشکی البرز'
MED_ARAK = 'MED_ARAK', 'دانشگاه علوم پزشکی اراک'
MED_ZANJAN = 'MED_ZANJAN', 'دانشگاه علوم پزشکی زنجان'
MED_MAZANDARAN= 'MED_MAZANDARAN','دانشگاه علوم پزشکی مازندران'
MED_BABOL = 'MED_BABOL', 'دانشگاه علوم پزشکی بابل'
MED_GOLESTAN = 'MED_GOLESTAN', 'دانشگاه علوم پزشکی گلستان'
MED_GILAN = 'MED_GILAN', 'دانشگاه علوم پزشکی گیلان'
MED_HORMOZGAN = 'MED_HORMOZGAN', 'دانشگاه علوم پزشکی هرمزگان'
MED_BUSHEHR = 'MED_BUSHEHR', 'دانشگاه علوم پزشکی بوشهر'
MED_BIRJAND = 'MED_BIRJAND', 'دانشگاه علوم پزشکی بیرجند'
MED_BOJNORD = 'MED_BOJNORD', 'دانشگاه علوم پزشکی خراسان شمالی (بجنورد)'
MED_SABZEVAR = 'MED_SABZEVAR', 'دانشگاه علوم پزشکی سبزوار'
MED_NEYSHABUR = 'MED_NEYSHABUR', 'دانشگاه علوم پزشکی نیشابور'
MED_GONABAD = 'MED_GONABAD', 'دانشگاه علوم پزشکی گناباد'
MED_SHAHROUD = 'MED_SHAHROUD', 'دانشگاه علوم پزشکی شاهرود'
MED_SEMNAN = 'MED_SEMNAN', 'دانشگاه علوم پزشکی سمنان'
MED_YAZD = 'MED_YAZD', 'دانشگاه علوم پزشکی یزد'
MED_URMIA = 'MED_URMIA', 'دانشگاه علوم پزشکی ارومیه'
MED_ARDABIL = 'MED_ARDABIL', 'دانشگاه علوم پزشکی اردبیل'
MED_HAMEDAN = 'MED_HAMEDAN', 'دانشگاه علوم پزشکی همدان'
MED_LARESTAN = 'MED_LARESTAN', 'دانشکده علوم پزشکی لارستان'
MED_FASA = 'MED_FASA', 'دانشگاه علوم پزشکی فسا'
MED_JAHROM = 'MED_JAHROM', 'دانشگاه علوم پزشکی جهرم'
MED_KASHAN = 'MED_KASHAN', 'دانشگاه علوم پزشکی کاشان'
MED_ILAM = 'MED_ILAM', 'دانشگاه علوم پزشکی ایلام'
MED_LORESTAN = 'MED_LORESTAN', 'دانشگاه علوم پزشکی لرستان'
MED_KHUZESTAN = 'MED_KHUZESTAN', 'دانشگاه علوم پزشکی دزفول/شوشتر (استان خوزستان)'
# ========= آزاد اسلامی (واحدهای شاخص و پرتردد) =========
IAU_TEH_CENTRAL = 'IAU_TEH_CENTRAL', 'دانشگاه آزاد اسلامی واحد تهران مرکزی'
IAU_TEH_NORTH = 'IAU_TEH_NORTH', 'دانشگاه آزاد اسلامی واحد تهران شمال'
IAU_TEH_SOUTH = 'IAU_TEH_SOUTH', 'دانشگاه آزاد اسلامی واحد تهران جنوب'
IAU_TEH_WEST = 'IAU_TEH_WEST', 'دانشگاه آزاد اسلامی واحد تهران غرب'
IAU_TEH_EAST = 'IAU_TEH_EAST', 'دانشگاه آزاد اسلامی واحد تهران شرق'
IAU_SRT_TEHRAN = 'IAU_SRT_TEHRAN', 'دانشگاه آزاد اسلامی واحد علوم و تحقیقات تهران'
IAU_QAZVIN = 'IAU_QAZVIN', 'دانشگاه آزاد اسلامی قزوین'
IAU_NAJAFABAD = 'IAU_NAJAFABAD', 'دانشگاه آزاد اسلامی نجف‌آباد'
IAU_MASHHAD = 'IAU_MASHHAD', 'دانشگاه آزاد اسلامی مشهد'
IAU_TABRIZ = 'IAU_TABRIZ', 'دانشگاه آزاد اسلامی تبریز'
IAU_SHIRAZ = 'IAU_SHIRAZ', 'دانشگاه آزاد اسلامی شیراز'
IAU_ISFAHAN = 'IAU_ISFAHAN', 'دانشگاه آزاد اسلامی اصفهان (خوراسگان)'
IAU_KARAJ = 'IAU_KARAJ', 'دانشگاه آزاد اسلامی کرج'
IAU_QOM = 'IAU_QOM', 'دانشگاه آزاد اسلامی قم'
IAU_RASHT = 'IAU_RASHT', 'دانشگاه آزاد اسلامی رشت'
IAU_LAHIJAN = 'IAU_LAHIJAN', 'دانشگاه آزاد اسلامی لاهیجان'
IAU_SARI = 'IAU_SARI', 'دانشگاه آزاد اسلامی ساری'
IAU_YAZD = 'IAU_YAZD', 'دانشگاه آزاد اسلامی یزد'
IAU_KERMAN = 'IAU_KERMAN', 'دانشگاه آزاد اسلامی کرمان'
IAU_BANDARABBAS = 'IAU_BANDARABBAS', 'دانشگاه آزاد اسلامی بندرعباس'
IAU_BUSHEHR = 'IAU_BUSHEHR', 'دانشگاه آزاد اسلامی بوشهر'
IAU_AHVAZ = 'IAU_AHVAZ', 'دانشگاه آزاد اسلامی اهواز'
IAU_KHORRAMABAD = 'IAU_KHORRAMABAD', 'دانشگاه آزاد اسلامی خرم‌آباد'
IAU_SANANDAJ = 'IAU_SANANDAJ', 'دانشگاه آزاد اسلامی سنندج'
IAU_HAMEDAN = 'IAU_HAMEDAN', 'دانشگاه آزاد اسلامی همدان'
IAU_ARAK = 'IAU_ARAK', 'دانشگاه آزاد اسلامی اراک'
IAU_URMIA = 'IAU_URMIA', 'دانشگاه آزاد اسلامی ارومیه'
IAU_ZANJAN = 'IAU_ZANJAN', 'دانشگاه آزاد اسلامی زنجان'
IAU_BIRJAND = 'IAU_BIRJAND', 'دانشگاه آزاد اسلامی بیرجند'
IAU_BOJNORD = 'IAU_BOJNORD', 'دانشگاه آزاد اسلامی بجنورد'
IAU_SEMNAN = 'IAU_SEMNAN', 'دانشگاه آزاد اسلامی سمنان'
IAU_GORGAN = 'IAU_GORGAN', 'دانشگاه آزاد اسلامی گرگان'
IAU_MARVDASHT = 'IAU_MARVDASHT', 'دانشگاه آزاد اسلامی مرودشت'
IAU_KISH_INTL = 'IAU_KISH_INTL', 'دانشگاه آزاد اسلامی بین‌الملل کیش'
IAU_QESHM_INTL = 'IAU_QESHM_INTL', 'دانشگاه آزاد اسلامی قشم (بین‌الملل)'
# ========= پیام نور (به تفکیک استان) =========
PNU_EAST_AZERBAIJAN = 'PNU_EAST_AZERBAIJAN', 'دانشگاه پیام نور آذربایجان شرقی'
PNU_WEST_AZERBAIJAN = 'PNU_WEST_AZERBAIJAN', 'دانشگاه پیام نور آذربایجان غربی'
PNU_ARDABIL = 'PNU_ARDABIL', 'دانشگاه پیام نور اردبیل'
PNU_ISFAHAN = 'PNU_ISFAHAN', 'دانشگاه پیام نور اصفهان'
PNU_ALBORZ = 'PNU_ALBORZ', 'دانشگاه پیام نور البرز'
PNU_ILAM = 'PNU_ILAM', 'دانشگاه پیام نور ایلام'
PNU_BUSHEHR = 'PNU_BUSHEHR', 'دانشگاه پیام نور بوشهر'
PNU_TEHRAN = 'PNU_TEHRAN', 'دانشگاه پیام نور تهران'
PNU_CH_BAKHTIARI = 'PNU_CH_BAKHTIARI', 'دانشگاه پیام نور چهارمحال و بختیاری'
PNU_SOUTH_KHORASAN = 'PNU_SOUTH_KHORASAN', 'دانشگاه پیام نور خراسان جنوبی'
PNU_RAZAVI_KHORASAN = 'PNU_RAZAVI_KHORASAN', 'دانشگاه پیام نور خراسان رضوی'
PNU_NORTH_KHORASAN = 'PNU_NORTH_KHORASAN', 'دانشگاه پیام نور خراسان شمالی'
PNU_KHUZESTAN = 'PNU_KHUZESTAN', 'دانشگاه پیام نور خوزستان'
PNU_ZANJAN = 'PNU_ZANJAN', 'دانشگاه پیام نور زنجان'
PNU_SEMNAN = 'PNU_SEMNAN', 'دانشگاه پیام نور سمنان'
PNU_SISTAN_BALUCH = 'PNU_SISTAN_BALUCH', 'دانشگاه پیام نور سیستان و بلوچستان'
PNU_FARS = 'PNU_FARS', 'دانشگاه پیام نور فارس'
PNU_QAZVIN = 'PNU_QAZVIN', 'دانشگاه پیام نور قزوین'
PNU_QOM = 'PNU_QOM', 'دانشگاه پیام نور قم'
PNU_KURDISTAN = 'PNU_KURDISTAN', 'دانشگاه پیام نور کردستان'
PNU_KERMAN = 'PNU_KERMAN', 'دانشگاه پیام نور کرمان'
PNU_KERMANSHAH = 'PNU_KERMANSHAH', 'دانشگاه پیام نور کرمانشاه'
PNU_KOHGILUYEH = 'PNU_KOHGILUYEH', 'دانشگاه پیام نور کهگیلویه و بویراحمد'
PNU_GOLESTAN = 'PNU_GOLESTAN', 'دانشگاه پیام نور گلستان'
PNU_GILAN = 'PNU_GILAN', 'دانشگاه پیام نور گیلان'
PNU_LORESTAN = 'PNU_LORESTAN', 'دانشگاه پیام نور لرستان'
PNU_MAZANDARAN = 'PNU_MAZANDARAN', 'دانشگاه پیام نور مازندران'
PNU_MARKAZI = 'PNU_MARKAZI', 'دانشگاه پیام نور مرکزی'
PNU_HORMOZGAN = 'PNU_HORMOZGAN', 'دانشگاه پیام نور هرمزگان'
PNU_HAMEDAN = 'PNU_HAMEDAN', 'دانشگاه پیام نور همدان'
PNU_YAZD = 'PNU_YAZD', 'دانشگاه پیام نور یزد'
# ========= جامع علمی‌ـ‌کاربردی (به تفکیک استان) =========
UAST_EAST_AZERBAIJAN = 'UAST_EAST_AZERBAIJAN', 'دانشگاه جامع علمی کاربردی آذربایجان شرقی'
UAST_WEST_AZERBAIJAN = 'UAST_WEST_AZERBAIJAN', 'دانشگاه جامع علمی کاربردی آذربایجان غربی'
UAST_ARDABIL = 'UAST_ARDABIL', 'دانشگاه جامع علمی کاربردی اردبیل'
UAST_ISFAHAN = 'UAST_ISFAHAN', 'دانشگاه جامع علمی کاربردی اصفهان'
UAST_ALBORZ = 'UAST_ALBORZ', 'دانشگاه جامع علمی کاربردی البرز'
UAST_ILAM = 'UAST_ILAM', 'دانشگاه جامع علمی کاربردی ایلام'
UAST_BUSHEHR = 'UAST_BUSHEHR', 'دانشگاه جامع علمی کاربردی بوشهر'
UAST_TEHRAN = 'UAST_TEHRAN', 'دانشگاه جامع علمی کاربردی تهران'
UAST_CH_BAKHTIARI = 'UAST_CH_BAKHTIARI', 'دانشگاه جامع علمی کاربردی چهارمحال و بختیاری'
UAST_SOUTH_KHORASAN = 'UAST_SOUTH_KHORASAN', 'دانشگاه جامع علمی کاربردی خراسان جنوبی'
UAST_RAZAVI_KHORASAN = 'UAST_RAZAVI_KHORASAN', 'دانشگاه جامع علمی کاربردی خراسان رضوی'
UAST_NORTH_KHORASAN = 'UAST_NORTH_KHORASAN', 'دانشگاه جامع علمی کاربردی خراسان شمالی'
UAST_KHUZESTAN = 'UAST_KHUZESTAN', 'دانشگاه جامع علمی کاربردی خوزستان'
UAST_ZANJAN = 'UAST_ZANJAN', 'دانشگاه جامع علمی کاربردی زنجان'
UAST_SEMNAN = 'UAST_SEMNAN', 'دانشگاه جامع علمی کاربردی سمنان'
UAST_SISTAN_BALUCH = 'UAST_SISTAN_BALUCH', 'دانشگاه جامع علمی کاربردی سیستان و بلوچستان'
UAST_FARS = 'UAST_FARS', 'دانشگاه جامع علمی کاربردی فارس'
UAST_QAZVIN = 'UAST_QAZVIN', 'دانشگاه جامع علمی کاربردی قزوین'
UAST_QOM = 'UAST_QOM', 'دانشگاه جامع علمی کاربردی قم'
UAST_KURDISTAN = 'UAST_KURDISTAN', 'دانشگاه جامع علمی کاربردی کردستان'
UAST_KERMAN = 'UAST_KERMAN', 'دانشگاه جامع علمی کاربردی کرمان'
UAST_KERMANSHAH = 'UAST_KERMANSHAH', 'دانشگاه جامع علمی کاربردی کرمانشاه'
UAST_KOHGILUYEH = 'UAST_KOHGILUYEH', 'دانشگاه جامع علمی کاربردی کهگیلویه و بویراحمد'
UAST_GOLESTAN = 'UAST_GOLESTAN', 'دانشگاه جامع علمی کاربردی گلستان'
UAST_GILAN = 'UAST_GILAN', 'دانشگاه جامع علمی کاربردی گیلان'
UAST_LORESTAN = 'UAST_LORESTAN', 'دانشگاه جامع علمی کاربردی لرستان'
UAST_MAZANDARAN = 'UAST_MAZANDARAN', 'دانشگاه جامع علمی کاربردی مازندران'
UAST_MARKAZI = 'UAST_MARKAZI', 'دانشگاه جامع علمی کاربردی مرکزی'
UAST_HORMOZGAN = 'UAST_HORMOZGAN', 'دانشگاه جامع علمی کاربردی هرمزگان'
UAST_HAMEDAN = 'UAST_HAMEDAN', 'دانشگاه جامع علمی کاربردی همدان'
UAST_YAZD = 'UAST_YAZD', 'دانشگاه جامع علمی کاربردی یزد'
# ========= غیرانتفاعی / مؤسسات شاخص (نمونه) =========
SCIENCE_CULTURE = 'SCIENCE_CULTURE', 'دانشگاه علم و فرهنگ'
KHATAM = 'KHATAM', 'دانشگاه خاتم'
SOOREH = 'SOOREH', 'دانشگاه سوره'
MOFID = 'MOFID', 'دانشگاه مفید'
SHOMAL = 'SHOMAL', 'دانشگاه شمال'
QURANIC_UNI = 'QURANIC_UNI', 'دانشگاه علوم و معارف قرآن کریم'

57
backend/utils/models.py Normal file
View File

@@ -0,0 +1,57 @@
from django.db import models
from django.utils import timezone
class SoftDeleteQuerySet(models.QuerySet):
def delete(self):
return super().update(is_deleted=True, deleted_at=timezone.now())
def hard_delete(self):
return super().delete()
def alive(self):
return self.filter(is_deleted=False)
def dead(self):
return self.filter(is_deleted=True)
class SoftDeleteManager(models.Manager):
def __init__(self, *args, **kwargs):
self.alive_only = kwargs.pop('alive_only', None)
super().__init__(*args, **kwargs)
def get_queryset(self):
if self.alive_only is True:
return SoftDeleteQuerySet(self.model).filter(is_deleted=False)
if self.alive_only is False:
return SoftDeleteQuerySet(self.model).filter(is_deleted=True)
if self.alive_only is None:
return SoftDeleteQuerySet(self.model)
def hard_delete(self):
return self.get_queryset().hard_delete()
class BaseModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
is_deleted = models.BooleanField(default=False)
deleted_at = models.DateTimeField(null=True, blank=True)
objects = SoftDeleteManager(alive_only=True)
all_objects = SoftDeleteManager(alive_only=None)
deleted_objects = SoftDeleteManager(alive_only=False)
class Meta:
abstract = True
def delete(self, using=None, keep_parents=False):
self.is_deleted = True
self.deleted_at = timezone.now()
self.save(using=using)
def hard_delete(self, using=None, keep_parents=False):
super().delete(using=using, keep_parents=keep_parents)
def restore(self):
self.is_deleted = False
self.deleted_at = None
self.save()

View File

@@ -0,0 +1,23 @@
from django import template
from django.utils import timezone
import jdatetime
import zoneinfo
register = template.Library()
TEHRAN_TZ = zoneinfo.ZoneInfo("Asia/Tehran")
PERSIAN_MAP = str.maketrans("0123456789", "۰۱۲۳۴۵۶۷۸۹")
@register.filter
def jdate(value, fmt="%Y/%m/%d %H:%M"):
"""Convert aware/naive datetime to Tehran TZ and format as Jalali."""
if not value:
return ""
# به زمان تهران
dt = timezone.localtime(value, TEHRAN_TZ) if timezone.is_aware(value) else value.replace(tzinfo=TEHRAN_TZ)
jdt = jdatetime.datetime.fromgregorian(datetime=dt)
return jdt.strftime(fmt)
@register.filter
def fa_digits(value):
"""Convert ASCII digits to Persian digits."""
return str(value).translate(PERSIAN_MAP)