import logging from odoo import http from odoo.http import request from odoo.addons.encoach_api.controllers.base import ( jwt_required, _json_response, _error_response, _get_json_body, _paginate, ) _logger = logging.getLogger(__name__) def _ser_register(r): return { 'id': r.id, 'name': r.name or '', 'course_id': r.course_id.id if r.course_id else 0, 'course_name': r.course_id.name if r.course_id else '', 'start_date': str(r.start_date) if r.start_date else '', 'end_date': str(r.end_date) if r.end_date else '', 'min_count': r.min_count if hasattr(r, 'min_count') else 0, 'max_count': r.max_count if hasattr(r, 'max_count') else 0, 'application_count': len(r.admission_ids) if hasattr(r, 'admission_ids') else 0, 'state': r.state or 'draft', } def _ser_admission(a): nationality = getattr(a, 'nationality', False) nationality_name = '' nationality_id = None if nationality: nationality_id = nationality.id nationality_name = nationality.name or '' return { 'id': a.id, 'name': a.name or '', 'application_number': getattr(a, 'application_number', '') or str(a.id), 'register_id': a.register_id.id if hasattr(a, 'register_id') and a.register_id else 0, 'register_name': a.register_id.name if hasattr(a, 'register_id') and a.register_id else '', 'course_id': a.course_id.id if a.course_id else 0, 'course_name': a.course_id.name if a.course_id else '', 'batch_id': a.batch_id.id if hasattr(a, 'batch_id') and a.batch_id else None, 'batch_name': a.batch_id.name if hasattr(a, 'batch_id') and a.batch_id else None, 'first_name': getattr(a, 'first_name', '') or a.name or '', 'middle_name': getattr(a, 'middle_name', '') or '', 'last_name': getattr(a, 'last_name', '') or '', 'email': getattr(a, 'email', '') or '', 'phone': getattr(a, 'phone', '') or '', 'birth_date': str(a.birth_date) if hasattr(a, 'birth_date') and a.birth_date else None, 'gender': a.gender if hasattr(a, 'gender') else 'o', 'nationality_id': nationality_id, 'nationality_name': nationality_name, 'state': a.state or 'draft', 'fees': getattr(a, 'fees', 0) or 0, 'student_id': a.student_id.id if hasattr(a, 'student_id') and a.student_id else None, 'created_at': str(a.create_date) if a.create_date else '', } class AdmissionsController(http.Controller): # ── Admission Registers ────────────────────────────────────────── @http.route('/api/admission-registers', type='http', auth='public', methods=['GET'], csrf=False) @jwt_required def list_registers(self, **kw): try: M = request.env['op.admission.register'].sudo() offset, limit, page = _paginate(kw) total = M.search_count([]) recs = M.search([], offset=offset, limit=limit, order='id desc') items = [_ser_register(r) for r in recs] return _json_response({'items': items, 'data': items, 'total': total, 'page': page, 'size': limit}) except Exception as e: return _error_response(str(e), 500) @http.route('/api/admission-registers', type='http', auth='public', methods=['POST'], csrf=False) @jwt_required def create_register(self, **kw): try: body = _get_json_body() vals = {'name': body.get('name', '')} if body.get('course_id'): vals['course_id'] = int(body['course_id']) if body.get('start_date'): vals['start_date'] = body['start_date'] if body.get('end_date'): vals['end_date'] = body['end_date'] if body.get('min_count'): vals['min_count'] = int(body['min_count']) if body.get('max_count'): vals['max_count'] = int(body['max_count']) rec = request.env['op.admission.register'].sudo().create(vals) return _json_response(_ser_register(rec)) except Exception as e: return _error_response(str(e), 500) @http.route('/api/admission-registers/', type='http', auth='public', methods=['PATCH', 'PUT'], csrf=False) @jwt_required def update_register(self, rid, **kw): try: rec = request.env['op.admission.register'].sudo().browse(rid) if not rec.exists(): return _error_response('Not found', 404) body = _get_json_body() vals = {} for k in ('name', 'start_date', 'end_date'): if k in body: vals[k] = body[k] for k in ('min_count', 'max_count', 'course_id'): if k in body: vals[k] = int(body[k]) if vals: rec.write(vals) return _json_response(_ser_register(rec)) except Exception as e: return _error_response(str(e), 500) @http.route('/api/admission-registers//confirm', type='http', auth='public', methods=['POST'], csrf=False) @jwt_required def confirm_register(self, rid, **kw): try: rec = request.env['op.admission.register'].sudo().browse(rid) if not rec.exists(): return _error_response('Not found', 404) if hasattr(rec, 'action_confirm'): rec.action_confirm() else: rec.write({'state': 'confirm'}) return _json_response(_ser_register(rec)) except Exception as e: return _error_response(str(e), 500) @http.route('/api/admission-registers//close', type='http', auth='public', methods=['POST'], csrf=False) @jwt_required def close_register(self, rid, **kw): try: rec = request.env['op.admission.register'].sudo().browse(rid) if not rec.exists(): return _error_response('Not found', 404) rec.write({'state': 'done'}) return _json_response(_ser_register(rec)) except Exception as e: return _error_response(str(e), 500) @http.route('/api/admission-registers/', type='http', auth='public', methods=['DELETE'], csrf=False) @jwt_required def delete_register(self, rid, **kw): try: rec = request.env['op.admission.register'].sudo().browse(rid) if rec.exists(): rec.unlink() return _json_response({'success': True}) except Exception as e: return _error_response(str(e), 500) # ── Admissions ─────────────────────────────────────────────────── @http.route('/api/admissions', type='http', auth='public', methods=['GET'], csrf=False) @jwt_required def list_admissions(self, **kw): try: M = request.env['op.admission'].sudo() domain = [] if kw.get('state'): domain.append(('state', '=', kw['state'])) if kw.get('register_id'): domain.append(('register_id', '=', int(kw['register_id']))) if kw.get('course_id'): domain.append(('course_id', '=', int(kw['course_id']))) q = (kw.get('q') or kw.get('search') or '').strip() if q: domain += ['|', '|', '|', '|', ('name', 'ilike', q), ('first_name', 'ilike', q), ('last_name', 'ilike', q), ('email', 'ilike', q), ('application_number', 'ilike', q)] offset, limit, page = _paginate(kw) total = M.search_count(domain) recs = M.search(domain, offset=offset, limit=limit, order='id desc') items = [_ser_admission(r) for r in recs] return _json_response({'items': items, 'data': items, 'total': total, 'page': page, 'size': limit}) except Exception as e: return _error_response(str(e), 500) @http.route('/api/admissions/', type='http', auth='public', methods=['GET'], csrf=False) @jwt_required def get_admission(self, aid, **kw): try: rec = request.env['op.admission'].sudo().browse(aid) if not rec.exists(): return _error_response('Not found', 404) return _json_response(_ser_admission(rec)) except Exception as e: return _error_response(str(e), 500) @http.route('/api/admissions', type='http', auth='public', methods=['POST'], csrf=False) @jwt_required def create_admission(self, **kw): try: from odoo import fields as odoo_fields body = _get_json_body() vals = { 'name': f"{body.get('first_name', '')} {body.get('last_name', '')}".strip() or body.get('name') or 'Applicant', 'application_date': body.get('application_date') or odoo_fields.Date.today(), } if body.get('register_id'): vals['register_id'] = int(body['register_id']) if body.get('course_id'): vals['course_id'] = int(body['course_id']) for k in ('first_name', 'middle_name', 'last_name', 'email', 'phone', 'gender', 'birth_date'): if body.get(k): vals[k] = body[k] if body.get('nationality_id') or body.get('nationality'): vals['nationality'] = int(body.get('nationality_id') or body.get('nationality')) if body.get('batch_id'): vals['batch_id'] = int(body['batch_id']) rec = request.env['op.admission'].sudo().create(vals) return _json_response(_ser_admission(rec)) except Exception as e: _logger.exception('create_admission') return _error_response(str(e), 500) @http.route('/api/admissions/', type='http', auth='public', methods=['DELETE'], csrf=False) @jwt_required def delete_admission(self, aid, **kw): try: rec = request.env['op.admission'].sudo().browse(aid) if rec.exists(): rec.unlink() return _json_response({'success': True}) except Exception as e: return _error_response(str(e), 500) @http.route('/api/admissions/', type='http', auth='public', methods=['PATCH', 'PUT'], csrf=False) @jwt_required def update_admission(self, aid, **kw): try: rec = request.env['op.admission'].sudo().browse(aid) if not rec.exists(): return _error_response('Not found', 404) body = _get_json_body() vals = {} for k in ('first_name', 'middle_name', 'last_name', 'email', 'phone', 'gender', 'birth_date', 'name'): if k in body: vals[k] = body[k] for fk in ('register_id', 'course_id', 'batch_id'): if fk in body and body[fk]: vals[fk] = int(body[fk]) if vals: rec.write(vals) return _json_response(_ser_admission(rec)) except Exception as e: _logger.exception('update_admission') return _error_response(str(e), 500) @http.route('/api/admissions//submit', type='http', auth='public', methods=['POST'], csrf=False) @jwt_required def submit_admission(self, aid, **kw): try: rec = request.env['op.admission'].sudo().browse(aid) if not rec.exists(): return _error_response('Not found', 404) if hasattr(rec, 'submit_form'): rec.submit_form() else: rec.write({'state': 'submit'}) return _json_response(_ser_admission(rec)) except Exception as e: return _error_response(str(e), 500) @http.route('/api/admissions//confirm', type='http', auth='public', methods=['POST'], csrf=False) @jwt_required def confirm_admission(self, aid, **kw): try: rec = request.env['op.admission'].sudo().browse(aid) if not rec.exists(): return _error_response('Not found', 404) if hasattr(rec, 'confirm_in_progress'): rec.confirm_in_progress() else: rec.write({'state': 'confirm'}) return _json_response(_ser_admission(rec)) except Exception as e: return _error_response(str(e), 500) @http.route('/api/admissions//admit', type='http', auth='public', methods=['POST'], csrf=False) @jwt_required def admit(self, aid, **kw): try: rec = request.env['op.admission'].sudo().browse(aid) if not rec.exists(): return _error_response('Not found', 404) if hasattr(rec, 'enroll_student'): rec.enroll_student() else: rec.write({'state': 'admission'}) return _json_response(_ser_admission(rec)) except Exception as e: return _error_response(str(e), 500) @http.route('/api/admissions//reject', type='http', auth='public', methods=['POST'], csrf=False) @jwt_required def reject_admission(self, aid, **kw): try: rec = request.env['op.admission'].sudo().browse(aid) if not rec.exists(): return _error_response('Not found', 404) rec.write({'state': 'reject'}) return _json_response(_ser_admission(rec)) except Exception as e: return _error_response(str(e), 500)