From 65c25a1a57eb8955d1692e0791b8e0fafdd7bcab Mon Sep 17 00:00:00 2001 From: Faheed Date: Tue, 21 Oct 2025 14:26:56 +0300 Subject: [PATCH 1/4] ... --- .../__pycache__/models.cpython-312.pyc | Bin 60434 -> 61006 bytes recruitment/__pycache__/urls.cpython-312.pyc | Bin 11703 -> 11879 bytes recruitment/__pycache__/views.cpython-312.pyc | Bin 87698 -> 92006 bytes .../views_frontend.cpython-312.pyc | Bin 20692 -> 23025 bytes templates/recruitment/interview_detail.html | 1 + 5 files changed, 1 insertion(+) diff --git a/recruitment/__pycache__/models.cpython-312.pyc b/recruitment/__pycache__/models.cpython-312.pyc index 53b4e48a8c834ab0ce83e7084611c875c94151c8..b0e098721859db43eaca552b5d2d2cf14f28bd40 100644 GIT binary patch delta 15536 zcmaib34D}AviN+HWHLD?Avd`uH$zAW0TL2Ik|7u85J8q-5u1o?izaKT- z)zwwi)z#hA^)(M%3OWBlNbK7&F_8-R>#_cGi{<#?*i_-l;i9DjwwR6>L19*yRn}OW zrbAxiRzxHZxi-w{t`wRMUup(BCH5!OUoQb!V%Bdy7{l#UcCM_E&CX&q@)jAX6tU=d2#!vn=+F^16|iYO(t+uOoC?VF0McT@ zW&k!b06T-QS%A$Bz?KkJ3)q|hY$;)L0h( z1z^hwI~}ma0od7uodMXA0PGyXmI8KW0Cp~6%K$q|Eb*JCg3#rFo*h73N!U4no$E8& zta*g20AytVX%%7T0k$dtTisu+o6o;jRxb#VBAcxaldIVxTFp{K!xj^hi_weiE^)Ic z*K|rLw87+bN$LiN$tpU#M4ccB%_D0<&Im##PYIg=urciUk^(T@RQTr%2e40ZDIw*6 zniWHtl>jj4qF5nTiV#fWnX1{kWGG6ZPHW$0B4N|9iF(YyQo0u;@P5@s6*Z*uS)Zki ze5+b22s3!SI#bBux2Q98*k;g02TH)s=xI{qVw-8RNF!ru{3&(rEDfT=8}w}r`o<=FA}9v_)ZB2goyT8JXo&IEbpntn6MN%GT_2jI@I8qos!hnIlm9A_O`VU$8U#UIIfLlHqUFR2~OEHaCI zGt1;hQcBZ;rWQStxdDvuk5U?B*DB$$$I`ey)hg`bFQ)2rbMR{)DglBPZ{2zT?d>3K8u z1FNe)!XHb4k`z)_Vb;Yk#4>+N;n4eA>J`PlFO@M|@({}MJ|JRK3px?F!(?*VGJ}M*S8o^*k?s z0jzjaeyMPsAIe|mQ8RX04KFWf%sY#HqRg;6K`)oZVIL<88&mkHf)qYnkS~Ps9}3g> zR|Qc4JXRF8@&72&`g$!WKL;v#yQP|Xd#xUUu&80+eO;3X-!-j6NaUBM1q5Q2dlY3 zw{g6`y`pOtQuzPqP*&FTi}4pg&iFB?ikAo(d}Z<6bllIn(7(NZ5m3M#^ZEn)XmM4n z3-@vQGYhT={$cUdSaZm6^ceViKJ>W2Ti;F32|Mm#(WcO;4AKmf#b~mdto=@l(+I9( zGIHIF^noEkigxt5diz|)Zai%mvH@hQ)4^P(POE5ib~%{%ou*_wLZ@P5Kq;wBcDuuc zo)`mF7L6bZ!4U+3-U)Rn)?~FByG(Yo1)bOFPUEl5NbAW1MV+@o`<;r9H3|0*92mH$ zDH_uh{c`6Up`%UCZxxD#N`vw`{Kd*RCAZ6hR?wwep_;Z&Ch@ zAW#^Uy+{$a4ap<6DH$y`ZdqT>4YMQpk26)=Rg#$e5vuwKf>c*8ySx)-;nz!pc)EcezQ*OcCfrzsOINpPX)6k`nx87 zjsjp7gQOgsT_e;2d8wZ?{jZaf0#cgFPt2LhpD&NWUqR2$%?aq246ZPlh`n=bg(lL- zQ5K$kQBymnslA}7A63^=;G3o2(q9mKh2R?me@F1&2);w`J%S$;rJz}i(b#1*IUyW{wQd{| z*wfHP$927YT(=-Cg8Y%c&$EX{Z&O|mQK(|CDTT0Y+_B)KeCW6ElG&I4>i0Jh3U+ZceY_Fu=5F9100(78U2hG5V{P|Edj)}gsl_HaP-i&D4?z0 z*JE)2R!`W4VwniM`1$6P0X>$?O9N;cJzPCh$lJqzSpZd&kN@%jY_kt*2*9@Zuqy(v zix8_O@vZwpd27qm0l=&ZF!EBUw*}Of?N@XQ=JtK+j^*an`xG4pXkQc1z5?oN1M02j zbwITeuK*)kxMNP6@3C|b``;w2;e9J*Hj0) z=1l(Zq5|!7q#*B_0VOG{%>^FLbl_<#;GeUam%Ww9zg{$5UJ#``d-1NufSVfjo{1e* zt@^gMrbbECtY5sWsWHf%rAR!UfVZp9$;yE7YX0%!BAMr0;MvYiOLUX+RqGoXnp)d| zvwBt2lBNbI1@l&U_*Men_5A!258oQ%yJBg6Y7sOT;7AG9o8Pl^YF>~5V)SynWp}mr z!{$^AT{rPJmlmxe8!dz?T%yL?)^BB9D4WFga*z@NkvAMj{!36M*Dp(vFLs&ymSt%v zxU^X&f(>ZVu+}XOyU5n^`G+)bSb1Q*WUH57o7lNkN z^-KAy9kEt}6vb#ZDH?{kTningkjV+AH?4eO6LM!8CzESJxdG#}nOt34Q7XC;SXHHnOT4Jb8Pnuk z)D(u237T=Xx=Qz_06yxV0ge{x&j6pMQFW6? zsnRvpN%$OJQ>D8az$e&HqlNQM7I=e7(r5Ep%jAQz^FOaG(0z4NX0>O+E@+xZ)y*CU z8(7yjIkRm%a($-m`c0WtjPurCraOR|O)wR%1}D$%$k+Y%O}Q;N*%x3hTyT!bRqNw5 z8*+3%-jrGO$%Pj*b))J!kMTd=uqt_S_4uNV^QVO>Z{n(3hhYNdjjHGQY^LF1n^sJ& zoSSdml&y}isBpSpVThk0N8mErA^8PK znC;@!n;NF-Bxqhcs;>2DUSL{r6V3PX`%Rg;>;R4v7h#}_;$8DAQ@!wOKC?5kAn;0x zE_x7vJJzqd-DDFB__j{S_E9=;g(W-n9MHh+1WCtj!2I*hycGBXqHsn-lbn+1KhQs_ zPKALi7_R0UyBf#mcAoDl7E1V~t^(lxL)T*sk0Hy)0YFSrkL4#2Jc;0G0M1YVTCMg@ z`8tGzfx2R9a1Ot0MqOLir;TKaYN6^AAcDhC+1mrL)B`yG$ca6SfVT20P?BQX+Vw3> z#jS|=eKkxLwc^SyGp3yC%QX;DVpwyttzhD{75b_pwve`FqOi(Ee!lJ z(472}%>{6WR&ObXu9)6x-_lcpwu5u{r`RU~PQzZv$U#m$1kyX>I-`1z@xN|K6&iV% zr3^S=G8U}Agg6N701hQk9QM!yaL4;+&y&tw?4OfMkS4n0z#XINOqdfn=QdwB$78l; z#6KR)kymfk3Cp;7t2fQ}#8!9FZ8(5XHi*PWQ0AjhlA_%Xhs|gcMa&|T_3C<(zR<|ZNmcnpGifR{kx*Ftf6|5B1oQt3a!9oNaK{5imPvaGrZUYP_l0{c?X9Q9a-Em;UKkYW^n{1h8ZPz9gE zPhHH6P2C7A2u@+U6-#ymVOZUUCCnr+6;}JOv=f0F0q(DC0D*`*7u$<~RyR4>eOSe{ z#vZ~Fx-NSRfgW*3vGfZBFCxfBpal?^x4@{F(R~IRJ{=j}))+Dn8diLy?V199jwM{j zpKFPb%lI4QGHQHTjhc_cVh~g7!_)%ino=1y??~G>3i$CfKnX%tOob@J77Bx_v2CH? zYg{P!T5AVqV`J@rud&wC782Gh40e5^z+X=z7O%y6`09m0Gj`Q`Te0Zl+aeqb!PXXk zYm2|NW-xTH?PvrNct$q>n%4MwgJdT*`XpoVTC_)Uy)f8#Ea6z!vDBjmq^kGJsQ1gL zl37&w23F-`UptsT=sMOgoN#Q>(L2U+D}c#>&!}JwpQOqoWSvSMk4hhpc}E&h_GA{X zlWkh(>s9CJ6%tl62v&g~pFwM`Mbb3$KWu+izQ7dm(+7%1hIT9vYMa16q_B32%L-p= zq1+CiG##*L?C??fau47j`Kp=$h%k?J#i1jA#2|XaYffVMV z5lnCdVCGKffb-Hb9`8rj7r`FvT{Hli!l28T)E`bD0huWhwIa{>FC0&#=kztsvzQsA zlK}%q5OW#vL}iIcqBeWXA)mkGLF%mzi{04AtZ2lo9fFt9$9Dn6J_TQJ;C5N(>m#QR zJT0WY0_gUkz~mbF)>?ksJvnlQt&{)!p2G5NKqtj^JDAPr5^cR!{Qfr-7Lb$kJ0db@ zc4zbNUrAG&;EU^a5$>Fro0@a)KH)b0+P!&mFbzcsDJcRzXUaqdb|+$kW|>A84g9x8{=@LLZRdHf_f$WIvFv;)43_+v+Z*mw|Cz<^QyjzzvienT5D zJavPu7^VCDCI+hs2zXn4_6A&IEr?rM5494j;AO? zlzbhZCOG+S{&4V_wj1^GuPvV_SrTcJ0-VCR;lWJrJa2o@R(lup8&XPYuiH($@*!hA z0C#*d_$O??n?>(-7R@srD)wBOzA|O-T@NiUOGSOBV5eZGIRwUWYy3>QtfI-T;om*v zosTIuo)5A!*^Aa}77B?(Av7Pj^Dz>P6ClNa*TXXtc*A6|i{^l-Kn?t}Ae#pB0Z|O$ zKjEMAZvOR94u9w2t+J7lXgXFu@-t=QOW3&u0Nj0E#`0n+qv>|SCM=rV5qK@p>Y)fE zn2B^p;ax(zx)*|YGvJ2#oS&}lMlbfxE7~<-nWYGL(jU0X!0{L&x>+q+ zQTf;bA(g-WSXN0I%9+et;60*ZWe7B4B0~<3O6ba6@c1`ER3ReaeWZfvc)~2?A^8g)yK84Ei z$+zHrBAmVe;3KQwzKncK&BSee7H~2;c4gdmU~JQXHKb&c05Y z#p%SSKk&7~9|2RiQ-dP#)Bp#h(4J&B^GsG0VTrbrLgv_K2lMfJ#!b$Q zdJuk?|Nhwu?_Lsn>d0@OdqPm-%^4RsH$R`B!_X)( zG);Z94>)JS`lTz3e5ljmefIgm)pYAdyJMyaUK>pkl>0Y$SebB(N3ah;kcPD1F9B=6 z#9w`3fp?BDj7oUXs$B{VjGUW9PMn4(Uz{qu#((`Hz6`-&KzX8Sd{VFFM4s?3yywJJ z55bcss^puIlC41I1_Xh8`QJ|z2xocva1Qn8F1iP71a|OKA4H=DcEMrY$IlIGg*W*Z z!$r^!6Mi#ZS}mw3E&B}A6Zy|xuE{$Gr0|mOUy-GfVa8Yzw)^4&-Ur*?;2$2XL=fD2t)kwNnVYTaUeA39-U(FVT`TQTR zlxv;9wOxvH!Xs%|3f@EB31*V_2EORkU523RvERvjQUjuh4It$zc%L%{Si^hil#>0? zm$K%LsnflO1crYzPBtfJqK?5cs^|MpW(!~PV<+=GrVNhOgQKvZHBP%P#L;$kepheUxxnrER#0e|D-aDfn)R ztU7tsZ|@c?{Po|?joX9>UthT4s!rDjye{^LT64NN$$wAqlW*WJoi^w?VaT9;zr9Nf zF&sR1fRn;6mqH0yjQ5UPh0E#&;XkyvV`WQtPu}^VKplz3EtcMUuAT?;}5&Z3`g=dwrYq%72?wa115vuCO(QW4Z z&4$%MONMm04Vy9h!-#MIOS=(Z79?oMQjDHn%X*X8ZXj9Ai{CQJd-Yy^=&j@?(x(wM z$3Re0$z8l&M^i?#jLDRCN!?^O_rgWrHRK5o$?Y=v7jNamyXUxbGozLxt6Nc-Pxz8^ z#e#uvKeunDC+xZxtwQEh;f)dABGWZ;;`-ISoi5mU)7urWBY$+Eh(GmqJ={C5ygj`p z$SAv!BUy&D+=JC1i_biAtAJLlhOT&0Wu5u8`&E*lGLKd(vr$1 zy0$pX>YXS~v&e$~&p}Irut0VIUGFBl!xNzTVSdMdOrukSENIY8 z2oERQ9b&s=BN$Zj>h3^nMofddyOtTjTkG4T0e8dL-B}TRf8^LZc zd)mqO4w@JQdwA0y&dUcfR`EdQ>L|N_G`6QbG& z2R%K~dMP6$53d>E3^mBa=MipC8Wvw)u|@p;KW3DEf&yrezknX@I8q#s8c((sc+fWB z33~tYkF8Uvz6ltEPtm2Ni#}J*I9bCFeUP3`NtazHcY@*9e#1ZeASVnhK}ObI ze!)P|GcHejwj@$g+%PoZeI0qpUSxd3*clVGzvby4E(~jKizqU|Ph#}W zj;XLj+u;dd&V~_SG$=(whPnsV0_fcDWXBNin=Ofd@L?|e2Z|p*EGW^S#*}8#V~IAA zpsnLM?2O>($jXnpJzK|fBd0zdRz?qkEKk~@h4+7&UJ!=FD^RON0Nk;@XZCV-ohEbx zf9=yUm4rk#{`IF*V|r1v33|dll7$gDpLykeEiPX9+v*MG>%%MA!sq;lEBKv!)@QFT zqPe{td*PI^ArK(N`oEph_3$i6F|e0V%b;P>(BFWDFL?Ezmj_N!`u{OSG##|NBX?Ql zM$~}v!B62h$%ap3$vLv5DcvufEE&n> zAxK4lkCUaa<#4cC<^RPv2eIVUxo7|~9(_q7Yf%QAqH{`~&>e^FJ&P#xS%)L0({v}6 za5JPWMm8`GJ!o1bb&bto?z4)u><`ci5*1E-0eCG$5QNK$jLVAbj}+Q5h4!){=Oab! zn4VSruL16Lfc3pI3OiRUB8;)m>#>_u;Yo-1mOF{;TSnE0e(H_oJr2 z>h9|5s_N>l>gKKAh90>T8uxl^Y?KQBGMD^ytMlaHxO8d!aM7|+No7)*)RtIlTwffQ zBP{XOguVnWYb=S@q`o9BM_Q7tDSatij>upDnnuxPEheYw`WzC1}4602IQG9~U&nUZ8_TN^yBO@Dkj88>;nq2TiD9uNu>MLaIG{mL{wjM2FdWA%ug8GtQg z>@3924#1W(wgj=I0oV%0&OvOMJjXAgN=BC>x+0+QT*g)+c5a~D%BvV(h4|`#*42!y zLF~K$Y|Timem*3G&ew*xquMNXqqEH{TTJfA=B-A-MZM$>Yc@KZV|Rw0m848q5_$^68_1fDSsIB9hw|T3kNmXdct?=V*;sDM=~jQRJ+xqK;ZN5C|H(oNxrPp(wIV8M}PU5xGKB+DlcH2(F}1sTF}f zR1nr3F|gHc9*`aG2$MW$9JV;c3b>k>s^%_z5S=tDnmURK0vn+zX@*i&34=)`E2{`= z@YPdGeTdSQ%b{+Kso!9>ndDu5>=mNb=4BvyNSLigF=E&*j|eS%n)HKd16Y3|Ol-y< zW>T!9QXlM1UY6jSiZW~!e3IN8%N!CLdI_6VrVJ%8yFRo?fw7blbsv#2z#mdX<~%Ca z5(sL!8ANJjg3{7o4bP@p5||wK$y5lHr`0LKVF_fy&a}E<{xV_wR0h1C_T0P@?Bfo1 znw=K;gydEalA$`p9K?2>hzzm>x5h3^vM}4Wh)j5GT4_d*s>wRVP6W?DLVB~J>Y1=E z{SL_mAExW|^;qSQ5NHLPC7FvWX{o)x%kFR@)l!4O;S>hL&!Ie{MkJCTonupwB{dT)WA1)R^Pr(B807nW+rLW;!!Ez6$R|g`YOt&-t zW$F`ck{tus%W1aTCX7Xu)8Nm#Y4EYGKnjC7MHw)oFnR)wYPh|yC70>M?HD#%%!B3u zBT;fpAO)Wnwn>plpuj!X-y|-xY8l%l-cal9t)9`ef5qD2wB&4KN zjVBA0qaIdO)M~D(RFT~wf(&>){Iw({%}qUiIH{YqbiSm6^`$x%sWI&`wfJaKv+qjF z(1_NTX2z(;$dUiN&2_ze=*t64zeJz_UVHg8XwLQ=(isTw*e*5FK^ zu5{-87F(PM6@Ix)?owCTCe^}FbtW9GOi{X}eL{r4nnb;BZoRaCn;x0#ZTi{NP0Op= zq(*M4EsKErt71Krzqm&8>ISI=o0lfh-mPC1=&<2*^-OfU?^n-kdW?Gil)&Qz5(u0l z@CyX)7>Ch9JDo7vw#eewgwph`TCVK%vDEBm&{k6v{UjA%CvXSss?n<1C#Ax}HI~d- z)G5hgwr!V9W}9IM{kd#17@gu7D41u>-bbDOliI|07;Pgxc7h81+3?i7_EFwBXgd)5 z39w%~Nu^T+o+Y3-fgxcZl7(|byh6BN5_pZk8w7X-UZfH$?qe$bp1>6XUlRCl0$&sO zmcU;Le5Wc!&SDLQ0gKV$7?3R%gW-fE9>F@^ts0fxs)gDT$RB&O))p4i9r8`6N*#AK zL<;YQoQ5+IqylUJ7oJatZyWyKD7AG*lPnB)l-MFWL=9qG;e?rk9%(MMuR_qNj|x;A zq3O&eng}dH;11np?-vW{GmSo@{6vF~TiFseBCrI$U)Z2!p6HVfFTOu=6ZH2@;n>DT zoqANBI~ZbW+!OYMf>!la$(5#say4R`0NOECU(9%C>;Y249!O0oa9%ZIsJoB@*Q-4MyT~(6KtJjWrp3wI z7ZN4YvVhhtJ{rpdu&q99M*z0XhwTi&E=KH%Ju07Am*98T9u@p!apve=)u3crwMWyp z%+$R{)wdk0dIFku;CFApcc*DJwpxMMH38Tz{9YUIy%N9I1$?jCtJ)>?b$6@ueHeWh zZ6-6FJ;)Z|`6d5S^Z^#crvyGH@FxVFdQGq`&IVJvE_>ox&mG?FM3WZzXj+{T9Ne7_ z|JFWJSpvlpTsV~u>ZPWZd?H&wKu2IU0=K%Wsk^(i#jS2@YG2;k5@f*csMcLZD-w4O zJH$++-UFwW7Ab`1cnR0RoMrkciEEmgn_Ihjki2G9>(bU{ECmms_7E>e;%njPG7s@; zKk=O91--d6G2BF^nn7e!SJ(3P=BCab6lzmvOM6RGPiycnu}#WR!{+Q6L61}{} zmKUw!C0UQ37-~$EyoaA^l?A5 z8uSw2rt7H0jcRc^t_0tVwTg&QeB6W^b2oofL)~1Fq-$*pnj}srunvvQ70s0%O5qBn zU?MQoc_@K7;4uuukOLA{l&7+I{3L6cRgQY>E5JOE3MFtWf!hd7TpUUaz8uGR5w>@=dIO>7x^&VK_-$9dbQ65MDIJDBj8;pkkx+dY zgs$vZ=1wr04Mv;MGU6~h47g5>cn*vm9-(B#}Va6yxINfUE0a$n?lZsoXk?%v4XXsSdp zw0FO{k;uD4x5&;3M_C$YHP*ONeKISx8l3}MmE-9fG*pfmKbe>vUtN$c`POy;1^>t@@FUB{IYnnZD%(+vsD-4+s8HS zOl%o^w<#VD^$ku(n|LhTDu8#qrl8n0*>08nAG) z`#Y{fa3}2P*XmQQD}nkm$YRsDrpd!%(ZGu9P#l5713CJP0E&~BU!Y-PItH!|G)m7y zxhY2%m|r2IybFOV&M#D((JIdXhY9mYm}r`peje-b)KASOcqaIxDSui%F%g4Rx2ish zPd+%ZZ)9APj+3Aa)dE?bm>4)E&ytG3Eo0bxWbkP7{Y3Er1h}cQ!+wwul-CiDAaH~s zK(BqP5@k@sKsG7gR0 zdzu!v8oFCo_O^C5x8mNh05)$;!&rUi)>^3&p5EF=b4RHiv#4Q~`QAJx@I#_99jUm( z2h9R)FHn;3saYr0LDaSi>`JMT)!Vk0kmztXIz)XUh3pu@{0^pWLyZ>8gw90x2>f|l zy3_y>+shQeFXi5nz+0Dzf~VFL61o!oO7kQLoBiszgzC6u-!0>s98`yrtErRDL%bzB z5rQc~y+tpz!Jx&PBRXbr740JC!^Az*_--2WAWb92Ww%=mR#~RJBulQznu?NJW37_f z;Rn`wPSlNEwq}J?Ka3sp5uWTEQD9mu#;5Sp9p*G!Ww%=1Wp+3nUL!aRbB3yrpp38! z9vnI;)45RJ6MXKVJ>4DMBkyuHD;aT7Oq|XkP)&eNl42hLyq{76RE`<>u+4f@vO+gf z?M-lU$MhL^VTBoXqsfH2a=0Vg%oa~#e>b&>fX{X;&f$X_n^A%%XJ&I^c9xIjvtXIX zPX7^6Nif?m_jH3<-s!DW!Kj$8=2J={yeu*}ws(i39f=4MPB)E#S7R!1FMX~iD&d24 zNh10PyMcg#z>8GhPbCw9aQfUrB{KmveQu|cjld8Aa-3qAz)k`q1lIG4X6xER-?YHQ zekzf@iX#L#^KdVf9whJ>feZq8Z8sqYkV{Ac9aQn_v6mbzp`+p9)%SH@RpHO^;77WKi?>c0xaQ4j8X<6;jPlKUaD)Ae3h+|ueM1#R!Ox@{@NyQZD@GA zbZp>j75!4*QKU!Zt8pIEEz&U)b#C!@Zt->w312E552f0r{@SJf+J(o$j&(m0NeveI z7+dJ$3rBWPoiZ{{qn*U9?SGe!lWf;6$CQ{@49jlJE#}C}*UA;uEMz>{o3#BS*xMhjWWw3K8SvDN z&YJ5-AVp-y982;=#Z3A`ey%{-Xn}=8~V8pnDV~O+e8Iy}qH&#giN3!_;EuY1gkqpP zp*Tqr4I4z?qc|=aMfU@IKD`KU6{m&Ph?`93s#8 zr`SyNC(?4qb|?;B2{OfNNcAQ-u)BGb<@#SVl1K6OA@hKuc#f%EQJ$XK_7?Q$n~65Z zrZcFNiQs>ukf?BKd(iibMM%l5X&DxL_kpJjY9WjW+!|`&!uZ^!S!y@iw3v8xB|_Kj zNx5y@sS8t*JMr2LN8th3fH!Y)d$0YFDkEb=I zQ6%@_2I!fj*B*|eJ&0Fv1dk15PiX@`p$06wC>oKi;RBjWlxI6N%rlz=XN;q8LlI5` z?T-RqTA(yc9vLaSDI1Mu8_LBnEG)P)eYIy*%X8E)mG|c@Xs|ntn7Q_xIRpid%3ax1 zrgNTZ3EVh#=N%^`Wu>3zl|HuO&PEB3C5QG-Px^Oi#;ZC+QPf6Ul6SSxL80?RMDUz> zeyq`n7?N%##8m}78!>PM! z*hD+^2|?_*BMb(UeZXK)G8B9y;At=N>Ec@&k5?N-Xv$>(FVSl*xhvF;z>{?Dx)~{9 z4%4*%CPjc(6ajv}f4{VF4C{JM1SY38)3`kdTp68s;?~*+wa%@wcF-=YTBmFsvY-kv z^~APnfY*LdDB0lZ57LzU4QFlqNu14)b)Zlh;w;Yk1AC-h@X>+%xsVDb=9G&er48Bb@o?)^!)Ft{qc0}#97453 zQy=11qm5JUfAS5|u0s`gSNp`F>B^<=7PF932$JIV!Os zvC*)1j-ZNv5bzrf1-~MafY1CBl$hp!s3C#ZVKMxhVm1FGL2N|&SpE-dBppqoM|?-E z*isS$ErrD={wBfb-NmT;<9FZF7qs*6lJl=X-{{KV%wQ~zAmN0+Nx{kBi<*?IL$!M~ zm!{?Kjkz>^)&)(LvXjo_Xz1yCdKzxWb|*sI8n1~?jtfaDV5#SDGTWXe6Z;1iyke?>nR@EjomicGLY2h9o^s zoth9}bab4`&7eP;lln_6x}qth(Dn}DsosRuPr>@5y)k6eUM<5*M>Euv&k<|k{i7Mt zy!<)jFu?am)1*z1_D}(8yY8Xg(S0;C-sTMO>xb@^Qee}=`=mJd{Nd>(l)nh(oE1(1 z`!ZCxNT3$HozLX>dHIjNmZGx>Ii0`^Xn&+!`X$`>$nF@j4dFnh+VF)_w=>{{*$tpAA0n@)+8JNx9tyonxQr24!0Ql<;iie-;@-Bo=A5G zxE^ctEaRN1?7$t}*510j#n7{^tF=48>67M^HO=Ek5fk{p4liO5;H{*^I3RDeTktuL zVB^pTdB?CBt%EmW#cHNed)#i9paiLiZwFNZ9|hv7CoqcuzVP!n0k$HVMzBICgChvU zjotPW;n{XGLg;`!mh^bJBpra3<2|Fa{@n?*F&G@f{Z_NXLGMKH*1>-^W-H)LVKa_{ zmPJ1zg8(~@)Ii7K3tPn|Y~V_3wHnP9@BZVf#IrXOspRm|z=!Xu6UPeZF5o)52tNE% z?T5desP^t6RVN?bNKV5Qr(0K|vzF*gTHTWQx(+k|UX`SKQG>nQ8VrR8`N$J&RBQuj z>sJV(RI?@eE$d^!9)$b{6t3WPpLNE zClrHBvI_7JK|b{WHWvhjA@Rv)6%ia5d*jLHB@M;Xw8~-ssRGFkr%$Cu&!wp=yEty$ zFZ6QUP4cA#6FxVa;>hmz=D3Fc*+okuO7#i2{I3hVy2w3!M_m&l6@%yDrWAE5FEzXc zDnC6PTopvv=9j70J5La<-bH^(!FF3*56f+MBYu-T}alA$LKKN@=&|^nU12{P^xID zermUq1_DWvnD)R|&uFDrAZe@!`KN4Q_gJr_CYL52#qSh&uoPD`0n+2-`twfCIU=YlHdm+S}U6{&Lf?L7n zvv*2^@cG%QguV$p2qTo7YYceP>KW?hb8V^qXu;3aTDWwsQ@<8xi`f+)aq!u(Q(Pq#O=Uj)*l!-J zd{x)1oKvuGr#?N{$Fn2kZG1MdMynBZ&AKo+>4kxEScey0EmBi(ElS`IuNFp-q2Ng! zl7CT|&x?kaPY@fdasppGYW_utVhuaS?7wOaQ*WS2ZG;#9qq#R|O)wifsG6LI;D*Cg zqO_6NMPTAE?${=NZ0Sv84`GvLSoOMrmw*_-PbHtcMah#GEcPu9!MrulEY{ML)d~%- z<+0jW)0C*`acf#_rXkE1I8S&?lZ}cRTp`)HqL=jabZI+e=T^JP6|)M@JhH#>EMvPda-oilOYN*OOhC)YYI4=P6pZLoRyLqg8qFfsPcEdND57J2$?hAes- z*{zX1LU*gJELrg!BwWayaR+fkX6cT_W2Rl;eTu_DuZCo*7=*41g(ZHQWN&^a)dWr6 zMmPcuV~<|AS5nN=Hr9CYF{#TzjM3Sz#}(bQMYau$Xz2{-H4mTfx^fS;!Fx5#*`n68 zU9xbX=59u!dPxZ`$hyQDnEM-DwT;_$%N7}%4%mk=$xAs}pMP>k_gjp%?FK%{;~uJ1 zklR>zo~T?Wk+8%}&*v3Rz0PBAp!3+f3f8`pJb##2h*w%`xw#p02(;+0<4Asp)7cL{ zd8b%eP_)vgI4n-(Na6+*!5GkwkYMOMC>|%kq22dL$sMs%?su3mL(Cct$7jdLQ5@HJ zWF$^d57emE6A}a|l9ff^Ca}EwmZC=oG+r84ze61_LE3wp8+e(8hz}9NhNWZ&CoM0e z;!0eEDfI1>K=q39UijI2x^%_FC%vis3w-rnN(nDCqAngHyJGtb;`0HjAaEEe+zXY^ z_W>pJJ>(7zT}qJ(+Cwe!;5Q1FC*e!4nK|#6W9lu5#;t~zcGky?0 z_#i!+SG}@t9l6|<#Gidg8!d}NpUr%)dE@0ZS)876(Xf-`0bgF8ED^E}t zfA~}qnBPhV~b{WuSU|H6-TB{4*W z(@}mW62$v4>P+Clv0WbzdR)h`u}^<@Iwa;E9LtlBXn|wD&(i%LG1N|g^7XE`cJI}u zlEi1Vt%Z+%Usf_sjke+N?#KZ<<}hW9sPHMEwl==a+jG;s5mZ-$Ye|38{w BI_3ZX diff --git a/recruitment/__pycache__/urls.cpython-312.pyc b/recruitment/__pycache__/urls.cpython-312.pyc index 0baf2e898c605d8ffde1d5b9049dcc7058d40272..95341511093e3ca8eeddef74f4b1c805fc7872f7 100644 GIT binary patch delta 1939 zcmZ{lNo-q17=ZokN%K;g6q?v+aI<;0W5-$QZqDkZS)1KX8rNH5XK9l*apERvajf2Q zf|NOc5C<0!jZ_XsIS`3Uj)h*{s84#Ls1hI~Dpf*L2>}uk;(2~b;eciT()Yf9{+T!b zjQmCDrz>TTN=uI_# zXZ)8O!k?6kbE^H{OMXO6%;u8lYL2DR02}E<;N*cA$ak(y3@EqKdejzaZEpU zep7zR$-gy?yxCO6aokhIDfTUYs;H$X!yQ+CgZP~jI}xeWMoMjYt%%yGDubWvbzBCQ z8LG|{a$X!$6qN`i&b(S`?jg-R!ca^^aazh;8FTtv;C|#@2)+7mS4$2^;ltykj)T@lzHbu}F=E zBdp39{J>aM%%(pp4>D=}?C}LwygA;WZJhQ$N^?_yenn?*Zt?53MH00KgE8V`n-{ z++q31BwrnwVMrRmTASQMfC=1X)9?X+Adbi|2{2uNYzQC%g;}ROq}lVZT11mH3Ni-L zvS*ZRUBuRPm?`X69OMj0_d!5vpC;|oLj0D9Zqr$?39v1BzjS(voR$wuws5|?l{Co` zvM=T!qwOFmb;L1MHq>z;1)}9Qq|+l=z~; z+@^@OXcnwb#rAqw7!69Jt7LRlo?(j%uo;3!mDI0d{gF4lp@#1P=*5Q(CcY1#AO9@F z0KgDFWv}6f0Y8yng`H9Uh49tjV zmL|cjfOYJpC1)>j_6oxZ5hdv=*c8~#L$%Z$BHbZjhV9-O*mbbohc3w*C0==N<*S*c hX|RS(&}R;cq;uos+_*5kDxwtKV*1W&shjfu!(Z=2ZEFAk delta 1700 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 delta 21635 zcmch9d3@B>wfOhWmPuxkO!mn>gd}7j350#$gM=k4LBvrQCYebH%y$y*Oju%If+&JZ z0k3`ILJKanBG{_YqSb0t+!qqTntp{ATebDsz8BHY&zAaLf9IUD_jzCV7yX+7NK z+UuF&62Yn*>a8}hw^5xRkk{;a;_s+&U55ZS+X}@E^ri3 zI>lQk7deV3o$4)?Z4MiyE#47wiKB$lY2J}?siPFq>Fx}#SuS&w$>ol6d6Z+6T;ZsY z?GC#DO=6vq@wXM3m0(;U+% zo#UM@&v49;XF6uevmCRaEZuGO&X(sm=1@Aa5>}$! z(N5`7byei8j;%6xa4IYFPAioC4nLDLlBap|Ur_pn{yZHgm|Ei4rjf3a+~qe(?opm8 zoBt!UbuG&fbF{|P9aK>P74{(&!JSkw8Y;$kl01t~=)yg9Qh6nmS3&vGX!#9PUJd1A zp?pcSyo<`mL3s_7*G0>BxyRomId*%D?g=+ZC&Gj~f{>qx`CxdsZYY=(hp-3oljHI? zx~D)ld)-q3-sG0tQ4Rv$v^cz*-O~YMpL+(tTii1N?sv}uc))WtV0O4?-^3zB(7!b> zzT;L;I`B5rJ*S05IO(1n>on59aT{WZl{)Kc$L-MDf*6Y94#+Qz%m2t@q%P;hby*v$ zk9K)5jJHTUqbm*`axVs24|~?S>teW$JE89-ad`pxrE&SYAipdw|6})Z=;hzs^#DWe z6#(ycuLO9HdlkTY0ef{E_I;3VQ1i4Hjw4X8CJx~zkiR-E|5Nu`=;kPtUK3Y(4D##Z z^7ljj+PM4!kaxu8AB6mMaruWJAG|)U;Ac>TUvfA_#)z_MVg zt)Rzy96gZU47E?eKs}zPqC{+o8|3L>b>6tTUqP?3_mupM;~5sjEgs*AFAnk9VRdbB zb-(tcyW8XP&jIhY#^s-fJdex&#_b1^UvLKizPOXww|$P=uwLAlFsG!sjmv&JQ}pe; z)fa$-g?oH%4|fLIoc;imwTRaeWDQ#-#u-QU^cpjDMd{F3(JyH0@C6j@ylpMeC~1+m z%@tVG>hZe8=jQv0>JTNNt#PxbDd1PMF0WTHZtd{!oqkV%SBVFb>yy?23P;c&E+>~6 zT$B}`ncd<*O4g!lG3!8Z9fHLOu1ByQ!3G4?2%HEuBA^Z$G3Abcb>fqhaL?|Z)YR+r zv$LQ|(fZo9^9oGqJ)F03C4qZ@IG8P}2cCgI#%j}Ml_*mRmPi(tLDCnr3e=AP3zPA%IYO7rI!k)q>_w~Hw-MSTs6~)<8Q4jG45j=#&I+dG^FdAwey)6UfX8C1))}RJcDE!pCCY zv`rH>d0e0e{d^o2#gu|U_5?Pyx%m_<_5)B1YVRsHX&s2A#LYd3pasNiZAcU` zjqigLa;_qdbxM|_txaC;@dQBoE+op=wtBYn*8%rWJ%%w$46IkIs>w?yDM@PL9$JaU zojfFV)#Q~%r@sdFl0X7L0-Ua?&&J!=%*8s=F9vmVMIUGlcs+3}h|S*MZEI-(HG)i045V>Y zrh*0{mXK5lQ8Hm-Ik6+EUsOp_!ZUPkZfoQhp_8PZt_fO0$#Y0VF929&lu7<3fJGdc z!io5hxPMv^dr$OED`b7*_tWxOzqmXtFQ|@(4YSqtuEQpAT)^!62+krnhk&-!2blUT zf+%zNhnS^(L@WOhW}|cG=P^stfKsH&z_jq*#g*YiOGF6bWx(ihw+3j+e*(N3P)+{* z;>`N2o{y*B&rHcsriK5$x}+0*&&?Eb-^~=ZpBshsLZ%q}HmOHD>nV-SZ8@1HobwAd zxYHwk%H}F)H0&2ZnWvvSBZ3#eDX3+cfeDc`s!sf!%sQb7r?O9IMDO$Y!RQFP%w6V% z(!t~=O^ei|S)U+DyOO(--RZc)4{L5u)JeNipyWz8IdM3t!*HzOeyoVICp9oh9bb~5 zZzx+VN$%VTQ9kC*gQ4>C$%Ty7XO!u7oaQS7KLES4vlEm&Kib#JnplfZLdU zU6Q+?D=p-m%yPxI3vF6<`wmfDo0FTo9p=H{zg2()(uz$kmXV(_XgHbNY}Dr5Y%7H1qD{|YEkQe8t!KgZSL2<&DqMBd_i zl9CXGx)zo?YimJlBfxfZ`P{9j-TkV!bqxE|H=)1Be}+93A}GdEQ+t~~;B1v$Er5)= zPTfYmn2PP2xa}bh*IAd){!rDyHkTJXFU9Ec`P#tg@bER*^lAia0VsM7!@5Za+tcGT zC~cl^Br$GDrtKeyeHp<&5qyi_zYzR4f_;+sc8N9XUznC)8*zrR;-y1b*{Zqv zE7l``P=MqQYI?3++Q5PaDXaLy%(DK>vVl_jK=p({y_8k{m88uwd}ELjlJ_+CC6}Bv zjQsiH`xl?L7T)c?&vbrt)g$sdqu;JPH~JdDE~^6UGQv*Xv#Bq&^sJ$5Fj>;4f0-`L zSj^6*Eq=D@@zO)3eL0n9)2p7T>R!^9w)l55>(1sZd3O2ZqHaZ6@OQo&&Zc$s`)=rK z-u!r=Z|3s;DfN9*9Cwx7t?MhS?zfJ8JndZiguacg{&ZKL?*{ClYtSfJG6u430|jFS za?1y@iU;yX59E{#WRDmqsG{;pfM4b&ry9Di`no_erym;CmtXVvl(VK8eYzQc|GJe) z=B!JSMnAs(lY+5l3u=CA%>Cz}9`fH_g2+sI9s7rpv*aI2T9 zBTfntle98PBHGJ{Eh5_~q=kTho0>#ONg)Auw)(&?_BDB84sh5&S->)>o50!84hJDO zhmf80;Df(eqhamhg|%~P$-)rz4`8pfi^w8qRGEe-p5(_38up$P^A?w@V-si)?g5Kw zh3Z$Cn19V`oePkFhfWQDPW(`A2pMC$jw=@Pas99p&bv1@Q#OM_VuPb1oo|D%lvFWrRIdS8(BMS0V(Y5-(y(CuR zLMRD-kKd1{riTz^w-~&>WgXei)tD!mwjv&LDyeYh^l+cciQ;3KTFoK;60Kh$ zFd^zM;bd?+;+N~Q4HZ!HJJ$2|`aiP#O6=L(;t4oi9f3{g@eyTq;D~s`S)A91^(o#~ z-xe^iJ}3Altv+4_9V7_0aRRVn(ngm?oqwS?()gpv4?+WVCL};Hv7wPHG*S}?g&$7L zTRc8)LozeP#-@A+&hoo68jA>H04Qcxe8Vew0clY}o8S!H=xW-+Cqm1to)4OCVaZvL z1m}l1+Adl>rBjGe5dM{TK7b*su4KB}+r6!z+{vwQx;+6`tCvp(yh?G}Q#C}g);5o{ zeqUeWaC5GHDm1GRzib|(Hmli_ExvAkFF1%ZM(0Q|Mvk|NDU!nVJpgr`ITUmli_qEF z(dq>^yLwYV_QED4Ii8EXkOM~jy^Gm#0KlCkv7U(&Jc*?921yENC_J7W*U*WI)X(RK z5bItjt+(eWy3PJJpQ1by}1p*S{RA`0^68D3h`rmC<{RY5U*puHrTf-jgaq!EUAhADDrJ@dd zK+eW-llrg4G6?=ld@cZ3l$cy#0bc-MO+AQDv|KT{J^m&*wov%y9Uw?GG{`epZCVpt z*8&1OTk*TVhgYjp0)) zIVilHrA&y!omRG2Jla{lKBmg%A_55vnIf8ZI+h(nUfQ+!BVfNx}n^<7g2F%`i%f0>kpJ~xgl2%7aY=4;=m1m1H!j=9bqNCfTJGRI#U;c zGO$H7g{_32fjZ8`q}^qW*eN)!Xj@cTdNCDqFNu0Ok;P0rEkF(85v5^!NaT^u&_WfE zN4}quDdz6ZOyB{a?@f*PaQ9Kt6-`XIN;1Wv;1j`SoM8)ssDN=?*vQe;?Q{i{q)14_ z6<8AyF)tv&TF*s7hOrxN2g5t?8bk^^0@z@PBai{xRXp3BX4nBW=QX0Q`)cMA<$Hd` zri%-EDxDzoG$*DnyuTV>(YrY*JT=Z>AUn0&@CQW6gsn#rG~7_n3?IsOI4XEC-sp7S%U=F zTm6}uFy;qqhhSF6V+OK-Qu@JxETM~aY2C&nniEJc{2C;CqL{jOf&q6_=Qc6xj@;mM z+nP;QL-du(li zP1s-?7(`d2*JFcIO{dK8o@1sLOrQRwux$`C++*ih3Zi2DxnU1XRLS_LO?pcTxWx=X_Gn5dX= z98QfOr4<3P+NEbllLri>dx#q>&g{)jx)IR71TWVAnE21VCBXrs<)Hb1xqHDtcJ7DS zll!wL_vx~JmtZ{)xHd1_9k|DhN zEUb)DhagoBP3EzRXv4Al^}>2ffq4IkSlgyserVf#RxRe;U!LwxIhh&>#OyM4={Hlc zIKDqEf{+%6kQ_zGJrG66h(kz?A{;o77MiDF+2Zj7I!t6)exmKtJ29j}zpmuaTn)=i zfwH`4nLe~?9fNDo(AlfNX=s#M}7yV3*8BKgfLXyI1hUYQo1vOCY6AJlJN zi8WOPN3;>XH%QQDd`}~xr&udpph29u{kmi_2fZ)=Tp?tNDR)#C-2i)_9t<&B8O5MF zh-92W!w*Vg?;RzXO<1L;$OmZV{gC5L;@LYMHPL29&l=8lz8}pijp}x|k?ClZTj^AV zUi3=DS%u(UarQ@(7LAV62xKN#0ZHJw1lr`*Ce?JK^-)H6VKwqsm7-KVUW$V%Z&VW{j31NBOM?euUs4 z0`jd7W9m)>0s%Uve4lv!P{CX}2bzej5K{x^gFg%y$zW&vp9AQYK$%!ZJXG-bm~*MK zyB7}{BxC9=yZ7wAJNs-x@t~$&WFNkI#`*kF5Ets3?CiI0{7S1S$o|G8rI+`om3?iI ziYh-WoX}r5;lsk|{e{ze7xxuTKU=u`P|`PPfHIibbL#M|8k0+-;{WsOO0n#&6Ty7x z)V#9#4DHJWi7WG^m&TQ}=^Cm#%wG=FRZNxln{dCRir5eb* zK59|^icIOf41IlJ!h2RD6uoE5sGp*LZ-N%nlNqL`Px;_if;h-gUQLGw~)wN5c6d0ANes zf@$>0;er$oK~85Ihr_CR#0$^n-FwHyWCh~onhF&j@jem zNDn#TL#Ai>j=O#PeIxbos6px$Pu=$xOfPukC02mb11%I~nA+1k?6XN+|I<Upv9fkLJcz6b2V zKSDC2apz?Tucf}jg2IE|@S5xj=rbp&sSzT-32K7&b| zGM(K$r0c-E+=;E;#5z=d_9Xs;d&M?S3)iC+L7KMFkB(#qX!P&xL8S)UMJa@M0`b2W z$-pCok4KtYA;uV$-1E?GRnKR?8mpa3tJe$Y5NIa7Mgfk~ zP{47~Id0D@1W~QR`CP944^VkjZ29#(oeLTWjDF62*)DpYol?0|;=hMlh*1se6~`Xd zp;-M~x&C7)e^~5#Zi?C$T#snF7#vX^U6}~SW^N9cU&hpwP8T~?b3E7gsb&%%7*LFJS@ZOQb@ZK;M}d> zWelXL*l^P-xf8pLv6DDB$mU2LxY`NuG7dv=%QKX&c4ezJx6k86{G=B;A&H%J31Kk{U-H7Vz+} zFa!m=zH73?q2Bzde*@x9>OfTg0K|YtnIxGCjx2d(&AFuUa41g8{4mYlpJwk~axteU zbi?5rLcznqW4q7hOcu#6iu{)oF8L9 zF%uXjp};`YuTMfRJ?!EVs&IH!O;Rx409j1N8ExvxUVjNBs zd<9xBVi~a_95p1Bju^41p;-1-iT=N!8=dgKRS6EvvA3o%cnhJtT@*y2hiGlAujmmG z?j=wP=-5ez$Jlhs*YSlIPm&iXenx>`b0=&c1nY4Ia z)oM>O_xLy2)8f>8FLpw!`791Xj3iTwhEp+w58P39#H}Xk(b$rbvpVE>BP2T@XkcRG zUGlTgzhVRe+98_h8G5)8e>+pChu7#*nn>;YAS$0=pxi0->VBmu|0fge{o|&^_Gl*E z#cqR_X2Uls{}RTF+XFZqtLW~x8n_7tDi+`LPXi&Sd4HO=jCR1cIR7tjQoR7eZ?b-c z`BMnCh=U(gEJo=CZ!n@0Fs|XpT9RK9atv$J2S_H?e6*+?ALV<4PhligHC|i3M9BsO|a1M@h(%XV1T_H4#gaQPA!b2QPMyY=M^G z8jxU6?1z{{qXn?az&{e>Kdyocv5g-uh?5r#^2H8+>H(HKVt9KjH$sRXo`2vY1=<*> zyW;bKR=8))Kmxn58w&y&*F}V3_FV)hXJ`@vo76K*kSL52rwWuQPM`!f$c#9yaIlP! z;OE6S++nOw0aL*Pq)>^FZY(szWo4|W5RpmV(2b08R!8Rb-ai)VD*$0_&+~tLof%w! z(WDg@n={2vJ_(R5qo5`9faE|L|KW$l=uho+F&QBS;$p{}BE=k~7&o@s5L**1F`EP? z>By(~`Y}Mo?c(`QmoiuAKUT2Zo)MqDsUtt}xQ3Gfq8@Sq?XtnPy*04O7JhS&eP%-O zqRTlA$PF8E0xyE_oQ+o-)kC7CGry<~ZoxLBh-j%ufH{`=5umW}Z3wmlP!hJgAQ<3l zIc|)-s8$zy7&i4qO%kKacHE%KBN0zxQlgQJ5+4Z!!+ZTNzbIrWBK5CRvtsIwhNrIY z6W9OM8blpv&mX=eKSKIQvU)K^M(1-Bxn#_u`0@eF{yT!0YMYD|w4Gx|Kw7@oaWA%~ ziIO0aq8P#FZ6*=JjUGPLDMq}@_Io>8IBjg2ByB&`uMy$IR^&2wW1+?8f=9@ZN4cdA zNe$!vS28={)w5GppFM}4r}#BILj?X-3CHpK|5mD>3w--Y&s%?cT04ife--kv7aDV{ z0a2NO1w;)Ri+b=dqf{wL_yW4kM^A$0h!?&rSrLL~1MNU7;~K?{gUcKz`h*^pXg&eQnuuT$f)pTP4WEq3 zDF~(_AVDn}E~uyRlfM{0`A0a;{|~{X2~7vWf^^3ae%BHwAVU{Y<;P5%NH>x=3sX_q zz)Dw3{K(E!JNud-C!ZN#!I5*atY4sM3_=nD65R zyG#T<7)sN#Om-?%u4fg?qGA`XP5~7qCvps?9fwpQ4#h3i$l5|EQsqjOrqI25R$>_{ zM4gpl-WP?T&-KhwO`;SN!CxU4hUrI=8C5@qMj2RNI<7vr5^>rql$gK@RHZd0P8MQD z_5tjdI7!&8`(00>i>mqGP1d; zjYz^$tVFQj)LA3DGbK)^#feFr1?k0BF^+X(Hnw70LJ#GzO4AbTH3U^kL1?U=6%_Ji zSVAI`sD5uiRH||l%Cxd+Y+WZGrFU zd^WfiY2$nq)|*0wxolMM*C6EJ6X1C~riM9+DktIG2q}AIoRp9jzLKaQrs~O)Pv46@ zos!NU+c!8!j8e7#o}O4-ggF0VpNB0ZFaF)EF6H zBUCE07FT^BXN@(41*}%FX+5fYvM2j91EDKVb9OuKQ;T&RnZEq;w&Nf+T`H}&5 zhyme^q5JHtRPTc}(@&kYvr$@bh5uT~#%eSg@%T06p#@cJigsThO}OB#)qPbgN32_A z5r^|K#JJOm+F9_zYTOihrXkL+vV|sAv*t2$T<}(VG8R3C$6H+*d{(tfA1D)DUs*$6 zRI^m=NG65;tD4QW?}A4axBosC!L8?bpod2d?;}%s5qtrlvp}>rz@wGW9b?&+Al6+@ z>+pN{*mmBASO4mp-tZ%S9aJj`;TqnCtXYN~U5`LPK=#0fsa^yY+}h_bMG88mjA@bR zOc34KAW%~%SVYB0iDC&46@9hO{W#`#jvt|)k7LE_wnN>q1lU&?VD6SafjI4&V~yub z_U?s)2EBgP#r)!? z>b@ygoy%Fg-+a+p8roLFie^oa%tiPW#;i~BOODRDXU>QDHU03JMgYFmIGaE7eIN%u z$(VK7p9W+L^MZ8gm2~@p+1giTF@PAU)of-F>B-9tzzo%2m-b}z1A2JNCzvHm{A4hJ ztrM$uWQ*rM%M!a=lbAl7vz5a|Ljrt4rE$i3FhGd`N{rDy;Y+Z|1wkgk6@t!f0O?8? z_Lwgr{_=oHF>+3X``D!e!MjC$(_=TPVi$`e#U6LSQItfHmNWos7m4@k$ldI~m9{~j zanT<#60z4IBvZI|?cw{~sO0c%*qVBdp_AC)Oe33C)x7vk6-V$2$_~z=yHYwIFFZz_ ze%wG*c+TfkMV5Hb2yzrUKY_Is|9x;I(~pC?vpHjLHDC6dpdVqKUn;#^YMwt{8)CCr z_NnHHY^s(8Lr14DyJ0i#jqK2SQ`pkjMF%f~cItjQhN*HyD#uhQ0*D~O;|nYsgQ?K~ zz}9rg^v2iEwOB(8Q6n}=GJG20cf!kd^$~D4PIUve+=D54e}KJBQW8}}d?`$9`fdmZ z0>3W*PW;xw&(SCTIN{X0Q&}&Yw-qw*mrj7K#7`x?)$jCoz?i5;oN(U^-#gq6IBCFo zy6@|j2280RnhN?&1%0{#?mG3}bQWUez0gIc3C{n`%{FXmQ$^(toYO%7of=yOKNPxc zCaa~dKS5kb+l+vAs>?7mW~#2*`sdzDdeNn-MEhetL1 z$1uRO(2Du&>1fyx_Jn8}2ckx=`PEc$|6gmk=>?ix(|9;>fPFd~^-y=Qc!cLL2a<@s;p*t+rU>Uj4;2 z2xNp_T*eB-mVHTXChdg(*^|Qhsuy}+)S0eIBZaCwGWbK&ZJoLJY#2YohA5)j=I@}d zf12T&(4DkwYdUk_(ejn5JBtJxZw=ZSJ>ItMksBmhrqeK(x>oOCiUbA;xZ+w-&`~v? zh;kROeAv=t!J}#X&J!HamKJ!h0;_~~Q6a#rH^R#LaTKtRiFrpR9vgoyvAlcXfGXFA zw!NQFc;1-2-+j<`z<17Acs{x4?(Ijr?&&(4T)AHd+xFnB1G8?QGmx5baQCgd2Z~D% z>F!Dyuw;f34=3JbI&ZOlXtDKMY{zo?#>{%g{o>|lH$QWIUtMFLz3H6AeLknS&$f2l z*_@g_OU=dNkw2*I#y-32oTZW4hMR_sZeQVy56rU$izQ^jDJLzT5`a>2dG z8H%#}7!(I63epU(U}5euJ(%;mgRUz4{3zG)c? zQEAx&D}-;D$iw2F0>W{PVhq>#>2Ds;ABg}$P*d?ILmhRjL=Adhg#|Q+5=`|Xh;8gA zF^kFoUXQ}}b8w=oz>=*9hzYpM`7t0k_H8g7cfbXsosZtLN&t?Gf53ytMbl6z4S6z- z)fq0gI~wwfpgst_cb%HQgr!Ae((uUZl)RK(qe({oz_bQwm{9+6Hrm87-HYIhkfEN9 z3?j$)PmxAs4L=I0`pCzmH2vjRd_N-KRMjbxGfA7{dzte;av{b5xQ2ocL&D1h!EfT} z12`J8q~`UI6L-N)HXduzF0YTQs@T@yo(UC#;)O@7|YlQ3N}9sMTw?u+_?oe^kPcO;&*)Q~ua?dXn1F^92m z`}uiVXzqHJy&*lmJ$yLor?_RbM|@4hGZ81!x+BmENEC0#!LF?c=;)b;seA+l2nqp& zK3mU<7AqEXgSUN)mUr^_vwdS9%$+a z_*Lsq8yxq6k{QpW>K2a=x@qF$v4aT+CW4?tL>N)^Dl6#FJOxXqBAA9?I)WJpW+I?h zW3w?e2Y_NwnGhP~WFteX5!~%$MZtPRSb+%IhK5?c5>ts`a@>u473NdaymM=Hz~$fK zS9Nd$He7??Y6NQ$F%h0!E>r&o$+cK`9t+LO@vktgh4pWMw`}XM+>M|aLGTWQPat>- z!RrVvBKQ-6zamHniKY*;)lY;fFk6LSA_DxZmeW&y`~a12Kmd*coE8uS5bQwEh2Ta6 z`23tdir_K$%V3~GG5G=ldXIJIWW1IO!sHK0TH z$#jE?7kwP>+32o><2{8Mfu!&e#vP)2ttki}MOEW>KJ@t{Jf=ouJR{R#hkSS?3qD9j z6Hy&@8LHL2v=6avL4b}sIl<)ID7oR~3yW|ywZ(_`eooFMI)LP8fH}nZqZQz&1vx4z zj;e(;oT^qDVF?uDOpqRUkvg0ALoLi+@;8Ap8`Lt!K9WoyNvRj4nhVmH3(_?Dzx9HY zeLE5!VQl7CT1jIW z)L?ROo#xcmCN_fUbD3dqYAEDp+tWs~RV<8y$w9}dVh>x(Oe5H|ON&@8z?mWVez3XV q%L+-8-j`l_mX&>}Nn^9IQTZUIpsRm2vl*$ErZSfJl@S2V@&5uDOA^lj diff --git a/recruitment/__pycache__/views_frontend.cpython-312.pyc b/recruitment/__pycache__/views_frontend.cpython-312.pyc index 188826cf7c87223e9e51d04f9df39cfe229242b9..329fd5438257977fac46a8f342bc76c1ab4323f4 100644 GIT binary patch delta 7716 zcmbVR4{(#mmH$5dvn<(`WLuVOOSb%1mNEVV{)4d%7-Iu&FeK2Fs3fYa@52^+lFaHe z1fN|w6WVDm8A7^ELwdQEw7Cu$m|j|^S90`{ayN7BrFR!8rf2RenUI-GnzU(a3YT1` zb949Jev&0TCb_A`{%QBUw{PF>+kN|Xb@h4v<^o^z^TI+C2cM(T$CDooKUL(^n6ytd z4JSCkAekct{sNv8I3Z6ej1>8cA{M_TV)a`iHouM0jZ$%>#9spCe8D7@M(ln&qno9& zh{Nw-^a7we{Z2+Nl*%I&{t8y+rAmJ#=q{365x3vXXcnm|Qthwixdbq*k|$E*uVDb{q8yufK%)%|9%Lhzm9E~q2m{C!Yw&Z+l9ech=PnCkVQy7dnGw=#Mg z(A!s;xs7o;fU{whnS+e85jdT|@vhAH_A$oj0!BA$lAXRGFsCQSoE=c#lv5vudT&mB z!^F8-WlL6#!rw2_nd_SEr?d7-7*GDi zd`09_`bE9_5e^`z24Ly42=@ahMW`t-O{Bol6G1XTR#|os1rhFn|2R(9Def8#6}72G z9%M!eO*`p-7q#>EQJ0f&%=@L77!lJ4~o{jj~9{?76g z->@)m9ngBQOK=%}!CKTFiH$4zxE!1iffzys>hhxRmK<|=QOHVgedM@l2Uf@Fu~O&$ zZY-`^Uv8xJAZ!9qbkSH;BpaaUgGGnr%?PY3T)&ys=TVnV2fbeE<%I>EeJc;k@5#<` z`e50)d+%KHWE@rC^ru%n*^Y!e4N>x7Cj@1gkfEGzRu=h~V;%npopId%Ag-+!3)b{O z4Art_$$Ws0C3_H7HUk;M>Ry0&&IWi0i3o@2dS`kAJOrMQ=r5d|h5#@=5a_(Me4(lQ zb&W4OI5sXeH6m)5KnNooMTpQ!S2LVrP-LDdVmn^7<<7Aa=9oJ@p?Z*wXbM#vLtuU} z%jj5dszi>7YMz)$yknK6G`bowU$j^)g?R9mt9r#RMxXa5yZ< zA|WAa^R#}B`OU1_zJ}j&RvOx=XoHf(>{N_GI4*~yA$e_&e%<5c&(l{ue_zj{g^VLv z?U>_8MED9g#z|kUsZuxRaon5>H*22ZzkoY~1QF01nXqccuo{kr<#13UYzM$ZVe{t_*$AA|LMs6Lfg>Ck6fOS57OM`43TL!#;z7UfNN z+60aVrLd6cS%)N5WQ}hB5{#Is8VW{*FdPcv5D@|I4~r*S>BR;U{~G;K!`=kW8|?SB z0%dk56oZgbxT0wUd%au8Bwq$$f_<;OPaZ`M!uR1nPQTQ+U3JH!>45$We~Nz5+c1Gs zbhi+Gr)A^`RC!l>)(V@au?50EQ&Ur)YQX7quugyh?>04jVxZ0%@c#|eXRt?vH)zn; zuJ(8a;{koi_jTS&cQ$u?&I)YB3Yi5gsOZEV@D{Mm`GVxCX$Z z#!{tFPPYz7uyM%Kz`8--XddRbEZEm=;dQvk>1$0D^jOO#>oZWviS#l0N{iRL62{?J z{!L5uFpDy5y)yB$*ydS;Zvezs;zYWCYbdka0s@5Mutd&**n4#E`txR#MdNS%2S?in z`)IJdj6SX}(Z!o(Gqu=UiCIpz0H1vX%>@ju@VS8FgAdQiHnqfYf;Pk5&&eej>MSSd z1pTZg%wNEM;Ikh#^GwH%aC}M%p7h{ufzv@0JVcC7M?{Y-Mt~uU$ngYscvg&O!C?zVxm)xOZURJ$QnyWvvlRqK}d-8am|Pxe37zhw5jY4%(< zTAwU>tmw>%7x-lDzD3WySB>{ww>Xl{rbUY{Y4p8oww>`ND|cQqmYjKDS*sc44YxQ= zLEbW_(dV(OZQ+m_iAH8;~?M}t)1zxQT!R1 z&P&iWK`5geyL;47_7VioAM;Ps^*xtHS;Syrg!%plDBg~Mhk{S5W*(0tfgM`vYEDlO zip;n(A&@@bVCQ@3@TLuo?3}W!c}``=QB41OQ^mktPXbiF_M!AcNE5hxEhr zffS%W==F9(- z3CO0bYiYlX+7Wirzv^pLwO?kVywP`39UdVjj(P@0opOGLCGeS0e-VxZx;#)(kd6Lx zJiTEkqx(jT+BuC(Bh^)O_h1Q~Z*@86w6pvU?nzxpGr@&44;FFUoNiWk#7djDxJ%aH z&?~mm&{LWxtU7MaFsGC483ShdBaTct`z@De%7SjiKz*hp7?AxiAJ@R+P@Z7SoMCf$ zStE-#+V%MtO)#c?0~On3%-q>WFz1vDk*Xvi*Q^Lz0LJGuir zU!2nhs59Vrp=<^YJ7J|+lo#^m3c#+)%m}jIg5#nyV+E>C%oVPw8mMk;Y6Z`#rnj%TJU`aI=PtJ+r3S!r7wP0-^l5{5gy4%P51iq+-^RO-Vv9O(D&k z?gU__6}}*WfHQM4IwCPzWY=R7@75cuRvvFnohs zO(m#79kD0`SdGTEx)b)*_fBIl8jZmNf~daIVY;p8nNETkzoM7JvLv$USM&t>5|sSl z!~_v1unopA^%ic#QUL;l9gaQoDY_%^SX9vq(-CkNhB{xu%2FJ~3fJX$;6zxSRPB$G zf5TS)jxdgpL`WgL0if7dmP5Lg>d~@Qlf%3($>dFJQy{~*B-J4T`334)OdwuG7zT)2 z0U)cqIUWlVLCq-N0m%apz2gUAu|Y;@;+$1Wj;55OY01%^arVGsY0LI`jXzB`O&0p(|>jiFWN^^ zUBl-?XF^M5zQr!~_1!3UgW+yyu5}we zHgI{CM<%bAHC`(yzh2-v`_RRElWl{G>$fi!4BgUe9VX~1&vJ{?=NUdWG1+$=m1p<< zxcPF+RmaX{eS&edd4^>hr>|Icaa9|a-2Ewc|Mg;fvaE5j7;UW@09&gJHw-o~wW=hk ztGI3C9Im8m!<(+2mx7mUi)DTDdzVdIsc)&IHC58OSkgX!&$V3#lb=8I=B`6u>pI(# z^!27HdN1uym2dk=&DD|}$??$qJ`7JjTys@HPp(bSlM9?=enfn90v%Ki zLJ#m^K6zAn^Pu!xSF*M{*}FScyZdMRQ#JdN_wB!0c_2yRFkj$EN6j@?%Qa6Y+%FuJ z&m4K`$hnHevX<)=Ro`lUw)xycixr)q&9x3B@XuL)vvNa`#W26~b`@7pj2DWYOO8eJ zU{W{u$3Of9&lUInQL&H2aT8tHTC%HF_m9q!UET%9;5oiO2*mW8C6+{lRqtl_Sf=Rr z9zHA*cr0PN2*WGsqqnvX9>%54-k%j~3`GLj9hLKHo_$cmK%nkfL(Z)vM=SE#Cc;ac zx`W67{l-v*{yiXklfE+a8r;B7?$GLr(RjGNV?L+ab)KHyRm*>uet*~Bno*jZ1DI)| z&+o3FU)pUmup9R{eQtLw@jkM%x2N4$RRhx$#By0NL_~QqCXinPL(xWKC&+J531A#?LOK81FK11IGRO zs9XOhAYESgaP;TAnWgSK$uEII|LLCH372pLe!hsc3gfMjm>^2=R(6=gTQNcs)TP*n z7$VbQIRbILby^Nfae@h)~m5LWEN!4gnbysXwJaD!8Z0 zV1pL$)G@ZF-hdAYV)bV9h*;7F~#!AWwW+aL^tsZ_Ah!YpK zanr#uXQB#=n64?>{riWB2TO${9GYy61j$h$b|Ok@Py`b*_HzdN<$%53vxj5$NXeeY z*wYkyEn+V?Y(=npJoz5BeF=eGSzf`?WrSC`&jY@LMYf3kgrz|QmT(V1Nip`rd{0Z_ z7E;LLdkRGGUjZ&_d7l3zXMUU8n&P&;#nrvV)xX8{zQuLE&2=ww-EVR0zEiuGx3_Q_ p>rIV`&%33C(lVBoowRP>vC>^UznxE0S$X+B4gH&a>vY)n{{b>l=70bI delta 5599 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 diff --git a/templates/recruitment/interview_detail.html b/templates/recruitment/interview_detail.html index e411fba..29a3a1b 100644 --- a/templates/recruitment/interview_detail.html +++ b/templates/recruitment/interview_detail.html @@ -49,6 +49,7 @@ {% endblock %} {% block content %} +jhashkdhkashkdhkash
-- 2.39.5 From e6daa39f1ede6a31a6cbf359bd8ec6bcb61f0ddd Mon Sep 17 00:00:00 2001 From: Faheed Date: Tue, 21 Oct 2025 19:25:06 +0300 Subject: [PATCH 2/4] ... --- recruitment/__pycache__/views.cpython-312.pyc | Bin 92006 -> 93930 bytes recruitment/migrations/0001_initial.py | 478 ++++++++++++++++++ templates/includes/easy_logs.html | 2 +- 3 files changed, 479 insertions(+), 1 deletion(-) create mode 100644 recruitment/migrations/0001_initial.py diff --git a/recruitment/__pycache__/views.cpython-312.pyc b/recruitment/__pycache__/views.cpython-312.pyc index 8fb9bd05de3dbf19f205b8bf2821cf0d10141ac1..19c121a751dcd8b7f816f306356a047b49b05730 100644 GIT binary patch delta 4997 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 delta 3688 zcmb7Hd014}6`%8l_XcMWsVw3ELeNhb1~rHvibQJxKX(wshzl773y7!}hz3WYiTh_# z$*tZdE}+J^p+%p`sEvTTiE%@k2rkj6Y1Am#V2x{g&Ksj9ZThA2$L~Amcb0qZdH3CS z=Eep2n-jA8vDU4PI{Zz}yO$lGTjuTyN!vr*TwsRU!{w?JoMp(IK3BJeJn)ykGpltb zdqJoZ+eN?Y_!HbrNV zdFtF4zHnZrD49hg%LWh#f*iIT;Iy+yw!M5D^^@xGwH10e z#hcgnRT_}EqgSIoOi?W7$@v1oMS@c5(N`p0BDhTOHNh3Wy)qWg@LQFBy{{6{8a*vW z_N(J5<`nP0wdXG{>0F2$os09eTNnJY_kR>PVjGv6G1^IY)_3@+e353I9)# z7L)VjoS;tp>OlUfBM7^D!|^+~%De8WMQqv??(ui3VKil0scnl}cbf-%i(;dDN|EvO)ttS%F4``IJGFhkbOt|a`L#vm+X#~@1Z_V zJ+ga{UZJhC2L4jD5AU+qEI&Z?3?H($y4`)0@c3(QMiPY{CAf#4G4dm{HLByQAL%{* zMe#Zb0SF|XyZ>k~iH&UvbFx^3vx1C*LdKrEN)q4R5WsiUyYblv+Q{zcen~Ama2H;B zLg{K~rSA|n>78BG_NAa#aVI`!zYpJgC|CAGHBb#dyaT|Ke|6*|*&B&)^}VB$B=CIq z*aq1T^`2_wv2`GKKyjd&dVC&$J8wMkh8%>%F!j}w(i*2T!7sHdsTbr}F2JgGhn+VTzc;j$I!O!aL2Og#kf;uIOS@W)q>zIXN9`z+CxbmgyLy+)wg|R-(Dy_P=aRU6lMoGU&Xo9 zz#hEi)(KN28rfsg`}5q#xA2g+70VA7}LiOCAMyXdNQxr{EW3p2TDChN_nzH5(yP)EQu$;%t_Pa)plV z$D?1PTTXsXVU8^?BhyxBV-qP~rkL&u`KIUH*~61>dy2=da1PQ09;Bh(+LGGaT0&)L z1&tQ5MhO1z`xMLw2_D+@tQ{1(qgj7(#0a5*&XQ>1JOb_ONToUVHAT3aV5Kpa2!e%< zohA_OiuQaXMY0(zinCHtYK90?4mqyC^o{<)!xj7`Hd!>9!3^WYT{HB8iK3ey#47pZ zHdRdXgN4d8lC9#2AB0GM193SFyi8gFS~p5WqCa#}v>lg-Y5w2~--t#25Dufo$NrFz z^7CC$wj$c!B?3lj3`x@wENx$Wwq$y~=jG(&+_)GP0Ns?=$zCYl3V<+=86?jnn1WEy zmiHU%%`*lo901?+6K81ILArf*8 z@6x(eI$rg@msk=Be)2LTt~n|rp(99Pz_(X-=2f2?jXw@^v-P~J#z$Nl3kGYOqKR-J2qDnkA}wkosn0^$98$4sA~g~` zM`#(I8>`S*U_c0R{@5h)E~5$vo}j6KzSpI?^Cth5sTC9IO_tL57DeY3cE;0MI^?Xu zU4-|9sk|w`$8oGD1iF}3Q}6^zQ!ehtLLYe@5KHc$ie#u3XI_IOvvy;ZQr4f}P$JF-gQ2rnWP^C)XB1DMb9`xo zVo)}qY&qx{H4)ajl+eEqwvT}RATXN#8IA3XMs=o5b~NcR8tNF$Y>Xx?=1D-)67wVI zKtKZ#qZtRUAcQUiFB8zn!3Gg%pD+4|Ygav9Yj{A|+rpj={{7w|nqGM4DW}8P=xxi( zvlSI)cePE_rqHgh=VZ+&U>}gzdICDHjLspe6lb#`FtCbbIxvh*0HbHl=t*fEWSmM(R>r-Ho)Ep)z=R?WA0p@?)@c;k- diff --git a/recruitment/migrations/0001_initial.py b/recruitment/migrations/0001_initial.py new file mode 100644 index 0000000..d0c43dc --- /dev/null +++ b/recruitment/migrations/0001_initial.py @@ -0,0 +1,478 @@ +# Generated by Django 5.2.7 on 2025-10-21 11:27 + +import django.core.validators +import django.db.models.deletion +import django_ckeditor_5.fields +import django_countries.fields +import django_extensions.db.fields +import recruitment.validators +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='BreakTime', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('start_time', models.TimeField(verbose_name='Start Time')), + ('end_time', models.TimeField(verbose_name='End Time')), + ], + ), + migrations.CreateModel( + name='FormStage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')), + ('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')), + ('name', models.CharField(help_text='Name of the stage', max_length=200)), + ('order', models.PositiveIntegerField(default=0, help_text='Order of the stage in the form')), + ('is_predefined', models.BooleanField(default=False, help_text='Whether this is a default resume stage')), + ], + options={ + 'verbose_name': 'Form Stage', + 'verbose_name_plural': 'Form Stages', + 'ordering': ['order'], + }, + ), + migrations.CreateModel( + name='HiringAgency', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')), + ('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')), + ('name', models.CharField(max_length=200, unique=True, verbose_name='Agency Name')), + ('contact_person', models.CharField(blank=True, max_length=150, verbose_name='Contact Person')), + ('email', models.EmailField(blank=True, max_length=254)), + ('phone', models.CharField(blank=True, max_length=20)), + ('website', models.URLField(blank=True)), + ('notes', models.TextField(blank=True, help_text='Internal notes about the agency')), + ('country', django_countries.fields.CountryField(blank=True, max_length=2, null=True)), + ('address', models.TextField(blank=True, null=True)), + ], + options={ + 'verbose_name': 'Hiring Agency', + 'verbose_name_plural': 'Hiring Agencies', + 'ordering': ['name'], + }, + ), + migrations.CreateModel( + name='Source', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')), + ('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')), + ('name', models.CharField(help_text='e.g., ATS, ERP ', max_length=100, unique=True, verbose_name='Source Name')), + ('source_type', models.CharField(help_text='e.g., ATS, ERP ', max_length=100, verbose_name='Source Type')), + ('description', models.TextField(blank=True, help_text='A description of the source', verbose_name='Description')), + ('ip_address', models.GenericIPAddressField(blank=True, help_text='The IP address of the source', null=True, verbose_name='IP Address')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('api_key', models.CharField(blank=True, help_text='API key for authentication (will be encrypted)', max_length=255, null=True, verbose_name='API Key')), + ('api_secret', models.CharField(blank=True, help_text='API secret for authentication (will be encrypted)', max_length=255, null=True, verbose_name='API Secret')), + ('trusted_ips', models.TextField(blank=True, help_text='Comma-separated list of trusted IP addresses', null=True, verbose_name='Trusted IP Addresses')), + ('is_active', models.BooleanField(default=True, help_text='Whether this source is active for integration', verbose_name='Active')), + ('integration_version', models.CharField(blank=True, help_text='Version of the integration protocol', max_length=50, verbose_name='Integration Version')), + ('last_sync_at', models.DateTimeField(blank=True, help_text='Timestamp of the last successful synchronization', null=True, verbose_name='Last Sync At')), + ('sync_status', models.CharField(blank=True, choices=[('IDLE', 'Idle'), ('SYNCING', 'Syncing'), ('ERROR', 'Error'), ('DISABLED', 'Disabled')], default='IDLE', max_length=20, verbose_name='Sync Status')), + ], + options={ + 'verbose_name': 'Source', + 'verbose_name_plural': 'Sources', + 'ordering': ['name'], + }, + ), + migrations.CreateModel( + name='ZoomMeeting', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')), + ('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')), + ('topic', models.CharField(max_length=255, verbose_name='Topic')), + ('meeting_id', models.CharField(db_index=True, max_length=20, unique=True, verbose_name='Meeting ID')), + ('start_time', models.DateTimeField(db_index=True, verbose_name='Start Time')), + ('duration', models.PositiveIntegerField(verbose_name='Duration')), + ('timezone', models.CharField(max_length=50, verbose_name='Timezone')), + ('join_url', models.URLField(verbose_name='Join URL')), + ('participant_video', models.BooleanField(default=True, verbose_name='Participant Video')), + ('password', models.CharField(blank=True, max_length=20, null=True, verbose_name='Password')), + ('join_before_host', models.BooleanField(default=False, verbose_name='Join Before Host')), + ('mute_upon_entry', models.BooleanField(default=False, verbose_name='Mute Upon Entry')), + ('waiting_room', models.BooleanField(default=False, verbose_name='Waiting Room')), + ('zoom_gateway_response', models.JSONField(blank=True, null=True, verbose_name='Zoom Gateway Response')), + ('status', models.CharField(blank=True, db_index=True, default='waiting', max_length=20, null=True, verbose_name='Status')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='FormField', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')), + ('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')), + ('label', models.CharField(help_text='Label for the field', max_length=200)), + ('field_type', models.CharField(choices=[('text', 'Text Input'), ('email', 'Email'), ('phone', 'Phone'), ('textarea', 'Text Area'), ('file', 'File Upload'), ('date', 'Date Picker'), ('select', 'Dropdown'), ('radio', 'Radio Buttons'), ('checkbox', 'Checkboxes')], help_text='Type of the field', max_length=20)), + ('placeholder', models.CharField(blank=True, help_text='Placeholder text', max_length=200)), + ('required', models.BooleanField(default=False, help_text='Whether the field is required')), + ('order', models.PositiveIntegerField(default=0, help_text='Order of the field in the stage')), + ('is_predefined', models.BooleanField(default=False, help_text='Whether this is a default field')), + ('options', models.JSONField(blank=True, default=list, help_text='Options for selection fields (stored as JSON array)')), + ('file_types', models.CharField(blank=True, help_text="Allowed file types (comma-separated, e.g., '.pdf,.doc,.docx')", max_length=200)), + ('max_file_size', models.PositiveIntegerField(default=5, help_text='Maximum file size in MB (default: 5MB)')), + ('multiple_files', models.BooleanField(default=False, help_text='Allow multiple files to be uploaded')), + ('max_files', models.PositiveIntegerField(default=1, help_text='Maximum number of files allowed (when multiple_files is True)')), + ('stage', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='fields', to='recruitment.formstage')), + ], + options={ + 'verbose_name': 'Form Field', + 'verbose_name_plural': 'Form Fields', + 'ordering': ['order'], + }, + ), + migrations.CreateModel( + name='FormTemplate', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')), + ('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')), + ('name', models.CharField(help_text='Name of the form template', max_length=200)), + ('description', models.TextField(blank=True, help_text='Description of the form template')), + ('is_active', models.BooleanField(default=False, help_text='Whether this template is active')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='form_templates', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Form Template', + 'verbose_name_plural': 'Form Templates', + 'ordering': ['-created_at'], + }, + ), + migrations.CreateModel( + name='FormSubmission', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')), + ('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')), + ('submitted_at', models.DateTimeField(auto_now_add=True, db_index=True)), + ('applicant_name', models.CharField(blank=True, help_text='Name of the applicant', max_length=200)), + ('applicant_email', models.EmailField(blank=True, db_index=True, help_text='Email of the applicant', max_length=254)), + ('submitted_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='form_submissions', to=settings.AUTH_USER_MODEL)), + ('template', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='submissions', to='recruitment.formtemplate')), + ], + options={ + 'verbose_name': 'Form Submission', + 'verbose_name_plural': 'Form Submissions', + 'ordering': ['-submitted_at'], + }, + ), + migrations.AddField( + model_name='formstage', + name='template', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stages', to='recruitment.formtemplate'), + ), + migrations.CreateModel( + name='Candidate', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')), + ('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')), + ('first_name', models.CharField(max_length=255, verbose_name='First Name')), + ('last_name', models.CharField(max_length=255, verbose_name='Last Name')), + ('email', models.EmailField(db_index=True, max_length=254, verbose_name='Email')), + ('phone', models.CharField(max_length=20, verbose_name='Phone')), + ('address', models.TextField(max_length=200, verbose_name='Address')), + ('resume', models.FileField(upload_to='resumes/', verbose_name='Resume')), + ('is_resume_parsed', models.BooleanField(default=False, verbose_name='Resume Parsed')), + ('is_potential_candidate', models.BooleanField(default=False, verbose_name='Potential Candidate')), + ('parsed_summary', models.TextField(blank=True, verbose_name='Parsed Summary')), + ('applied', models.BooleanField(default=False, verbose_name='Applied')), + ('stage', models.CharField(choices=[('Applied', 'Applied'), ('Exam', 'Exam'), ('Interview', 'Interview'), ('Offer', 'Offer')], db_index=True, default='Applied', max_length=100, verbose_name='Stage')), + ('applicant_status', models.CharField(blank=True, choices=[('Applicant', 'Applicant'), ('Candidate', 'Candidate')], default='Applicant', max_length=100, null=True, verbose_name='Applicant Status')), + ('exam_date', models.DateTimeField(blank=True, null=True, verbose_name='Exam Date')), + ('exam_status', models.CharField(blank=True, choices=[('Passed', 'Passed'), ('Failed', 'Failed')], max_length=100, null=True, verbose_name='Exam Status')), + ('interview_date', models.DateTimeField(blank=True, null=True, verbose_name='Interview Date')), + ('interview_status', models.CharField(blank=True, choices=[('Passed', 'Passed'), ('Failed', 'Failed')], max_length=100, null=True, verbose_name='Interview Status')), + ('offer_date', models.DateField(blank=True, null=True, verbose_name='Offer Date')), + ('offer_status', models.CharField(blank=True, choices=[('Accepted', 'Accepted'), ('Rejected', 'Rejected')], max_length=100, null=True, verbose_name='Offer Status')), + ('join_date', models.DateField(blank=True, null=True, verbose_name='Join Date')), + ('ai_analysis_data', models.JSONField(default=dict, help_text='Full JSON output from the resume scoring model.', verbose_name='AI Analysis Data')), + ('submitted_by_agency', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='submitted_candidates', to='recruitment.hiringagency', verbose_name='Submitted by Agency')), + ], + options={ + 'verbose_name': 'Candidate', + 'verbose_name_plural': 'Candidates', + }, + ), + migrations.CreateModel( + name='JobPosting', + fields=[ + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')), + ('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')), + ('title', models.CharField(max_length=200)), + ('department', models.CharField(blank=True, max_length=100)), + ('job_type', models.CharField(choices=[('FULL_TIME', 'Full-time'), ('PART_TIME', 'Part-time'), ('CONTRACT', 'Contract'), ('INTERNSHIP', 'Internship'), ('FACULTY', 'Faculty'), ('TEMPORARY', 'Temporary')], default='FULL_TIME', max_length=20)), + ('workplace_type', models.CharField(choices=[('ON_SITE', 'On-site'), ('REMOTE', 'Remote'), ('HYBRID', 'Hybrid')], default='ON_SITE', max_length=20)), + ('location_city', models.CharField(blank=True, max_length=100)), + ('location_state', models.CharField(blank=True, max_length=100)), + ('location_country', models.CharField(default='Saudia Arabia', max_length=100)), + ('description', django_ckeditor_5.fields.CKEditor5Field(verbose_name='Description')), + ('qualifications', django_ckeditor_5.fields.CKEditor5Field(blank=True, null=True)), + ('salary_range', models.CharField(blank=True, help_text='e.g., $60,000 - $80,000', max_length=200)), + ('benefits', django_ckeditor_5.fields.CKEditor5Field(blank=True, null=True)), + ('application_url', models.URLField(blank=True, help_text='URL where candidates apply', null=True, validators=[django.core.validators.URLValidator()])), + ('application_start_date', models.DateField(blank=True, null=True)), + ('application_deadline', models.DateField(blank=True, db_index=True, null=True)), + ('application_instructions', django_ckeditor_5.fields.CKEditor5Field(blank=True, null=True)), + ('internal_job_id', models.CharField(editable=False, max_length=50, primary_key=True, serialize=False)), + ('created_by', models.CharField(blank=True, help_text='Name of person who created this job', max_length=100)), + ('status', models.CharField(choices=[('DRAFT', 'Draft'), ('ACTIVE', 'Active'), ('CLOSED', 'Closed'), ('CANCELLED', 'Cancelled'), ('ARCHIVED', 'Archived')], db_index=True, default='DRAFT', max_length=20)), + ('hash_tags', models.CharField(blank=True, help_text='Comma-separated hashtags for linkedin post like #hiring,#jobopening', max_length=200, validators=[recruitment.validators.validate_hash_tags])), + ('linkedin_post_id', models.CharField(blank=True, help_text='LinkedIn post ID after posting', max_length=200)), + ('linkedin_post_url', models.URLField(blank=True, help_text='Direct URL to LinkedIn post')), + ('posted_to_linkedin', models.BooleanField(default=False)), + ('linkedin_post_status', models.CharField(blank=True, help_text='Status of LinkedIn posting', max_length=50)), + ('linkedin_posted_at', models.DateTimeField(blank=True, null=True)), + ('published_at', models.DateTimeField(blank=True, db_index=True, null=True)), + ('position_number', models.CharField(blank=True, help_text='University position number', max_length=50)), + ('reporting_to', models.CharField(blank=True, help_text='Who this position reports to', max_length=100)), + ('joining_date', models.DateField(blank=True, help_text='Desired start date', null=True)), + ('open_positions', models.PositiveIntegerField(default=1, help_text='Number of open positions for this job')), + ('max_applications', models.PositiveIntegerField(blank=True, default=1000, help_text='Maximum number of applications allowed', null=True)), + ('cancel_reason', models.TextField(blank=True, help_text='Reason for canceling the job posting', verbose_name='Cancel Reason')), + ('cancelled_by', models.CharField(blank=True, help_text='Name of person who cancelled this job', max_length=100, verbose_name='Cancelled By')), + ('cancelled_at', models.DateTimeField(blank=True, null=True)), + ('hiring_agency', models.ManyToManyField(blank=True, help_text='External agency responsible for sourcing candidates for this role', related_name='jobs', to='recruitment.hiringagency', verbose_name='Hiring Agency')), + ('source', models.ForeignKey(blank=True, help_text='The system or channel from which this job posting originated or was first published.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='job_postings', to='recruitment.source')), + ], + options={ + 'verbose_name': 'Job Posting', + 'verbose_name_plural': 'Job Postings', + 'ordering': ['-created_at'], + }, + ), + migrations.CreateModel( + name='InterviewSchedule', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')), + ('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')), + ('start_date', models.DateField(db_index=True, verbose_name='Start Date')), + ('end_date', models.DateField(db_index=True, verbose_name='End Date')), + ('working_days', models.JSONField(verbose_name='Working Days')), + ('start_time', models.TimeField(verbose_name='Start Time')), + ('end_time', models.TimeField(verbose_name='End Time')), + ('break_start_time', models.TimeField(blank=True, null=True, verbose_name='Break Start Time')), + ('break_end_time', models.TimeField(blank=True, null=True, verbose_name='Break End Time')), + ('interview_duration', models.PositiveIntegerField(verbose_name='Interview Duration (minutes)')), + ('buffer_time', models.PositiveIntegerField(default=0, verbose_name='Buffer Time (minutes)')), + ('candidates', models.ManyToManyField(blank=True, null=True, related_name='interview_schedules', to='recruitment.candidate')), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('job', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='interview_schedules', to='recruitment.jobposting')), + ], + ), + migrations.AddField( + model_name='formtemplate', + name='job', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='form_template', to='recruitment.jobposting'), + ), + migrations.AddField( + model_name='candidate', + name='job', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='candidates', to='recruitment.jobposting', verbose_name='Job'), + ), + migrations.CreateModel( + name='JobPostingImage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('post_image', models.ImageField(upload_to='post/', validators=[recruitment.validators.validate_image_size])), + ('job', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='post_images', to='recruitment.jobposting')), + ], + ), + migrations.CreateModel( + name='Profile', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('profile_image', models.ImageField(blank=True, null=True, upload_to='profile_pic/', validators=[recruitment.validators.validate_image_size])), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='SharedFormTemplate', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')), + ('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')), + ('is_public', models.BooleanField(default=False, help_text='Whether this template is publicly available')), + ('shared_with', models.ManyToManyField(blank=True, related_name='shared_templates', to=settings.AUTH_USER_MODEL)), + ('template', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='recruitment.formtemplate')), + ], + options={ + 'verbose_name': 'Shared Form Template', + 'verbose_name_plural': 'Shared Form Templates', + }, + ), + migrations.CreateModel( + name='IntegrationLog', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')), + ('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')), + ('action', models.CharField(choices=[('REQUEST', 'Request'), ('RESPONSE', 'Response'), ('ERROR', 'Error'), ('SYNC', 'Sync'), ('CREATE_JOB', 'Create Job'), ('UPDATE_JOB', 'Update Job')], max_length=20, verbose_name='Action')), + ('endpoint', models.CharField(blank=True, max_length=255, verbose_name='Endpoint')), + ('method', models.CharField(blank=True, max_length=10, verbose_name='HTTP Method')), + ('request_data', models.JSONField(blank=True, null=True, verbose_name='Request Data')), + ('response_data', models.JSONField(blank=True, null=True, verbose_name='Response Data')), + ('status_code', models.CharField(blank=True, max_length=10, verbose_name='Status Code')), + ('error_message', models.TextField(blank=True, verbose_name='Error Message')), + ('ip_address', models.GenericIPAddressField(verbose_name='IP Address')), + ('user_agent', models.CharField(blank=True, max_length=255, verbose_name='User Agent')), + ('processing_time', models.FloatField(blank=True, null=True, verbose_name='Processing Time (seconds)')), + ('source', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='integration_logs', to='recruitment.source', verbose_name='Source')), + ], + options={ + 'verbose_name': 'Integration Log', + 'verbose_name_plural': 'Integration Logs', + 'ordering': ['-created_at'], + }, + ), + migrations.CreateModel( + name='TrainingMaterial', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')), + ('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')), + ('title', models.CharField(max_length=255, verbose_name='Title')), + ('content', django_ckeditor_5.fields.CKEditor5Field(blank=True, verbose_name='Content')), + ('video_link', models.URLField(blank=True, verbose_name='Video Link')), + ('file', models.FileField(blank=True, upload_to='training_materials/', verbose_name='File')), + ('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Created by')), + ], + options={ + 'verbose_name': 'Training Material', + 'verbose_name_plural': 'Training Materials', + }, + ), + migrations.CreateModel( + name='ScheduledInterview', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')), + ('interview_date', models.DateField(db_index=True, verbose_name='Interview Date')), + ('interview_time', models.TimeField(verbose_name='Interview Time')), + ('status', models.CharField(choices=[('scheduled', 'Scheduled'), ('confirmed', 'Confirmed'), ('cancelled', 'Cancelled'), ('completed', 'Completed')], db_index=True, default='scheduled', max_length=20)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('candidate', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='scheduled_interviews', to='recruitment.candidate')), + ('job', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='scheduled_interviews', to='recruitment.jobposting')), + ('schedule', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='interviews', to='recruitment.interviewschedule')), + ('zoom_meeting', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='interview', to='recruitment.zoommeeting')), + ], + ), + migrations.CreateModel( + name='MeetingComment', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')), + ('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')), + ('content', django_ckeditor_5.fields.CKEditor5Field(verbose_name='Content')), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='meeting_comments', to=settings.AUTH_USER_MODEL, verbose_name='Author')), + ('meeting', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='recruitment.zoommeeting', verbose_name='Meeting')), + ], + options={ + 'verbose_name': 'Meeting Comment', + 'verbose_name_plural': 'Meeting Comments', + 'ordering': ['-created_at'], + }, + ), + migrations.CreateModel( + name='FieldResponse', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')), + ('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')), + ('value', models.JSONField(blank=True, help_text='Response value (stored as JSON)', null=True)), + ('uploaded_file', models.FileField(blank=True, null=True, upload_to='form_uploads/')), + ('field', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='responses', to='recruitment.formfield')), + ('submission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='responses', to='recruitment.formsubmission')), + ], + options={ + 'verbose_name': 'Field Response', + 'verbose_name_plural': 'Field Responses', + 'indexes': [models.Index(fields=['submission'], name='recruitment_submiss_474130_idx'), models.Index(fields=['field'], name='recruitment_field_i_097e5b_idx')], + }, + ), + migrations.AddIndex( + model_name='formsubmission', + index=models.Index(fields=['submitted_at'], name='recruitment_submitt_7946c8_idx'), + ), + migrations.AddIndex( + model_name='interviewschedule', + index=models.Index(fields=['start_date'], name='recruitment_start_d_15d55e_idx'), + ), + migrations.AddIndex( + model_name='interviewschedule', + index=models.Index(fields=['end_date'], name='recruitment_end_dat_aeb00e_idx'), + ), + migrations.AddIndex( + model_name='interviewschedule', + index=models.Index(fields=['created_by'], name='recruitment_created_d0bdcc_idx'), + ), + migrations.AddIndex( + model_name='formtemplate', + index=models.Index(fields=['created_at'], name='recruitment_created_c21775_idx'), + ), + migrations.AddIndex( + model_name='formtemplate', + index=models.Index(fields=['is_active'], name='recruitment_is_acti_ae5efb_idx'), + ), + migrations.AddIndex( + model_name='candidate', + index=models.Index(fields=['stage'], name='recruitment_stage_f1c6eb_idx'), + ), + migrations.AddIndex( + model_name='candidate', + index=models.Index(fields=['created_at'], name='recruitment_created_73590f_idx'), + ), + migrations.AddIndex( + model_name='jobposting', + index=models.Index(fields=['status', 'created_at', 'title'], name='recruitment_status_8b77aa_idx'), + ), + migrations.AddIndex( + model_name='jobposting', + index=models.Index(fields=['slug'], name='recruitment_slug_004045_idx'), + ), + migrations.AddIndex( + model_name='scheduledinterview', + index=models.Index(fields=['job', 'status'], name='recruitment_job_id_f09e22_idx'), + ), + migrations.AddIndex( + model_name='scheduledinterview', + index=models.Index(fields=['interview_date', 'interview_time'], name='recruitment_intervi_7f5877_idx'), + ), + migrations.AddIndex( + model_name='scheduledinterview', + index=models.Index(fields=['candidate', 'job'], name='recruitment_candida_43d5b0_idx'), + ), + ] diff --git a/templates/includes/easy_logs.html b/templates/includes/easy_logs.html index 094b933..307dad7 100644 --- a/templates/includes/easy_logs.html +++ b/templates/includes/easy_logs.html @@ -275,7 +275,7 @@ {% elif active_tab == 'request' %} {{ log.datetime|date:"Y-m-d H:i:s" }} - {{ log.user.get_full_name|default:log.user.email|default:"Anonymous" }} + {{ log.user.email|default:"Anonymous" }} {{ log.method }} -- 2.39.5 From f33cf97975914ea9450b713df9c395c8c0a7508e Mon Sep 17 00:00:00 2001 From: Faheed Date: Wed, 22 Oct 2025 13:13:03 +0300 Subject: [PATCH 3/4] .... --- .../__pycache__/settings.cpython-312.pyc | Bin 8446 -> 8446 bytes .../__pycache__/urls.cpython-312.pyc | Bin 2313 -> 2342 bytes NorahUniversity/settings.py | 6 +- NorahUniversity/urls.py | 4 +- recruitment/__pycache__/admin.cpython-312.pyc | Bin 11915 -> 11903 bytes recruitment/__pycache__/forms.cpython-312.pyc | Bin 26564 -> 25868 bytes .../linkedin_service.cpython-312.pyc | Bin 16316 -> 16316 bytes .../__pycache__/models.cpython-312.pyc | Bin 61006 -> 60843 bytes .../__pycache__/signals.cpython-312.pyc | Bin 6657 -> 3138 bytes recruitment/__pycache__/urls.cpython-312.pyc | Bin 11879 -> 11888 bytes recruitment/__pycache__/views.cpython-312.pyc | Bin 93930 -> 92389 bytes .../views_frontend.cpython-312.pyc | Bin 23025 -> 24051 bytes recruitment/forms.py | 33 +- recruitment/migrations/0001_initial.py | 7 +- ...emove_jobposting_application_start_date.py | 17 + recruitment/models.py | 12 +- recruitment/signals.py | 2 +- recruitment/views.py | 94 +-- recruitment/views_frontend.py | 26 + templates/base.html | 34 +- templates/jobs/create_job.html | 229 ++++---- templates/jobs/edit_job.html | 229 ++++---- templates/jobs/job_detail.html | 268 ++++----- templates/jobs/job_list.html | 4 +- templates/meetings/meeting_details.html | 555 +++++++----------- templates/recruitment/candidate_detail.html | 8 +- .../candidate_resume_template.html | 27 + templates/recruitment/dashboard.html | 68 +++ 28 files changed, 753 insertions(+), 870 deletions(-) create mode 100644 recruitment/migrations/0002_remove_jobposting_application_start_date.py diff --git a/NorahUniversity/__pycache__/settings.cpython-312.pyc b/NorahUniversity/__pycache__/settings.cpython-312.pyc index 160b1cfceb5f7b32aab0dfe633c253c6fd66dfd9..42db791e7b29f27065ffeae054ec23e091f91874 100644 GIT binary patch delta 29 jcmez8_|K8|G%qg~0}ve9@;yUyBX6!eBgf`y`DR7{oIMGj delta 29 jcmez8_|K8|G%qg~0}yoif6H*$$eSzA$hEmzzL^mKlk^E3 diff --git a/NorahUniversity/__pycache__/urls.cpython-312.pyc b/NorahUniversity/__pycache__/urls.cpython-312.pyc index df79ce761314b4191b32d5bc38616df503fb4f47..17d54d837030259f9ed01a70db25de4911e8dcba 100644 GIT binary patch delta 264 zcmeAaS|-GMnwOW00SNwZ|H$y)$eYNbpqQ3llp9~3S(R9nqHj~2Q<`p7lA2qPlUR}( z58_R(XOWNuE5a(ff+aOtIk6y9AEv1on=(87TS7Vci7D}5%V0{YvUBMri+V06Y_G6H-elppzzG(zzo=(_AomJO$Yg5{U1hxutk(@ZE*f}T@K3(Nk^)v{ Yx}o&CdEiC!zzY$1S6K2VcXQMM06L*$@c;k- delta 235 zcmZ1`)G5S!nwOW00SJoNzGhf$ zHB=$7AX6Wvv{)Zqjh+52p`850l=!s#qTG0xx+-=2x;EFd?qE`sol$yS-t?lp=?>p3 zEM7NRI4*FiEJ(esW`0r4d`IpT7N5xx9J/', views.form_wizard_view, name='form_wizard'), - path('/submit/', views.submit_form, name='submit_form'), + path('form_wizard//', views.form_wizard_view, name='form_wizard'), + path('form//submit/', views.submit_form, name='submit_form'), path('api/templates/', views.list_form_templates, name='list_form_templates'), path('api/templates/save/', views.save_form_template, name='save_form_template'), diff --git a/recruitment/__pycache__/admin.cpython-312.pyc b/recruitment/__pycache__/admin.cpython-312.pyc index 0b0a860ce53c120f77f595c875d38c38198f10a5..cd0678a80dfb8fd30cebcd7c9b2f9d2d5c32b0d2 100644 GIT binary patch delta 469 zcmXAk%S%F05Qm!{he$36AwJSHAGb7uik9|()ZH5v~;B zx+rf2ZPF+tvw~>T9}z?(NvpbZI*X6rd^4OmXJ_GeUa2ZdTZ3^v^!n1)nW9;!8CRAe z{l_v+6vMFfi;@_yg(;3z+q*~_qnmD!)rJkbhZ4qs6{q$ibIfQ&CKz!>0&|W$&FC#1 z>mC1GIOKSQnzPTmCoMzv_w@nSG*Jri&M;+g+xba3T)4+5i*NU}Kf{Ca{wyaS z!_NpXb|vuUd8S=NTkR-y;=z0g^lL-BW+|0CBIj7yC8??i!P z0j+@pDj*%ulp7W$1Hq<99<%Bo9V4lF1gppmPF1V1>Rwevkwp{n;oJ<(jOrGz=L=YgqrW`96s}WpXcHI^1lCW&rN9Cn%3Up zf37%uP}C}dI`p}u(_J>}|_3qqDd6V+5o+O&V<>707t8jb*xgPRD3sLsZ#+4KjOzCz9tkjJFsxw}fOVacnMFLZ=I^{38p1YrSvng*X wpL1H>CRe`Vrx_6qmJM9%%TNQ=zN3hGDfK4mf;G<7@&@Yt3Hl*__s_Tf2l8yLbN~PV diff --git a/recruitment/__pycache__/forms.cpython-312.pyc b/recruitment/__pycache__/forms.cpython-312.pyc index 9725eb3dbdf5f2ae28daf02c5c52b51aac2fc152..7d31dceac68cb3d54970d89cf0bb043d4b5d0865 100644 GIT binary patch delta 2921 zcmaKue@t7~702Iw_A_9cAI9N_4aNpzz{Frf2n`Jo!jF<)7y@cqU{B<^AqF!p3$9?af5nh4VS8xDWp7|WYwY2Ttg9NiV@E$9;qN~QWp`p?r3u|05oZ3;A*Zm5PRI0QKv zb~Xe}8E9PzMPZagyiU;C& z#khXbBUeg(WHjZWC{`||%Bc@l77eH4+BAEO_O$=#Hw8MI0>J^Ff9DecsjslXJK(V= zN+Yl%>o};ajS#RFz=U-p+_O5{UAUEYUUJ|+=@epGRgKnwf0}PtKOFm{-#6eDEiD6{ z0dH_2ZCcpl=^gYA>#|E-4wuViDX?U(kw?=?5%cVdNHssal%1E?k2Qz&)*hdPm*cR0 zC(s$__xf>+#oZgX6%@OQR~NWkMey(JEZ=Z?gJ;OsH`r(K5B7C>B}<^&;_2`2^>umt z13`P7B)8Ndy4J&lBZQ-b9}s>>I6(lyNx~T6MZ%8=A%xqmg{F1caLAU#f^a>-bYK*t zm+>z+ft_`bn@TW_3Uho^qIy&{vw};u9e?s<$BB+9L++G$!&JIuHcIJ;o9C3t@iS^J zEq}~5?hH92>a3tBLP?PpKNHOvY-7T>Hl&?03NjZRGA&P-eKrU%T-)i!i$(QLmBb<$&h$qRAhtgvtWya5FIg?|oZoDznD7%VL zT1Ap6e#XezO3u`sZJdy$)QqV#Gv2{kRFyU|nq6bw4>FwZWjM(SPvs^&uI7yPv7~Wx z$ShYYnH7{S$~VT(#Bmnq*x>kq&;eO0#Dz*}Aq!oe$pOF3O~HG~ECy#@nsT<4-wN(L z8-I<1^0aKW4?b>BhCgiA3&9EzXBUc-^dfJ-t?v*J@<&uG#FY=l1v%a*sveB*<@R#+ zDEG9g*|*mt_Q?G(93Pojnxw!UpTEm1H^{KI#WN`SEbAptr_Up|i(LhY`PPMFs3AX9 zXTc5#?!XJV{|q;;;$q_9aDF;m$}eRx;ji+$85@Hgj#rS%f(GUYHy2!GYy=F>o}5?F zB()%>6}?`+^g2xyg!2e|cec@Z1kO6wu+s1+&aI3cgW{rfvA1oE>@KZpJDn( zaK9>Rp~k0FgK+D?y)o0?m?Jelm21HI^UM!b)g?@#V@CJ~nm&V*)isey>3^q6gxgq2 z`j}?&)1VM+O-&A4YC??Nfs3_!)OSfG+=a*MyzFlHOkF)=r{MD^%Geu_Ro}o)h5PGo zF*XD4jrFzTl%7wxLy(`!7c_DpUW=9lT2V#lq38@Dnx-)XH9-S^-I%XBL&`nqug($_ z7>y0PHXUJ132$v)$^HqSZ*E~`DBp5BBML=4`ImZjTH*5#U_kErC@61eVYzU;VT9>G z>(0UgPPZX}Oi~rCu!WEUx-Nreo`!_48SHb9uzBh;C@-x5cjLQwW~4WT1Tz{7!xx+I z<=Y3(Hd{3BlWD1eQs8oPI$H~$G#@hmg_P}xAbPkeX&uc?v@pQ|qb+&N6rOC+@wMN) zDc`uIk`{}(rC0`E>r;eWoNR)uZC4gr#zxB#Ht_#{os?Q?J4EE6+hDS#3Ob%TEv&@E z_7|SEEtu_OCbTX$^MZ}~%@#4+W%J8VpA%e|_-$~vF1{Lt$_^DGCHz%&0(Y1!<_Q(Pxh z7bd;QNph>oy(B+j`AHSR-@N98Vp_3|AYWB8Xu3_z1NQF2iCcK4kNlvR=V(0N1i$b8 G@BaY(e)#VI delta 3588 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 delta 7172 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 M{XQ87T_5lIUzP#psQ>@~ diff --git a/recruitment/__pycache__/signals.cpython-312.pyc b/recruitment/__pycache__/signals.cpython-312.pyc index e9aa0133583bd346189a097ebefbd331358fdca8..9bc8496b6db39600ac6c467e47bf409b60d97a48 100644 GIT binary patch delta 769 zcmYLH&rcIU6rS1bmZj}(rEH-;RF)s6tdgP##Hi6|fTWOc77sSd&Y}g{EwkG|3H~7A zpeJc2M#8~6DbWM}fH6@IaPZ)P5ThaSpf?CH5-<9uKzx(=^38j1zU+K&7kl5u)J;VR zAPBYP@Il{&iW zqL*_DhCn5d*b$0TYiw1xcQx?8k4B-wzt}wu@C5DFso&+ucBp?lq&**bHu6jI)d%(@ zB!>^6jy8%|$Jb~WXibxz0_OSvbO@>e*=ceuhuT@oERY;AJv&Qnx0JVO5{gk46>q0# z6HrS8IEf$-z7Jl5Dg4>Xm=0|`661p8Ck;enZ~eD2J`yEOL?q3yW2AmPUX_pTV?+{s zoj8h7IZ;luqf5xevjRqA2*WBT=EN~Hi;X1vs(kdfz+I}ds(R;4V$|e5nbUe^K=0Nw zGiKh@M@#u}oBov8Up3z2hvxZkx=1Fv(!{Z9FlWfLjf=E%=-_aU!?Eyi_$*s&=(;FT zg=ZT$L^w18>?oE~@J!3gx}JI8cKLj`gJ2;WizI`6aOOJhGTwL`xr}iSGh+sO)2Mg; zp20|M`=qq)i7=IKN-NMmZU~xJ28_X=_&z8NYIR1GZN*l5v@NirtKT_CY1P(=00RE;@!zzT>sQq8UBn@`$8QK9EeEh+~aItV;|xvZ3ttPC(rK- IoYo}&0nRP4ssI20 delta 2272 zcma)8O>7%Q6yEjUuGecjZ8wfn|83$Vj)U{lCT&t$0U-^gsG_Bb1iesgcP7pf+Z*k! zn`8xwD)rDK(H;sFAi<3$w_f4Gr64%e5|XXGa4wg&G!hag-ptzhK@qUlj^6v`&G+8> z=B?x(l6R(JKS!ei1JC`>|5*O1uoX+P-)$A{veB)b94l`9k_>FH#fZbRUp;#46Ij9Z zt*#hBh%Y+5z7L&e{$#KRyqF^f-t@g>oNIwzaR~_TGavgt4I2HA>VaOLBq2ZQhBtx2 zJ3ZSx$;UWf1ZIvUQ5gAm0^0!!F`opTuS1hk5cQ&y=os?B9=9FZ4^JWSPK+}giD4^qqI^apVlRO$mMX%v9gGRn#cV5}%_S-HI@eZgI zrYeQe=+P>Tq47iE0tx2?G(q%ma>2QaCBkYH7Ez-8H8e7#sVD%UgKe0#I?o^Qf*WmZsO-&_!H^I5%>+W?Gt6ryzet z_qOf$B||}V8Y*8@EbImlS%vxaRcvUureZsGP2V&%a!y{FY(m-F?l_%Z9R9t!lNhd_}31>q;4$uJD!txz}`K#k8eGU9S*+%A{BH zGNdbV{~{@f>vH-kX~}fCg?hEB7#p?(xt6eL0!oVUP&YP*4Qo?df(mK;Q}Th^#|gRz zdO}E-O|wqQylRw{nr72@TOcU*M2Ul{nz1jo-7~wU7|4_rknK8F^>U5sY(6EQlP%C) zLY~2Pl-v#p!f^S>ja5SGbhL*k)<0JH>&D2OHr+xrUkmWalJD> z9RPO*r44l9y^C)nqDe2R?L}b6c6}7rS?LS7f4zrkH7nnWi|<5C>X`!B%3pl^S&J2-54)Q8e=ZrO7&9hKm8< z%XbXfc~7870gRqEBt|Yaa}$l+L^C(t$W7BK`}XMN8K_c@JrUDKlsVK&3{hGz208}i zXNQ~z;Zgu_ncy54)9r>fB_=)COqCj`QZqH#NKMj=nZ1nZDae?P-Mex`!hTPeR&Uk| zca!fwk2BH1U51awb`wlysF@yZq(__SsYZH=61O8k@XQ$?&cvL%;bfrHE(Y2k7;WaK z8u_Va{(K{Uo}K}@+LttN0nQ9S`|=UhjIo^fSJZ7d~Rr GlYavdGm2>d diff --git a/recruitment/__pycache__/urls.cpython-312.pyc b/recruitment/__pycache__/urls.cpython-312.pyc index 95341511093e3ca8eeddef74f4b1c805fc7872f7..47958fabea638f05aabc4f81852ec4774d410ff0 100644 GIT binary patch delta 1307 zcmaKsOH5lw6o!o%S3rVUBz8!67{|W$^^5BSoDiU-*ch9Jgz|6-Ho@4z1QMuu*l9>x zXm?qX-bFW2MA}8Xs47=%*i@mbBDJb!q>)DII#L&j)M-_zs+2|U%xQN~yzuXTzWMa#k*H&_+ zLRPr_QTwynloxX1`%R$%ZL^$TT`pFlRWjFJ>gn8*xq~1@3EpJXzHp!JmHedS zo{EL3QKCliNS2~`Zj;O|*`zg8dQ#i9m(K<7$_! zd;Z(Cm8l7${(s_2M%{Cd6C(XG(pj~#aEgRec(z1QnZIj9TwXaL=~cv_qE~rG_Dt$O zdL3w_##s9S&~pgZt1=h{`4D7VZ57pz)Rs0`Jzpc|b?hlmJD+q`w<#LtInj%%9ua({ zw!xU&U;0j=JA(B3+60;Lwe-stccDdR)xyG25{@3VQ#8##HloHoz9-;==G_Q85hN#q zxGPD~2;UNYsy?}uUqN1iH2CGB3Nq{uicuwyul@1@`~>n6A`O97*kD?>2J8bFBX5kI zGs|P0uf|z-oOH*Ju2PidS%C8Z1CwUQ=*Mi1j`C`*R2c<~-ZTYLoQHK1d7{5l(7C*$kfWZJ4png2GK zEZ5C^3{oHH?+4rK#=%VJYe7%lB$z4vv0+kRruAQp*bJDo{+B^AVDfrL=;V!?U>0EJ z`D%o9O^~h$JiSR#i5Gw_3i_aRxA0Z*VX@Lj(M5g>$dV*2yD4V#5t|QdmnnLWF9W=- zKMdLG?tod*zYE!SR>6D(<9ro``QyYN$5-+c-Q-1}_kqfnElIQ_9$TQOz&`={DbUM@ zHa3_cgBhHc7w_>6ygob&58442k>l L#j%aM#=qffMhKXe delta 1551 zcmaKtO-vg{7>11*SB3|f1I2_tn}oIo z^+s=0dnkuWB_}N9vQaMd6i!v7UUt-xMm_Z0Q>3XBsfS*=GoPwTty&-a>6_<$-xS}G)Z?*9I@?-gBeOqJO<*Ekz&&YY;I>^#G71yaoGeI|4H6Q=Y zX>-&ZTsn+VR|LBv)YXk$-9NdKr!xeNuo@w$<&xGTH}!}iCc+pIwVmjJ$_JZ+8P)|inYXn?(MSsNs;-6~

l4BzK85#ih+dTO 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 hx3VD^U~rpZTQ^#Lb|luG~r diff --git a/recruitment/forms.py b/recruitment/forms.py index 1794f3f..7d16b42 100644 --- a/recruitment/forms.py +++ b/recruitment/forms.py @@ -197,10 +197,10 @@ class JobPostingForm(forms.ModelForm): fields = [ 'title', 'department', 'job_type', 'workplace_type', 'location_city', 'location_state', 'location_country', - 'description', 'qualifications', 'salary_range', 'benefits','application_start_date' - ,'application_deadline', 'application_instructions', - 'position_number', 'reporting_to', 'joining_date', - 'created_by','open_positions','hash_tags','max_applications' + 'description', 'qualifications', 'salary_range', 'benefits', + 'application_deadline', 'application_instructions', + 'position_number', 'reporting_to', + 'open_positions','hash_tags','max_applications' ] widgets = { # Basic Information @@ -249,13 +249,11 @@ class JobPostingForm(forms.ModelForm): # 'placeholder': 'https://university.edu/careers/job123', # 'required': True # }), - 'application_start_date': forms.DateInput(attrs={ - 'class': 'form-control', - 'type': 'date' - }), + 'application_deadline': forms.DateInput(attrs={ 'class': 'form-control', - 'type': 'date' + 'type': 'date', + 'required':True }), 'open_positions': forms.NumberInput(attrs={ @@ -278,15 +276,8 @@ class JobPostingForm(forms.ModelForm): 'class': 'form-control', 'placeholder': 'Department Chair, Director, etc.' }), - 'joining_date': forms.DateInput(attrs={ - 'class': 'form-control', - 'type': 'date' - }), - - 'created_by': forms.TextInput(attrs={ - 'class': 'form-control', - 'placeholder': 'University Administrator' - }), + + 'max_applications': forms.NumberInput(attrs={ 'class': 'form-control', 'min': 1, @@ -296,19 +287,15 @@ class JobPostingForm(forms.ModelForm): def __init__(self,*args,**kwargs): - # Extract your custom argument BEFORE calling super() - self.is_anonymous_user = kwargs.pop('is_anonymous_user', False) # Now call the parent __init__ with remaining args super().__init__(*args, **kwargs) if not self.instance.pk:# Creating new job posting - if not self.is_anonymous_user: - self.fields['created_by'].initial = 'University Administrator' # self.fields['status'].initial = 'Draft' self.fields['location_city'].initial='Riyadh' self.fields['location_state'].initial='Riyadh Province' self.fields['location_country'].initial='Saudi Arabia' - + def clean_hash_tags(self): hash_tags=self.cleaned_data.get('hash_tags') diff --git a/recruitment/migrations/0001_initial.py b/recruitment/migrations/0001_initial.py index d0c43dc..bf6f650 100644 --- a/recruitment/migrations/0001_initial.py +++ b/recruitment/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.2.7 on 2025-10-21 11:27 +# Generated by Django 5.2.7 on 2025-10-21 22:26 import django.core.validators import django.db.models.deletion @@ -236,8 +236,8 @@ class Migration(migrations.Migration): ('salary_range', models.CharField(blank=True, help_text='e.g., $60,000 - $80,000', max_length=200)), ('benefits', django_ckeditor_5.fields.CKEditor5Field(blank=True, null=True)), ('application_url', models.URLField(blank=True, help_text='URL where candidates apply', null=True, validators=[django.core.validators.URLValidator()])), - ('application_start_date', models.DateField(blank=True, null=True)), - ('application_deadline', models.DateField(blank=True, db_index=True, null=True)), + ('application_start_date', models.DateField()), + ('application_deadline', models.DateField(db_index=True)), ('application_instructions', django_ckeditor_5.fields.CKEditor5Field(blank=True, null=True)), ('internal_job_id', models.CharField(editable=False, max_length=50, primary_key=True, serialize=False)), ('created_by', models.CharField(blank=True, help_text='Name of person who created this job', max_length=100)), @@ -251,7 +251,6 @@ class Migration(migrations.Migration): ('published_at', models.DateTimeField(blank=True, db_index=True, null=True)), ('position_number', models.CharField(blank=True, help_text='University position number', max_length=50)), ('reporting_to', models.CharField(blank=True, help_text='Who this position reports to', max_length=100)), - ('joining_date', models.DateField(blank=True, help_text='Desired start date', null=True)), ('open_positions', models.PositiveIntegerField(default=1, help_text='Number of open positions for this job')), ('max_applications', models.PositiveIntegerField(blank=True, default=1000, help_text='Maximum number of applications allowed', null=True)), ('cancel_reason', models.TextField(blank=True, help_text='Reason for canceling the job posting', verbose_name='Cancel Reason')), diff --git a/recruitment/migrations/0002_remove_jobposting_application_start_date.py b/recruitment/migrations/0002_remove_jobposting_application_start_date.py new file mode 100644 index 0000000..750027d --- /dev/null +++ b/recruitment/migrations/0002_remove_jobposting_application_start_date.py @@ -0,0 +1,17 @@ +# Generated by Django 5.2.7 on 2025-10-21 23:25 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('recruitment', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='jobposting', + name='application_start_date', + ), + ] diff --git a/recruitment/models.py b/recruitment/models.py index 91a1fb6..00a51ac 100644 --- a/recruitment/models.py +++ b/recruitment/models.py @@ -84,8 +84,8 @@ class JobPosting(Base): null=True, blank=True, ) - application_start_date=models.DateField(null=True, blank=True) - application_deadline = models.DateField(db_index=True, null=True, blank=True) # Added index + + application_deadline = models.DateField(db_index=True) # Added index application_instructions =CKEditor5Field( blank=True, null=True,config_name='extends' ) @@ -137,7 +137,7 @@ class JobPosting(Base): reporting_to = models.CharField( max_length=100, blank=True, help_text="Who this position reports to" ) - joining_date = models.DateField(null=True, blank=True, help_text="Desired start date") + open_positions = models.PositiveIntegerField( default=1, help_text="Number of open positions for this job" ) @@ -732,8 +732,10 @@ class FormTemplate(Base): blank=True, help_text="Description of the form template" ) created_by = models.ForeignKey( - User, on_delete=models.CASCADE, related_name="form_templates",null=True,blank=True, db_index=True - ) + User, on_delete=models.CASCADE, related_name="form_templates",null=True,blank=True, db_index=True + ) + # FIXME: on Delete model SETNULl + is_active = models.BooleanField( default=False, help_text="Whether this template is active" ) diff --git a/recruitment/signals.py b/recruitment/signals.py index ebc9f9b..2d1ed97 100644 --- a/recruitment/signals.py +++ b/recruitment/signals.py @@ -10,7 +10,7 @@ logger = logging.getLogger(__name__) @receiver(post_save, sender=JobPosting) def format_job(sender, instance, created, **kwargs): if created: - FormTemplate.objects.create(job=instance, is_active=True, name=instance.title) + # FormTemplate.objects.create(job=instance, is_active=True, name=instance.title) async_task( 'recruitment.tasks.format_job_description', instance.pk, diff --git a/recruitment/views.py b/recruitment/views.py index 73fc246..3c24c73 100644 --- a/recruitment/views.py +++ b/recruitment/views.py @@ -273,21 +273,12 @@ def create_job(request): if request.method == "POST": form = JobPostingForm( - request.POST, is_anonymous_user=not request.user.is_authenticated + request.POST ) # to check user is authenticated or not if form.is_valid(): try: job = form.save(commit=False) - if request.user.is_authenticated: - job.created_by = ( - request.user.get_full_name() or request.user.username - ) - else: - job.created_by = request.POST.get("created_by", "").strip() - if not job.created_by: - job.created_by = request.user.username - job.save() job_apply_url_relative=reverse('job_detail_candidate',kwargs={'slug':job.slug}) job_apply_url_absolute=request.build_absolute_uri(job_apply_url_relative) @@ -302,7 +293,7 @@ def create_job(request): else: messages.error(request, f"Please correct the errors below.{form.errors}") else: - form = JobPostingForm(is_anonymous_user=not request.user.is_authenticated) + form = JobPostingForm() return render(request, "jobs/create_job.html", {"form": form}) @@ -313,21 +304,11 @@ def edit_job(request, slug): if request.method == "POST": form = JobPostingForm( request.POST, - instance=job, - is_anonymous_user=not request.user.is_authenticated, + instance=job ) if form.is_valid(): try: - job = form.save(commit=False) - if request.user.is_authenticated: - job.created_by = ( - request.user.get_full_name() or request.user.username - ) - else: - job.created_by = request.POST.get("created_by", "").strip() - if not job.created_by: - job.created_by = "University Administrator" - job.save() + form.save() messages.success(request, f'Job "{job.title}" updated successfully!') return redirect("job_list") except Exception as e: @@ -338,7 +319,7 @@ def edit_job(request, slug): else: job = get_object_or_404(JobPosting, slug=slug) form = JobPostingForm( - instance=job, is_anonymous_user=not request.user.is_authenticated + instance=job ) return render(request, "jobs/edit_job.html", {"form": form, "job": job}) @@ -347,6 +328,7 @@ def edit_job(request, slug): def job_detail(request, slug): """View details of a specific job""" job = get_object_or_404(JobPosting, slug=slug) + # Get all candidates for this job, ordered by most recent applicants = job.candidates.all().order_by("-created_at") @@ -632,15 +614,15 @@ def application_success(request,slug): @ensure_csrf_cookie @login_required -def form_builder(request, template_slug=None): +def form_builder(request, template_id=None): """Render the form builder interface""" context = {} - if template_slug: + if template_id: template = get_object_or_404( - FormTemplate, slug=template_slug + FormTemplate, id=template_id, created_by=request.user ) context['template']=template - context["template_slug"] = template.slug + context["template_id"] = template.id context["template_name"] = template.name return render(request, "forms/form_builder.html", context) @@ -653,12 +635,12 @@ def save_form_template(request): data = json.loads(request.body) template_name = data.get("name", "Untitled Form") stages_data = data.get("stages", []) - template_slug = data.get("template_slug") + template_id = data.get("template_id") - if template_slug: + if template_id: # Update existing template template = get_object_or_404( - FormTemplate, slug=template_slug + FormTemplate, id=template_id, created_by=request.user ) template.name = template_name template.save() @@ -667,7 +649,7 @@ def save_form_template(request): else: # Create new template template = FormTemplate.objects.create( - name=template_name + name=template_name, created_by=request.user ) # Create stages and fields @@ -703,7 +685,7 @@ def save_form_template(request): return JsonResponse( { "success": True, - "template_slug": template.slug, + "template_id": template.id, "message": "Form template saved successfully!", } ) @@ -712,9 +694,9 @@ def save_form_template(request): @require_http_methods(["GET"]) -def load_form_template(request, template_slug): +def load_form_template(request, template_id): """Load an existing form template""" - template = get_object_or_404(FormTemplate, slug=template_slug) + template = get_object_or_404(FormTemplate, id=template_id, created_by=request.user) stages = [] for stage in template.stages.all(): @@ -747,7 +729,6 @@ def load_form_template(request, template_slug): "success": True, "template": { "id": template.id, - "template_slug": template.slug, "name": template.name, "description": template.description, "is_active": template.is_active, @@ -762,7 +743,7 @@ def load_form_template(request, template_slug): def form_templates_list(request): """List all form templates for the current user""" query = request.GET.get("q", "") - templates = FormTemplate.objects.filter() + templates = FormTemplate.objects.filter(created_by=request.user) if query: templates = templates.filter( @@ -802,7 +783,7 @@ def create_form_template(request): @require_http_methods(["GET"]) def list_form_templates(request): """List all form templates for the current user""" - templates = FormTemplate.objects.filter().values( + templates = FormTemplate.objects.filter(created_by=request.user).values( "id", "name", "description", "created_at", "updated_at" ) return JsonResponse({"success": True, "templates": list(templates)}) @@ -812,25 +793,26 @@ def list_form_templates(request): @require_http_methods(["DELETE"]) def delete_form_template(request, template_id): """Delete a form template""" - template = get_object_or_404(FormTemplate, id=template_id) + template = get_object_or_404(FormTemplate, id=template_id, created_by=request.user) template.delete() return JsonResponse( {"success": True, "message": "Form template deleted successfully!"} ) -def form_wizard_view(request, template_slug): +def form_wizard_view(request, template_id): """Display the form as a step-by-step wizard""" - template = get_object_or_404(FormTemplate, slug=template_slug, is_active=True) + template = get_object_or_404(FormTemplate, pk=template_id, is_active=True) job_id = template.job.internal_job_id job=template.job - is_limit_exceeded = job.is_application_limit_reached + is_limit_exceeded=job.is_application_limit_reached if is_limit_exceeded: messages.error( request, 'Application limit reached: This job is no longer accepting new applications. Please explore other available positions.' ) return redirect('job_detail_candidate',slug=job.slug) + if job.is_expired: messages.error( request, @@ -841,16 +823,14 @@ def form_wizard_view(request, template_slug): return render( request, "forms/form_wizard.html", - {"template_slug": template_slug, "job_id": job_id}, + {"template_id": template_id, "job_id": job_id}, ) -@csrf_exempt @require_POST -def submit_form(request, template_slug): +def submit_form(request, template_id): """Handle form submission""" - template = get_object_or_404(FormTemplate, slug=template_slug) - job = template.job + template = get_object_or_404(FormTemplate, id=template_id) if request.method == "POST": try: with transaction.atomic(): @@ -864,7 +844,6 @@ def submit_form(request, template_slug): {"success": False, "message": "Application limit reached for this job."} ) submission = FormSubmission.objects.create(template=template) - # Process field responses for field_id, value in request.POST.items(): if field_id.startswith("field_"): @@ -909,7 +888,7 @@ def submit_form(request, template_slug): ) submission.applicant_email = email.display_value submission.save() - # time=timezone.now() + time=timezone.now() Candidate.objects.create( first_name=first_name.display_value, last_name=last_name.display_value, @@ -917,16 +896,10 @@ def submit_form(request, template_slug): phone=phone.display_value, address=address.display_value, resume=resume.get_file if resume.is_file else None, - job=job + job=submission.template.job, + ) - return JsonResponse( - { - "success": True, - "message": "Form submitted successfully!", - "redirect_url": reverse('application_success',kwargs={'slug':job.slug}), - } - ) - # return redirect('application_success',slug=job.slug) + return redirect('application_success',slug=job.slug) except Exception as e: logger.error(f"Candidate creation failed,{e}") @@ -2071,6 +2044,7 @@ def user_detail(request, pk): user = get_object_or_404(User, pk=pk) try: + profile_instance = user.profile profile_form = ProfileImageUploadForm(instance=profile_instance) except: @@ -2224,10 +2198,6 @@ def account_toggle_status(request,pk): messages.error(f'Please correct the error below') -@login_required -def user_detail(requests,pk): - user=get_object_or_404(User,pk=pk) - return render(requests,'user/profile.html') @csrf_exempt diff --git a/recruitment/views_frontend.py b/recruitment/views_frontend.py index 50c05e3..61d5fa2 100644 --- a/recruitment/views_frontend.py +++ b/recruitment/views_frontend.py @@ -394,6 +394,27 @@ def dashboard_view(request): ).count() high_potential_ratio = round((high_potential_count / total_candidates) * 100, 1) if total_candidates > 0 else 0 + #donut chart data + jobs=models.JobPosting.objects.all() + selected_job_id=request.GET.get('selected_job_id') + print(jobs) + print(selected_job_id) + apply_counts,exam_counts,interview_counts,offer_counts=[0]*4 + if selected_job_id: + job=jobs.filter(internal_job_id=selected_job_id) + apply_counts=job.screening_candidates_count or 0 + exam_counts=job.exam_candidates_count or 0 + interview_counts=job.interview_candidates_count or 0 + offer_counts=job.offer_candidates_count or 0 + + + + + applicant_stages=['APPLIED','EXAM','INTERVIEW','OFFER'] + stage_counts=[apply_counts,exam_counts,interview_counts,offer_counts] + + + context = { 'total_jobs': total_jobs, @@ -409,8 +430,13 @@ def dashboard_view(request): 'high_potential_count': high_potential_count, 'high_potential_ratio': high_potential_ratio, 'scored_ratio': scored_ratio, + 'applicant_stages':json.dumps(applicant_stages), + 'stage_counts':json.dumps(stage_counts), + 'jobs':'jobs', + 'selected_job_id':selected_job_id } return render(request, 'recruitment/dashboard.html', context) + @login_required def candidate_offer_view(request, slug): """View for candidates in the Offer stage""" diff --git a/templates/base.html b/templates/base.html index 0250f32..b4a6c35 100644 --- a/templates/base.html +++ b/templates/base.html @@ -16,9 +16,9 @@ {% endif %} - + - + @@ -120,7 +120,7 @@ {% endif %}

+ {# ================================================= #} - {# SECTION 2: JOB CONTENT (CKEDITOR 5 Fields) #} + {# SECTION 2: INTERNAL AND PROMOTION #} + {# ================================================= #} + +
+
+
{% trans "Internal & Promotion" %}
+
+
+
+
+
+ + {{ form.position_number }} + {% if form.position_number.errors %}
{{ form.position_number.errors }}
{% endif %} +
+
+
+
+ + {{ form.reporting_to }} + {% if form.reporting_to.errors %}
{{ form.reporting_to.errors }}
{% endif %} +
+
+
+
+ + {{ form.open_positions }} + {% if form.open_positions.errors %}
{{ form.open_positions.errors }}
{% endif %} +
+
+
+
+ + {{ form.max_applications }} + {% if form.max_applications.errors %}
{{ form.max_applications.errors }}
{% endif %} +
+
+ + +
+
+ + {{ form.hash_tags }} + {% if form.hash_tags.errors %}
{{ form.hash_tags.errors }}
{% endif %} +
{% trans "Comma-separated list of hashtags, e.g., #hiring, #professor" %}
+
+
+
+
+
+ + + {# ================================================= #} + {# SECTION 3: LOCATION AND DATES #} + {# ================================================= #} + +
+
+
{% trans "Location, Dates, & Salary" %}
+
+
+
+
+
+ + {{ form.location_city }} + {% if form.location_city.errors %}
{{ form.location_city.errors }}
{% endif %} +
+
+
+
+ + {{ form.location_state }} + {% if form.location_state.errors %}
{{ form.location_state.errors }}
{% endif %} +
+
+
+
+ + {{ form.location_country }} + {% if form.location_country.errors %}
{{ form.location_country.errors }}
{% endif %} +
+
+ +
+
+ + {{ form.application_deadline }} + {% if form.application_deadline.errors %}
{{ form.application_deadline.errors }}
{% endif %} +
+
+ +
+
+ + {{ form.salary_range }} + {% if form.salary_range.errors %}
{{ form.salary_range.errors }}
{% endif %} +
+
+ +
+
+
+ {# ================================================= #} + {# SECTION 4: JOB CONTENT (CKEDITOR 5 Fields) #} {# ================================================= #}
@@ -179,21 +284,15 @@
{# ================================================= #} - {# SECTION 3: COMPENSATION AND APPLICATION #} + {# SECTION 5: APPLICATION Instructions #} {# ================================================= #}
-
{% trans "Compensation & Application" %}
+
{% trans "Benefits & Application Instructions" %}
-
-
- - {{ form.salary_range }} - {% if form.salary_range.errors %}
{{ form.salary_range.errors }}
{% endif %} -
-
+ {% comment %} (application_url comment removed for brevity) {% endcomment %}
@@ -215,117 +314,7 @@
- {# ================================================= #} - {# SECTION 4: LOCATION AND DATES #} - {# ================================================= #} -
-
-
{% trans "Location, Dates, & Status" %}
-
-
-
-
-
- - {{ form.location_city }} - {% if form.location_city.errors %}
{{ form.location_city.errors }}
{% endif %} -
-
-
-
- - {{ form.location_state }} - {% if form.location_state.errors %}
{{ form.location_state.errors }}
{% endif %} -
-
-
-
- - {{ form.location_country }} - {% if form.location_country.errors %}
{{ form.location_country.errors }}
{% endif %} -
-
-
-
- - {{ form.application_deadline }} - {% if form.application_deadline.errors %}
{{ form.application_deadline.errors }}
{% endif %} -
-
-
-
- - {{ form.application_start_date }} - {% if form.application_start_date.errors %}
{{ form.application_start_date.errors }}
{% endif %} -
-
-
-
- - {{ form.joining_date }} - {% if form.joining_date.errors %}
{{ form.joining_date.errors }}
{% endif %} -
-
-
-
-
- - {# ================================================= #} - {# SECTION 5: INTERNAL AND PROMOTION #} - {# ================================================= #} -
-
-
{% trans "Internal & Promotion" %}
-
-
-
-
-
- - {{ form.position_number }} - {% if form.position_number.errors %}
{{ form.position_number.errors }}
{% endif %} -
-
-
-
- - {{ form.reporting_to }} - {% if form.reporting_to.errors %}
{{ form.reporting_to.errors }}
{% endif %} -
-
-
-
- - {{ form.open_positions }} - {% if form.open_positions.errors %}
{{ form.open_positions.errors }}
{% endif %} -
-
-
-
- - {{ form.max_applications }} - {% if form.max_applications.errors %}
{{ form.max_applications.errors }}
{% endif %} -
-
-
-
- - {{ form.created_by }} - {% if form.created_by.errors %}
{{ form.created_by.errors }}
{% endif %} -
-
-
-
- - {{ form.hash_tags }} - {% if form.hash_tags.errors %}
{{ form.hash_tags.errors }}
{% endif %} -
{% trans "Comma-separated list of hashtags, e.g., #hiring, #professor" %}
-
-
-
-
-
{# ================================================= #} {# ACTION BUTTONS #} diff --git a/templates/jobs/edit_job.html b/templates/jobs/edit_job.html index 5e3fa74..c311ec6 100644 --- a/templates/jobs/edit_job.html +++ b/templates/jobs/edit_job.html @@ -150,8 +150,113 @@
+ {# ================================================= #} - {# SECTION 2: JOB CONTENT (CKEDITOR 5 Fields) #} + {# SECTION 2: INTERNAL AND PROMOTION #} + {# ================================================= #} + +
+
+
{% trans "Internal & Promotion" %}
+
+
+
+
+
+ + {{ form.position_number }} + {% if form.position_number.errors %}
{{ form.position_number.errors }}
{% endif %} +
+
+
+
+ + {{ form.reporting_to }} + {% if form.reporting_to.errors %}
{{ form.reporting_to.errors }}
{% endif %} +
+
+
+
+ + {{ form.open_positions }} + {% if form.open_positions.errors %}
{{ form.open_positions.errors }}
{% endif %} +
+
+
+
+ + {{ form.max_applications }} + {% if form.max_applications.errors %}
{{ form.max_applications.errors }}
{% endif %} +
+
+ + +
+
+ + {{ form.hash_tags }} + {% if form.hash_tags.errors %}
{{ form.hash_tags.errors }}
{% endif %} +
{% trans "Comma-separated list of hashtags, e.g., #hiring, #professor" %}
+
+
+
+
+
+ + + {# ================================================= #} + {# SECTION 3: LOCATION AND DATES #} + {# ================================================= #} + +
+
+
{% trans "Location, Dates, & Salary" %}
+
+
+
+
+
+ + {{ form.location_city }} + {% if form.location_city.errors %}
{{ form.location_city.errors }}
{% endif %} +
+
+
+
+ + {{ form.location_state }} + {% if form.location_state.errors %}
{{ form.location_state.errors }}
{% endif %} +
+
+
+
+ + {{ form.location_country }} + {% if form.location_country.errors %}
{{ form.location_country.errors }}
{% endif %} +
+
+ +
+
+ + {{ form.application_deadline }} + {% if form.application_deadline.errors %}
{{ form.application_deadline.errors }}
{% endif %} +
+
+ +
+
+ + {{ form.salary_range }} + {% if form.salary_range.errors %}
{{ form.salary_range.errors }}
{% endif %} +
+
+ +
+
+
+ {# ================================================= #} + {# SECTION 4: JOB CONTENT (CKEDITOR 5 Fields) #} {# ================================================= #}
@@ -179,21 +284,15 @@
{# ================================================= #} - {# SECTION 3: COMPENSATION AND APPLICATION #} + {# SECTION 5: APPLICATION Instructions #} {# ================================================= #}
-
{% trans "Compensation & Application" %}
+
{% trans "Benefits & Application Instructions" %}
-
-
- - {{ form.salary_range }} - {% if form.salary_range.errors %}
{{ form.salary_range.errors }}
{% endif %} -
-
+ {% comment %} (application_url comment removed for brevity) {% endcomment %}
@@ -215,117 +314,7 @@
- {# ================================================= #} - {# SECTION 4: LOCATION AND DATES #} - {# ================================================= #} -
-
-
{% trans "Location, Dates, & Status" %}
-
-
-
-
-
- - {{ form.location_city }} - {% if form.location_city.errors %}
{{ form.location_city.errors }}
{% endif %} -
-
-
-
- - {{ form.location_state }} - {% if form.location_state.errors %}
{{ form.location_state.errors }}
{% endif %} -
-
-
-
- - {{ form.location_country }} - {% if form.location_country.errors %}
{{ form.location_country.errors }}
{% endif %} -
-
-
-
- - {{ form.application_deadline }} - {% if form.application_deadline.errors %}
{{ form.application_deadline.errors }}
{% endif %} -
-
-
-
- - {{ form.application_start_date }} - {% if form.application_start_date.errors %}
{{ form.application_start_date.errors }}
{% endif %} -
-
-
-
- - {{ form.joining_date }} - {% if form.joining_date.errors %}
{{ form.joining_date.errors }}
{% endif %} -
-
-
-
-
- - {# ================================================= #} - {# SECTION 5: INTERNAL AND PROMOTION #} - {# ================================================= #} -
-
-
{% trans "Internal & Promotion" %}
-
-
-
-
-
- - {{ form.position_number }} - {% if form.position_number.errors %}
{{ form.position_number.errors }}
{% endif %} -
-
-
-
- - {{ form.reporting_to }} - {% if form.reporting_to.errors %}
{{ form.reporting_to.errors }}
{% endif %} -
-
-
-
- - {{ form.open_positions }} - {% if form.open_positions.errors %}
{{ form.open_positions.errors }}
{% endif %} -
-
-
-
- - {{ form.max_applications }} - {% if form.max_applications.errors %}
{{ form.max_applications.errors }}
{% endif %} -
-
-
-
- - {{ form.created_by }} - {% if form.created_by.errors %}
{{ form.created_by.errors }}
{% endif %} -
-
-
-
- - {{ form.hash_tags }} - {% if form.hash_tags.errors %}
{{ form.hash_tags.errors }}
{% endif %} -
{% trans "Comma-separated list of hashtags, e.g., #hiring, #professor" %}
-
-
-
-
-
{# ================================================= #} {# ACTION BUTTONS #} diff --git a/templates/jobs/job_detail.html b/templates/jobs/job_detail.html index 06ecf71..2a9322a 100644 --- a/templates/jobs/job_detail.html +++ b/templates/jobs/job_detail.html @@ -1,4 +1,3 @@ - {% extends "base.html" %} {% load i18n static %} @@ -217,8 +216,17 @@ padding-top: 0.5rem; } - - + /* Custom CSS for simplified stat card (from previous answer) */ + .stats-grid .kpi-card { + border-left: 4px solid var(--kaauh-teal); + background-color: #f0faff; + } + .stats-grid .card-body { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + } {% endblock %} @@ -236,7 +244,7 @@
{# LEFT COLUMN: JOB DETAILS WITH TABS #} -
+
{# HEADER SECTION #} @@ -248,6 +256,7 @@
+ {# Corrected status badge logic to close the span correctly #} {% if job.status == "ACTIVE" %} {% elif job.status == "DRAFT" %} @@ -262,6 +271,7 @@ {% endif %} {{ job.get_status_display }} + @@ -281,13 +291,12 @@ {% trans "Description & Requirements" %} - {% if job.application_instructions %} - {% endif %} +
@@ -323,21 +332,20 @@
- + - -
+ +
{% trans "Financial & Timeline" %}
@@ -392,19 +400,74 @@
{{ job.benefits|safe}}
{% endif %} -
- - {# TAB 3 CONTENT: APPLICATION INSTRUCTIONS #} - {% if job.application_instructions %} -
-
+ {% if job.application_instructions %} +
{% trans "Application Instructions" %}
{{ job.application_instructions|safe }}
-
- {% endif %} + {% endif %} +
+ + {# TAB 3 CONTENT: APPLICATION KPIS #} +
+
+ + {# 1. Job Avg. Score #} +
+
+
+ +
{{ avg_match_score|floatformat:1 }}
+ {% trans "Avg. AI Score" %} +
+
+
+ + {# 2. High Potential Count #} +
+
+
+ +
{{ high_potential_count }}
+ {% trans "High Potential" %} +
+
+
+ + {# 3. Avg. Time to Interview #} +
+
+
+ +
{{ avg_t2i_days|floatformat:1 }}d
+ {% trans "Time to Interview" %} +
+
+
+ + {# 4. Avg. Exam Review Time #} +
+
+
+ +
{{ avg_t_in_exam_days|floatformat:1 }}d
+ {% trans "Avg. Exam Review" %} +
+
+
+
+ +

+ {% trans "KPIs based on completed applicant data." %} +

+ +
+
+ + +
{# FOOTER ACTIONS #} @@ -423,7 +486,7 @@
{# RIGHT COLUMN: TABBED CARDS #} -
+
{# New Card for Candidate Category Chart #}
@@ -440,44 +503,9 @@
-
-
-
{% trans "Applicant Tracking" %}
- {% include 'jobs/partials/applicant_tracking.html' %} -
-
- -
-
-
-

{% trans "Job Avg. Score" %}

-
-
{{ avg_match_score|floatformat:1 }}
-
{% trans "Average AI Match Score (0-100)" %}
-
-
-
-

{% trans "High Potential Count" %}

-
-
{{ high_potential_count }}
-
{% trans "Candidates with Score ≥ 75%" %}
-
-
-
-

{% trans "Avg. Time to Interview" %}

-
-
{{ avg_t2i_days|floatformat:1 }}d
-
{% trans "Applied to Interview (Total Funnel Speed)" %}
-
-
-
-

{% trans "Avg. Exam Review Time" %}

-
-
{{ avg_t_in_exam_days|floatformat:1 }}d
-
{% trans "Days spent between Exam and Interview" %}
-
-
-
+ {# REMOVED: Standalone Applicant Tracking Card (It is now in a tab) #} + +
{# RIGHT TABS NAVIGATION #} @@ -503,35 +536,7 @@ {# TAB 1: APPLICANTS CONTENT #} - {# TAB 2: MANAGEMENT (LinkedIn & Forms) CONTENT #} + {# NEW TAB 2: APPLICANT TRACKING CONTENT #} +
+
{% trans "Pipeline Stages" %}
+ {% include 'jobs/partials/applicant_tracking.html' %} +

{% trans "View the number of candidates currently in each stage of the hiring pipeline." %}

+
+ + {# TAB 3: MANAGEMENT (Form Template) CONTENT #}
- {# LinkedIn Integration (Content from old card) #} - - - {# Applicant Form Management (Content from old card) #}
{% trans "Form Management" %}

@@ -569,8 +577,8 @@

- {# TAB 3: INTERNAL INFO CONTENT #} -
- - {# TAB 3: INTERNAL INFO CONTENT #} -
-
{% trans "Internal Information" %}
-
-

{% trans "Internal Job ID:" %} {{ job.internal_job_id }}

-

{% trans "Created:" %} {{ job.created_at|date:"M d, Y" }}

-

{% trans "Last Updated:" %} {{ job.updated_at|date:"M d, Y" }}

- {% if job.reporting_to %} -

{% trans "Reports To:" %} {{ job.reporting_to }}

- {% endif %} -
- -
@@ -660,10 +626,8 @@
- {% include "jobs/partials/image_upload.html" %} -