From d672e9c566d70b3dfdf5ec0eda7d5f79e688bd69 Mon Sep 17 00:00:00 2001 From: Truptimayee Dash Date: Wed, 6 Aug 2025 14:53:00 +0530 Subject: [PATCH] update school management --- __manifest__.py | 5 +- .../__pycache__/application.cpython-310.pyc | Bin 3429 -> 4137 bytes models/__pycache__/enrollment.cpython-310.pyc | Bin 2315 -> 1923 bytes models/__pycache__/schedule.cpython-310.pyc | Bin 2299 -> 1735 bytes .../__pycache__/school_course.cpython-310.pyc | Bin 1280 -> 1202 bytes .../school_course_assignment.cpython-310.pyc | Bin 2031 -> 1459 bytes .../school_course_schedule.cpython-310.pyc | Bin 1638 -> 414 bytes .../school_student.cpython-310.pyc | Bin 2127 -> 2234 bytes .../school_subject.cpython-310.pyc | Bin 3012 -> 2889 bytes .../school_subject_lesson.cpython-310.pyc | Bin 1846 -> 1293 bytes ...chool_subject_teacher_info.cpython-310.pyc | Bin 1635 -> 1105 bytes models/application.py | 100 ++++++------- models/enrollment.py | 41 +++--- models/schedule.py | 12 +- models/school_course.py | 5 - models/school_course_assignment.py | 12 +- models/school_course_schedule.py | 37 +---- models/school_student.py | 27 ++-- models/school_subject.py | 40 +++--- models/school_subject_lesson.py | 12 +- models/school_subject_teacher_info.py | 37 ++--- report/school_id_card_report.xml | 30 ++++ security/ir.model.access.csv | 3 - views/application.xml | 85 ++++++----- views/assignment_views.xml | 5 - views/class.xml | 2 +- views/course.xml | 13 -- views/enrollment.xml | 92 ++++++------ views/menu.xml | 2 +- views/school_student_views.xml | 21 ++- views/school_subject_teacher_views.xml | 134 +++++++----------- views/subject.xml | 3 +- views/timeoff_views.xml | 69 ++++----- 33 files changed, 344 insertions(+), 443 deletions(-) create mode 100644 report/school_id_card_report.xml diff --git a/__manifest__.py b/__manifest__.py index 2ffdbff..26e1899 100644 --- a/__manifest__.py +++ b/__manifest__.py @@ -1,11 +1,12 @@ { 'name': 'School_Management', 'version': '1.0', - 'depends': ['base', 'web', 'mail','product'], + 'depends': ['base', 'web', 'mail','product','hr'], 'license': 'LGPL-3', 'data': [ 'security/security.xml', 'security/ir.model.access.csv', + 'report/school_id_card_report.xml', 'views/schedule.xml', 'views/class.xml', 'views/subject.xml', @@ -23,7 +24,7 @@ 'views/school_student_views.xml', 'views/fee_structure_views.xml', 'views/fee_element_views.xml', - 'views/menu.xml', + 'views/menu.xml', ], 'installable': True, 'application': True, diff --git a/models/__pycache__/application.cpython-310.pyc b/models/__pycache__/application.cpython-310.pyc index e53371b17f4ea1710fc1645afa7fad3b169aa4d4..f0350a17d7e44eb90d1716aa7315af302a2a4982 100644 GIT binary patch delta 2199 zcmZ{k&36-36u{@rcc)3(hEizx8opWrCA6g!kb*$5$T>DD?LwoTIm5iyCS@`c-b}#8 za^e9tE?AV=xNO+5a={;e-#Ag+r}#$MxGqtZYL6tUF|uktRLVV6S(FO;#)FBCZ%1TP-uQ96 zMSC7AWs8}sz0{(;H1k+4XK<9IIob!KEROo=z++O*A?K0%fcxnVh#3U00T|`!PPFU* z9$b;=&{INp;hai&Cr0i@`%u?D4EELtsO0i4Q0=CB&^(N;dyz-FuKU1sKYH##>jAXx z1>Q$(mE4nfpmjIz6$BcM4-M`6W-py{P!Eetq>gJZ~tkqgL2kdGrDMLvN% ziad@y2AroSk&glQ(;{*KeNG`CNBsoy3Di#_k26mMOyS_Irsxc4&eC(JIZe;gw;oC5Y4p7SmRWicEobN@`Zic*=w-M;3#izg@j(X)a@ln2bspYjG&Qeu2|QtYtIUgq z_GXuOLCj84gR*6};m6JFyc<_o@`Lt$%iwSZCkQYX^8Wwzv)ZUWEmAH6Dv>R;$Nrwi{5p z5iKxodw$is9oeuWd%4PdT5R@Kc`<@pW`W1J0qd6v3O@z^sltN0X(nKw$Ih)a#|tTY zMp89m{_-=4PbYK6?EHWe242MtR+!U0+lLSt=^%7vh^T)x4=;L^F!bTlU}ZP1hCy*# zO!Ad}tt2p`Ix}rk=t^Vj}}P+&=F^Zy3g?{%)9N>D`CJOH6MX8 z5~XL#gTy5Am+H&psgV#PnK3UCGl|V>(|kfiDx59zDWLyOxdUn)j_E{|@Sanpj^}df zB)^$gTUNIlRD(vS`mI#MV|MP!s@7ac+vNGFiBv;Q`@Bx4IxeNq$x&)_;f?1Ue3i#n=kj5> zCZHb8c!P;n(O}L9TfqIZj&9Mke z&8fKooU8_)o+4-UkjGBP(AvsILFLzAHq0ZR2THSD$4=_rc-(9qzF6_r6b*=qR1hY~ zljec#MgA}EQsHcBI?15*@nv(t4c4Zh*f2e*I#+QyCJB3v-w^x4TGp>t1DCJy_r(6x zCFnw40({=Kz9udBZg$#^&j_;xiGweyTMZ(9LCkPni1&pM{rFmiV)={8=h&kFQ2@e} zRML4&(y!!{9Lc~Vq@}2u{vu;oM3(iJ85K0Lyi3vl%xJ;|2EdjktNI@qBl#{fJOqh1 zb@7^6i)2h(s9+_(X2x%vgQZgamK(8|=~P>QFN%-mH*GLAXKNvC`0SGSLSj!2N*U-$ IlMKm!1IdIx!2kdN delta 1523 zcmZvb&u`pB6vsWb*T1qq^1E%Cv}u03`CUp8QVOLh;Y0*YDkM|1GJccn2Jd=1_67)z z7Lgo@MC1#{hFeu`<;DpP94b`x>>CIE0wfNA6yCgSXeDZEoxt0hAI9c@g?G6;t}FYEt-td zWQ2H(c$9dYcnrA&6U5`l1(+nBpqMG*Nzz^7Dbg&ft{U*qepni+8-s`bsx z68v7XDmXm;UMsLJPk+}Bx%6-F8j_bj(f@3X;K8G&t}TnvQ(PBgh++thms|GZgu5EX zm^|F48y%n?sc~1LfwsrKV)s-~un+p` zj&T>hSX|i6l=P9cFq^4@XZA)j3~PQ8RKz4^6EZjc3O(lGMrH^eL;@ZvVmAHNTpBHv zg9;BmDK{!notNv;9a)6@-&txmvzU6UAE(#s6ia<#UuSk|Ik&E58n16>n&2BQ6Vq~w z+5gNOQr6=KNj0jM<4W{txeDdL7w}>FrE{}Y#I}Xiz$bSV0*2wIkL-hngZeOmKz%6g z$_^-^kkEHa-D7p?N?B`nL0uKHYpyP?<0sSb7Kqo8JSRT6AXtK{QlTHqs)PTPTMnXH zqnYsX^92=55F2PLb%5!|JL79XC5l2k>(lb*Ub1S{y^{Wzzk5|*uJ}UOvYZ^=xoSu! zkr_9ubzgj*<*GG*lV|!m|18N&A3*Rpe*8h Q9_P{YDwq#_MX3;?Ku8DzNI(>{G?*f?awl0wUe7Z2HYrGv zbZ7-(egIL>@&R=47gN#FQy`Io>j@BS`Rbfw&$-8U=5_O^QRlT<*}&^mz8z5Sq~3kJ ziVO@Oi7_N08JeLvv_gv*4-7EDIyS&!WS<^cp$)We1oro0d0;7L$blu9a&}{uK&Gr{ z6ra4GC#{puYlk*C6D#zXz3)H?%20tSI@M4sp;m@E*wC1mVFg)r&j9}efhp9ARW;P= z(1hs;2^$)>H1;)~(Rd1R6WSV2YrUg!3o-f~!Ymrj!Mtucb0)$9YF)UXwe}zFB5IeQ zr?n1hv#2r;hg4IkuPaJkKBP}jJASNuT5yU00E9i` z^_!}4XEaLUohXla`YbS&ljR~#_mn5t%W*6i98?6$)<==ZQzk;UpO1m1xs1){q$s zMxW9}w37GjM`TI9vtPBfv&U21LY6b(;oHriD}Oo7UI0r3Tk7q@X2mq@eE2R@u^Q* zq;8c7wVhv8w@UO~aO#|vo%8CuK53iUV>7@c95@$dVOv-VibdH^ibGm_v-W>;9ivE~ UyjysT#|gVlkY&Z1meDqU0~N~88UO$Q delta 1202 zcmZuw%Wl+45Oud7u`(!z*AQ17UOT0uYD*LWlsG6-HoLu7+{s$I$LUU;(46 zu)B&x@E!p>*s|hREb$d=k)YfYL>9Ew?Q^P6RaaHpo2~yl&7{$=6dd2~z8Su&Za2IC zo;UtQL7e*cU_2 zJjiAx@q7_H4aD<)6g&%JzdUUBFpylrnO@u8K0T>|g^_Dps$(*JqY8CsfDTRM7IFhr zJi7&L9l8O{}ApUh9h!+FWUCOQ8)(6s8O9o$&VvH zA^8$=18kUwlbGtMEzRjl%V{`-ot3#;Z2$WMu=0UGAI`j1Hi>f(&SIBW^UvgJ)u{}` z7+5UwA7m+Cp#xIO|D(~Q>}62__Q)HDBC~cxy&G%Atm`MyXe^kUPCeZKY?V(PcD4#V z6$xjVnKIFf$6;vGslZHPU?CGMYuw?JOL*We} z-y3w3!~_t#>JthIHkPgzimmY#^eEI+On5;9D6C!GqP+Z33Y9aT*APvYdWl-N{DU(s zi#O>a(SBw}2mUZg!ao)E|8fQEcCRp9H})dtx`pMsQ3B%-asEj^XUlAyYAOR^p@nv3 z=yAS^hdA}$nU%gdHJ0kt!ppnh p%C@KG2PK9}X+J}qf&B~_EDJEG^e*s%KCHVjV diff --git a/models/__pycache__/schedule.cpython-310.pyc b/models/__pycache__/schedule.cpython-310.pyc index 7e16979d2e163436670b646f7295ec2c6554fa65..26e5b4c8423862b8a38aff958356eb09e606bc0e 100644 GIT binary patch delta 105 zcmew@c$}9npO=@50SG*%Pso_WK9O$^BiF{$+>9*244U$rKQV4$V)oON-F%nLiji|A vLynH?iX^TZ(irgQm>pY{po|$sd_C7$qi4F_$w& zO`gQuF2R>rT%4Jnmz$bb5}%n;ypo|v0jR%7VX_O0JEOwn9u~#P>si#bAc9~S5TOVp ZZgJS;=BJeAq}nk8dBrS1LV!Vx830juB1ZrK delta 212 zcmdnQ*}%n{&&$ij00d7<`!ilm4l-3&NDf=Va!k#%HD!NAV>V7iXsD<)-G9fcPsJiWGrvDN>yLgV~)?X|e;0;^cT1 hO)ZEZSO!EW0f}22Ho5sAd+iv3ykZt0A;2KU3;-k9K2-n! diff --git a/models/__pycache__/school_course_assignment.cpython-310.pyc b/models/__pycache__/school_course_assignment.cpython-310.pyc index 2c280d17bb29ef67638ab4b1a539efe189260fa6..b0b19884f8c4467dbd325d13b5f4814dd9e2be3a 100644 GIT binary patch delta 78 zcmaFQznPmapO=@50SJPpPssSpGLdgKrL=A%rLo7!vV+lhFV+~^#qZmUo zV-sTv1JD#EzbfhA)Vvf0-_+vb#Pn2!#6wEQ9k)#8;*MXW#rZn5Mg=B5HU zG9V6HQEGC2QA&{fJEBNJ?pu4e15vZU@8AKpl1a=TV)SjID^!PlWMh%b}H3kM| zhAK5=cfjO{aDyYzi)EQ5m1yCF+YJ&hzb0p-rj+KS#)J4E6Lf%K0(K2Ul|INZ(zq1* qX-ZF4X1U6(3Ua+Vh|rk)g+-CkWU?5mJ_i>g2L}fW56fhC)*Ju=s*ryG diff --git a/models/__pycache__/school_course_schedule.cpython-310.pyc b/models/__pycache__/school_course_schedule.cpython-310.pyc index d9b0ae24a7e3a86f82badb1ff56bfd84fcc32909..524770f1c4aeb1c7b67ef005d6e497888acda7e2 100644 GIT binary patch literal 414 zcmYjN!Ab)`49(1J%UUe-Abx_dmwteVR6KaHm)@3zVcA4?WoAcrTcKX{2gI-Nm*ymR z68r*B&CC{TAjx}4NFH(1=>*t*zuxN)&fkF?TEb+(-k)(mKw-d&Tv(Y)0XKjW)f=E9 z@t|H+o?xeAke{z6#|-6HFHD{fq-aE)a5wB3CGRjq)d}s&>v? zyG_>X9y16eKMfvrq7cF<8;jrY zJR5s9C=|%t*kG2)9L$*8-d9HI&$L#0yh|bfHv!plWR-@)GJ? zuJ?`8PEx0ypw#Gx_oTd^uSVyFgZ~)Xpt;9}X=2g@Bt_9wIxFW^s1l7?5#@ww*$iHaJAfWJO|COB){7(zNpT5^V3Dgz{WdEov){7YM#Jnd!_1pX;m@ zO;TAgO{!XN6g9put?7lRb30jCaYv;|m8mic?n<307Oxw3my z=BkVhLWzq8%3B0KKqB}K_y1mB#|;0ks3y-j_`+c55#B~FU%sQ}qa#&4>#lwq4fH!i z$g_rAL(UG{cXBn4OFZZd$GEe8_hqm)=C1(hR@>;$WZ=b+u54Uy;~0}nU&U2|?y!CE zGHjdppPxG#U$i2QDb;aox8fMnhJA~CKaRhxlf2#OIulfaG^x&(lsVm@D2cS>qmxWfLly(zY>%en1f*I1Fa4P%3)YZz*ASMJxzn;S&lC-QGz z97oB~^a;{5BP4?P+~>PqpKozb1b_5<#QA>kmk5R5_nr08SXiHmRa3Jx;D;nn__&GJC)A6EzMoyz=YsEh{{WAd(HsB( diff --git a/models/__pycache__/school_student.cpython-310.pyc b/models/__pycache__/school_student.cpython-310.pyc index e84bf7a648ce3e7dad964895e7802f697d3c1c0e..c8c2892f4c8f5cd98fe43e5cb670b2c6b4bc5645 100644 GIT binary patch delta 696 zcmZ8fO>fgc5cTZZ&dT{{lIEjrS{f)RN`<%}QN#fuE*uaMf(!T(OlI3Uvc1v9IW!!Q zXs(fnd}T)FWlxN!16;KDE9z}OUo*wv2b&AfR#WBY6MORb{HWyhek^X~1*9kHrx zA0H4x10gU%a3N$a3%Sd|cwityzA%tW7@KF@wa|QO^sVn%d7r0ts89ye)IRcMfYX$F z6MvND{#`bKdvvBhR-bOY7U*CREi5g$>qu){#4=VcaEY+MHLPCXa*k_QCv4&R(sU~n zv9WrW%{_>$%EKo^RZ}AY3BCE`^xe%+uXG z-NMUwWns8&x$$8W_dWt%#ood=19uDeY4B^wD|pioG)!6;sc# zbO*EWrPO^>mowqN>Z#DuLlp(5NyN^fmehC;L~_WxAU;3iw;6PkmG#ZaKKMa0wr@fw zd2c^IEKTDX$|xR2UMN%hz8`t|G%ZiGI`RWKr1oN!ia%Y_SihS|I)ynn$*yR>&=yH@ zI@9Z9gkgdSRYsdvp$c_quo5_6n)c6<Q;P1QCJ<4y+h}`F!V#uhTEQ(9&#YF8_&x*X%&0p2xc7ZC@j(O{y_nRdN3!u;c04M5yL;wH) diff --git a/models/__pycache__/school_subject.cpython-310.pyc b/models/__pycache__/school_subject.cpython-310.pyc index 2dffe324c54fa6531e15d831c4bcadccb23f5192..50eae0c3a7bf8c55a69d196f9ee3804b8cbf598d 100644 GIT binary patch delta 1297 zcmZuw%}>){7+<^6c3Xil7$Aad@-ZsmW8*_jM2MVbCSZn%>18S1yRD>am!~6Sz3c!- zFXTO%cvj<)qu#uD@#4kI|G~t>lP2Q(z5`~FCVldJ{GQ+QynTQDIP__-$La142gvjF z%Sj~|J?VMLy*PP$II`bY>?_8O14o<|EA|%$jsseMF`f^ogLs|Ga2f_~@|Gs$4HMZ0 zQu$W2R%y7Vp<4yFo%8T1mmKw!oLNGN4lYziP8oE9*6*&Hbg zPSMmgVVhVI^&-1$nQo;(wy0Kh@bGUQHOI*(Q2Afdrlq@XA_ECuyaY*KybQN}@d`}% z;#HXR#dl%K7vFqX8egXsQyF-?vR8RZZ~Y{Rpdo-$aNh%v194B z%E1_37P2dm3e2Nw&2kzDdCD%*$tQ(G)-E{)M+hz+>UWcOlf3R0{w!=a$!$lrQ~_j? zf)F(kYKDnXyRK$$UY5kGr5m)w>LavOy0+fy2N9Ac&2+~0(2&js#v)&3iTdim_-K#% zFH)f(dQ3(Febnn9LlC2hern_ZnGXZhWjoNJFhmX8fp)5X`~{qW7@ReB;0jQcF=;V9 zF%dE4Fu5>|Fkvt;z&KR^yLEQcZvraU5?o}JV2&2%a7=Q)a1ZwOkx_RGdyRrY z1-wK6E?q$k;+hmsapF&JB5zb2$I7>{^Vjv^chU!?6=oC#n{EtKKXxE30I42u*OBy(D#0Z6YSBBgnf)0Fdl3zR}r zY;<^ef|hh%YoBqIk}lwHq1oPGm=n%Kp8pf;iUs8$j)#v#dQ3>;SK(5!tLhYy#b&}9 cO}Dqc^cHX`GAjy%MTz3)k&Wno_1BTnzk^9AJpcdz delta 1419 zcmZuwOHUI~6rQ;qW;&%n3-SsIMNt`1gerofpgbZ?5HYx_F-@7dv_slXJyT;KC=1y8 zxJzA>rN$WlfIBxX`~#Ed(qCX=(gk|%Ed>Ug$()?WcfND(L% z*A;bH2;IDdKg%E$Z912B-B=t3eeo5z z?2E6$kS`vAVPAX=;=XtkuK40Hxay0qkHAPZ5v(pSJOtPLiD4M^C*m;1B1(@uz=o8> zgD%(1I!7P4BqQyR9rRLxCx#`Va>5IS0y?%qJvW>L`p_74 zN3$39OX|_mIbIU=e%`8KebdJ%0Ih!1F_xCv01zy}qf^>_br5vC$2g2^;-IL6^92iZ z^7sI%Ll;k+;zpdhhkN4ad?=jehM!+F8vln2kbsNE19%v?7KH#eh3tgZgusNVgp`DS zgl2?Jgf?Id`_{?Dn4x&es$&eB%5m4e7ab)3mGo} z)O;_&9c-ywr#Dzx9eWf_nbo_L+C#fs+inbv8c^l`zQ2Qw9kTLwy=O_Na%oSLN151& z_N7iN$ab~cDjy4X*i5jmO}JASd!d_rWxm410(%imsQf%I%f1KW^7tFQgCtv7uh!ZL zw>Vlgfu>6ohg9Hneg^ nvuKePEEo7)fCX-<%k6tp>|Am)t~$a4u(=} diff --git a/models/__pycache__/school_subject_lesson.cpython-310.pyc b/models/__pycache__/school_subject_lesson.cpython-310.pyc index 82a0bd79b1dd2305d9561b2750ea81136bb3bc0a..b3950e18f4c24b486f0bc17debcdc4f322b0f1a6 100644 GIT binary patch delta 133 zcmdnS*UQD1&&$ij00f!SCuAtGOyrx*IBVjn*(|{fnlhUc8ILlGXfoYmDNfBvyTw+N znw(#hvXY@lYO)n`8?&FL$mIR3o8_c{x{DBmG>FRvBv^pBSZVTnHf1J0#>uDH90U-G Lz%1#>QtUDS25=rC delta 690 zcmeC>+Q!G1&&$ij00dWL+B0^sPUM@-xM||5*)l0IEeug2DY7YYKw30KK1BgYi=`+A zGiWMp_GCQDD6*327E5tzPTDQDqSWO4qLh^kMbeX%nA_@;8A0Yj0TYmB0b*w${wxI~ zY8YG?VmWFVOBhlZYZ$W_#Tc3yn;26VfCe-9RY?b@=A|h3rWO|`rl%?-=VT^lr=}>R zFt$SjhE6EYwf;l$*U%=-Mi_+p?b@wpIFKr)}%fCL94 zA0x~ED)r#xjQsqZ;L@b5)Z`K$prZUdJ&;B;eK@^QBnvbQSuoW^ILR@&z9h3Ov!oI&@Nhdx0_OMRjMS9U zoYZ&_A7p|G+-*8|+*XXPjoD9AeDZ4M&AMQ}DS-@81`&w30<%ETQUrfgc5Z$#M+jTzLrfm+K!VPoifg?f))D$REBc%3%6|{1_)5ekQP1g=IQ8~5O z9+3C}aOB@`-YX~m0vDLwd=Mly+Q}QwcxUFlwP-d2g6s18r(wq?9opZC`7hjPR>StYlhTDF1mfI&0#a9LBM%awsYl^j3Jb z*M|??Wn#AnG0)NhX6?hPF~}5(1iBC2LM+R0793txGVUG~=R$eMaS>mDoHbsHv+f&F zrd28m)nSRq$CC=!vQbvVIh=-;@)i+QD=Q&EIXaNgH9;)IcpJz8?y`gCn)Jv!_anWg zBXUg{y|g$%R%k!8WDDb}`A-!r;*^k`D_cVHjmS2p{CWY82Z9SR$fxFSP8-Wj` literal 1635 zcmZ`(OK;mo5a#kB(u!!yir(ShQAB~{%1f$^ z1m~0->;KRmd+7fu_S#eLJ++t4E+xe|WCgCiZ)Rs_cjhBS7`81MfBf*v@XwZI{iVsx z;S%|Vp6WB2zyg+A1&di>$9Cbw4zs?szy{~71rD;2`^JeqaL=s1_cyJ#`i^Q90x+*s zYmi|Mm2#4CmTKS4L7AH@{}4bcW?;oOu-E}RcF`NPzyTLLXn}w2#=fxxutJvhwG#)# zSKt|2p)pS-eKL3%3nkH}(yKdj@YBeB0nHgEt6o z!nVO%gtuYG;2pwU*fn_9;5~!)aR1i>2!3O*4+n3pH!MDcL#o$DYUeB+3Xz{pE=HKv z&oN1dD4&!AG25?<=csC2M|I;n%CvK19uUnVA``Oueu(lH+bTazsx$%At*L66l`mBw z@p6($1Qm#qnuRsadh=vFgGIhsXOZH&3MIw+67!@+kO6f~c~vbWzFTyX6sWd&DvI%> zMm|3@Z)DJSnjnAfmL0Rj=}?rYyhlZn<+Jcqib0lRMAllU;C@@lS}ih}*Q@zqG+3T{tJodfX3G`&~bjKd+^7 zOI_m-i*YWdh}=*Qb@h}tHnnVL1znkc{>8n!DjYWj<>aabHPEdvA1Fs+s@w_n^mj`} zbd`S}&MzlPu5VAwYs%2!fK@89v2MN8tx^H? ze|nD;CO3)3Ym4LRtCP-^`*4^@xkEm=r>9*V)OwJWiJZy&&7aWXcfjQBT^yPHmSeJ z%BL(?LS;&9ns#IQSRdY_N#DAogtcvX0YX@BadOm6@oMeoMK!@6y&A k=}nrX-ZT9vH*0QWi?m;-RKZtGOTN}GN~O=aVQty}1H_@$`2YX_ diff --git a/models/application.py b/models/application.py index c6819e5..7526c51 100644 --- a/models/application.py +++ b/models/application.py @@ -1,7 +1,6 @@ from odoo import models, fields, api from odoo.exceptions import ValidationError import re -from odoo.exceptions import UserError import base64 class SchoolApplication(models.Model): @@ -11,56 +10,54 @@ class SchoolApplication(models.Model): _rec_name = 'name' _inherit = ['mail.thread', 'mail.activity.mixin'] - name = fields.Char(string="Student Name", required=True,) - email = fields.Char(string="Email", ) - phone_no = fields.Char(string="Phone Number") - image = fields.Binary("Profile Photo", store=True) + # Link to res.partner + partner_id = fields.Many2one('res.partner', string="Student Contact", ondelete="cascade") + + # Basic Info + name = fields.Char(string="Student Name", required=True) + roll_no = fields.Char(string="Roll Number", readonly=False) + email = fields.Char(string="Email") + phone_no = fields.Char(string="Phone Number") + image = fields.Binary("Profile Photo", store=True) address = fields.Text(string="Address") + + # Class and Academic Info class_name = fields.Selection([ - ('1', 'Class 1'), - ('2', 'Class 2'), - ('3', 'Class 3'), - ('4', 'Class 4'), - ('5', 'Class 5'), - ('6', 'Class 6'), - ('7', 'Class 7'), - ('8', 'Class 8'), - ('9', 'Class 9'), - ('10', 'Class 10'), - ('11', 'Class 11'), - ('12', 'Class 12'), + ('1', 'Class 1'), ('2', 'Class 2'), ('3', 'Class 3'), + ('4', 'Class 4'), ('5', 'Class 5'), ('6', 'Class 6'), + ('7', 'Class 7'), ('8', 'Class 8'), ('9', 'Class 9'), + ('10', 'Class 10'), ('11', 'Class 11'), ('12', 'Class 12'), ], string="Class", required=True) - + academic_year = fields.Char(string="Academic Year") gender = fields.Selection([ - ('male', 'Male'), - ('female', 'Female'), - ('other', 'Other') + ('male', 'Male'), ('female', 'Female'), ('other', 'Other') ], string="Gender") + date_of_birth = fields.Date(string="Date of Birth") parent_email = fields.Char(string="Parent Email") + blood_group = fields.Selection([ - ('a+', 'A+'), ('a-', 'A-'), - ('b+', 'B+'), ('b-', 'B-'), - ('ab+', 'AB+'), ('ab-', 'AB-'), - ('o+', 'O+'), ('o-', 'O-') + ('a+', 'A+'), ('a-', 'A-'), ('b+', 'B+'), ('b-', 'B-'), + ('ab+', 'AB+'), ('ab-', 'AB-'), ('o+', 'O+'), ('o-', 'O-') ], string="Blood Group") + school_name = fields.Char(string="Previous School") has_disability = fields.Boolean(string="Any Disability") is_ex_service_child = fields.Boolean(string="Ex-Service Man's Child") + caste = fields.Selection([ - ('general', 'General'), - ('OBC', 'OBC'), - ('SC', 'SC'), - ('ST', 'ST'), - ('other','Other') + ('general', 'General'), ('OBC', 'OBC'), ('SC', 'SC'), + ('ST', 'ST'), ('other', 'Other') ], string="Caste") + status = fields.Selection([ ('pending', 'Pending'), ('approved', 'Approved'), ('rejected', 'Rejected') ], default='pending') + # Parent Info father_name = fields.Char(string="Father's Name") father_phone = fields.Char(string="Father's Phone") mother_name = fields.Char(string="Mother's Name") @@ -80,14 +77,21 @@ class SchoolApplication(models.Model): aadhaar_card = fields.Binary(string="Aadhaar Card") aadhaar_card_filename = fields.Char(string="Filename") - - + + @api.onchange('roll_no') + def _onchange_roll_no(self): + """Auto-generate roll number only when it's empty and user clicks the field.""" + if not self.roll_no: + self.roll_no = self.env['ir.sequence'].next_by_code('school.application') + + # Constraint on phone number @api.constrains('phone_no') def _check_phone_no(self): for record in self: - if not re.fullmatch(r'\d{10}', record.phone_no or ''): + if record.phone_no and not re.fullmatch(r'\d{10}', record.phone_no): raise ValidationError("Phone number must contain exactly 10 digits.") - + + # Show ID card action def action_show_id_card(self): self.ensure_one() return { @@ -97,22 +101,20 @@ class SchoolApplication(models.Model): 'res_model': 'school.application', 'res_id': self.id, 'view_id': self.env.ref('school_management.view_school_id_card_form').id, - 'target': 'new', # or 'current' for full page + 'target': 'new', } + # Optional: Sync partner details with application + @api.onchange('partner_id') + def _onchange_partner_id(self): + if self.partner_id: + self.name = self.partner_id.name + self.email = self.partner_id.email + self.phone_no = self.partner_id.phone + self.image = self.partner_id.image_1920 + self.address = self.partner_id.contact_address - @api.depends('application_id') - def _compute_student_id(self): - for rec in self: - rec.student_id = str(rec.application_id.id) if rec.application_id else '' + def print_id_card(self): + self.ensure_one() + return self.env.ref('school_management.report_school_id_card').report_action(self) - # def action_open_id_card_wizard(self): - # return { - # 'type': 'ir.actions.act_window', - # 'name': 'Generate ID Card', - # 'res_model': 'wizard.generate.id.card', - # 'view_mode': 'form', - # 'target': 'new', - # 'context': {'default_application_id': self.id}, - # } - \ No newline at end of file diff --git a/models/enrollment.py b/models/enrollment.py index 8d4e73a..d6780b5 100644 --- a/models/enrollment.py +++ b/models/enrollment.py @@ -1,58 +1,51 @@ from odoo import models, fields, api -_inherit = ['mail.thread', 'mail.activity.mixin'] - class SchoolEnrollment(models.Model): _name = 'school.enrollment' _description = 'Enrollment' - application_id = fields.Many2one('school.application', string="Student", required=True) + # Relations + application_id = fields.Many2one('school.application', string="Application", required=True) + student_id = fields.Many2one('res.partner', string='Student', required=True) school_id = fields.Many2one('res.company', string="School", default=lambda self: self.env.company) - student_id = fields.Char(string="Student ID", compute='_compute_student_id', store=True) - student_name = fields.Many2one('school.application', string="Student", ondelete='set null') + + # Basic Info image = fields.Binary("Profile Photo", store=True) class_name = fields.Selection([ - ('1', 'Class 1'), - ('2', 'Class 2'), - ('3', 'Class 3'), - ('4', 'Class 4'), - ('5', 'Class 5'), - ('6', 'Class 6'), - ('7', 'Class 7'), - ('8', 'Class 8'), - ('9', 'Class 9'), - ('10', 'Class 10'), - ('11', 'Class 11'), - ('12', 'Class 12'), + ('1', 'Class 1'), ('2', 'Class 2'), ('3', 'Class 3'), + ('4', 'Class 4'), ('5', 'Class 5'), ('6', 'Class 6'), + ('7', 'Class 7'), ('8', 'Class 8'), ('9', 'Class 9'), + ('10', 'Class 10'), ('11', 'Class 11'), ('12', 'Class 12'), ], string="Class", required=True) course = fields.Char(string="Course") session = fields.Char(string="Session") academic_year = fields.Char(string="Academic Year") + enrollment_date = fields.Date(string="Enrollment Date") + + # Fee Info fees_structure = fields.Char(string="Fees Structure") fees_status = fields.Selection([ ('paid', 'Paid'), ('partial', 'Partially Paid'), ('unpaid', 'Unpaid') ], string="Fees Status", default="unpaid") + session_status = fields.Selection([ ('active', 'Active'), ('completed', 'Completed'), ('drop', 'Dropped') ], string="Session Status", default="active") - enrollment_date = fields.Date(string="Enrollment Date") + status = fields.Selection([ ('draft', 'Draft'), ('confirmed', 'Confirmed'), ('cancelled', 'Cancelled') ], string="Status", default='draft') + + # Linked lines subject_line_ids = fields.One2many('school.enrollment.subject', 'enrollment_id', string="Subjects") fee_summary_line_ids = fields.One2many('school.enrollment.fee.summary', 'enrollment_id', string="Fee Summary") - course_id = fields.Many2one('school.course', string='Course', ondelete='cascade', required=True) - student_id = fields.Many2one('res.partner', string='Student', required=True) - @api.depends('application_id') - def _compute_student_id(self): - for rec in self: - rec.student_id = str(rec.application_id.id) if rec.application_id else '' \ No newline at end of file + course_id = fields.Many2one('school.course', string='Course', ondelete='cascade', required=True) diff --git a/models/schedule.py b/models/schedule.py index b835cde..8af4170 100644 --- a/models/schedule.py +++ b/models/schedule.py @@ -56,14 +56,4 @@ class SchoolClassSchedule(models.Model): ('ended', 'Ended') ], string="Session Status") - def action_send_message(self): - for record in self: - raise UserError("Send Message clicked for %s" % record.name) - - def action_log_note(self): - for record in self: - raise UserError("Log Note clicked for %s" % record.name) - - def action_schedule_activity(self): - for record in self: - raise UserError("Activity clicked for %s" % record.name) \ No newline at end of file + \ No newline at end of file diff --git a/models/school_course.py b/models/school_course.py index af31434..2b21ef3 100644 --- a/models/school_course.py +++ b/models/school_course.py @@ -17,9 +17,4 @@ class SchoolCourse(models.Model): attendance_ids = fields.One2many('school.course.attendance', 'course_id', string='Attendance') enrolled_student_ids = fields.One2many('school.course.student', 'course_id', string='Enrolled Students') attendance_ids = fields.One2many('school.course.attendance', 'course_id', string='Attendance') - schedule_line_ids = fields.One2many('school.course.schedule', 'course_id', string='Weekly Schedule') assignment_ids = fields.One2many('school.course.assignment', 'course_id', string='Assignments') - - - - \ No newline at end of file diff --git a/models/school_course_assignment.py b/models/school_course_assignment.py index 86dc3c9..76864d3 100644 --- a/models/school_course_assignment.py +++ b/models/school_course_assignment.py @@ -33,14 +33,4 @@ class SchoolCourseAssignment(models.Model): rec.assignment_count = 0 - def action_send_message(self): - for record in self: - raise UserError("Send Message clicked for %s" % record.name) - - def action_log_note(self): - for record in self: - raise UserError("Log Note clicked for %s" % record.name) - - def action_schedule_activity(self): - for record in self: - raise UserError("Activity clicked for %s" % record.name) \ No newline at end of file + \ No newline at end of file diff --git a/models/school_course_schedule.py b/models/school_course_schedule.py index decf9ce..2f3154e 100644 --- a/models/school_course_schedule.py +++ b/models/school_course_schedule.py @@ -1,39 +1,6 @@ from odoo import models, fields -from odoo.exceptions import UserError -_inherit = ['mail.thread', 'mail.activity.mixin'] class SchoolCourseSchedule(models.Model): - _name = 'school.course.schedule' - _description = 'Weekly Schedule' - - course_id = fields.Many2one('school.course', string='Course', ondelete='cascade') - schedule_time = fields.Char(string='Schedule Time') - day = fields.Selection([ - ('mon', 'Monday'), - ('tue', 'Tuesday'), - ('wed', 'Wednesday'), - ('thu', 'Thursday'), - ('fri', 'Friday'), - ('sat', 'Saturday'), - ('sun', 'Sunday'), - ], string='Day') - location = fields.Char(string='Location') - period = fields.Char(string='Period') - status = fields.Selection([ - ('planned', 'Planned'), - ('ongoing', 'Ongoing'), - ('completed', 'Completed') - ], string='Status', default='planned') + _inherit = 'hr.leave' # not 'school.course.schedule' - - def action_send_message(self): - for record in self: - raise UserError("Send Message clicked for %s" % record.name) - - def action_log_note(self): - for record in self: - raise UserError("Log Note clicked for %s" % record.name) - - def action_schedule_activity(self): - for record in self: - raise UserError("Activity clicked for %s" % record.name) \ No newline at end of file + \ No newline at end of file diff --git a/models/school_student.py b/models/school_student.py index 7a328bd..4785084 100644 --- a/models/school_student.py +++ b/models/school_student.py @@ -1,32 +1,25 @@ from odoo import models, fields, api -from odoo.exceptions import UserError class SchoolStudent(models.Model): _name = 'school.student' _description = 'Student' application_id = fields.Many2one('school.application', string="Application", required=True) - - # Use computed char field instead of invalid related field - student_id = fields.Char(string="Student ID", compute='_compute_student_id', store=True) - profile_photo = fields.Binary(related='application_id.image', string="Profile Photo", store=True) + student_id = fields.Char(string="Student ID", compute='_compute_student_id', store=True) + + # Related fields (autofilled from application) student_name = fields.Char(related='application_id.name', string="Student Name", store=True) + profile_photo = fields.Binary(related='application_id.image', string="Profile Photo", store=True) + phone_no = fields.Char(related='application_id.phone_no', string="Phone No", store=True) + roll_no = fields.Char(related='application_id.roll_no', string="Roll Number", store=True, readonly=True) + school_id = fields.Many2one('res.company', string="School", default=lambda self: self.env.company) enrollment_date = fields.Date(string="Enrollment Date") class_name = fields.Selection([ - ('1', 'Class 1'), - ('2', 'Class 2'), - ('3', 'Class 3'), - ('4', 'Class 4'), - ('5', 'Class 5'), - ('6', 'Class 6'), - ('7', 'Class 7'), - ('8', 'Class 8'), - ('9', 'Class 9'), - ('10', 'Class 10'), - ('11', 'Class 11'), - ('12', 'Class 12'), + ('1', 'Class 1'), ('2', 'Class 2'), ('3', 'Class 3'), ('4', 'Class 4'), + ('5', 'Class 5'), ('6', 'Class 6'), ('7', 'Class 7'), ('8', 'Class 8'), + ('9', 'Class 9'), ('10', 'Class 10'), ('11', 'Class 11'), ('12', 'Class 12'), ], string="Class", required=True) academic_year = fields.Char(string="Academic Year") session_status = fields.Selection([ diff --git a/models/school_subject.py b/models/school_subject.py index 814d930..ab9cf41 100644 --- a/models/school_subject.py +++ b/models/school_subject.py @@ -45,38 +45,42 @@ class SchoolSubject(models.Model): lesson_plan = fields.Text(string='Lesson Plan') teacher = fields.Many2one('res.users', string='Teacher') lesson_plan_line_ids = fields.One2many('school.subject.lesson', 'subject_id', string='Lesson Plans') - teacher_info_line_ids = fields.One2many('school.subject.teacher.info', 'subject_id', string="Teacher Info") + teacher_info_line_ids = fields.One2many('hr.employee', 'subject_id', string="Teacher Info") - @api.depends('class_name') - def _compute_subjects(self): - subject_mapping = { - 'Class 1': ['Math', 'English', 'Science', 'MIL'], - 'Class 2': ['Math', 'English', 'Science', 'Drawing', 'MIL'], - 'Class 3': ['Math', 'English', 'Science', 'Odia', 'Drawing', 'English Grammar'], - 'Class 4': ['Math', 'English', 'Science', 'Odia', 'Drawing', 'English Grammar'], - 'Class 5': ['Math', 'English', 'Science', 'Odia', 'History', 'Drawing', 'English Grammar'], - 'Class 6': ['Math', 'English', 'Science', 'Geography', 'MIL', 'English Grammar'], - 'Class 7': ['Math', 'English', 'Science', 'Political Science', 'MIL', 'English Grammar', 'History', 'Geography'], - 'Class 8': ['Math', 'English', 'Science', 'Political Science', 'MIL', 'English Grammar', 'History', 'Geography'], - 'Class 9': ['Math', 'English', 'Physical Science', 'Life Science', 'English Grammar', 'Economic Science', 'History', 'Geography'], - 'Class 10': ['Math', 'English', 'Physical Science', 'Life Science', 'English Grammar', 'Economic Science', 'History', 'Geography'], - 'Class 11': ['Physics', 'Chemistry', 'Math', 'Biology', 'English', 'English Grammar', 'Computer Science', 'MIL', 'Economic Science'], - 'Class 12': ['Physics', 'Chemistry', 'Math', 'Biology', 'Computer Science', 'English Grammar', 'English', 'MIL', 'Economic Science'], + + @api.model + def get_subjects_by_class(self): + return { + 'Class 1': ['math', 'english', 'science', 'mil'], + 'Class 2': ['math', 'english', 'science', 'drawing', 'mil'], + 'Class 3': ['math', 'english', 'science', 'odia', 'drawing', 'english_grammar'], + 'Class 4': ['math', 'english', 'science', 'odia', 'drawing', 'english_grammar'], + 'Class 5': ['math', 'english', 'science', 'odia', 'history', 'drawing', 'english_grammar'], + 'Class 6': ['math', 'english', 'science', 'geography', 'mil', 'english_grammar'], + 'Class 7': ['math', 'english', 'science', 'political_science', 'mil', 'english_grammar', 'history', 'geography'], + 'Class 8': ['math', 'english', 'science', 'political_science', 'mil', 'english_grammar', 'history', 'geography'], + 'Class 9': ['math', 'english', 'physical_science', 'life_science', 'english_grammar', 'economic_science', 'history', 'geography'], + 'Class 10': ['math', 'english', 'physical_science', 'life_science', 'english_grammar', 'economic_science', 'history', 'geography'], + 'Class 11': ['physics', 'chemistry', 'math', 'biology', 'english', 'english_grammar', 'computer_science', 'mil', 'economic_science'], + 'Class 12': ['physics', 'chemistry', 'math', 'biology', 'computer_science', 'english_grammar', 'english', 'mil', 'economic_science'], } - for rec in self: - rec.subject_list = ', '.join(subject_mapping.get(rec.class_name, [])) + def action_generate_subjects(self): if not self.class_name: raise UserError("Please select a class name first.") + # Get existing subjects for this class existing_subjects = self.search([ ('class_name', '=', self.class_name) ]).mapped('name') + # Get list of subjects by key (not label) subject_list = self.get_subjects_by_class().get(self.class_name, []) + # Filter out already existing ones new_subjects = [sub for sub in subject_list if sub not in existing_subjects] + # Create new records for subject in new_subjects: self.create({ 'class_name': self.class_name, diff --git a/models/school_subject_lesson.py b/models/school_subject_lesson.py index 23ceb01..6f3d425 100644 --- a/models/school_subject_lesson.py +++ b/models/school_subject_lesson.py @@ -25,14 +25,4 @@ class SchoolSubjectLesson(models.Model): for record in self: record.activity_count = len(record.subject_id.teacher_info_line_ids) - def action_send_message(self): - for record in self: - raise UserError("Send Message clicked for %s" % record.name) - - def action_log_note(self): - for record in self: - raise UserError("Log Note clicked for %s" % record.name) - - def action_schedule_activity(self): - for record in self: - raise UserError("Activity clicked for %s" % record.name) \ No newline at end of file + \ No newline at end of file diff --git a/models/school_subject_teacher_info.py b/models/school_subject_teacher_info.py index 1949564..93bd01c 100644 --- a/models/school_subject_teacher_info.py +++ b/models/school_subject_teacher_info.py @@ -1,34 +1,19 @@ from odoo import models, fields, api -class SchoolSubjectTeacherInfo(models.Model): - _name = 'school.subject.teacher.info' - _description = 'Subject Teacher Info' +class HrEmployee(models.Model): + _inherit = 'hr.employee' - subject_id = fields.Many2one('school.subject', string='Subject', required=True, ondelete='cascade') - - # Related fields to auto-fetch from related subject's teacher (res.users) - teacher_user_id = fields.Many2one(related='subject_id.teacher', string="Teacher User", store=True) - employee_name = fields.Char(string='Teacher Name', compute="_compute_teacher_fields", store=True) - phone = fields.Char(string='Phone', compute="_compute_teacher_fields", store=True) - email = fields.Char(string='Email', compute="_compute_teacher_fields", store=True) - profile_photo = fields.Binary(string="Profile Photo", compute="_compute_teacher_fields", store=True) - - # Editable fields for extra info + subject_id = fields.Many2one('school.subject', string="Subject") activity = fields.Char(string='Activity') + department = fields.Many2one('hr.department', string="Department") activity_deadline = fields.Date(string='New Activity Deadline') - department = fields.Char(string='Department') - job_position = fields.Char(string='Job Position') - manager = fields.Char(string='Manager') - address = fields.Text(string="Address") experience = fields.Integer(string="Experience (Years)") - date_of_birth = fields.Date(string="Date of Birth") - join_date = fields.Date(string="Join Date") + extra_info = fields.Text(string="Extra Info") + manager = fields.Char(string="Manager") + job_position = fields.Char(string="Job Position") + employee_name = fields.Char(compute="_compute_employee_name", store=True) - @api.depends('subject_id.teacher') - def _compute_teacher_fields(self): + @api.depends('name') + def _compute_employee_name(self): for rec in self: - user = rec.subject_id.teacher - rec.employee_name = user.name if user else '' - rec.email = user.email if user else '' - rec.phone = user.phone if user else '' - rec.profile_photo = user.image_1920 if user else False + rec.employee_name = rec.name diff --git a/report/school_id_card_report.xml b/report/school_id_card_report.xml new file mode 100644 index 0000000..2256a91 --- /dev/null +++ b/report/school_id_card_report.xml @@ -0,0 +1,30 @@ + + + + ID Card + school.application + qweb-pdf + school_management.report_school_id_card_document + school_management.report_school_id_card_document + "'ID Card - %s' % (object.name)" + + + + diff --git a/security/ir.model.access.csv b/security/ir.model.access.csv index 018e9b8..4e2cb33 100644 --- a/security/ir.model.access.csv +++ b/security/ir.model.access.csv @@ -10,11 +10,8 @@ access_school_subject,School Subject,model_school_subject,,1,1,1,1 access_school_course,School Course,model_school_course,,1,1,1,1 access_school_course_attendance,School Course Attendance,model_school_course_attendance,,1,1,1,1 access_school_course_student,School Course Student,model_school_course_student,,1,1,1,1 -access_school_course_schedule,School Course Schedule,model_school_course_schedule,,1,1,1,1 access_school_course_assignment,School Course Assignment,model_school_course_assignment,,1,1,1,1 access_school_subject_lesson,School Subject Lesson,model_school_subject_lesson,,1,1,1,1 -access_school_subject_teacher_info,School Subject Teacher Info,model_school_subject_teacher_info,,1,1,1,1 -access_school_subject_teacher_info_admin,Subject Teacher Info,model_school_subject_teacher_info,school_management.group_school_admin,1,1,1,1 access_teacher_attendance,Teacher Attendance,model_school_teacher_attendance,,1,1,1,1 access_school_notice_board,School Notice Board,model_school_notice_board,,1,1,1,1 access_school_reporting_dummy,School Reporting Dummy,model_school_reporting_dummy,,1,1,1,1 diff --git a/views/application.xml b/views/application.xml index c9c66a9..c235a55 100644 --- a/views/application.xml +++ b/views/application.xml @@ -1,6 +1,6 @@ - + school.application.list school.application @@ -8,6 +8,7 @@ + @@ -28,18 +29,20 @@
+ + + - - + @@ -53,47 +56,53 @@ string="Show ID Card" type="object" class="btn-primary"/> +