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, ) _logger = logging.getLogger(__name__) def _ser_ticket(t): return { 'id': t.id, 'subject': t.subject or '', 'description': t.description or '', 'type': t.type or 'support', 'status': t.status or 'open', 'source': t.source or 'platform', 'page_context': t.page_context or '', 'reporter_id': t.reporter_id.id if t.reporter_id else None, 'reporter_name': t.reporter_id.name if t.reporter_id else '', 'assignee_id': t.assignee_id.id if t.assignee_id else None, 'assignee_name': t.assignee_id.name if t.assignee_id else '', 'entity_id': t.entity_id.id if t.entity_id else None, 'entity_name': t.entity_id.name if t.entity_id else '', 'created_at': t.create_date.isoformat() if t.create_date else '', 'resolved_at': t.resolved_at.isoformat() if t.resolved_at else '', } class TicketsController(http.Controller): @http.route('/api/tickets', type='http', auth='public', methods=['GET'], csrf=False) @jwt_required def list_tickets(self, **kw): try: Ticket = request.env['encoach.ticket'].sudo() domain = [] status = kw.get('status') if status and status != 'all': domain.append(('status', '=', status)) t = kw.get('type') if t and t != 'all': domain.append(('type', '=', t)) src = kw.get('source') if src and src != 'all': domain.append(('source', '=', src)) assignee = kw.get('assignee_id') if assignee: try: domain.append(('assignee_id', '=', int(assignee))) except (TypeError, ValueError): pass search = kw.get('search') or kw.get('q') if search: domain.append('|') domain.append(('subject', 'ilike', search)) domain.append(('description', 'ilike', search)) try: size = min(int(kw.get('size') or 50), 200) except (TypeError, ValueError): size = 50 try: page = max(int(kw.get('page') or 1), 1) except (TypeError, ValueError): page = 1 total = Ticket.search_count(domain) recs = Ticket.search(domain, limit=size, offset=(page - 1) * size) items = [_ser_ticket(t) for t in recs] return _json_response({ 'data': items, 'items': items, 'total': total, 'page': page, 'size': size, }) except Exception as e: _logger.exception('list_tickets') return _error_response(str(e), 500) @http.route('/api/tickets', type='http', auth='public', methods=['POST'], csrf=False) @jwt_required def create_ticket(self, **kw): try: body = _get_json_body() if not body.get('subject'): return _error_response('subject is required', 400) vals = { 'subject': body['subject'], 'description': body.get('description') or '', 'type': body.get('type') or 'support', 'status': body.get('status') or 'open', 'source': body.get('source') or 'platform', 'page_context': body.get('page_context') or '', } if body.get('assignee_id'): vals['assignee_id'] = int(body['assignee_id']) if body.get('entity_id'): vals['entity_id'] = int(body['entity_id']) # reporter defaults to current user via the model default. rec = request.env['encoach.ticket'].sudo().create(vals) return _json_response(_ser_ticket(rec)) except Exception as e: _logger.exception('create_ticket') return _error_response(str(e), 500) @http.route('/api/tickets/', type='http', auth='public', methods=['GET'], csrf=False) @jwt_required def get_ticket(self, tid, **kw): try: rec = request.env['encoach.ticket'].sudo().browse(tid) if not rec.exists(): return _error_response('Not found', 404) return _json_response(_ser_ticket(rec)) except Exception as e: _logger.exception('get_ticket') return _error_response(str(e), 500) @http.route('/api/tickets/', type='http', auth='public', methods=['PATCH', 'PUT'], csrf=False) @jwt_required def update_ticket(self, tid, **kw): try: from odoo import fields as odoo_fields body = _get_json_body() rec = request.env['encoach.ticket'].sudo().browse(tid) if not rec.exists(): return _error_response('Not found', 404) vals = {} for k in ('subject', 'description', 'type', 'status', 'source', 'page_context'): if k in body: vals[k] = body[k] if 'assignee_id' in body: vals['assignee_id'] = int(body['assignee_id']) if body['assignee_id'] else False if 'entity_id' in body: vals['entity_id'] = int(body['entity_id']) if body['entity_id'] else False # Auto-stamp resolved_at when transitioning to resolved/closed. if vals.get('status') in ('resolved', 'closed') and not rec.resolved_at: vals['resolved_at'] = odoo_fields.Datetime.now() if vals: rec.write(vals) return _json_response(_ser_ticket(rec)) except Exception as e: _logger.exception('update_ticket') return _error_response(str(e), 500) @http.route('/api/tickets/', type='http', auth='public', methods=['DELETE'], csrf=False) @jwt_required def delete_ticket(self, tid, **kw): try: rec = request.env['encoach.ticket'].sudo().browse(tid) if rec.exists(): rec.unlink() return _json_response({'success': True}) except Exception as e: _logger.exception('delete_ticket') return _error_response(str(e), 500) @http.route('/api/tickets/assignedToUser', type='http', auth='public', methods=['GET'], csrf=False) @jwt_required def assigned_to_user(self, **kw): try: uid = request.env.user.id recs = request.env['encoach.ticket'].sudo().search([ ('assignee_id', '=', uid), ], limit=100) items = [_ser_ticket(t) for t in recs] return _json_response({'data': items, 'items': items, 'total': len(items)}) except Exception as e: _logger.exception('assigned_to_user') return _error_response(str(e), 500)