From 6df81afbf4eec0a0cbc78200f05cdbbe4055ad88 Mon Sep 17 00:00:00 2001 From: Yamen Ahmad Date: Sun, 12 Apr 2026 11:07:38 +0400 Subject: [PATCH] feat: add GET /api/exam/custom/list endpoint for Exams List page - Lists custom exams with pagination, search, and status filter - Returns exam sections for module badge display Made-with: Cursor --- .../__pycache__/custom_exam.cpython-312.pyc | Bin 17721 -> 19199 bytes .../controllers/custom_exam.py | 31 ++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/custom_addons/encoach_exam_template/controllers/__pycache__/custom_exam.cpython-312.pyc b/custom_addons/encoach_exam_template/controllers/__pycache__/custom_exam.cpython-312.pyc index bb455e7841618d6bf945a646fbf013a6d493b508..3fe8eb35ee15dc4ec0b821510b3a15e4fe4db1d2 100644 GIT binary patch delta 2845 zcma)7Z%kX)6@T|Vzvus8z{Yk$Y!eKLQ;b0c+OU9Iupw) zM>>sRWG0iw=$59E{Lc6`SuwbubZ8dFB$D_yg=HSXFpSJgwO5(t@?z)ry!AzAz@_dd z*TegpW*i|gmkP<#;&>=Nkyo!&*V2(Pex=c1BtK2}8{KnL5Hc*wB{%;;%* zS7Zx_tQ@jeK1qGE)rBjz=+z2x2p3$cypCsqw z0Z!%9sqvJe3fV*=FDoja#gdEzI_jaw<9U@=vWl2ibvZF9tA?D6V<62q%bnqaF7ZKo z_!43&ElYoWh?p=FuwkgL%E_5YRhOTTvMQH^;IxfWIaLsIIXNS#mNLy)JUfw5Fw_Qj zP$2JB1!l2c3qTzL78*iMCsg**l&Xu;gqoEqNZD~QmC??GkAZVHKo7uCaOQzrUPW@= zLYKZ>f7l88Cg2^@jAojmnRr%=kM?N|ADt#|gsrYe`)$-dUr&4Q3bSFTC0VCyb}q8+ zaNZuiIXr)Sab(RAxbFz9IznrXwz+<~G1vb=rDJ{n!Nq~4;gx;uEAEaP!vD1gQ(NtA z>rLzY^is`IV#U+(zOD0t-F4sIxN2`)Osv_1bJ33)TbA&TFRoe+&P8q<9-r@Dx4Uki zxOrkxSQ>q2a=j_E!7&csCW9!2=wE8;KWIO?=I**1UAlZHxP<<+@5o!xRd?6A+q3Sf zTd(tfYUCR#HW}Vtxxw((%Fk4H*S{W`7@PYa3~Oxt$Wn9Pa$wbRV8!#)`v)PY&Myp;IF?04R&}Qa zhfbG1Hm&hIZl{sS?`=Qoz+ox{YA_5I+zZeL0KK4f6n=(Es%|1LV@$tL20u%IEL3&* za6c>u0FDEEl|rBbKL_#&3dC6b^@DhjN_qGob~OVPwSK@C!7S(V=*tXGm0qvD#g;l8 zBM7yV`P#N>jhy8X5&SIqu(lz*N9LdM<;>@3NG&}+43d@}Cb5>joVAy9JN@WdX~g+k z!3KrEV*r-`PLn4+jcACR^Rzk6fI>Sn@W;adXUT%68GV!d(c?F3sqCOVPyX%kc4=hm zc9Vs@G{883R#TV<Ui8TK{~f18RbCrVN|C)7q2CNk+%<`RAZ%mjcV0DGK2 z;Mnv0B3bp;I7XE+H({)ZUJcgJ3U_E$}LWkQlO3Utov5a|wp*5qfYG-Jr-T1G@AK00Hf(v~rP3S9Lt zQ>b4+z}lDe26(;(P!2>|d!C=w4sZXG!yCZq(Z#?gt8yv&z`@(5>PN-As3;gOfZ0xU zRQ;5QGpS6n+jgRDGBM38;}u$yB;xJS4E%0ZG0KZnkg-VR@8Q3dh$ zcKT0&UTYPN+bk@v0(=kPHo(uwi@l!iU(jdnDzjl?1lyI<-#P#C`4!utrNld(^yQe> zFUk)&Bm^JuRiCm>zIBshgz8P6YBmJA+<3aQ&^w3FtK@KGGQ12i2LN0EFe_A3UzS!P wn@-aK-VEBG1GoXSH`#D(JS$D4qMABO(PfUKGR7ho@^jsO4v delta 1602 zcma)+OKclO7=S%~tY5WBNgb2aYFe@`Y~04ROHC7}HspbmK+{*S#G{z4cbb^mYcsoc z9|(d(52a8c@+(Iw8YECprP@Sptfn1YYx9_4+iY=F)2yTt;hW*t@Mh&qG^sW!NqS1HCCg32tcxE;Rg*H8*p|EXx=y+K;DIARf;+60 zuIrx2pWRe1*VXdE5PA)@y`a{!viHZ^#Nkl7nGaoE^VH-X!(^2P^9luX+ghr(xVvdk z#zJ-gqp8(lB02)c!u=b$OV}%6?lx%kICq{n2^XXLU7S$3743CT2#2NZTfFTAQ&#$c zWv7R`3X^lzjlN@qWMD9sx<4nZlnr(?_PCJQIMiYT`6(2q5i^J<1ulEoQz&N<`wdK(z8N{=QJ@DB;oICgAjQ%}XDHG@5YiadNT$BUCf&`d%MB06+HiFEA1EU5AB$N}6dWYDr%sq02bQ%#i}gg4_`cOJs+ z4&$;UmP-|l9YM_;;%QX-&3Z|rRVv1)2w%r%$!ROT{igf>opUF!bAySYS-TVA^>pGP z409Y|*Vdsdb`(BL{wCz&*0V#6(Bx%%mEZ)JB8q8hnwKgL&KtkA{uGU+Lkat06ihuLL@tiJeRj?lFsD zLShgaRdG*Cx>}>$cjvF@_tNe|^f+XX%uKfGucwdo#3`OsA<5s|;Q|AbI1%8=sNf&W>8eW>|?^{8!7lE%8 i_l?%-TC+-X>@s{XQ;0m~A-mp}KT2Lo{_a58HvI>d!E-|Z diff --git a/custom_addons/encoach_exam_template/controllers/custom_exam.py b/custom_addons/encoach_exam_template/controllers/custom_exam.py index 90e6ba5f..bd6eb9a9 100644 --- a/custom_addons/encoach_exam_template/controllers/custom_exam.py +++ b/custom_addons/encoach_exam_template/controllers/custom_exam.py @@ -43,6 +43,37 @@ def _exam_to_dict(exam): class EncoachCustomExamController(http.Controller): + # ------------------------------------------------------------------ + # GET /api/exam/custom/list + # ------------------------------------------------------------------ + @http.route('/api/exam/custom/list', type='http', auth='none', + methods=['GET'], csrf=False) + @jwt_required + def list_exams(self, **kw): + try: + Exam = request.env['encoach.exam.custom'].sudo() + search = kw.get('search', '').strip() + domain = [] + if search: + domain = [('title', 'ilike', search)] + status = kw.get('status', '').strip() + if status: + domain.append(('status', '=', status)) + + total = Exam.search_count(domain) + page, per_page, offset = _paginate(kw) + exams = Exam.search(domain, limit=per_page, offset=offset, + order='id desc') + return _json_response({ + 'items': [_exam_to_dict(e) for e in exams], + 'total': total, + 'page': page, + 'per_page': per_page, + }) + except Exception as e: + _logger.exception('custom exam list failed') + return _error_response(str(e), 500) + # ------------------------------------------------------------------ # POST /api/exam/custom/create # ------------------------------------------------------------------