-
-
Notifications
You must be signed in to change notification settings - Fork 320
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by pedrobaeza
- Loading branch information
Showing
31 changed files
with
4,781 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
====================== | ||
pingen.com integration | ||
====================== | ||
|
||
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
!! This file is generated by oca-gen-addon-readme !! | ||
!! changes will be overwritten. !! | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png | ||
:target: https://odoo-community.org/page/development-status | ||
:alt: Beta | ||
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png | ||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html | ||
:alt: License: AGPL-3 | ||
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freport--print--send-lightgray.png?logo=github | ||
:target: https://github.com/OCA/report-print-send/tree/16.0-mig-pingen/pingen | ||
:alt: OCA/report-print-send | ||
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png | ||
:target: https://translation.odoo-community.org/projects/report-print-send-16-0-mig-pingen/report-print-send-16-0-mig-pingen-pingen | ||
:alt: Translate me on Weblate | ||
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png | ||
:target: https://runbot.odoo-community.org/runbot/144/16.0-mig-pingen | ||
:alt: Try me on Runbot | ||
|
||
|badge1| |badge2| |badge3| |badge4| |badge5| | ||
|
||
Pingen.com is a paid online service. | ||
It sends uploaded documents by letter post. | ||
|
||
One can decide, per document / attachment, if it should be pushed | ||
to pingen.com. The documents are pushed asynchronously. | ||
|
||
The informations of the documents from pingen.com are updated through webhook calls. | ||
|
||
**Table of contents** | ||
|
||
.. contents:: | ||
:local: | ||
|
||
Configuration | ||
============= | ||
|
||
The authentication token, client ID, organization ID and webhook secret is configured | ||
on the company's view. You can also tick a checkbox if the staging environment | ||
(https://stage-api.pingen.com) should be used. | ||
|
||
Webhooks should be configured on pingen account. Organization ID and webhook secret must match. | ||
|
||
Usage | ||
===== | ||
|
||
On the attachment view, a new pingen.com section has been added. | ||
You can tick a box to push the document to pingen.com. | ||
|
||
There is 3 additional options: | ||
|
||
* Send: the document will not be only uploaded, but will be also be sent | ||
* Speed: priority or economy | ||
* Type of print: color or black and white | ||
|
||
Once the configuration is done and the attachment saved, a Pingen Document | ||
is created. You can directly access to the latter on the Link on the right on | ||
the attachment view. | ||
|
||
You can find them in `Pingen Documents` App or in the more convenient `Documents` menu if you have installed the | ||
`document` module. | ||
|
||
Errors | ||
====== | ||
|
||
Sometimes, pingen.com will refuse to send a document because it does not meet | ||
its requirements. In such case, the document's state becomes "Pingen Error" | ||
and you will need to manually handle the case, either from the pingen.com | ||
backend, or by changing the document on OpenERP and resolving the error on the | ||
Pingen Document. | ||
|
||
When a connection error occurs, the action will be retried on the next | ||
scheduler run. | ||
|
||
|
||
Dependencies | ||
============ | ||
|
||
* Require the Python library `requests_oauthlib <https://github.com/requests/requests-oauthlib>`_ | ||
* The address must be in a format accepted by pingen.com: the last line | ||
is the country in English or German. | ||
|
||
Bug Tracker | ||
=========== | ||
|
||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/report-print-send/issues>`_. | ||
In case of trouble, please check there if your issue has already been reported. | ||
If you spotted it first, help us smashing it by providing a detailed and welcomed | ||
`feedback <https://github.com/OCA/report-print-send/issues/new?body=module:%20pingen%0Aversion:%2016.0-mig-pingen%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. | ||
|
||
Do not contact contributors directly about support or help with technical issues. | ||
|
||
Credits | ||
======= | ||
|
||
Authors | ||
~~~~~~~ | ||
|
||
* Camptocamp | ||
|
||
Contributors | ||
~~~~~~~~~~~~ | ||
|
||
* Guewen Baconnier <guewen.baconnier@camptocamp.com> | ||
* Anar Baghirli <a.baghirli@mobilunity.com> | ||
* Akim Juillerat <akim.juillerat@camptocamp.com> | ||
* Anna Janiszewska <anna.janiszewska@camptocamp.com> | ||
|
||
|
||
Maintainers | ||
~~~~~~~~~~~ | ||
|
||
This module is maintained by the OCA. | ||
|
||
.. image:: https://odoo-community.org/logo.png | ||
:alt: Odoo Community Association | ||
:target: https://odoo-community.org | ||
|
||
OCA, or the Odoo Community Association, is a nonprofit organization whose | ||
mission is to support the collaborative development of Odoo features and | ||
promote its widespread use. | ||
|
||
This module is part of the `OCA/report-print-send <https://github.com/OCA/report-print-send/tree/16.0-mig-pingen/pingen>`_ project on GitHub. | ||
|
||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from . import controllers | ||
from . import models |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Author: Guewen Baconnier | ||
# Copyright 2012-2023 Camptocamp SA | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
{ | ||
"name": "pingen.com integration", | ||
"version": "16.0.1.0.0", | ||
"author": "Camptocamp,Odoo Community Association (OCA)", | ||
"maintainers": ["ajaniszewska-dev", "grindtildeath"], | ||
"license": "AGPL-3", | ||
"category": "Reporting", | ||
"maturity": "Production/Stable", | ||
"depends": ["base_setup"], | ||
"external_dependencies": { | ||
"python": ["requests_oauthlib", "oauthlib"], | ||
}, | ||
"website": "https://github.com/OCA/report-print-send", | ||
"data": [ | ||
"views/ir_attachment_view.xml", | ||
"views/pingen_document_view.xml", | ||
"data/pingen_data.xml", | ||
"views/base_config_settings.xml", | ||
"security/ir.model.access.csv", | ||
], | ||
"installable": True, | ||
"application": True, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import main |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
# Copyright 2022 Camptocamp SA | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) | ||
import hashlib | ||
import hmac | ||
import json | ||
import logging | ||
|
||
import werkzeug | ||
|
||
from odoo import http | ||
|
||
from ..models.pingen import pingen_datetime_to_utc | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
class PingenController(http.Controller): | ||
def _verify_signature(self, request_content): | ||
webhook_signature = http.request.httprequest.headers.get("Signature") | ||
companies = http.request.env["res.company"].sudo().search([]) | ||
for company in companies: | ||
# We could not search on `pingen_webhook_secret | ||
# if this field is computed (e.g. env field) | ||
if not company.pingen_webhook_secret: | ||
continue | ||
secret_signature = hmac.new( | ||
company.pingen_webhook_secret.encode("utf-8"), | ||
request_content, | ||
hashlib.sha256, | ||
).hexdigest() | ||
if webhook_signature == secret_signature: | ||
return company | ||
msg = "Webhook signature does not match with any company secret" | ||
_logger.warning(msg) | ||
raise werkzeug.exceptions.Forbidden() | ||
|
||
def _get_request_content(self): | ||
return http.request.httprequest.stream.read() | ||
|
||
def _get_json_content(self, request_content): | ||
return json.loads(request_content) | ||
|
||
def _get_document_uuid(self, json_content): | ||
return ( | ||
json_content.get("data", {}) | ||
.get("relationships", {}) | ||
.get("letter", {}) | ||
.get("data", {}) | ||
.get("id", "") | ||
) | ||
|
||
def _find_pingen_document(self, document_uuid): | ||
if document_uuid: | ||
return http.request.env["pingen.document"].search( | ||
[("pingen_uuid", "=", document_uuid)] | ||
) | ||
return http.request.env["pingen.document"].browse() | ||
|
||
def _get_error_reason(self, json_content): | ||
return json_content.get("data", {}).get("attributes", {}).get("reason", "") | ||
|
||
def _get_letter_infos(self, json_content, document_uuid): | ||
for node in json_content.get("included", {}): | ||
if node.get("type") == "letters" and node.get("id") == document_uuid: | ||
return node.get("attributes", {}) | ||
return {} | ||
|
||
def _get_emitted_date(self, json_content): | ||
emitted_at = "" | ||
for node in json_content.get("included", {}): | ||
if node.get("type") == "letters_events": | ||
attributes = node.get("attributes", {}) | ||
if attributes.get("code") == "transferred_to_distributor": | ||
emitted_at = attributes.get("emitted_at", "") | ||
break | ||
return pingen_datetime_to_utc(emitted_at.encode()) | ||
|
||
def _update_pingen_document(self, request_content, values): | ||
json_content = self._get_json_content(request_content) | ||
document_uuid = self._get_document_uuid(json_content) | ||
pingen_doc = self._find_pingen_document(document_uuid) | ||
if pingen_doc: | ||
info_values = pingen_doc._prepare_values_from_post_infos( | ||
self._get_letter_infos(json_content, document_uuid) | ||
) | ||
info_values.update(values) | ||
pingen_doc.sudo().write(info_values) | ||
msg = "Pingen document with UUID %s updated successfully" % document_uuid | ||
_logger.info(msg) | ||
return msg | ||
msg = "Could not find related Pingen document for UUID %s" % document_uuid | ||
_logger.warning(msg) | ||
return msg | ||
|
||
@http.route( | ||
"/pingen/letter_issues", type="http", auth="none", methods=["POST"], csrf=False | ||
) | ||
def letter_issues(self, **post): | ||
_logger.info("Webhook call received on /pingen/letter_issues") | ||
request_content = self._get_request_content() | ||
json_content = self._get_json_content(request_content) | ||
self._verify_signature(request_content) | ||
values = { | ||
"state": "pingen_error", | ||
"last_error_message": self._get_error_reason(json_content), | ||
} | ||
self._update_pingen_document(request_content, values) | ||
|
||
@http.route( | ||
"/pingen/sent_letters", type="http", auth="none", methods=["POST"], csrf=False | ||
) | ||
def sent_letters(self, **post): | ||
_logger.info("Webhook call received on /pingen/sent_letters") | ||
request_content = self._get_request_content() | ||
json_content = self._get_json_content(request_content) | ||
self._verify_signature(request_content) | ||
emitted_date = self._get_emitted_date(json_content) | ||
values = { | ||
"state": "sent", | ||
} | ||
if emitted_date: | ||
values["send_date"] = emitted_date | ||
self._update_pingen_document(request_content, values) | ||
|
||
@http.route( | ||
"/pingen/undeliverable_letters", | ||
type="http", | ||
auth="none", | ||
methods=["POST"], | ||
csrf=False, | ||
) | ||
def undeliverable_letters(self, **post): | ||
_logger.info("Webhook call received on /pingen/undeliverable_letters") | ||
request_content = self._get_request_content() | ||
json_content = self._get_json_content(request_content) | ||
self._verify_signature(request_content) | ||
values = { | ||
"state": "error_undeliverable", | ||
"last_error_message": self._get_error_reason(json_content), | ||
} | ||
self._update_pingen_document(request_content, values) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<odoo noupdate="1"> | ||
|
||
|
||
<record forcecreate="True" id="ir_cron_push_pingen" model="ir.cron"> | ||
<field name="name">Run Pingen Document Push</field> | ||
<field eval="True" name="active" /> | ||
<field name="user_id" ref="base.user_root" /> | ||
<field name="interval_number">1</field> | ||
<field name="interval_type">hours</field> | ||
<field name="numbercall">-1</field> | ||
<field eval="False" name="doall" /> | ||
<field name="model_id" ref="model_pingen_document" /> | ||
<field name="code">model._push_and_send_to_pingen_cron</field> | ||
</record> | ||
|
||
<record forcecreate="True" id="ir_cron_update_pingen" model="ir.cron"> | ||
<field name="name">Run Pingen Document Update</field> | ||
<field eval="False" name="active" /> | ||
<field name="user_id" ref="base.user_root" /> | ||
<field name="interval_number">1</field> | ||
<field name="interval_type">days</field> | ||
<field name="numbercall">-1</field> | ||
<field eval="False" name="doall" /> | ||
<field name="model_id" ref="model_pingen_document" /> | ||
<field name="code">model._update_post_infos_cron</field> | ||
</record> | ||
|
||
|
||
</odoo> |
Oops, something went wrong.