Metadata-Version: 2.4
Name: odoo-addon-helpdesk_ticket_to_lead_outbound
Version: 16.0.1.0.1
Summary: Forward CRM lead and ticket data to external CRM platforms via outbound webhooks when converting a helpdesk ticket.
Home-page: https://gitlab.com/somitcoop/erp-research/odoo-helpdesk
Author: Som IT Cooperatiu SCCL
License: AGPL-3
Classifier: Programming Language :: Python
Classifier: Framework :: Odoo
Classifier: Framework :: Odoo :: 16.0
Classifier: License :: OSI Approved :: GNU Affero General Public License v3
Requires-Python: >=3.10
Requires-Dist: odoo-addon-helpdesk_ticket_mail_message<16.1dev,>=16.0dev
Requires-Dist: odoo-addon-helpdesk_ticket_to_lead<16.1dev,>=16.0dev
Requires-Dist: odoo-addon-webhook_hub<16.1dev,>=16.0dev
Requires-Dist: odoo<16.1dev,>=16.0a
Dynamic: author
Dynamic: classifier
Dynamic: description
Dynamic: home-page
Dynamic: license
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

####################################
 Helpdesk Ticket to Lead — Outbound
####################################

.. |badge1| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
   :alt: License: AGPL-3
   :target: https://www.gnu.org/licenses/agpl-3.0-standalone.html

|badge1|

Extends the *Helpdesk Ticket to Lead* conversion workflow with an
optional outbound webhook step. When an agent converts a helpdesk ticket
into a CRM lead they can select an **external destination** so that the
lead data and the full ticket conversation history are also forwarded to
an external CRM platform (e.g. Zoho CRM) through an intermediate
automation layer such as **n8n**.

No external API client code lives inside this module. All HTTP
dispatching, logging and error handling are handled by the **Webhook
Hub** module.

**********
 Features
**********

-  ``crm.lead.destination`` — lightweight configuration model that pairs
   a friendly name with an outbound ``webhook.webhook`` record. Managed
   under *CRM → Configuration → CRM Lead Destinations*.

-  ``destination_id`` field on ``crm.lead`` — selectable in the
   conversion wizard so the agent picks the target at conversion time
   (one lead at a time). Leaving it empty keeps the lead in Odoo CRM
   only.

-  ``sent_to_destination`` status flag on ``crm.lead`` marks whether
   outbound synchronization has succeeded. Leads with destination and
   pending status are retried by a scheduled job every 2 hours.

-  Payload sent to the intermediate layer includes:

   -  Lead fields: name, email, partner name, mobile, phone.

   -  Ticket fields: id, reference number, origin email of the customer,
      and the full conversation history as an HTML string.

      -  **Origin email** resolution order: ticket partner email → first
         received inbound email (``message_type_mail =
         email_received``). Left empty if no customer email is found
         (never falls back to a support agent's address).

      -  **Conversation history** is built by
         ``get_message_body_with_history()`` when
         ``helpdesk_ticket_mail_message`` is installed; raw ticket
         description is the fallback.

   -  Attachment metadata (id, name, MIME type, download URL) for every
      attachment across all ticket messages.

-  Webhook failures **never abort** the lead creation; errors are logged
   at ``WARNING`` / ``ERROR`` level and the webhook log in Webhook Hub
   records the full request and response.

-  CRM form warning banner: if a lead has destination configured but is
   still pending synchronization, a warning is displayed to inform users
   that automatic retry runs every 2 hours.

***************
 Configuration
***************

The setup requires three manual steps. Repeat for every external CRM
target.

Step 1 — Payload Template
=========================

*Webhook Hub → Payloads → New*

+------------------+-----------------------------------------------+
| Field            | Value                                         |
+==================+===============================================+
| Name             | CRM Lead — Ticket to Lead Outbound            |
+------------------+-----------------------------------------------+
| Model            | CRM Lead (crm.lead)                           |
+------------------+-----------------------------------------------+
| Content          | *(see template below)*                        |
+------------------+-----------------------------------------------+

**Template content** (copy-paste and adjust as needed):

.. code::

   {
       "lead": {
           "name": {{ record.name | safe_tojson("") }},
           "email_from": {{ record.email_from | safe_tojson("") }},
           "partner_name": {{ record.partner_name | safe_tojson("") }},
           "mobile": {{ record.mobile | safe_tojson("") }},
           "phone": {{ record.phone | safe_tojson("") }}
       },
       "ticket": {
           "id": {{ record.helpdesk_original_ticket_id.id | safe_tojson("") }},
           "name": {{ record.helpdesk_original_ticket_id.name | safe_tojson("") }},
           "number": {{ record.helpdesk_original_ticket_id.number | safe_tojson("") }},
           "origin_email": {{ context.get('ticket_origin_email', '') | safe_tojson("") }},
           "body_with_history": {{ context.get('ticket_body', '') | safe_tojson("") }}
       },
       "attachments": {{ context.get('ticket_attachments', []) | tojson }}
   }

The Jinja2 template context exposes:

-  ``record`` — the ``crm.lead`` record just created.
-  ``context.get('ticket_body', '')`` — HTML string with the full
   conversation history.
-  ``context.get('ticket_attachments', [])`` — list of dicts ``{id,
   name, mimetype, url}`` for every ticket attachment.
-  ``context.get('ticket_origin_email', '')`` — origin email of the
   customer who opened the ticket (empty string if not determinable).
-  ``context.event_type`` — always ``"create"`` for this flow.

Filters: use ``safe_tojson("")`` for scalar fields (handles
``False``/``None`` gracefully) and ``tojson`` for lists/dicts.

Save.

Step 2 — Webhook
================

*Webhook Hub → Webhooks → New*

+---------------------+------------------------------------------------+
| Field               | Example value                                  |
+=====================+================================================+
| Name                | n8n — CRM Lead (Zoho)                          |
+---------------------+------------------------------------------------+
| Direction           | Outbound                                       |
+---------------------+------------------------------------------------+
| URL                 | http://host.docker.internal:5678/webhook/crm   |
+---------------------+------------------------------------------------+
| Allowed Methods     | POST                                           |
+---------------------+------------------------------------------------+
| Payload             | CRM Lead — Ticket to Lead Outbound             |
+---------------------+------------------------------------------------+
| Custom Headers      | {"X-Odoo-Event": "create",                     |
|                     |    "X-Odoo-Model": "crm.lead"}                 |
+---------------------+------------------------------------------------+
| Log Retention Days  | 30 (0 = keep forever)                          |
+---------------------+------------------------------------------------+

.. note::

   When running Odoo inside Docker and n8n on the host machine, use
   ``http://host.docker.internal:<port>/...`` as the URL. ``localhost``
   inside the container resolves to the container itself.

Save, then **activate** the webhook.

Step 3 — CRM Lead Destination
=============================

*CRM → Configuration → CRM Lead Destinations → New*

+------------------+-------------------------------------------+
| Field            | Value                                     |
+==================+===========================================+
| Name             | Zoho CRM via n8n                          |
+------------------+-------------------------------------------+
| Outbound Webhook | n8n — CRM Lead (Zoho) *(from Step 2)*     |
+------------------+-------------------------------------------+
| Notes            | Contact: ops team / n8n workflow ID: …    |
+------------------+-------------------------------------------+

Save, then **activate** the destination (toggle the *Active* switch).

Converting a Ticket
===================

#. Open a helpdesk ticket and click **Convert into CRM Lead**.

#. In the conversion wizard, set **External Destination** to the
   destination created in Step 3 (leave it empty to create the lead in
   Odoo CRM only).

#. Fill in the remaining lead fields and click **Save**.

The lead is created in Odoo and, if a destination was selected, the
webhook fires immediately. Check *Webhook Hub → Webhooks → <webhook> →
Logs* to inspect the request and response.

*********
 Credits
*********

Authors
=======

-  Som IT Cooperatiu SCCL

Contributors
============

-  Juan Manuel Regalado <juanmanuel.regalado@somit.coop>

Maintainers
===========

-  Som IT Cooperatiu SCCL
