From 2a9121e7d00dd1d9b4e9038a3836007106ddf1c2 Mon Sep 17 00:00:00 2001 From: Faheed Date: Sun, 5 Oct 2025 19:47:08 +0300 Subject: [PATCH] added the hiring agency and source models --- db.sqlite3 | Bin 327680 -> 348160 bytes recruitment/__pycache__/admin.cpython-312.pyc | Bin 2784 -> 2419 bytes .../__pycache__/models.cpython-312.pyc | Bin 22755 -> 24620 bytes recruitment/admin.py | 10 ++-- ..._candidate_submitted_by_agency_and_more.py | 43 ++++++++++++++++++ ...bmitted_by_agency_and_more.cpython-312.pyc | Bin 0 -> 2770 bytes recruitment/models.py | 39 ++++++++++++++++ 7 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 recruitment/migrations/0015_hiringagency_candidate_submitted_by_agency_and_more.py create mode 100644 recruitment/migrations/__pycache__/0015_hiringagency_candidate_submitted_by_agency_and_more.cpython-312.pyc diff --git a/db.sqlite3 b/db.sqlite3 index 2e5ca9143fda238f8ab6e872229fbb075b4ca82d..d2c0aab043226b827ce2c1aa863d565c7da2f37a 100644 GIT binary patch delta 1674 zcmah}eP|nH7{B-Kz1}75<;~o7>6)g!CU$GLrp-swn8pliCMdG4Q`-i#gyeFz!R4B? znYD_VSY&>zv?a_J{9qGwP(_D}cz>v12lEdrs8B%%>pEm0YNegjf$h+{q=RH_@!)>k zJs@fFz4!VKE}d;;~3t3XhzKCgSO|6bnbk!W&-I8BPohOD>1YV|P024v*mM=xp!k zba`8y4);Cn?fJI5615=qo=h@TjbF7$m3Li3}34%7Txw+6D2;5++F8Yd| zEy(ur5ZJ*cNb-``wG}wz@Bk#LE#p_ z%@oCRS25E~9w51^8e`64<{@Eg+-8!>dOxYRRyPr77BrzW+Q&Uyb)(9nyPy4weXruO zDpNf`ueV8z$>#&7$I_ALaS5M!jpP*-8fasSU@eYpLy-8XNwT@Bbc#5$mugay8PW!D z%U%lMrU_EOdt$(hA9$6l#{YU@Pa4(+0s-)Hupp7`0=Kgt!)G#NO}Wyq9R?n3k$?feIYDyx z@kvr|5QpS+L`;X1((uTTj2k3i!dFCK#ft}F9WyFLN8)J-Pfd_DP##jhW>1kj-v~fK SJ0=#;tbF8#V*uCr;qrfkq!7aZ delta 419 zcmZozAllF%GC^7}i-Cb50El7W=|ml4$t(uFszO$v5DWinkc12WZ~kxmANgNz7Az>^ zXEtu+oBWYqnAwm?e=@s3@@7MYql}yNg>q#WLpIOVlVxNSoxEG$Mb?lDs8y8rF9Tl> zUmpKE{?q)o`1kTJ;E(0|z;|)8oWUX9$qfSXoB!IfGckuSuA9v6uyS&tz`xDw9K-mS zLpY92W)D~iG+T^g^RWoKa^?^|-pTA2Kq9fc&Aj)v^WJ0pUdSxU`)4|P0FyRQ_!RH< zKe0?)N>Y;<_z!Ybap`hC;9y~2&329XH}e|iSjNc=`9Smix8G`GQegy<&pG(JTvFM^ zEiDHA<)lu(;L9qu-M5iRk(E(%`@w!D=Lw7g+gTNu6FHa|3W2(Fx7V4o>|t!5 zsKvZ}q83X5t31~)25#oH3|s=7{v5N|POv^@RpsI1KEy4{63@Jre-+SOz0BLE`?6Lt zZnw5%xz5U{3^Yc5I=?^bNAC8#Mrn3&b92VN>g_d#EYFx3H8(Y|C~Rj*VEHp20Mj0S Ang9R* diff --git a/recruitment/__pycache__/admin.cpython-312.pyc b/recruitment/__pycache__/admin.cpython-312.pyc index e63ade84e7c9d7c5d36f97b03dc9626a96e6279b..72b3fe5b2008bb7c6364381b6a298cc41e12cf90 100644 GIT binary patch delta 190 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 AlK=n! literal 0 HcmV?d00001 diff --git a/recruitment/models.py b/recruitment/models.py index 9e87292..a7aab57 100644 --- a/recruitment/models.py +++ b/recruitment/models.py @@ -112,6 +112,16 @@ class JobPosting(Base): help_text="The system or channel from which this job posting originated or was first published." ) + hiring_agency = models.ForeignKey( + 'HiringAgency', + on_delete=models.SET_NULL, + null=True, + blank=True, + related_name='jobs', + verbose_name=_('Hiring Agency'), + help_text=_("External agency responsible for sourcing candidates for this role") + ) + class Meta: ordering = ['-created_at'] verbose_name = "Job Posting" @@ -203,6 +213,16 @@ class Candidate(Base): weaknesses = models.TextField(blank=True) criteria_checklist = models.JSONField(default=dict, blank=True) + + submitted_by_agency = models.ForeignKey( + 'HiringAgency', + on_delete=models.SET_NULL, + null=True, + blank=True, + related_name='submitted_candidates', + verbose_name=_('Submitted by Agency') + ) + class Meta: verbose_name = _('Candidate') verbose_name_plural = _('Candidates') @@ -356,5 +376,24 @@ class Source(models.Model): verbose_name_plural = _('Sources') +class HiringAgency(models.Model): + name = models.CharField(max_length=200, unique=True, verbose_name=_('Agency Name')) + contact_person = models.CharField(max_length=150, blank=True, verbose_name=_('Contact Person')) + email = models.EmailField(blank=True) + phone = models.CharField(max_length=20, blank=True) + website = models.URLField(blank=True) + notes = models.TextField(blank=True, help_text=_("Internal notes about the agency")) + + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + def __str__(self): + return self.name + + class Meta: + verbose_name = _('Hiring Agency') + verbose_name_plural = _('Hiring Agencies') + ordering = ['name'] + \ No newline at end of file