[IMP] pingen: pre-commit stuff

This commit is contained in:
Anna Janiszewska
2023-01-26 12:55:11 +01:00
parent eb4a9f3b5a
commit 0529340243
17 changed files with 471 additions and 385 deletions

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Author: Guewen Baconnier
# Copyright 2012-2017 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

View File

@@ -1,30 +1,29 @@
# -*- coding: utf-8 -*-
# Author: Guewen Baconnier
# Copyright 2012-2017 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
'name': 'pingen.com integration',
'version': '10.0.1.0.0',
'author': "Camptocamp,Odoo Community Association (OCA)",
'maintainer': 'Camptocamp',
'license': 'AGPL-3',
'category': 'Reporting',
'complexity': 'easy',
'depends': ['base_setup'],
'external_dependencies': {
'python': ['requests'],
"name": "pingen.com integration",
"version": "10.0.1.0.0",
"author": "Camptocamp,Odoo Community Association (OCA)",
"maintainer": "Camptocamp",
"license": "AGPL-3",
"category": "Reporting",
"complexity": "easy",
"depends": ["base_setup"],
"external_dependencies": {
"python": ["requests"],
},
'website': 'http://www.camptocamp.com',
'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',
"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",
],
'tests': [],
'installable': True,
'auto_install': False,
'application': True,
"tests": [],
"installable": True,
"auto_install": False,
"application": True,
}

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import ir_attachment

View File

@@ -1,11 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class BaseConfigSettings(models.TransientModel):
_inherit = 'base.config.settings'
_inherit = "base.config.settings"
pingen_token = fields.Char(related='company_id.pingen_token')
pingen_staging = fields.Boolean(related='company_id.pingen_staging')
pingen_token = fields.Char(related="company_id.pingen_token")
pingen_staging = fields.Boolean(related="company_id.pingen_staging")

View File

@@ -1,37 +1,40 @@
# -*- coding: utf-8 -*-
# Author: Guewen Baconnier
# Copyright 2012-2017 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import requests
import base64
from odoo import models, fields, _, api
import requests
from odoo import _, api, fields, models
from odoo.exceptions import UserError
class IrAttachment(models.Model):
_inherit = 'ir.attachment'
_inherit = "ir.attachment"
send_to_pingen = fields.Boolean("Send to Pingen.com")
pingen_document_ids = fields.One2many(
'pingen.document', 'attachment_id',
string='Pingen Document', readonly=True)
"pingen.document", "attachment_id", string="Pingen Document", readonly=True
)
pingen_send = fields.Boolean(
'Send', help="Defines if a document is merely uploaded or also sent",
default=True)
"Send",
help="Defines if a document is merely uploaded or also sent",
default=True,
)
pingen_speed = fields.Selection(
[('1', 'Priority'), ('2', 'Economy')],
'Speed', default='2',
help='Defines the sending speed if the document is automatically sent')
pingen_color = fields.Selection([('0', 'B/W'), ('1', 'Color')],
'Type of print',
default='0')
[("1", "Priority"), ("2", "Economy")],
"Speed",
default="2",
help="Defines the sending speed if the document is automatically sent",
)
pingen_color = fields.Selection(
[("0", "B/W"), ("1", "Color")], "Type of print", default="0"
)
def _prepare_pingen_document_vals(self):
return {'attachment_id': self.id,
'config': 'created from attachment'}
return {"attachment_id": self.id, "config": "created from attachment"}
def _handle_pingen_document(self):
"""Reponsible of the related ``pingen.document``
@@ -48,35 +51,37 @@ class IrAttachment(models.Model):
* If it has already been pushed to pingen.com, raises
an `osv.except_osv` exception
"""
pingen_document_obj = self.env['pingen.document']
document = self.pingen_document_ids[0] if \
self.pingen_document_ids else None
pingen_document_obj = self.env["pingen.document"]
document = self.pingen_document_ids[0] if self.pingen_document_ids else None
if self.send_to_pingen:
if document:
document.write({'state': 'pending'})
document.write({"state": "pending"})
else:
pingen_document_obj.create(
self._prepare_pingen_document_vals())
pingen_document_obj.create(self._prepare_pingen_document_vals())
else:
if document:
if document.state == 'pushed':
if document.state == "pushed":
raise UserError(
_('Error. The attachment %s is '
'already pushed to pingen.com.') % self.name)
document.write({'state': 'canceled'})
_(
"Error. The attachment %s is "
"already pushed to pingen.com."
)
% self.name
)
document.write({"state": "canceled"})
return
@api.model
def create(self, vals):
attachment = super(IrAttachment, self).create(vals)
if 'send_to_pingen' in vals:
if "send_to_pingen" in vals:
attachment._handle_pingen_document()
return attachment
@api.multi
def write(self, vals):
res = super(IrAttachment, self).write(vals)
if 'send_to_pingen' in vals:
if "send_to_pingen" in vals:
for attachment in self:
attachment._handle_pingen_document()
return res
@@ -86,14 +91,12 @@ class IrAttachment(models.Model):
Returns None if the type is 'url' and the url is not reachable.
"""
decoded_document = None
if self.type == 'binary':
if self.type == "binary":
decoded_document = base64.b64decode(self.datas)
elif self.type == 'url':
elif self.type == "url":
response = requests.get(self.url)
if response.ok:
decoded_document = requests.content
else:
raise UserError(
_('The type of attachment %s is not handled')
% self.type)
raise UserError(_("The type of attachment %s is not handled") % self.type)
return decoded_document

View File

@@ -1,31 +1,30 @@
# -*- coding: utf-8 -*-
# Author: Guewen Baconnier
# Copyright 2012-2017 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import requests
import logging
import urlparse
import json
import pytz
import logging
from datetime import datetime
import pytz
import requests
import urlparse
from requests.packages.urllib3.filepost import encode_multipart_formdata
_logger = logging.getLogger(__name__)
POST_SENDING_STATUS = {
100: 'Ready/Pending',
101: 'Processing',
102: 'Waiting for confirmation',
1: 'Sent',
300: 'Some error occured and object wasn\'t sent',
400: 'Sending cancelled',
100: "Ready/Pending",
101: "Processing",
102: "Waiting for confirmation",
1: "Sent",
300: "Some error occured and object wasn't sent",
400: "Sending cancelled",
}
DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S' # this is the format used by pingen API
DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S" # this is the format used by pingen API
TZ = pytz.timezone('Europe/Zurich') # this is the timezone of the pingen API
TZ = pytz.timezone("Europe/Zurich") # this is the timezone of the pingen API
def pingen_datetime_to_utc(dt):
@@ -62,8 +61,8 @@ class Pingen(object):
@property
def url(self):
if self.staging:
return 'https://stage-api.pingen.com'
return 'https://api.pingen.com'
return "https://stage-api.pingen.com"
return "https://api.pingen.com"
@property
def session(self):
@@ -71,7 +70,7 @@ class Pingen(object):
if self._session is not None:
return self._session
self._session = requests.Session()
self._session.params = {'token': self._token}
self._session.params = {"token": self._token}
self._session.verify = not self.staging
return self._session
@@ -99,28 +98,24 @@ class Pingen(object):
p_url = urlparse.urljoin(self.url, endpoint)
if endpoint == 'document/get':
complete_url = '{}{}{}{}{}'.format(p_url,
'/id/',
kwargs['params']['id'],
'/token/',
self._token)
if endpoint == "document/get":
complete_url = "{}{}{}{}{}".format(
p_url, "/id/", kwargs["params"]["id"], "/token/", self._token
)
else:
complete_url = '{}{}{}'.format(p_url,
'/token/',
self._token)
complete_url = "{}{}{}".format(p_url, "/token/", self._token)
response = method(complete_url, **kwargs)
if response.json()['error']:
if response.json()["error"]:
raise APIError(
"%s: %s" % (response.json()['errorcode'],
response.json()['errormessage']))
"%s: %s"
% (response.json()["errorcode"], response.json()["errormessage"])
)
return response
def push_document(self, filename, filestream,
send=None, speed=None, color=None):
def push_document(self, filename, filestream, send=None, speed=None, color=None):
"""Upload a document to pingen.com and eventually ask to send it
:param str filename: name of the file to push
@@ -135,9 +130,9 @@ class Pingen(object):
3. dict of the created item on pingen (details)
"""
data = {
'send': send,
'speed': speed,
'color': color,
"send": send,
"speed": speed,
"color": color,
}
# we cannot use the `files` param alongside
@@ -146,25 +141,26 @@ class Pingen(object):
# the entire body and send it to `data`
# https://github.com/kennethreitz/requests/issues/950
formdata = {
'file': (filename, filestream.read()),
'data': json.dumps(data),
"file": (filename, filestream.read()),
"data": json.dumps(data),
}
multipart, content_type = encode_multipart_formdata(formdata)
response = self._send(
self.session.post,
'document/upload',
headers={'Content-Type': content_type},
data=multipart)
"document/upload",
headers={"Content-Type": content_type},
data=multipart,
)
rjson = response.json()
document_id = rjson['id']
if rjson.get('send'):
document_id = rjson["id"]
if rjson.get("send"):
# confusing name but send_id is the posted id
posted_id = rjson['send'][0]['send_id']
item = rjson['item']
posted_id = rjson["send"][0]["send_id"]
item = rjson["item"]
return document_id, posted_id, item
@@ -178,16 +174,17 @@ class Pingen(object):
:return: id of the post on pingen.com
"""
data = {
'speed': speed,
'color': color,
"speed": speed,
"color": color,
}
response = self._send(
self.session.post,
'document/send',
params={'id': document_id},
data={'data': json.dumps(data)})
"document/send",
params={"id": document_id},
data={"data": json.dumps(data)},
)
return response.json()['id']
return response.json()["id"]
def post_infos(self, post_id):
"""Return the information of a post
@@ -195,12 +192,9 @@ class Pingen(object):
:param int post_id: id of the document to send
:return: dict of infos of the post
"""
response = self._send(
self.session.get,
'document/get',
params={'id': post_id})
response = self._send(self.session.get, "document/get", params={"id": post_id})
return response.json()['item']
return response.json()["item"]
@staticmethod
def is_posted(post_infos):
@@ -208,4 +202,4 @@ class Pingen(object):
:param dict post_infos: post infos returned by `post_infos`
"""
return post_infos['status'] == 1
return post_infos["status"] == 1

View File

@@ -1,17 +1,17 @@
# -*- coding: utf-8 -*-
# Author: Guewen Baconnier
# Copyright 2012-2017 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import logging
from requests.exceptions import ConnectionError
from cStringIO import StringIO
from requests.exceptions import ConnectionError
import odoo
from odoo import models, fields, _
from odoo import _, fields, models
from odoo.exceptions import UserError
from .pingen import APIError, pingen_datetime_to_utc, POST_SENDING_STATUS
from .pingen import POST_SENDING_STATUS, APIError, pingen_datetime_to_utc
_logger = logging.getLogger(__name__)
@@ -24,46 +24,54 @@ class PingenDocument(models.Model):
It also serves as a queue of documents to push to pingen.com
"""
_name = 'pingen.document'
_inherits = {'ir.attachment': 'attachment_id'}
_name = "pingen.document"
_inherits = {"ir.attachment": "attachment_id"}
attachment_id = fields.Many2one(
'ir.attachment', 'Document',
required=True, readonly=True,
ondelete='cascade')
"ir.attachment", "Document", required=True, readonly=True, ondelete="cascade"
)
state = fields.Selection(
[('pending', 'Pending'),
('pushed', 'Pushed'),
('sendcenter', 'In Sendcenter'),
('sent', 'Sent'),
('error', 'Connection Error'),
('pingen_error', 'Pingen Error'),
('canceled', 'Canceled')],
string='State', readonly=True,
required=True, default='pending')
push_date = fields.Datetime('Push Date', readonly=True)
[
("pending", "Pending"),
("pushed", "Pushed"),
("sendcenter", "In Sendcenter"),
("sent", "Sent"),
("error", "Connection Error"),
("pingen_error", "Pingen Error"),
("canceled", "Canceled"),
],
string="State",
readonly=True,
required=True,
default="pending",
)
push_date = fields.Datetime("Push Date", readonly=True)
# for `error` and `pingen_error` states when we push
last_error_message = fields.Text('Error Message', readonly=True)
last_error_message = fields.Text("Error Message", readonly=True)
# pingen IDs
pingen_id = fields.Integer(
'Pingen ID', readonly=True,
help="ID of the document in the Pingen Documents")
"Pingen ID", readonly=True, help="ID of the document in the Pingen Documents"
)
post_id = fields.Integer(
'Pingen Post ID', readonly=True,
help="ID of the document in the Pingen Sendcenter")
"Pingen Post ID",
readonly=True,
help="ID of the document in the Pingen Sendcenter",
)
# sendcenter infos
post_status = fields.Char('Post Status', size=128, readonly=True)
parsed_address = fields.Text('Parsed Address', readonly=True)
cost = fields.Float('Cost', readonly=True)
currency_id = fields.Many2one('res.currency', 'Currency', readonly=True)
country_id = fields.Many2one('res.country', 'Country', readonly=True)
send_date = fields.Datetime('Date of sending', readonly=True)
pages = fields.Integer('Pages', readonly=True)
post_status = fields.Char("Post Status", size=128, readonly=True)
parsed_address = fields.Text("Parsed Address", readonly=True)
cost = fields.Float("Cost", readonly=True)
currency_id = fields.Many2one("res.currency", "Currency", readonly=True)
country_id = fields.Many2one("res.country", "Country", readonly=True)
send_date = fields.Datetime("Date of sending", readonly=True)
pages = fields.Integer("Pages", readonly=True)
_sql_constraints = [
('pingen_document_attachment_uniq',
'unique (attachment_id)',
'Only one Pingen document is allowed per attachment.'),
(
"pingen_document_attachment_uniq",
"unique (attachment_id)",
"Only one Pingen document is allowed per attachment.",
),
]
def _get_pingen_session(self):
@@ -83,33 +91,38 @@ class PingenDocument(models.Model):
StringIO(decoded_document),
self.pingen_send,
self.pingen_speed,
self.pingen_color)
self.pingen_color,
)
except ConnectionError:
_logger.exception(
'Connection Error when pushing Pingen Document %s to %s.' %
(self.id, pingen.url))
"Connection Error when pushing Pingen Document %s to %s."
% (self.id, pingen.url)
)
raise
except APIError:
_logger.error(
'API Error when pushing Pingen Document %s to %s.' %
(self.id, pingen.url))
"API Error when pushing Pingen Document %s to %s."
% (self.id, pingen.url)
)
raise
error = False
state = 'pushed'
state = "pushed"
if post_id:
state = 'sendcenter'
elif infos['requirement_failure']:
state = 'pingen_error'
error = _('The document does not meet the Pingen requirements.')
push_date = pingen_datetime_to_utc(infos['date'])
state = "sendcenter"
elif infos["requirement_failure"]:
state = "pingen_error"
error = _("The document does not meet the Pingen requirements.")
push_date = pingen_datetime_to_utc(infos["date"])
self.write(
{'last_error_message': error,
'state': state,
'push_date': fields.Datetime.to_string(push_date),
'pingen_id': doc_id,
'post_id': post_id},)
_logger.info(
'Pingen Document %s: pushed to %s' % (self.id, pingen.url))
{
"last_error_message": error,
"state": state,
"push_date": fields.Datetime.to_string(push_date),
"pingen_id": doc_id,
"post_id": post_id,
},
)
_logger.info("Pingen Document %s: pushed to %s" % (self.id, pingen.url))
def push_to_pingen(self):
"""Push a document to pingen.com
@@ -123,28 +136,38 @@ class PingenDocument(models.Model):
try:
session = self._get_pingen_session()
self._push_to_pingen(pingen=session)
except ConnectionError as e:
state = 'error'
error_msg = _('Connection Error when asking for '
'sending the document %s to Pingen') % self.name
except ConnectionError:
state = "error"
error_msg = (
_(
"Connection Error when asking for "
"sending the document %s to Pingen"
)
% self.name
)
except APIError as e:
state = 'pingen_error'
error_msg = _('Error when asking Pingen to send the document %s: '
'\n%s') % (self.name, e)
except Exception as e:
state = "pingen_error"
error_msg = _(
"Error when asking Pingen to send the document %s: " "\n%s"
) % (self.name, e)
except Exception:
_logger.exception(
'Unexpected Error when updating the status of pingen.document '
'%s: ' % self.id)
error_msg = _('Unexpected Error when updating the '
'status of Document %s') % self.name
"Unexpected Error when updating the status of pingen.document "
"%s: " % self.id
)
error_msg = (
_("Unexpected Error when updating the " "status of Document %s")
% self.name
)
finally:
if error_msg:
vals = {'last_error_message': error_msg}
vals = {"last_error_message": error_msg}
if state:
vals.update({'state': state})
vals.update({"state": state})
with odoo.registry(self.env.cr.dbname).cursor() as new_cr:
new_env = odoo.api.Environment(
new_cr, self.env.uid, self.env.context)
new_cr, self.env.uid, self.env.context
)
self.with_env(new_env).write(vals)
raise UserError(error_msg)
@@ -158,40 +181,39 @@ class PingenDocument(models.Model):
"""
with odoo.api.Environment.manage():
with odoo.registry(self.env.cr.dbname).cursor() as new_cr:
new_env = odoo.api.Environment(
new_cr, self.env.uid, self.env.context)
new_env = odoo.api.Environment(new_cr, self.env.uid, self.env.context)
# Instead of raising, store the error in the pingen.document
self = self.with_env(new_env)
not_sent_docs = self.search([('state', '!=', 'sent')])
not_sent_docs = self.search([("state", "!=", "sent")])
for document in not_sent_docs:
session = document._get_pingen_session()
if document.state == 'error':
if document.state == "error":
document._resolve_error()
document.refresh()
try:
if document.state == 'pending':
if document.state == "pending":
document._push_to_pingen(pingen=session)
elif document.state == 'pushed':
elif document.state == "pushed":
document._ask_pingen_send(pingen=session)
except ConnectionError as e:
document.write({'last_error_message': e,
'state': 'error'})
document.write({"last_error_message": e, "state": "error"})
except APIError as e:
document.write({'last_error_message': e,
'state': 'pingen_error'})
except BaseException as e:
_logger.error('Unexpected error in pingen cron')
document.write(
{"last_error_message": e, "state": "pingen_error"}
)
except BaseException:
_logger.error("Unexpected error in pingen cron")
return True
def _resolve_error(self):
"""A document as resolved, put in the correct state"""
if self.post_id:
state = 'sendcenter'
state = "sendcenter"
elif self.pingen_id:
state = 'pushed'
state = "pushed"
else:
state = 'pending'
self.write({'state': state})
state = "pending"
self.write({"state": state})
def resolve_error(self):
"""A document as resolved, put in the correct state"""
@@ -207,29 +229,29 @@ class PingenDocument(models.Model):
# for consistency
if not self.pingen_send:
self.write({'pingen_send': True})
self.write({"pingen_send": True})
try:
post_id = pingen.send_document(
self.pingen_id,
self.pingen_speed,
self.pingen_color)
self.pingen_id, self.pingen_speed, self.pingen_color
)
except ConnectionError:
_logger.exception(
'Connection Error when asking for sending Pingen Document %s '
'to %s.' % (self.id, pingen.url))
"Connection Error when asking for sending Pingen Document %s "
"to %s." % (self.id, pingen.url)
)
raise
except APIError:
_logger.exception(
'API Error when asking for sending Pingen Document %s to %s.' %
(self.id, pingen.url))
"API Error when asking for sending Pingen Document %s to %s."
% (self.id, pingen.url)
)
raise
self.write(
{'last_error_message': False,
'state': 'sendcenter',
'post_id': post_id})
{"last_error_message": False, "state": "sendcenter", "post_id": post_id}
)
_logger.info(
'Pingen Document %s: asked for sending to %s' % (
self.id, pingen.url))
"Pingen Document %s: asked for sending to %s" % (self.id, pingen.url)
)
return True
def ask_pingen_send(self):
@@ -241,23 +263,30 @@ class PingenDocument(models.Model):
try:
session = self._get_pingen_session()
self._ask_pingen_send(pingen=session)
except ConnectionError as e:
except ConnectionError:
raise UserError(
_('Connection Error when asking for '
'sending the document %s to Pingen') % self.name)
_(
"Connection Error when asking for "
"sending the document %s to Pingen"
)
% self.name
)
except APIError as e:
raise UserError(
_('Error when asking Pingen to send the document %s: '
'\n%s') % (self.name, e))
_("Error when asking Pingen to send the document %s: " "\n%s")
% (self.name, e)
)
except BaseException as e:
except BaseException:
_logger.exception(
'Unexpected Error when updating the status '
'of pingen.document %s: ' % self.id)
"Unexpected Error when updating the status "
"of pingen.document %s: " % self.id
)
raise UserError(
_('Unexpected Error when updating the status '
'of Document %s') % self.name)
_("Unexpected Error when updating the status " "of Document %s")
% self.name
)
return True
def _update_post_infos(self, pingen):
@@ -271,30 +300,30 @@ class PingenDocument(models.Model):
post_infos = pingen.post_infos(self.pingen_id)
except ConnectionError:
_logger.exception(
'Connection Error when asking for '
'sending Pingen Document %s to %s.' %
(self.id, pingen.url))
"Connection Error when asking for "
"sending Pingen Document %s to %s." % (self.id, pingen.url)
)
raise
except APIError:
_logger.exception(
'API Error when asking for sending Pingen Document %s to %s.' %
(self.id, pingen.url))
"API Error when asking for sending Pingen Document %s to %s."
% (self.id, pingen.url)
)
raise
country = self.env['res.country'].search(
[('code', '=', post_infos['country'])])
send_date = pingen_datetime_to_utc(post_infos['date'])
country = self.env["res.country"].search([("code", "=", post_infos["country"])])
send_date = pingen_datetime_to_utc(post_infos["date"])
vals = {
'post_status': POST_SENDING_STATUS[post_infos['status']],
'parsed_address': post_infos['address'],
'country_id': country.id,
'send_date': fields.Datetime.to_string(send_date),
'pages': post_infos['pages'],
'last_error_message': False,
"post_status": POST_SENDING_STATUS[post_infos["status"]],
"parsed_address": post_infos["address"],
"country_id": country.id,
"send_date": fields.Datetime.to_string(send_date),
"pages": post_infos["pages"],
"last_error_message": False,
}
if pingen.is_posted(post_infos):
vals['state'] = 'sent'
vals["state"] = "sent"
self.write(vals)
_logger.info('Pingen Document %s: status updated' % self.id)
_logger.info("Pingen Document %s: status updated" % self.id)
def _update_post_infos_cron(self):
"""Update the informations from pingen of a
@@ -304,11 +333,10 @@ class PingenDocument(models.Model):
Do not raise errors, only skip the update of the record."""
with odoo.api.Environment.manage():
with odoo.registry(self.env.cr.dbname).cursor() as new_cr:
new_env = odoo.api.Environment(
new_cr, self.env.uid, self.env.context)
new_env = odoo.api.Environment(new_cr, self.env.uid, self.env.context)
# Instead of raising, store the error in the pingen.document
self = self.with_env(new_env)
pushed_docs = self.search([('state', '!=', 'sent')])
pushed_docs = self.search([("state", "!=", "sent")])
for document in pushed_docs:
session = document._get_pingen_session()
try:
@@ -319,7 +347,7 @@ class PingenDocument(models.Model):
# logged by _update_post_infos
pass
except BaseException as e:
_logger.error('Unexcepted error in pingen cron: %', e)
_logger.error("Unexcepted error in pingen cron: %", e)
raise
return True
@@ -332,19 +360,26 @@ class PingenDocument(models.Model):
try:
session = self._get_pingen_session()
self._update_post_infos(pingen=session)
except ConnectionError as e:
except ConnectionError:
raise UserError(
_('Connection Error when updating the status '
'of Document %s from Pingen') % self.name)
_(
"Connection Error when updating the status "
"of Document %s from Pingen"
)
% self.name
)
except APIError as e:
raise UserError(
_('Error when updating the status of Document %s from '
'Pingen: \n%s') % (self.name, e))
except BaseException as e:
_("Error when updating the status of Document %s from " "Pingen: \n%s")
% (self.name, e)
)
except BaseException:
_logger.exception(
'Unexpected Error when updating the status '
'of pingen.document %s: ' % self.id)
"Unexpected Error when updating the status "
"of pingen.document %s: " % self.id
)
raise UserError(
_('Unexpected Error when updating the status '
'of Document %s') % self.name)
_("Unexpected Error when updating the status " "of Document %s")
% self.name
)
return True

View File

@@ -1,18 +1,18 @@
# -*- coding: utf-8 -*-
# Author: Guewen Baconnier
# Copyright 2012-2017 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import models, fields
from odoo import fields, models
from .pingen import Pingen
class ResCompany(models.Model):
_inherit = 'res.company'
_inherit = "res.company"
pingen_token = fields.Char('Pingen Token', size=32)
pingen_staging = fields.Boolean('Pingen Staging')
pingen_token = fields.Char("Pingen Token", size=32)
pingen_staging = fields.Boolean("Pingen Staging")
def _pingen(self):
"""Return a Pingen instance to work on"""

View File

@@ -9,8 +9,14 @@
<xpath expr="//group/group[2]" position="after">
<group string="Pingen info" groups="base.group_no_one">
<field name="send_to_pingen" />
<field name="pingen_send" attrs="{'required': [('send_to_pingen', '=', True)]}"/>
<field name="pingen_speed" attrs="{'required': [('pingen_send', '=', True)]}"/>
<field
name="pingen_send"
attrs="{'required': [('send_to_pingen', '=', True)]}"
/>
<field
name="pingen_speed"
attrs="{'required': [('pingen_send', '=', True)]}"
/>
<field name="pingen_color" />
</group>
</xpath>
@@ -23,5 +29,6 @@
name="Pingen Document"
groups=""
res_model="pingen.document"
src_model="ir.attachment"/>
src_model="ir.attachment"
/>
</odoo>

View File

@@ -24,23 +24,40 @@
<field name="arch" type="xml">
<form string="Pingen Document">
<header>
<field name="state" widget="statusbar"
<field
name="state"
widget="statusbar"
statusbar_visible="pending,pushed,sent"
statusbar_colors='{"error":"red","pingen_error":"red","canceled":"grey","pushed":"blue","sent":"green"}'/>
statusbar_colors='{"error":"red","pingen_error":"red","canceled":"grey","pushed":"blue","sent":"green"}'
/>
</header>
<group colspan="4" col="6">
<field name="name" readonly="True" />
<field name="type" readonly="True" />
<field name="company_id" readonly="True" groups="base.group_multi_company" widget="selection"/>
<field
name="company_id"
readonly="True"
groups="base.group_multi_company"
widget="selection"
/>
</group>
<notebook colspan="4">
<page string="Pingen.com">
<separator string="Options" colspan="4" />
<newline />
<group col="2" colspan="2">
<field name="pingen_send" attrs="{'readonly': [('state', 'in', ['sendcenter', 'sent'])]}"/>
<field name="pingen_speed" attrs="{'readonly': [('state', 'in', ['sendcenter', 'sent'])], 'required': [('pingen_send', '=', True)]}"/>
<field name="pingen_color" attrs="{'readonly': [('state', 'in', ['sendcenter', 'sent'])]}"/>
<field
name="pingen_send"
attrs="{'readonly': [('state', 'in', ['sendcenter', 'sent'])]}"
/>
<field
name="pingen_speed"
attrs="{'readonly': [('state', 'in', ['sendcenter', 'sent'])], 'required': [('pingen_send', '=', True)]}"
/>
<field
name="pingen_color"
attrs="{'readonly': [('state', 'in', ['sendcenter', 'sent'])]}"
/>
</group>
<separator string="Dates" colspan="4" />
@@ -49,7 +66,10 @@
<field name="push_date" />
</group>
<group colspan="4" attrs="{'invisible': [('last_error_message', '=', False)]}">
<group
colspan="4"
attrs="{'invisible': [('last_error_message', '=', False)]}"
>
<separator string="Errors" colspan="4" />
<newline />
<group col="2" colspan="2">
@@ -57,7 +77,10 @@
</group>
</group>
<group colspan="4" attrs="{'invisible': [('state', 'not in', ['sendcenter', 'sent'])]}">
<group
colspan="4"
attrs="{'invisible': [('state', 'not in', ['sendcenter', 'sent'])]}"
>
<separator string="Sendcenter" colspan="4" />
<newline />
<group col="4" colspan="2">
@@ -77,18 +100,34 @@
<separator string="Actions" colspan="4" />
<newline />
<group col="2" colspan="2">
<button name="push_to_pingen" type="object"
<button
name="push_to_pingen"
type="object"
states="pending"
string="Push to pingen.com" icon="fa-upload"/>
<button name="ask_pingen_send" type="object"
string="Push to pingen.com"
icon="fa-upload"
/>
<button
name="ask_pingen_send"
type="object"
states="pushed"
string="Ask pingen.com to send the document" icon="fa-share"/>
<button name="resolve_error" type="object"
string="Ask pingen.com to send the document"
icon="fa-share"
/>
<button
name="resolve_error"
type="object"
states="error,pingen_error"
string="Errors resolved" icon="fa-repeat"/>
<button name="update_post_infos" type="object"
string="Errors resolved"
icon="fa-repeat"
/>
<button
name="update_post_infos"
type="object"
states="sendcenter"
string="Update the letter's informations" icon="fa-refresh"/>
string="Update the letter's informations"
icon="fa-refresh"
/>
</group>
</page>
<page string="Attachment">
@@ -119,27 +158,29 @@
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Pingen Document">
<filter icon="terp-project"
<filter
icon="terp-project"
string="Pending"
domain="[('state','=','pending')]"/>
<filter icon="terp-stage"
string="Pushed"
domain="[('state','=','pushed')]"/>
<filter icon="gtk-print"
domain="[('state','=','pending')]"
/>
<filter icon="terp-stage" string="Pushed" domain="[('state','=','pushed')]" />
<filter
icon="gtk-print"
string="In Sendcenter"
domain="[('state','=','sendcenter')]"/>
<filter icon="kanban-apply"
string="Sent"
domain="[('state','=','sent')]"/>
<filter icon="kanban-stop"
string="Error"
domain="[('state','=','error')]"/>
<filter icon="STOCK_NO"
domain="[('state','=','sendcenter')]"
/>
<filter icon="kanban-apply" string="Sent" domain="[('state','=','sent')]" />
<filter icon="kanban-stop" string="Error" domain="[('state','=','error')]" />
<filter
icon="STOCK_NO"
string="Pingen Error"
domain="[('state','=','pingen_error')]"/>
<filter icon="terp-dialog-close"
domain="[('state','=','pingen_error')]"
/>
<filter
icon="terp-dialog-close"
string="Canceled"
domain="[('state','=','canceled')]"/>
domain="[('state','=','canceled')]"
/>
<separator orientation="vertical" />
<field name="attachment_id" />
</search>

View File

@@ -1,2 +1,3 @@
# generated from manifests external_dependencies
pycups
requests

View File

@@ -0,0 +1 @@
__import__('pkg_resources').declare_namespace(__name__)

View File

@@ -0,0 +1 @@
__import__('pkg_resources').declare_namespace(__name__)

View File

@@ -0,0 +1 @@
../../../../pingen

6
setup/pingen/setup.py Normal file
View File

@@ -0,0 +1,6 @@
import setuptools
setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)