From 4148c7eb169ba3c3bf7515faf14ad637ff362ffe Mon Sep 17 00:00:00 2001 From: Faheed Date: Sun, 9 Nov 2025 19:13:08 +0300 Subject: [PATCH] meetings list --- recruitment/__pycache__/forms.cpython-312.pyc | Bin 66384 -> 67017 bytes .../__pycache__/models.cpython-312.pyc | Bin 84640 -> 85226 bytes recruitment/__pycache__/urls.cpython-312.pyc | Bin 18177 -> 18460 bytes recruitment/__pycache__/views.cpython-312.pyc | Bin 143687 -> 146139 bytes recruitment/forms.py | 25 +- .../0005_scheduledinterview_meeting_type.py | 18 + ...cheduledinterview_meeting_type_and_more.py | 22 + ...g_type_interviewschedule_interview_type.py | 18 + .../0008_interviewschedule_location.py | 18 + .../0009_alter_zoommeeting_meeting_id.py | 18 + .../0010_alter_zoommeeting_meeting_id.py | 19 + ...1_alter_scheduledinterview_zoom_meeting.py | 19 + recruitment/models.py | 24 +- recruitment/tasks.py | 1 + recruitment/urls.py | 3 + recruitment/views.py | 133 +++++- templates/base.html | 10 + .../interviews/onsite_interview_list.html | 432 ++++++++++++++++++ templates/interviews/preview_schedule.html | 1 + .../schedule_interview_location_form.html | 34 ++ templates/interviews/schedule_interviews.html | 10 + 21 files changed, 771 insertions(+), 34 deletions(-) create mode 100644 recruitment/migrations/0005_scheduledinterview_meeting_type.py create mode 100644 recruitment/migrations/0006_remove_scheduledinterview_meeting_type_and_more.py create mode 100644 recruitment/migrations/0007_rename_meeting_type_interviewschedule_interview_type.py create mode 100644 recruitment/migrations/0008_interviewschedule_location.py create mode 100644 recruitment/migrations/0009_alter_zoommeeting_meeting_id.py create mode 100644 recruitment/migrations/0010_alter_zoommeeting_meeting_id.py create mode 100644 recruitment/migrations/0011_alter_scheduledinterview_zoom_meeting.py create mode 100644 templates/interviews/onsite_interview_list.html create mode 100644 templates/interviews/schedule_interview_location_form.html diff --git a/recruitment/__pycache__/forms.cpython-312.pyc b/recruitment/__pycache__/forms.cpython-312.pyc index 3a0a81a2342db8530f2c2f2b7c9895b3284a5696..54a27433149c15b9ef1cf3b41f8e02646c1493ca 100644 GIT binary patch delta 3204 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 delta 2804 zcmZuzYgAO%6`plnF)doX-CzuhdnYJ!4+Gr%!2YE z=iTR?dq;bzS{rb|-(RoczXOGVw)i`B0Yjw$r7q!npG?c3Dwy@0C5w%Qeyw(ikMUKO zrK_HU6^%adCidjNfTnYU@qA;r_@C7p>Z7yB7Hy-{qF`og%uk*MTVu60;Nhp_*>?UE z`P91?Xfzs)#k_Ld6vU#T;4Nve55t1#0JE^C@W$}hcm|`aR#FeEIk;t8v4aN|Q{Xl1 zv1Nl9pMUe%U=phN6fGq%1EzNk#gO^M`anhhK*OOwmaU(E5fmF&7O>m}agxplL0KF&!Jf_6URM?b8TqUaxLICy64Rpl2)Azav8|^Q{{y!y1g;@GD&Fi!6)=gld$G;G}f=1^_W)D)5%XUf_sQLKi_J%=M~wC=jY|w?8Rk8 zMe08(`CS50D#eWZ@bg0@@Gs0}b9L8gdiS4{m^e1*a4A3^t~`?Df8EoCsAPTEe#8Xd zq109=J@D+(ZOTb-7T;@2fZJl1F14+f-~-HUH|qXM?I&=3yIJ{~QyqKM?kB^k`V*7k zE>1a-rKLe(V___wJQ1%Ot>we$Kjo#f7>v-8ihD98M+_59U)&^1v~B6y$^$GP_D4b)E1fnT{I!GH() z!ddL)e*pO6|GJ-ta`xPnr4p#P_v%att-sa>sn}CD1}`o0@qz-)GN}R(mWJTu&rEX1 z6TauO47v6RALP!E^PccBw~2MQ^JSRL;;yI3a1*V)Q9SjU-e^e1UA;-VWQFfW1zzio z@Vn+4T$8pgt-k_+V0a=m#_>k}K2(xswTFv?n}~ zXv)8agIhN9cTn{CGGz;(2GRRu35#>W^yw5O_!B1gRYE#D(03DpqIqDZI*r8QvnEEu z?e~VsQ&eBpd2gQ&q@nuVDNxx9kLQ3_H*MA-i5I9ac3_}eGNe(?JThkxn?^95pcE%| zh3id33HGp#?}H(js1fc&a|8dINPpQI_rqgYcXSVc0al354e>!Cz7FUv7T2!0SjE*T zu0V00iOWe8Z&A@ife+Yi3B0 I1tR(X0Uf(dzW@LL diff --git a/recruitment/__pycache__/models.cpython-312.pyc b/recruitment/__pycache__/models.cpython-312.pyc index 84a3449e489ce6856b70be5389af4acb08e3754d..649b7893466e7a7d608a3ca106741a28ebf6f207 100644 GIT binary patch delta 2445 zcmZ`)4Nz3q6@K4)yKk2TmWADgT~^p#1e!&lKuok1e=vy=RFr7cSv1x7o`DQ5WWiW5 z{$xs9QXP`%HC~djg_syMyS1^e@i{fswlSHesV1bIvZ7RCo5pB0WV$9p+L+$E$`WVV z`)1C&_k7OADNEi_H)$?GotUfV<54Bk* zV-h@C&Kn{yndF{&6~*M8Q$I&3+4APQEVc!2%@r|+^!$DorW4QGH(=6o|4=PqDOqv) zRTiQ7%nO*Oy>e!eMLc65PhV{$%g)ZifJV-402(!%8#dv*cHv?^^RM0by8$q0(m(zL zq-cX5tp*0QyFOlNfS>eSJ%~aw?b=&#YB#PG$SBkN*FTXE(lW=E0-c)r#bIEp=J?M= z;QQL=U#0+0YxwG65xaE-cns*%{~{s_c!_>2VGM`#zZtL|IIP#n=mU=Gmrd9x;thR` z1wRH#^naydw+T0Bw;i9stZ#Q<1(2!_I^hRwbSxX!;M6bWpasa)A9Ujmz^8A^#rw>f zHcZ01DAN6T*anp9{rNBf1NuQPJ{2*OK3{;Xm_}Wb@sOjQ6$uqoAqYhXiVA{Kia@^n zWUfIms51TF9yml*CY8U;PK(MB1FtYa2wF(PUtJc(#2#}rB_fg2zw(J{I>DzoCZ>+2 zMhwJz+?S?iDhXCJEn=YGw88H+iGu1-(j%-Y`G{I0;>}sm$q)k>O?PJA^tR$lG;cZ(4Qn)NH+KqZWe*#<4tAHX6M zk^U38G$R$pvc$Ihq71L)B9Vc0!dVB4e8}9=x^8Vpb8Cop2T(3A;gL4b*8_Nddks(M zC@bDB;jCd=%uo?Gh{noZdC*ld;3|m=Y{Bl(?BZvZ4?2qmoJBFaGiJ*hv=t55iV~B; z0b60rSr$(*X3IP3N3DW2zkB&$dfq^KUjNjC%CYHxPQQ1@{1J<%yLiyz8L)U_=B(cJ zeWB+<@6A~9p8iA$LLg(8Sz#DSMNf_iiWrqxx2?Y7w;R~pm@I}AR%244f$7L(7}CB5 zr4rlwZpgPe7`Wmi-X9ssojne_NfG%IHAh&wd;~L?1>4icO;S^C!Ip?j47Glv$ab>R zHD&CF(q8M%;;Y*_9HhV2KU-8X6k7sIw&r?KxyerUB-1z&9OrmXFikes>?wx_E@G>5 z8^x$Q0%ERXK3Tuqx=Df_#lzZywJ2)~)*wn=@+9&$=Lft)S>p|$BsdMMqd%y`N*W3vlg2Bt$KA+lgo};5 zK(;0dWK+5^#19X4Y`e}j>u%Vp;%A-Hk`n^1O6ERnrJ~ab{L;z@OgTm8lR(!_RYj} zd`M$6G3sn$KzK0=B)o;sw)4EY>F_Mn;F9j04Kpgb88BpC+tHzJXzOSXTiG&T3Qri$ z=hin3xr?22#T?d5SLyyaXsr%$Rl@%iPRro_7jjX-MHfel88BqpptiTKeMAjUG+hf_ zQiB|H(xw^|F8Cg&R&t{%E=st!om|Jm3zu`0F vpUubqv>B*;rZ6tBSGpc5e&4;f zKhf;itTCMN^V6%?`fGvF-g^66gQeETS5&DS55Y_#v38nCW^DxwN1adhCh_iyZoc0K^c>@dFr4&K&;+ z3FNI4=U8nSC({K?ARB&MhcP7l)DviB%jpymFO#{=2Uvw(XLn+Xyzgw5UT9X64?ABa zIagD0UM5$U0eLc7+jMA^+pi4}ppu{5Py?bY{&o@Yk}u!P2QJCUx8|u4O*VAy#XvIV z&PkZ$CwF4BNR+LA-W9P-4tSUiRLZtT`+-%m>F;Ymjr`!TH?Tp*KZ^wrMFQRcwkekc z1OmJ1EfEi~SGlf65%9G#Q;Y4uA?3CX%LRO|EYjm6AYS>y2empprtb&gK6J`z6XpVX z<#I5rfIod0f;%uNzlWk2Fe|xc!~s!CwFN)1XgWIr=P*dIMxq)>P<9M}4mhvujY5}z z6uLDARTxdf24aEmg+L}YoqPlX>N!K6jU}pN$X-0#8FHRc)8TOlMvgK$4h}YTiV}|`XlAm4 z^J(W0WYPFh>}x#GKK`LN>pL0`IQD$Js;r*KlT-JdkwGplX>J%Ca2Vsy1j-Fr==`0^0SUQ5hD=1r({3WA1 zysyJWg2ac*Bn5dQ7{VnsNx@GcA#NnJA6cT7jP+q`IzQ;JvKE*J*adf$d#lT)#x#KVsCC4$IjYx~{tOAGAUT7~XC~;DK5{yc65|#q%l^r7y1R+bL z7lt5Ivych9kzRNX^AJU?(_x_#Mq!gBhwIHv5f{6%SL_iTMk~EF3ehl7eKLx?yG6mI zU6XlFORJM{Q^*lX*|aca^=Le=))cbnPwCNdNEDVZd}o*f_oPHTR~rO)N@++3%t zrehs*d(VJDh%Cb^EN2!jjG%W*re8(YaiX5;bNBeK0{2o*LsVGiH(z8edF&u+cb8`hZkZzwb<`Ht8h$%gp!x zpYxsX?3uZCo%-Mg)$nb7eXRyxw{AV3D<;+&4Ajg<_o3#bR+FVNds)Qp5%tL{^VerJ zpX$`LH42>j*t!3ti#%l>{NI^ezWlfKpUq(N4=pQ8J-NAJHouU|E;{n#Szk_SsJv4Ms$uKrg;EFip9;@BN8ijv_J6zgL)2!|}?GCD5 zJ-qs=TyGQWZM;!J0Y%4hoV&wF)O)oWea)(++$hslk+$;B61|S)1hIe6Sxjz zmr!FWXJw0BwAlG62}P6_Sgy@OW1G)o^n%R-w$@6c-0l+FU4nmDLZ_5g(Aq%jsKn(? zM(kvS$hd?ily;W8?jc)!;_1Nr-t!{nJx?cQlb4VIp7VA-16lexqnECFLqeAn7Y_20 z(A!=T`kU8i28$mya_|<}IVw6wg)?~x6_fzWwfjiIgzpIEMc)xM;UKr|Yt;?mr7aMC z0aF!2Om^Tn@CswbEAKHTwISyy*rlz~^|AdUJHITUgp$UFADM24~H&xNj>*b>n@o400i-abX%Q$|`Z^HcCPpbG1 zco$e5FsoZ7xIg_(p%YrjGpL2~oP1F3n-KdZgjWg@Dk?*&`qIiHaEJzn;2M~L zl@+{6cz_%#J3tD47q~G%=Hw^f!vS(wbA*rqo&hdK%mFAWgP{C@ZI>KPiP4lWgU4n? z!CxWrB3@9{<6r1y&zR^L6OxxClvi?y<-`aX^FJbF0&1fswNXXY-@V=_Tm7Qdza5g$ zm{L-cEj(3R#JSQ@Qr`;jCU6V56MZyC_=Siz>4x+y*BB$m^~FfQWbBdrGFOS2b>mom zALQ*Asp@AiJpj^i`0L{&YznvpEW`R&aDOLGdPpTm_j-V*feXN!2@<;n+)0>6pg+S^ z(7irBF83$J{-mPOq^YR(zDA>uX_Zq|U>Z?Pbh%4zaf&TY!F@tPgUV@8uhr!@@VD__ DF_Q%g delta 1699 zcmZuyOHW%z6t?jgnx;UTgh#Lq1h6shSB-6K^Ds7sV9YB9^Qa*ra05xoE4)(DC|Oap zN=dvZiz*_Es%{sRBQ~g;w#%wjGb4>OiWJoTfmXw!QjzQzt&3p{#vH$;GoHa`>QXtZAw(KNI5JJqRh|i47I3Be(J$jqE0g?P4> zIC2#@fzB25PQh-FU9gc0wq%4N56=U}42d<#HC7iSbwM1CQ#8dbTB6o%66TlPCJV%s zL0o;x${Ghq;{YDLNzpBC)e;ZfvdAyor2>C+mkIm>@O+E>?*e?UrA(ttQcx_$? zis``%#uX+FVLUuT(KSA%2R1I*9m}4P<=aWV9oMx{)Xt}bz^C2gmwKJx@5Z>!`>`wmv>Bc(nZ7^i50-&HlV zr$L3zLnCv=h%1KUcPRRRccekCU$KtV8goX8Gm0nIDcazjX7vZA!(NW1Kj~@zpJg?(k7*(^?~R zvfAW`n*d{N7S-6C%6d07%bJHt^DrJ?rRX--l;*}cR z9)+{ucto)kNiVC4kg5odUZ-fDk0LG6&?&w80dE0*4ER;2$pdXHsa(@ulv(PDr9O2} z9tF!vctw%L`&L%sASI5&eu~0;Rp|cHDLXL-B)S9AV>ED5tKazFO$d^5aYD>dr14H8 z_yrW(kaDo5LDDpcV=EM`@}N;mJOiEQfWHUIiXeVK#oLm`(-UBxq6I!E;_HLbHxiT+ zTm{?`6Tg8Y2 zl39C*wFeI@QMAn0l)}1VFYY;*$w5pG>>Z+Lm~SX{Te0vYjuGb=p8k-cd;G4@U+OyP zE1V8fs!qHfZo`W%u?LSsav912BO#k=t}6pl-G>h5i4ji> nPeJ*i3>a9qVr!)EAgLY1qi_uLWQYNWEN5lR{j)3Ih*!+NFqb+2 diff --git a/recruitment/__pycache__/views.cpython-312.pyc b/recruitment/__pycache__/views.cpython-312.pyc index 675f4d01871e9b5d7e197b2cf2476bd02a7bfde6..3b9e9d691b42d295eb81f014ceaa6af84c3d2d26 100644 GIT binary patch delta 30485 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�y`Ci@Pj5Own}l6f;i{a%~Yaj z6jU@V@4qu*%yIM%w3H(NzYsW`(Y_#{O$FZisw%hFJFC8?W^p^^Ka|^$HUjQ}EKyxM zyMP)TP*AR%QI`(P_Dd|N7->BVZU%+J7@+)yG#(Qnf)#SY0{RYel?X&xW{~w+l46s= z{V<(pX}N>A>vmQ9n94Y6V^LGdg(qUgaW!l7`SGBzToSuloiSQZ&7%_JzQt5tHQVW} zs#DxbzB+!)!r4VKJqqc*p4Cb*#jBT15;SY*4)>x;4@Q}r<`r)(F-B=e*?LSUom!0d zReRhtr8tqOl*r~1xVcbjsZa;K-cg-Ac6wYH6;QeY>}c9OwxcKsu}+Vzs;qTYqdTvh zZFUn8x~;0NzSgJgRb$2%Bs0TU$5@WPsr|>dOV2=SzvHnwe|(0WM}elU8GlP9Gq=Dr z44ApysIH#mtMgUXI0Fh!o%KMAJpp35PGxzbdVD$b9{ zd?Oaoye##!3re6N-8ORcxDiuK>dJkD=`1TLvvdX3364gD38ff$JAy_7+S_ zw@oLMx;33YEk7cT2Op2SA5_;B-9)x}+ZAP3goLl0hgM9IMKnyNp`LlPke_InG{zRf z3HpfSjHvn33v9FzXqluAo8BxM)MM9WscBcPN*qRMN;-k5WT989k6bx?_zZMc5AYno zUI11YtL$VZnzmAE(8R>gtE{Y_QxOI}b;69!qCuN@oTlg7X6&-snUU%0*s30duu)QcZEC7( z=aDt2byl(wbNcG$xobx%yP7sv#fkx}8W|=Oc-n?^NeydherDE!`+Ag@Y#=S%*cVqc z^;6euKg*#Oow2OhY73{H#J*-NjT{UEvhh4RVa|SU#O6?HXu2UT(w}q}ljqlYeT1$v zNPz;sY;#H$GC@n_Y6r3iCSbVmr!Dq0NBtgM=+_^D=d(`)lqiUjB;sU|afwR(l8s4wfc z8y(CdaF(v>Q z$Wp(oeTvk3Q(d08SADLo?IhOjOTkEBtw+{YdfajZ1&1k+-;V;D9ceM)+B_+{-%Z zWvi8aP&PPUtwpIPD7CyaU5}jWt*g~-HFcFPuO2zG&b3(Tk--R{Cr#K52=V&qUsPKz z&+XDjp}DlSo>)awgK`;VPSj(oz16ier_@%tm18JA4Imx>td)c8Ckm0<0TZG}@*?_P z1mmdQY`0fB#!STZYLA6^B1N6BFfaLLps@kq4uH*SR-1@^G5h?=s{g5lCdbmeY1vf-!|4TZxj`RZqpylLdi=r zZI4pnlBTXpyU~UTrlF>*{N1c}xoM(qyQYUd39W5aKe?tT8zh%T=rKV-cy$|Zl_?w5 zf@?cmW>_qyp64u{u5y9eZh*lA^k`Vh`J@d>3DRZ&07mYjh4pCxt(!Ay@02oet3O4@5ISr#&Tf$%LoSMNXCk-Mg-Mlgy>gK3wZfwtL=+~ zWsN#=#TMf9mn$BhwG-4C`p2Rzq%=J?xQeXw!4KeZ-%J_g)`W3(ESg~Lz<8vxJaeOL z$R$vJTbX5hg;M-#-m3A`^}JR0iY{v6>MldM;dQ7OY0_FY1ZWfU7pRE~G7l5!*~F@i ztFvtfsPWb6U90<(1*WxncGLH(4+uM3gba1>jg#%{G8|VkZd#hl3c8&t5ZeuV#A8WO zciq%}$RO%bE;$xZDLMP2DHtE}1Y z>)piSBNQX73pYF>cBpS}D9pfwChh4;YMe?)F{#mabT0}?Oi%FE&-7HYKg9kGD%}O} zgnGptef?p)W$)DkHrgwFb)M=fIqEP(bw^+~mXy^g6))g+ptZpS^kh%vqTmt)2GA=l z5c^)Ne3yd@n^7JENViq1DR*Wk^XyQ8tO{gZu3m8GAmLOS@67Ga$`Nu?q`Y|~@a&N) z)!2~i4)wJ=3(CPMJz8>Qnwjg?2T~zpJ;sEz9^Y#ZM=6Wv@u=2ziBK9h~QSMm)^m4W#C%@i%Z+rV`%E*jV z@4EMfpjSTVzT=|ztEdF@m46c;J$)ZxObvQGPs&bbodW0PCZq>waz4=Apoy(>X`+cR z*kI*c)UnK;L+)SzV@fdS4A}P9(HpbvXM}hHIE%>S-j&n(mzJfNGUOjk#~*IZvso#3)UA)aP7>U6 z1+A+-edK3R#0vN=mBvCnun$3l-b>r-_WAR$v91idbw{Z`mf9!uOM&Vs0I;8r#cHsw zo`>$AN4gUrq?dYBb#1k;y0S)+5s(j40K=@uO&Kv|%IFE@&aoq=@s2R*4IkjpC?G5p z8{w>{R8^`E@5pa^HEN_f=MbJXZYO5?-~m=56`QMmzGGib1C^=5gch)L~fxwjbEXrDvkIo{Z8lxLy8e<#d8si%i8WS6nwkK?hmAOlj zeQ|+;md505L^S@EID82*WU(|lv=?hds`}8*?!}3wWLvQCT^3i8Dczy|y0b7NxiPZQ z>T;NmKxSK(q^RfZYMYe0B(2fWn97K@X-rYq?oR8}nAX_Fm4YPtbuxJLn3g#mPXlq%xSABm-%Uw&9jr(yOeqEmhX(i9}<1W4e0q zf;4sM<1sPmt~MLvmSi+$sB0fDosv#GOF?fTz7fyRsw-n-ym6-EOAYbJ;yMSxRkT4^ zWnGfK&{CSI#y0JU8U&qs)1p4p)KRQgKW>^*29;49tmFWx0PB&KhEN-Tbbt(iOm*fH z=U)+xAe5IE3~q%;!MwK}wX%@M331d9h5vHXsA#jQr=BSG$Me3F9vwW3`afEdsG)uc zU0Tubu)_Q%9mJua{0c;;0(=5sI4>{=$`%wMf#+M4uMlTbF^>{UGflRBhq~*@^nUC~ z2DnK@|1y>8=_mW=gHw8>x2Ddgiz;#rf=6yxet9#oaTfu9-}6*~qmanDnU=U-x~WB; z&53w*(^EZ@Gjfh(lpM?`X({c0Fk`@~#HM$i@(5dgm)7he^}?rJ(HZesv8xhJWUG%n z-Ok#sn|k2s+zYZ25)w~FIg(>fSR662r%Eiz>86EGN+Fg_#7m88}wZJxleiO3PfzKAI1I2>P9ym&1h(gI!=60-k);`7bggxFh{*V0Z^F_Tp*e<&bZyy3 zwC{Q0o)Mxzo1Z}O@m>+HUeq^9y=PC6aH#wDRAr?siCP*p#p2@Mg<_#)QN%RMLQ&dI z9s2zGsANJ;iL|O8KHt$lg}UXfkpE+#g@#wa8c-9oE?^7t0>;jNJ>VO%a4e!W?9E8U ztb_@&+Qk#(TZEFjdGC3&LG=FKMRG@)PE>&?_m>Uy+f%1!ooUngK|>dLmR%4WRRy6_ z?c_XTcY2MDrwEgTor#bw|L9k_j7x!9=B@9s>Q8I z$+z`d>pzs*@laC7){G8Y797kdT^o5S+TzG*O&i{tmZyzdH?B1;LmRnnWNTWkHg?_E z*0jtG=|~Lx|7cuRclhJ~B`clZy+mF>K!dBUy=^bQE}JS&fRv}w_ecNrTfnGt>aE4SR6h7X^C=VpNO&${+Vav zKj6PXSKaq=l4HON(XS@Fm~c3$yd}E)-=~IH)jMCFoSQnfr{#^FG2`tKZ=65GGG0Wy zdA^{?Tf#QpuI_p>Lv8!Y(q6}*Pnb<U>)HeIt2KRl-_f?g4r`+IXhS4C@F1#&$Uk6(+q^q|5eS_=&w2s48Agixt>PbgKl>%9mUegOX#dHwEoc}=tM%d&7w_N zpB{S&*8Z?mis?KjK72?HQXf0esRMeWW58;+(nF3mI@MDY1DpQ9X21H|fi`yby))Gw z2Qux-2ufbm)bEXdirhXZ!Te4oqP9kuh#IJleyfX#iX=WhH4y+mW@~Vt9KvCS?59xJ zK6z@W5}&p@apO)ILp?XEhu#`O4CY%LWp9rXZ9<}#hutXDP@-OQI91*BPUajoBk+cT z3o*8LtQbW=!0^C$|AEaWBL%xAS1@LLL(PTZo2&LXlxG`9eeY8Tw=54RQPYPl4I+yX zTusgCk@M-InQos*khY!D)CKSM@dMxBVt5AnQIqpivJWZg0Do(mzpuIou^Ep&{=T2;NF>NSWgH6@ZokoO>70_E14X zWPz`)fORXlf5$yx)gZ6VbR-Q6KO8l-PD64cJdODWh#P28ME&UfY}=)T*_Y~X?=PT* z{(>X(B4}KGpl9{Nw653zpv=?`ev~wTHUPj!j~OB_gw*!{o2;D@^8f}t|h1t-XUfWz5sG^7j*7zFk8zsLD8 zF!e~EQtxhv9d%jP$?jRS^)QF-r?B8=5c*QZS)pQp11k;lnLUHOpwJ%JsWUh~2sK%& zu=+JNPFX#1K!DU0mNJ4YhG}S;x!DdFMTa&(qNreC_9j)k=4hU+iVA$+bl=hM>5M?0 zv6b&DRp0w?pgcNf=3k`d9qZ9QM1!8jC$O*rW_t*gR7O*CVWTlqEjyMOrOcw71iSj+ zvB4ztFOT()=)yyBDkV!>fx$2L^_4Ht)IR{06VMA3xAt)#k*3c0G+`8mlpb$bB-$;! z2_<<@F^|?Eitgmb(MpPv1~6lwj`D)sM)k>0OXODS3?#A)u0*H<0NbQ6b95Ur)&qP6 za0ft`j5MT$M!qr;QO3!E5I96*%NQMH)xeU`4@VE>?*{l9U=sjO1j(2PlsTvekZo^z z?6VoT5S#o(s#WeLF-sYDgC{?t)=7YM>P7!(A7^5Z>ib8LKb))NS^}-#^NpMzi}D?^ z%-4?$?lI%aQHaUn0|!HW4gN4g&?|GLoGybJY^nJpu1GderSSbVv@;L200!8b++W3j zCv{)H5x4?!8OH8*b;Nheik4Afa!gnijv<-3#MrJumYr@&sb789g|_U|zaM5&kxI%n zcGl!JVFIP$y0B*^9R>3mL+J=SY5`b7l2D7gz=BV9%T^Oggh|LZM{XW4E+I6evcxHI z23u&$^ZV>k4QLtHJL#%5-D2j;%x+wU;_mc#I)&uBQ=GI2h4)ioFAPUuoC}s6r(v%$m7P{piQia9*%J2ajriQM_RoXjsaMlrAx_ zhcJ*=FxnV}<>dkCS1c!#uA{Qvp;UgE<+IqFjbk33dN{V{vSI3~lYPiaIcC!4>5-GK zN0uI^B3rErPk`K;k1C(G7c8vy%_#_6he!W)>g)f`kGm5@1#)8AP0sr-=z@yA;tO0EPt{j|@NCzJltb9j)|*e6#pqyo2bQ0D zG+$Dysh_RzaNdD-wgbS726Y#;*yqJi(UWT{tJCO4fYfVlk^lVUl zzqOw_5^c-?U@o#HLqqZ&tXbKOc0=u*TgS828NcM%Hd7-XtdA9oM8lKUi4@yR16y81 za3^=6Cq`4*h~Opw=(DmCfEmFCrH-N_l~qVIX*AGYjkI%X_07nKo+>v`A+ol{WX6rM znz2Y(t+{wex0RdF@EU-d0j7~+OjT|{a4o<(2Gn?I{#mN%r#$AO1092b@)GL*sG9$^ zW=>U9V8&W0Z>^X#;%vzU_<`cgkJ}NF$_KPHM0qH0&?=)uW*eS`S#AI)VXv;Yu1^*v z%}+&%Z(`4938MnJlrT@`(;X*GuG~9>e>$;vTGwJv*J9Vy;!y*N$CE)inj%WZg;dOJ zRH-5~gk~=Td-{5o4KJVa$SXK^QIeRQO zBFb7K)k6CqRkWl)-sBV*e%2aoZ<@&UuLD}0P10w(QI9sB17O~@Mx5V$nYL0fbpeV&oSdCQZ=}6pQ{tp&fe4oJy~AR=uxY zaXUS7HZpnLVOn7D@L{yRRU6Sk__Eg#+fFB3TsyC}ZeeW!oiWpn$0Nv}r5)-ZI{ITN zOwJS^ewdIz30BZ&kl)3mGHi9vr8g)k4M_)xih1%ILPJSPQc;X4FF2q1e|KcV`sP5r zuK*?i7>W|cWP|3vpf@}mpfbvKpvnt?87ruLTKcj7b}pr1rN`*y!J%hCB6YqwZY4}E zUU@DXQ%lP&U)_AV-?0;w9@Q=@5uM_8A^bSNL)w}Wks~eBlSlyA97UFCxQ#4RLGuSC zqN7bTG~3FAElO_E88c=W`6e9$n|Qe(U8PckGokrJxe@(^&l1|wKBBlg)I@m#`BF{6 zmEUQ_Q^;=ycv?HuN0j<8$ti^>D`;(AS5Kd$JWEMiBf|8FcHGZ3ZT}Z~VpfyT%5AFr z^77AT9G3b;AdfW*j(%xE_%g=O{EgZ>=ZQI)Fc97ZDr@q_;g4$*`idg^>y+Cox_NP5 z(IJ9FwPk>)v!+Z1y{o24f$f;Z%lW>`b!3wznTfCJ66>(HH5o0AzeUaoFN&9~9l zehQs^mqokuLebWCkTUORzWPG3-s%Ts#_Hd=)DBwiGyZ&KKNXD)?q<9X|;OK6sp&YS6)_?J}XjQ0H~k-@j4tAu)@TUv9$ zXt7ju0RJ1}ruZsn%_=~Z0x8F%AQE@98mt8+$}#PgF=7ONy+pEPxs`zo79O~5`Uu2O zJT~yGeJsns9Y{hgq|nz(M(%@~y-J?^9HcKK_hKT)Fg`rP`{o z;!#>c_8liSCVx&v=yM}G*CH#ceL7AQ4`a#g1w!2cxZl90^Kq&m?GJMpx(E(S{rC!* z02wjb*zsZ%jo#bFi%&!X>o~}y>sj||*G&+Gb}sv-wta$_EWhW1vXku?i5^+SnIp^_ zX4SW7{5RyXVjB!%-h>7vEpWodB(v%)MD-LpRKyaCI7K_)@!o}WLrghA9TdfAt0#&l z2=NOii9S}lL|j`uMf4V5X^&13gXIPQBgkkmmKl&U^NR637na9R#6b0X>MU%Nunm2? zfDf){hMPT`E*BAg*kb>YO7?>k-z3_XSv1d7@dn}7|6*~u5I<<^FA?YYp8#8US^qh> z7$^5sPa!phfSy({VZwOlr6Y!pnlNFkbI8QeeEiAyZvL}@rZiu6sb~`se;iGLAGD*XEv^vl#JAdA z6{4UJSFX2O^=R5M^3X@oUb!0yXPefm>?^&eeOMvdOIGs)#He-)HfU0V_mBqFp_`xd zaSHighGH=NP+sL1Ld*EDjm1C{Fzd+*hF|ztI$u6Y+2Njq+e9y@mYr2KQ>hy=K;ko&bcwp?96Vb5&NjR$uU6L1P&@UrL zdDqgdi1LVLj_I@=`&v>#leFgcuft;j8g@P?}r zLG4IqJ;K!W3F z1@IU~VWIZj3^7J?%@Q93&Xk%jpDmU}I6~^KfLiGM@wr4gzAu(5B)R{pwVfw&xQTrWx?rPI+v(E8%QR~ULipmyNHFxHSWT8vMWMDf_N3ay_{boc+0>MA_|(2B{r zv4*oY^WvUG${HJ*?r0-|%^2Dv6Ug05=jZGhFNlit5|kXGBsG@Q8TGU;ed6w*GHr%9X4~s1QBbjYnwQ zu5!MFP4+h%>M;mnnt%ch>_*boC!K3)Un~@pq%CA|hbga=G%B)u&F3a(x2d#87li;t z0Ia6J_X?GCWCE0eC+`wZ=<7%Ah+iaVFE0`=hd$(M-m+L65%R`7i|PpE)dsa=fDX5F zM!WrLQ6!xjMu!*XnJAQnE&>!Zzt}_+ z;Ty^370bv+x{$|P9%aiZmrt=B5Yu~5N;Wb9I$&vnUke0Y=b510a;@lOqUu~aXqZ>F zHiJPL8y_Yu*5qLrdRYd9pz!CkKqMkbD>>EVR=4LnFOGm637zOzteC zvdMi8As&8v5y}M^3=n2=11ruKko6(~k}7@6GrLy$d*?E}(Nv0Q2HBvxP)`q#ZB(UC zmFb}6JfeLcX#baX#R7T^=+H`WEU3$Gt`gr!M}*#B(4N0h46>gA64_eBO`^=6K~+z8 z)Eo~G%YIuS;{5o8P3{lM%iRv5EO%1vWL(MQDQd>RK^eDtws0S@l`qMypT){`La?g8Ysu z5#Ldnbd+g|GYx|99+`0Jn@$F*m8yErEVrWFuuf!m8V-bb?30)Sv@*qVojCy608#PU z+v~*7hJF6{Rw1nN+J>~x+PAlf4*6UGdeGn)K@WEn3<+^`K!MUv>#<&BNqfy08ut2p z>Z8;l*QCsozn~Lg@@I~PsmSjPA9b5y_P5D?ORA-S^W(-5BHiOjvyM`vX4J_qU7pL^sgfkU4}OA}GLz?gdgaTztJr=^x~qye@Y}JGns=^O$HTkz->1 z=OSJkc!!9e#gz7@_WoG=nOO#XVT6Oo;9{I-Ce|_*s^OYwkKIArVG{_i(b}Oq#PcCZ zYTND<`=uaJuc4C(zq{@diSjDWY~WW9z=p}(gw*}8DOQdIaxJGohO?=uJu-2lK_sqEqL>2!#%XDwNo`Il&yZ4t%dYHjHj z+Sk6Ex@>HIWQ$0Pq>X{S_lq1yXYelOQg;ol@Z4Pr2)S?WCjvKW@ehbDetfGT&knc` z7I`mVz-azPA$kp|(#s>EQ{MG}aEf$jBK1eUQT`--}6lBPG>s7*&Sk0ZtIShyoK|V_%N@BvctgE)> z5n@S(*7S&&9MzQymMe?3_-!JS*i^ht3=qe(8QX*>&qdWK3*^qBpm{S*nWt^rF1m@2 zwCwGoy{OR!ZWrU)^CnLrmH$6#eXRX`yXYyhwZt8wQ+97^TTcnNwuUA5lD(b0LtJ!G zm<&b&AJ!K`t(k5%zdZ9gQH0sRw`m507jEsN9U|+pS?DanTknzciQI{&Wk|@};al1| zDkOQ?2ch`@EJ@}c*dpB%1)&81`|(0rdKw@2UWo*NW(=E~wdX$+)0K}{LYYCL*{RNpR*P(cryjV(q zC=uQ*UXE%k*L;Mo2VmKZ2@?*}$qoQZB;b*;Fjx*D5uC#noBOgTioJoF9zv}5eu|+{ z+Wg|n;&~bxSeJaA0;bXeIvPBZ17B<0FS_6*@n^xXuohD>DIFedyu}h){V2WAS$sf=q-G351vaWSX%u*Alx!~J zq(>N~g@BvZ(4FQ4rM}vyb$)}Ulyi(T(|BU#ZduJe4~p?Nf7tMbvIKXqd4#Z8 zGY$lgfsBs;J_h&%U@5iSkS?F-bGyPG@f!g2p@$9G{2_=eh6{gHxGk=od0#~P4GTf8 z4IA7)>ajHNOvrZd>`H38wC!K97R*y-F`I`lqRPUkVk^$1g`F_5?cSj^9T7znSpate z4OV8uzytr_u6i~6I@V8PvSrjaQ^l|Y;f}4Mz3omS>BHvoRuOL-eh$$n8raF`7g7uK z088i_96F}NgARCSm>2q)EE;Xo2XrF|)6LY8d_}JObjo;szp|jV&R0M$U)3$7yZ-6_ z0~47Uys@*9kkXTlwbT@OV1+ld7?(@KPwL{qHs;+=6eP67tEnYl?rCk_euqH(mR`!v##D(#ttQoP&T|g zW_UVgb99h!4xayNV?Gwy_Is%LzKPo0kHuxdy@jJ6i>=n2NtB^X27r3AP)5oJLo&53 zpNaIY{V0#d1v$~F*nZT1)9l!-&DtlEFR6743PgH2NdY=VB=2P(rkMW37g z38(757MFCrAN4})QXW9`L4bzoED8 zhrH}~jxjYqmvc9&R$8c)hSI-ANK3u&4nGE zU2sP9GVSA5g9zr{|8jH|B{BG`CuaeCYv^GspYj^v);3A|_Ze|8?C7joXp@DtP2l`& z3KJPRKMS;R_W9XbVeKF{a&tA2Y)#eP5!QHlhSm=RvMN9e!lxfLfo$$skUW1wnlvYv z&d_9^(!Dn}s;C$}JRwC8*lm5AXu5!Q(7kt2rdDCKZZw=lIvBiF4CFBd*~lX=#*Fqc zSZi@xgS;Aq^<+9PqpKeD{i};k&1U=Dv_^PKI~Hl3DXl%r?I6U4&ui_jr}!vOoKpRlLpC`EY#c>t3^NHZnj*-uMi+l^N}Jp6D%5A6k;^$~+CI{tc6 zX#JzDIpJqu2hb3ofpL>(G;g#ua0bRW@uZW9LT?fXo`Er8%#Qz2a^}+`?uXZBOf2o8 z7E7l=UXTh(FYsmI`-Da{h~BNOiMO`ZDq^hW1F?ZZn;2(xm_FuZ3QIu2YuZ(D)*&5A z5oT&xomLX_X!I3|wiG9Pp>!;HpQc6MTe^!G@1+RkKamhEF| z|90)|WGh{Ml5{jVtoO*1YB}WD|AG5UPi+U?2%R3b3`G=(upzF!;hM=E@o&L&!zY7C zM=E!N9-f~9chU@9H9K16REovNw4TeWf?p7{Fw9yI%f92FanJxh&KA zZDjUilq4NvUR-f^t?0N(>yu}_!v6&FnPJZ$v>Sl0$UKYCI+WZ^vnYK<^BfWkM}R2; z9&#&@Z^0Zx^dkVC&pt+I2C8x2>=*F7&E)q-Zk$2?P%S6lnpJZgU92jLU=N?R_j%r67Bi;X(1(HKdx(An@HYTm+mdhXYG;l% zX@~NyJ?t-0@7`2;!6?0*v{Gqae7tCU=EgpZa+-?$y?IDm>vXH;*eTM*hibtq!$nWE z+xg?vXWomCcZL49lPMN;`~_Klob2)+|K}zV^s-m@e{NzdU*zp$NTH#7sAq4t;FozO zY|eV=Meei)ZtUR^6u|#P%SN@z8?9@vdN(TXXhNrl`#yHT)(c+9Je)A5|EkE= z==fV=R>#~Fca+{6Njj8N(h^tyG_@CinG(3$`yVKU)lbQRqi{Vtyao2b<(11bRJtb^)SD_0gVIZm zq<24<-u*~=--GFWTP96wN$-0oy`m+uP2ic&AuYo$X}NSx%h2jWadTTD=gR+L<1^xO z2~Xe~1r3Hwm$tK=HP5<0XhYgtvzq_W&U#YNfymK9>w^7@wukgVc1vcAj#fwyemS=Erc-+qmXd*3Pag!~cg+M%TKlYw6)m zI!8w3Apk>BDmnC6H{EBxs+!(q9){#NiqU(1)eZP>I)k4EAcfUyAM2{!K-|XQl9|e20!15SH9BrceJ+k z^PO_s`{rBL3T`hexZtZq(x8$TKcf*!1;_#5dr%z^!o4HDhQs$!ltG9N0Ki$jG64Xm z%L-0qUaYr8p9g ztC3-ueS4|(^1=*Z{mJqN;0Mm=t}QOL9?m#1lm5@d5KNVR-#}-S6ljOOI9w#rcMhl-fm1!081e>z|2W*D$t^fc4 delta 28456 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

DFm7umlmm(Dc@W;(0cqNk96qDBj zU^7BuFG1c0unFJ}0EF}$?@EM=D!xFN!c#fVcoJ@3vOE4rFBxFZtNa)RF#MSRnZ-yv zom88?zICR|i^tcK$cYTseFN+l73T^2kG9_fRr(hL>~GnRdfN97wCCHi{X!&vJ3DTI z5S8CvYQ2h4nc2LJ#7 diff --git a/recruitment/forms.py b/recruitment/forms.py index 0e969c6..3d33c2a 100644 --- a/recruitment/forms.py +++ b/recruitment/forms.py @@ -584,11 +584,12 @@ class InterviewScheduleForm(forms.ModelForm): class Meta: model = InterviewSchedule fields = [ - 'candidates', 'start_date', 'end_date', 'working_days', + 'candidates', 'interview_type', 'start_date', 'end_date', 'working_days', 'start_time', 'end_time', 'interview_duration', 'buffer_time', 'break_start_time', 'break_end_time' ] widgets = { + 'interview_type': forms.Select(attrs={'class': 'form-control'}), 'start_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), 'end_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), 'start_time': forms.TimeInput(attrs={'type': 'time', 'class': 'form-control'}), @@ -1326,7 +1327,8 @@ class CandidateEmailForm(forms.Form): """Generate initial message with candidate and meeting information""" candidate=self.candidates.first() message_parts=[] - if candidate.stage == 'Applied': + + if candidate and candidate.stage == 'Applied': message_parts = [ f"Than you, for your interest in the {self.job.title} role.", f"We regret to inform you that you were not selected to move forward to the exam round at this time.", @@ -1335,7 +1337,7 @@ class CandidateEmailForm(forms.Form): f"Wishing you the best in your job search,", f"The KAAUH Hiring team" ] - elif candidate.stage == 'Exam': + elif candidate and candidate.stage == 'Exam': message_parts = [ f"Than you,for your interest in the {self.job.title} role.", f"We're pleased to inform you that your initial screening was successful!", @@ -1346,7 +1348,7 @@ class CandidateEmailForm(forms.Form): f"Best regards, The KAAUH Hiring team" ] - elif candidate.stage == 'Interview': + elif candidate and candidate.stage == 'Interview': message_parts = [ f"Than you, for your interest in the {self.job.title} role.", f"We're pleased to inform you that your initial screening was successful!", @@ -1357,7 +1359,7 @@ class CandidateEmailForm(forms.Form): f"Best regards, The KAAUH Hiring team" ] - elif candidate.stage == 'Offer': + elif candidate and candidate.stage == 'Offer': message_parts = [ f"Congratulations, ! We are delighted to inform you that we are extending a formal offer of employment for the {self.job.title} role.", f"This is an exciting moment, and we look forward to having you join the KAAUH team.", @@ -1366,7 +1368,7 @@ class CandidateEmailForm(forms.Form): f"Welcome to the team!", f"Best regards, The KAAUH Hiring team" ] - elif candidate.stage == 'Hired': + elif candidate and candidate.stage == 'Hired': message_parts = [ f"Welcome aboard,!", f"We are thrilled to officially confirm your employment as our new {self.job.title}.", @@ -1589,6 +1591,17 @@ KAAUH HIRING TEAM self.initial['message_for_agency'] = agency_message.strip() self.initial['message_for_participants'] = participants_message.strip() + + + +class InterviewScheduleLocationForm(forms.ModelForm): + class Meta: + model=InterviewSchedule + fields=['location'] + widgets={ + 'location': forms.TextInput(attrs={'placeholder': 'Enter Interview Location'}), + } + diff --git a/recruitment/migrations/0005_scheduledinterview_meeting_type.py b/recruitment/migrations/0005_scheduledinterview_meeting_type.py new file mode 100644 index 0000000..fe94194 --- /dev/null +++ b/recruitment/migrations/0005_scheduledinterview_meeting_type.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.7 on 2025-11-09 11:06 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('recruitment', '0004_remove_jobposting_participants_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='scheduledinterview', + name='meeting_type', + field=models.CharField(choices=[('Remote', 'Remote Interview'), ('Onsite', 'In-Person Interview')], default='Remote', max_length=10, verbose_name='Interview Meeting Type'), + ), + ] diff --git a/recruitment/migrations/0006_remove_scheduledinterview_meeting_type_and_more.py b/recruitment/migrations/0006_remove_scheduledinterview_meeting_type_and_more.py new file mode 100644 index 0000000..9270e59 --- /dev/null +++ b/recruitment/migrations/0006_remove_scheduledinterview_meeting_type_and_more.py @@ -0,0 +1,22 @@ +# Generated by Django 5.2.7 on 2025-11-09 11:12 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('recruitment', '0005_scheduledinterview_meeting_type'), + ] + + operations = [ + migrations.RemoveField( + model_name='scheduledinterview', + name='meeting_type', + ), + migrations.AddField( + model_name='interviewschedule', + name='meeting_type', + field=models.CharField(choices=[('Remote', 'Remote Interview'), ('Onsite', 'In-Person Interview')], default='Remote', max_length=10, verbose_name='Interview Meeting Type'), + ), + ] diff --git a/recruitment/migrations/0007_rename_meeting_type_interviewschedule_interview_type.py b/recruitment/migrations/0007_rename_meeting_type_interviewschedule_interview_type.py new file mode 100644 index 0000000..85e6f83 --- /dev/null +++ b/recruitment/migrations/0007_rename_meeting_type_interviewschedule_interview_type.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.7 on 2025-11-09 11:30 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('recruitment', '0006_remove_scheduledinterview_meeting_type_and_more'), + ] + + operations = [ + migrations.RenameField( + model_name='interviewschedule', + old_name='meeting_type', + new_name='interview_type', + ), + ] diff --git a/recruitment/migrations/0008_interviewschedule_location.py b/recruitment/migrations/0008_interviewschedule_location.py new file mode 100644 index 0000000..2800b75 --- /dev/null +++ b/recruitment/migrations/0008_interviewschedule_location.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.7 on 2025-11-09 12:37 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('recruitment', '0007_rename_meeting_type_interviewschedule_interview_type'), + ] + + operations = [ + migrations.AddField( + model_name='interviewschedule', + name='location', + field=models.CharField(blank=True, default='Remote', null=True), + ), + ] diff --git a/recruitment/migrations/0009_alter_zoommeeting_meeting_id.py b/recruitment/migrations/0009_alter_zoommeeting_meeting_id.py new file mode 100644 index 0000000..602917a --- /dev/null +++ b/recruitment/migrations/0009_alter_zoommeeting_meeting_id.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.7 on 2025-11-09 13:43 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('recruitment', '0008_interviewschedule_location'), + ] + + operations = [ + migrations.AlterField( + model_name='zoommeeting', + name='meeting_id', + field=models.CharField(blank=True, db_index=True, max_length=20, null=True, unique=True, verbose_name='Meeting ID'), + ), + ] diff --git a/recruitment/migrations/0010_alter_zoommeeting_meeting_id.py b/recruitment/migrations/0010_alter_zoommeeting_meeting_id.py new file mode 100644 index 0000000..d64f578 --- /dev/null +++ b/recruitment/migrations/0010_alter_zoommeeting_meeting_id.py @@ -0,0 +1,19 @@ +# Generated by Django 5.2.7 on 2025-11-09 13:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('recruitment', '0009_alter_zoommeeting_meeting_id'), + ] + + operations = [ + migrations.AlterField( + model_name='zoommeeting', + name='meeting_id', + field=models.CharField(db_index=True, default=1, max_length=20, unique=True, verbose_name='Meeting ID'), + preserve_default=False, + ), + ] diff --git a/recruitment/migrations/0011_alter_scheduledinterview_zoom_meeting.py b/recruitment/migrations/0011_alter_scheduledinterview_zoom_meeting.py new file mode 100644 index 0000000..dba9c62 --- /dev/null +++ b/recruitment/migrations/0011_alter_scheduledinterview_zoom_meeting.py @@ -0,0 +1,19 @@ +# Generated by Django 5.2.7 on 2025-11-09 13:50 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('recruitment', '0010_alter_zoommeeting_meeting_id'), + ] + + operations = [ + migrations.AlterField( + model_name='scheduledinterview', + name='zoom_meeting', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='interview', to='recruitment.zoommeeting'), + ), + ] diff --git a/recruitment/models.py b/recruitment/models.py index b712d0c..a4c54d2 100644 --- a/recruitment/models.py +++ b/recruitment/models.py @@ -742,6 +742,7 @@ class ZoomMeeting(Base): 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") # Added index + ) # Unique identifier for the meeting start_time = models.DateTimeField(db_index=True, verbose_name=_("Start Time")) # Added index duration = models.PositiveIntegerField( @@ -1599,6 +1600,20 @@ class BreakTime(models.Model): class InterviewSchedule(Base): """Stores the scheduling criteria for interviews""" + """Stores individual scheduled interviews""" + + class InterviewType(models.TextChoices): + REMOTE = 'Remote', 'Remote Interview' + ONSITE = 'Onsite', 'In-Person Interview' + + interview_type = models.CharField( + max_length=10, + choices=InterviewType.choices, + default=InterviewType.REMOTE, + verbose_name="Interview Meeting Type" + ) + + location=models.CharField(null=True,blank=True,default='Remote') job = models.ForeignKey( JobPosting, on_delete=models.CASCADE, related_name="interview_schedules", db_index=True @@ -1636,14 +1651,16 @@ class InterviewSchedule(Base): class ScheduledInterview(Base): - """Stores individual scheduled interviews""" - + + #for one candidate candidate = models.ForeignKey( Candidate, on_delete=models.CASCADE, related_name="scheduled_interviews", db_index=True ) + + participants = models.ManyToManyField('Participants', blank=True) system_users=models.ManyToManyField(User,blank=True) @@ -1653,7 +1670,8 @@ class ScheduledInterview(Base): "JobPosting", on_delete=models.CASCADE, related_name="scheduled_interviews", db_index=True ) zoom_meeting = models.OneToOneField( - ZoomMeeting, on_delete=models.CASCADE, related_name="interview", db_index=True + ZoomMeeting, on_delete=models.CASCADE, related_name="interview", db_index=True, + null=True, blank=True ) schedule = models.ForeignKey( InterviewSchedule, on_delete=models.CASCADE, related_name="interviews",null=True,blank=True, db_index=True diff --git a/recruitment/tasks.py b/recruitment/tasks.py index 415aebc..4515e1b 100644 --- a/recruitment/tasks.py +++ b/recruitment/tasks.py @@ -461,6 +461,7 @@ def create_interview_and_meeting( meeting_topic = f"Interview for {job.title} - {candidate.name}" # 1. External API Call (Slow) + result = create_zoom_meeting(meeting_topic, interview_datetime, duration) if result["status"] == "success": diff --git a/recruitment/urls.py b/recruitment/urls.py index e8ed14e..ad838ea 100644 --- a/recruitment/urls.py +++ b/recruitment/urls.py @@ -234,5 +234,8 @@ urlpatterns = [ path('jobs//candidates/compose_email/', views.compose_candidate_email, name='compose_candidate_email'), path('interview/partcipants//',views.create_interview_participants,name='create_interview_participants'), path('interview/email//',views.send_interview_email,name='send_interview_email'), + path('interview/schedule/location//',views.schedule_interview_location_form,name='schedule_interview_location_form'), + path('interview/list',views.InterviewListView,name='interview_list') + ] diff --git a/recruitment/views.py b/recruitment/views.py index 10d7e38..6cb373f 100644 --- a/recruitment/views.py +++ b/recruitment/views.py @@ -43,7 +43,8 @@ from .forms import ( LinkedPostContentForm, CandidateEmailForm, SourceForm, - InterviewEmailForm + InterviewEmailForm, + InterviewScheduleLocationForm ) from easyaudit.models import CRUDEvent, LoginEvent, RequestEvent from rest_framework import viewsets @@ -192,6 +193,43 @@ class ZoomMeetingListView(LoginRequiredMixin, ListView): context["status_filter"] = self.request.GET.get("status", "") context["candidate_name_filter"] = self.request.GET.get("candidate_name", "") return context + +@login_required +def InterviewListView(request): + interview_type=request.GET.get('interview_type','Remote') + print(interview_type) + if interview_type=='Onsite': + meetings=ScheduledInterview.objects.filter(schedule__interview_type=interview_type) + else: + meetings=ZoomMeeting.objects.all() + print(meetings) + return render(request, "meetings/list_meetings.html",{ + 'meetings':meetings, + 'current_interview_type':interview_type + }) + + # search_query = request.GET.get("q", "") # Renamed from 'search' to 'q' for consistency + # if search_query: + # interviews = interviews.filter( + # Q(topic__icontains=search_query) | Q(meeting_id__icontains=search_query) + # ) + + # # Handle filter by status + # status_filter = request.GET.get("status", "") + # if status_filter: + # queryset = queryset.filter(status=status_filter) + + # # Handle search by candidate name + # candidate_name = request.GET.get("candidate_name", "") + # if candidate_name: + # # Filter based on the name of the candidate associated with the meeting's interview + # queryset = queryset.filter( + # Q(interview__candidate__first_name__icontains=candidate_name) | + # Q(interview__candidate__last_name__icontains=candidate_name) + # ) + + + class ZoomMeetingDetailsView(LoginRequiredMixin, DetailView): @@ -1126,6 +1164,7 @@ def _handle_get_request(request, slug, job): def _handle_preview_submission(request, slug, job): + """ Handles the initial POST request (Preview Schedule). Validates forms, calculates slots, saves data to session, and renders preview. @@ -1137,6 +1176,7 @@ def _handle_preview_submission(request, slug, job): if form.is_valid(): # Get the form data candidates = form.cleaned_data["candidates"] + interview_type=form.cleaned_data["interview_type"] start_date = form.cleaned_data["start_date"] end_date = form.cleaned_data["end_date"] working_days = form.cleaned_data["working_days"] @@ -1197,6 +1237,7 @@ def _handle_preview_submission(request, slug, job): # Save the form data to session for later use schedule_data = { + "interview_type":interview_type, "start_date": start_date.isoformat(), "end_date": end_date.isoformat(), "working_days": working_days, @@ -1217,6 +1258,7 @@ def _handle_preview_submission(request, slug, job): { "job": job, "schedule": preview_schedule, + "interview_type":interview_type, "start_date": start_date, "end_date": end_date, "working_days": working_days, @@ -1260,6 +1302,7 @@ def _handle_confirm_schedule(request, slug, job): schedule = InterviewSchedule.objects.create( job=job, created_by=request.user, + interview_type=schedule_data["interview_type"], start_date=datetime.fromisoformat(schedule_data["start_date"]).date(), end_date=datetime.fromisoformat(schedule_data["end_date"]).date(), working_days=schedule_data["working_days"], @@ -1286,34 +1329,59 @@ def _handle_confirm_schedule(request, slug, job): available_slots = get_available_time_slots(schedule) # This should still be synchronous and fast # 4. Queue scheduled interviews asynchronously (FAST RESPONSE) - queued_count = 0 - for i, candidate in enumerate(candidates): - if i < len(available_slots): - slot = available_slots[i] + if schedule.interview_type=='Remote': + queued_count = 0 + for i, candidate in enumerate(candidates): + if i < len(available_slots): + slot = available_slots[i] - # Dispatch the individual creation task to the background queue - async_task( - "recruitment.tasks.create_interview_and_meeting", - candidate.pk, - job.pk, - schedule.pk, - slot['date'], - slot['time'], - schedule.interview_duration, - ) - queued_count += 1 + # Dispatch the individual creation task to the background queue + + async_task( + "recruitment.tasks.create_interview_and_meeting", + candidate.pk, + job.pk, + schedule.pk, + slot['date'], + slot['time'], + schedule.interview_duration, + ) + queued_count += 1 - # 5. Success and Cleanup (IMMEDIATE RESPONSE) - messages.success( - request, - f"Schedule successfully created. Queued {queued_count} interviews to be booked asynchronously. Check back in a moment!" - ) + # 5. Success and Cleanup (IMMEDIATE RESPONSE) + messages.success( + request, + f"Schedule successfully created. Queued {queued_count} interviews to be booked asynchronously. Check back in a moment!" + ) - # Clear both session data keys upon successful completion - if SESSION_DATA_KEY in request.session: del request.session[SESSION_DATA_KEY] - if SESSION_ID_KEY in request.session: del request.session[SESSION_ID_KEY] + # Clear both session data keys upon successful completion + if SESSION_DATA_KEY in request.session: del request.session[SESSION_DATA_KEY] + if SESSION_ID_KEY in request.session: del request.session[SESSION_ID_KEY] + + return redirect("job_detail", slug=slug) + else: + for i, candidate in enumerate(candidates): + if i < len(available_slots): + slot = available_slots[i] + ScheduledInterview.objects.create( + candidate=candidate, + job=job, + # zoom_meeting=None, + schedule=schedule, + interview_date=slot['date'], + interview_time= slot['time'] + ) + + messages.success( + request, + f"Onsite schedule Interview Create succesfully" + ) + + # Clear both session data keys upon successful completion + if SESSION_DATA_KEY in request.session: del request.session[SESSION_DATA_KEY] + if SESSION_ID_KEY in request.session: del request.session[SESSION_ID_KEY] + return redirect('schedule_interview_location_form',slug=schedule.slug) - return redirect("job_detail", slug=slug) def schedule_interviews_view(request, slug): job = get_object_or_404(JobPosting, slug=slug) @@ -1322,6 +1390,7 @@ def schedule_interviews_view(request, slug): return _handle_preview_submission(request, slug, job) else: return _handle_get_request(request, slug, job) + def confirm_schedule_interviews_view(request, slug): job = get_object_or_404(JobPosting, slug=slug) if request.method == "POST": @@ -4062,4 +4131,18 @@ def send_interview_email(request, slug): +def schedule_interview_location_form(request,slug): + schedule=get_object_or_404(InterviewSchedule,slug=slug) + if request.method=='POST': + form=InterviewScheduleLocationForm(request.POST,instance=schedule) + form.save() + return redirect('list_meetings') + else: + form=InterviewScheduleLocationForm(instance=schedule) + return render(request,'interviews/schedule_interview_location_form.html',{'form':form,'schedule':schedule}) + + +def onsite_interview_list_view(request): + onsite_interviews=ScheduledInterview.objects.filter(schedule__interview_type='Onsite') + return render(request,'interviews/onsite_interview_list.html',{'onsite_interviews':onsite_interviews}) diff --git a/templates/base.html b/templates/base.html index bfded3d..0463281 100644 --- a/templates/base.html +++ b/templates/base.html @@ -255,6 +255,16 @@ +