Ejemplo de consumo
Bolsa inicial: 100 h
helpdesk_halo_integration — Integración Helpdesk ↔ Halo ITSM| Versión | 17.0.1.0.0 |
| Autor | ITConsulting |
| Dependencias | helpdesk, mail, hr_holidays |
| Complejidad | Muy Alta (integración API bidireccional) |
Descripción Funcional:
Integración bidireccional entre Odoo Helpdesk y Halo ITSM via API REST con autenticación OAuth2. Sincroniza tickets, acciones (respuestas), adjuntos y notificaciones. Incluye un gestor inteligente de notificaciones que verifica vacaciones del agente antes de notificar.
Descripción Técnica:
Modelos:
| Modelo | Tipo | Descripción |
|---|---|---|
halo.api.service |
AbstractModel | Servicio central OAuth2. Gestión de tokens, reintentos, cache de estados/outcomes (5 min) |
helpdesk.ticket |
Herencia | Campos Halo (URL, JSON, contador adjuntos, estado cerrado). Métodos de sincronización |
helpdesk.halo.mapping |
Normal | Mapeo bidireccional Odoo ↔ Halo: status, priority, type. Constraint unique_mapping |
helpdesk.halo.update |
Normal | Audit trail de sincronizaciones |
helpdesk.halo.attachment |
Normal | Adjuntos descargados desde Halo |
helpdesk.notification.manager |
AbstractModel | Gestor inteligente de notificaciones con check de vacaciones |
res.config.settings |
Transient | Configuración OAuth2: endpoint, client_id, secret, token, scope |
OAuth2 — Gestión de token:
_refresh_token_if_needed()
→ _regenerate_token_with_scope_analysis()
→ Prueba: scope='all', luego 'read write', luego None
→ _verify_token_access(): GET /api/tickets para validar
→ Almacena en ir.config_parameter (encriptado)
_make_authenticated_request(): Reintento automatico en 401/403
Sincronización de tickets:
action_sync_halo_data()
→ _sync_halo_actions(): Crea notas en chatter desde acciones Halo
→ _sync_halo_attachments(): Descarga adjuntos desde API Halo
→ _update_basic_fields_from_halo(): Actualiza status, priority via mapeo
→ _generate_halo_summary_html(): Resumen HTML con datos Halo
Wizard halo.action.wizard:
- Campos: ticket_id, action_description, action_type, halo_response (HTML)
- action_create_halo_action(): POST a /api/Tickets/{id}/Actions
Notificación inteligente:
check_and_notify_ticket()
→ _is_user_on_leave(): Consulta hr_holidays
→ Si de vacaciones: _send_fallback_notification() (email)
→ Si disponible: _send_discuss_notification() (canal ExtendedSupport_PPHE)
→ _send_webhook_notification(): Notificacion webhook externo
Datos:
- Canal Discuss: ExtendedSupport_PPHE
- Cron: DESACTIVADO (se usa webhook externo)
- Mapeos iniciales en halo_mapping_data.xml
- Template de email de notificación Halo
Configuración en Odoo (Ajustes):
- URL endpoint Halo
- Client ID / Client Secret
- Botones: "Autorizar", "Comprobar conexion", "Diagnosticar permisos"
itc_helpdesk_solution_tab — Pestana de Solución| Versión | 17.0.1.0.3 |
| Autor | ITConsulting |
| Dependencias | base, helpdesk, portal |
Descripción Funcional:
Añade una pestana "Solucion" en tickets de helpdesk donde los agentes documentan la resolución. Visible en el portal del cliente.
Descripción Técnica:
- helpdesk.ticket (herencia): Campo solution (Html)
- Vista portal con solucion visible para el cliente
itc_ticket_user — Usuario Final del Ticket| Versión | 17.0.1.0.2 |
| Autor | ITConsulting |
| Dependencias | helpdesk, contacts |
Descripción Funcional:
Añade el campo "Ticket User" al ticket de Helpdesk para identificar a la persona real que solicita el trabajo en la propiedad (hotel), distinta del cliente/empresa principal (partner_id) y del Property User (x_studio_property_user). El desplegable solo muestra contactos hijos del Property User seleccionado y permite crear un contacto nuevo al vuelo. El email del Ticket User es obligatorio: sin él no se puede guardar el ticket ni crear el contacto — es la garantía de que Extended Support siempre podrá responder al solicitante.
Descripción Técnica:
Modelo helpdesk.ticket (herencia):
ticket_user_id (Many2one → res.partner): campo principal. Dominio: [('parent_id', '=', x_studio_property_user), ('is_company', '=', False)] — solo personas hijas del Property User. Contexto: default_parent_id = x_studio_property_user, default_is_company = False, default_type = 'contact', from_ticket_user = True.@api.constrains('ticket_user_id') → _check_ticket_user_email: lanza UserError si el contacto seleccionado NO tiene email. Bloquea el guardado del ticket.Modelo res.partner (herencia):
create() override: si context.get('from_ticket_user') y hay parent_id pero no email → ValidationError. Impide crear contactos hijos sin email desde el "crear al vuelo" del campo.@api.constrains('email', 'parent_id') → _check_email_for_ticket_user_contacts: si el contacto es hijo de una empresa y está usado como ticket_user_id en al menos un ticket, no permite dejarlo sin email. Protege ante ediciones posteriores del contacto que romperían la comunicación con el solicitante.Vistas (views/helpdesk_ticket_views.xml):
view_helpdesk_ticket_form_ticket_user: hereda de la vista de Studio y añade el campo tras x_studio_property_user con dominio, contexto y options="{'no_quick_create': False, 'no_create_edit': False}".view_helpdesk_ticket_tree_ticket_user: añade el campo (invisible por defecto, activable desde el selector de columnas) al listado de tickets.Fix multi-compañía (v17.0.1.0.2 — mayo 2026):
El dominio implícito que Odoo añade a partner_id por el check_company hace referencia a la variable company_id del formulario. Cuando esta variable NO existe en la vista renderizada (Studio la había ocultado), el autocomplete del campo Cliente revienta con Name 'company_id' is not defined y hace inutilizable la creación / edición de tickets.
El fix inyecta <field name="company_id" invisible="1"/> antes de partner_id, para que la variable esté disponible al evaluar el dominio. Y se aplica en DOS vistas core de Odoo (no en la vista Studio) para sobrevivir a cambios futuros de personalización:
view_helpdesk_ticket_form_company_fix → hereda helpdesk.helpdesk_ticket_view_form (form estándar del backend).view_helpdesk_ticket_quick_create_company_fix → hereda helpdesk.quick_create_ticket_form (form inline del "Nuevo" desde el kanban del cajetín, que reventaba de forma independiente).Ruta de configuración: Servicio de atención → Tickets → cualquier ticket → campo Ticket User justo debajo de Property User.
Cómo verificar:
ValidationError con el mensaje "Email Required for New Contact".company_id is not defined.itc_mastel_helpdesk_pes_tech_support — Support Status (PES / Technical Support / Hotel Dashboard)| Versión | 17.0.1.18.0 |
| Autor | ITConsulting |
| Dependencias | helpdesk, sale, contacts, mail |
| Ticket origen | #43073 |
| Complejidad | Alta (backend + OWL frontend + sincronización bidireccional) |
Descripción Funcional:
Da visibilidad inmediata al equipo de Soporte del Support Status contratado por cada cliente (PES OPERA, PES SIMPHONY, PES REVO, Technical Support, Hotel Dashboard…) y sus fechas de vigencia. Consta de cuatro piezas coordinadas:
extended_support_notified).Regla de alcance del aviso: saltan pop-up y email para TODO Support Status (PES, Technical Support, OHIP…) EXCEPTO los productos de panel/BI (Hotel Dashboard, HD - POWER BI, cualquier HD - *), que solo se muestran informativos en el pop-up.
Regla de datos: el Support Status solo puede asignarse a contactos tipo Empresa; un constraint Python en res.partner rechaza el intento en personas físicas por ambas vías (tabla y tags).
Descripción Técnica:
Modelos:
| Modelo | Tipo | Descripción |
|---|---|---|
itc.partner.support.status |
Normal | Fila cliente × tipo. Espejo 1:1 del campo Studio x_studio_support_status_ (tags). Constraint SQL uniq_partner_support impide duplicar el mismo tipo en el mismo cliente. |
res.partner |
Herencia | One2many support_status_line_ids, sincronización bidireccional tabla↔tags, HTML del pop-up, constraint "solo empresas". |
helpdesk.ticket |
Herencia | Campos calculados (partner_has_special_support, partner_show_support_popup, partner_support_popup_html), envío del aviso, flag anti-duplicado. |
Campos clave en itc.partner.support.status:
partner_id (Many2one → res.partner, cascade)support_status_id (Many2one → x_support_status, cascade)date_start, date_end (Date)state (Selection calculado + buscable, NO almacenado): active / expired / pending / pending_dates / not_contracted. Sin campo almacenado ni cron: el _search_state traduce cada valor a un dominio sobre las fechas evaluado con today — siempre correcto.Sincronización bidireccional tabla ↔ tag (evita bucles con skip_tag_sync / skip_line_sync):
Alta de fila → _sync_tag_to_partner(add=True) → añade tag al partner
Baja de fila → si es la última de ese tipo, quita el tag del partner
Cambio de tipo → añade el nuevo tag y, si el viejo queda huérfano, lo elimina
Cambio de tags en el partner (write x_studio_support_status_)
→ _sync_support_status_lines(): crea las filas que falten y
borra las que sobren, para dejar 1 fila por cada tag
Cálculo del pop-up y del email (helpdesk.ticket._compute_partner_support):
x_studio_property_user. Sin fallback al partner_id ni a la Commercial Entity — si el Property User está vacío, no hay aviso.partner_has_special_support (dispara el email): solo Support Status en alcance (PES / Technical). Hotel Dashboard NO cuenta aunque tenga fechas.partner_show_support_popup (dispara el pop-up): Support Status en alcance O Notas Internas del Property User. Así el pop-up también sale si el hotel solo tiene notas relevantes.Aviso a Extended Support (_notify_extended_support):
ir.config_parameter: itc_mastel_helpdesk_pes_tech_support.extended_support_email (por defecto [email protected]).recipient_ids (creando el partner si no existe) y con email_to=False para NO duplicar la entrega.email_from robusto: intenta company.email → user.email → [email protected].create() y también en write() cuando cambia x_studio_property_user (por eso funciona al asignar el Property User más tarde). El flag extended_support_notified evita reenvíos.Frontend OWL (static/src/js/support_status_popup.js):
itc_support_status_popup registrado sobre un booleano (partner_show_support_popup).useEffect ligado a resId Y a partner_show_support_popup: el pop-up salta al entrar al ticket y al pasar el booleano de false→true por asignar el Property User (el efecto se re-ejecuta sin recargar).partner_support_popup_html calculado en servidor dentro de un Dialog estándar (@web/core/dialog/dialog).views/helpdesk_ticket_views.xml).Plantilla de email (data/mail_template.xml): plantilla bilingüe con Customer, Property User, Support Status contratados, Título del Ticket / Ticket Title, Ticket ID y Notas Internas. auto_delete=False para conservar el rastro.
t-out="object.name", ubicada entre Support Status y Número de Ticket en ambos bloques idiomáticos, para que Extended Support vea el asunto del ticket directamente en el aviso sin necesidad de abrir Odoo.Menú y vistas (views/support_status_views.xml): tree, form y search con filtros por estado y agrupación por Tipo / Cliente. Menú Contactos → Support Status (sequence=20).
Permisos: la edición de la tabla se concede en tiempo de instalación al grupo Studio Projects por nombre (no tiene xml_id) vía <function> que llama a _itc_setup_projects_access — crea el ir.model.access con xml_id propio para actualizaciones idempotentes.
Ruta de configuración:
itc_mastel_helpdesk_pes_tech_support.extended_support_email.Cómo verificar:
x_studio_support_status_. Elimínala → el tag desaparece si no queda ninguna otra fila del mismo tipo.itc_mastel_pes_weekly_report — Informe PES Semanal| Versión | 17.0.1.0.13 |
| Autor | ITConsulting |
| Dependencias | helpdesk, hr_timesheet, mail |
| Dependencia sistema | wkhtmltopdf (invocado por subprocess) |
Descripción Funcional:
Cron semanal (todos los lunes a las 11:00 CET / 09:00 UTC) que genera un PDF corporativo con las horas de Premium Extended Support consumidas la semana anterior y lo envía por correo al equipo Extended Support de Mastel. El informe incluye: KPIs de la semana (tickets PES, horas brutas, horas PES, Δ vs semana anterior), detalle línea a línea (fecha, ticket, cliente, agente, tipo de horas, multiplicador, horas), desglose por tipo de horas y comparativa mes a mes de los últimos tres meses con marca "parcial" cuando el mes en curso no se ha cerrado.
Descripción Técnica:
Modelo mastel.pes.weekly.report (AbstractModel):
_get_previous_week_range(today=None): devuelve (monday, sunday) de la semana anterior a today. Si ir.config_parameter pes_report.today_override (formato YYYY-MM-DD) está fijado, se usa como "hoy" — permite regenerar informes de semanas históricas para validación sin desplegar código nuevo. Borrar el parámetro vuelve al comportamiento normal._get_pes_multiplier_ids(): busca en timesheet.time.multiplier por prefijo de nombre PREMIUM CS% / PREMIUM ACS% — no hardcodea IDs._get_pes_lines(date_from, date_to): sudo() obligatorio (el cron corre como OdooBot). Dominio: timesheet_time_multiplier_id in [PES ids] AND date entre from y to. Ordenado por fecha, id._build_report_context(): calcula filas del detalle, totales de la semana, agregación por tipo de horas (consumption_agg), Δ vs semana anterior y llama a _build_monthly_comparison._build_monthly_comparison(ref_date): recorre los 3 meses hasta ref_date, marca el último como "parcial" si end < month_end, calcula tickets distintos, horas brutas, horas PES y Δ vs mes anterior._render_html(ctx): construye HTML A4 apaisado con CSS inline (colores oro #CBB473, negro corporativo). Logo Mastel embebido como data URI base64 desde static/src/img/mastel_logo.png._html_to_pdf(html): escribe HTML a fichero temporal e invoca wkhtmltopdf vía subprocess con flags de landscape A4 y márgenes 14/10/10/30mm. Timeout 60s. Devuelve bytes del PDF._cron_send_weekly_report(): entrypoint del cron. Crea ir.attachment con el PDF (nombre Informe_PES_YYYYMMDD.pdf) y envía la plantilla con subject = "Informe PES - DDMMYYYY".Identificador canónico de "trabajo PES": el parte de horas (account.analytic.line) tiene en su timesheet_time_multiplier_id uno de los multipliers "PREMIUM CS Extended Support Hours X 1" o "PREMIUM ACS Extended Support Hours x 1.25". El factor sale del propio registro (multiplier), la etiqueta corta se abrevia en _short_multiplier_label (ej. "PREMIUM CS (OOH)").
Cron (data/ir_cron.xml): ir.cron Mastel — Envío semanal Informe PES. interval_number=7, interval_type=days, numbercall=-1, ejecutado como base.user_root. nextcall se fija al siguiente lunes 09:00 UTC.
Plantilla de correo (data/mail_template.xml) mail_template_mastel_pes_weekly:
res.users (se envía como el usuario que ejecuta el cron).ctx.pes_subject_date).Detalles del PDF:
MONTH_ES, WEEKDAY_ES)._fmt_num).Ruta de configuración:
pes_report.today_override con valor YYYY-MM-DD.Cómo verificar:
[PES] Generando informe … → … seguido de [PES] Enviado: N líneas, X h PES.Informe_PES_AAAAMMDD.pdf.pes_report.today_override = 2026-04-27 (un lunes), lanza el cron manualmente → sale el informe de la semana 14 – 20 abr 2026. Borra el parámetro cuando termines.account.analytic.line cuyo timesheet_time_multiplier_id no sea PREMIUM CS/ACS queda fuera; renombrar el multiplier rompe el informe (aparecerá "sin actividad PES").itc_development_request — Portal de Solicitudes de Desarrollo| Versión | 17.0.1.0.0 |
| Autor | IT Consulting |
| Dependencias | helpdesk, website |
Descripción Funcional:
Formulario web interno (/development-request) para que empleados de Mastel creen tickets de desarrollo HD/OHIP sin acceso al backend de Odoo.
Descripción Técnica:
Rutas del controller:
| Ruta | Método | Descripción |
|---|---|---|
/development-request |
GET, auth=user | Muestra formulario (solo usuarios internos) |
/development-request/submit |
POST, csrf | Valida, crea ticket, envia email, redirige |
/development-request/submitted |
GET | Página de confirmacion |
Creación del ticket:
team_id = "15. DEVELOPMENTS"
ticket_type_id = "Development Request"
x_studio_property_user = customer_id (cliente hotel)
Email: Tabla HTML con detalles del ticket → integrationsteam, hdteam, info
itc_helpdesk_partner_warning — Avisos de PartnerDescripción Funcional: Muestra los avisos de venta del partner al seleccionar cliente en un ticket. helpdesk.ticket (herencia con onchange en partner_id).
itc_github_link — Enlace GitHub para Helpdesk y ProjectPropósito: Añade un campo URL (github_url) en tickets de Helpdesk y tareas de Project para vincular directamente a repositorios, PRs, issues o branches de GitHub.
Origen: ITC Custom (LGPL-3)
Dependencias: helpdesk, project
Lo que añade:
github_url (Char, widget URL) en helpdesk.ticket — columna derecha, después de Estimated Timegithub_url (Char, widget URL) en project.task — después de Fecha límiteCampos clave:
| Campo | Modelo | Tipo | Widget |
|---|---|---|---|
github_url |
helpdesk.ticket |
Char | url |
github_url |
project.task |
Char | url |
Notas técnicas:
priority=990helpdesk.helpdesk_ticket_view_form — xpath a group[2] position=insideproject.view_task_form2 — xpath a date_deadline position=afterCómo verificar:
helpdesk_halo_integration — ver arriba (detallado)bi_website_ticket_problem_solution_ent — FAQ de Tickets (BrowseInfo Enterprise)Descripción Funcional: Sistema FAQ/Q&A para tickets. Modelo solution.ticket, reporte PDF de soluciones, vista web.
helpdesk_counting — Conteo de TicketsDescripción Funcional: Añade contadores y metricas de tickets de helpdesk. Herencia de helpdesk.ticket (Kanak Infosystems).
helpdesk_timesheet_customization — Hoja de Horas en HelpdeskDescripción Funcional: Personalizacion del registro de hojas de horas en tickets.
Ruta: Ajustes → Técnico → Halo Integration → configurar URL + API key de Halo
halo_ticket_id en el ticket de OdooRuta: Servicio de atención → Tickets → [cualquier ticket] → pestaña Solución
Ruta: Servicio de atención → Tickets → ticket → campo Ticket User justo debajo de Property User
company_id is not definedRutas:
itc_mastel_helpdesk_pes_tech_support.extended_support_emailx_studio_support_status_; elimínala → el tag se retira si nadie más la usa.extended_support_notified).ValidationError "solo puede asignarse a contactos tipo Empresa".Rutas:
pes_report.today_override (formato YYYY-MM-DD)[PES] Generando informe … y [PES] Enviado: N líneas, X h PES.Informe_PES_AAAAMMDD.pdf.pes_report.today_override = 2026-04-27, lanza el cron manualmente y bórralo al terminar.Ruta: Portal público → mastel.odoo.com/development-request (como usuario portal)
Ruta: Servicio de atención → [vista Kanban] → contadores en cabecera de cada columna
Ruta: Portal → ticket → sección Problema / Solución visible para el cliente
Tiempo prepagado, uso flexible y reportes claros. Dos modelos de consumo aplicados según la tarea para garantizar coste y alcance transparentes.
Bolsa inicial: 100 h
El tipo de consumo lo determina la naturaleza de la tarea. Trabajamos con dos modelos:
Descontamos exactamente las horas registradas por nuestro equipo.
Descontamos de tu bolsa las horas estimadas y aprobadas antes de iniciar.
Nota: Si el alcance cambia de forma significativa, revisamos la estimación contigo antes de continuar.