Merge lp:~camptocamp/report-print-send/6.1-pingen into lp:~report-print-send-core-editors/report-print-send/6.1

Proposed by Guewen Baconnier @ Camptocamp
Status: Merged
Merged at revision: 3
Proposed branch: lp:~camptocamp/report-print-send/6.1-pingen
Merge into: lp:~report-print-send-core-editors/report-print-send/6.1
Diff against target: 2325 lines (+2214/-0)
21 files modified
pingen/__init__.py (+26/-0)
pingen/__openerp__.py (+119/-0)
pingen/i18n/fr.po (+390/-0)
pingen/i18n/pingen.pot (+388/-0)
pingen/ir_attachment.py (+124/-0)
pingen/ir_attachment_view.xml (+31/-0)
pingen/pingen.py (+209/-0)
pingen/pingen_data.xml (+32/-0)
pingen/pingen_document.py (+420/-0)
pingen/pingen_document_view.xml (+161/-0)
pingen/res_company.py (+42/-0)
pingen/res_company_view.xml (+20/-0)
pingen/security/ir.model.access.csv (+3/-0)
pingen_document/__init__.py (+21/-0)
pingen_document/__openerp__.py (+41/-0)
pingen_document/i18n/de.po (+32/-0)
pingen_document/i18n/en.po (+32/-0)
pingen_document/i18n/es.po (+32/-0)
pingen_document/i18n/fr.po (+32/-0)
pingen_document/i18n/pingen_document.pot (+32/-0)
pingen_document/pingen_document_view.xml (+27/-0)
To merge this branch: bzr merge lp:~camptocamp/report-print-send/6.1-pingen
Reviewer Review Type Date Requested Status
Stefan Rijnhart (Opener) Approve
Review via email: mp+138657@code.launchpad.net

Description of the change

This is an integration of the pingen.com online service in OpenERP.

It contains 2 addons:
 - a main addon which has no OpenERP dependencies
 - a 'pingen_document' module which is a glue addon automatically installed when the addons 'pingen' and 'document' are installed.

It requires the python module: requests

To post a comment you must log in.
Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Nice addition! Looks good on the whole. Just a couple of remarks:

Would it not be better to encode the dependency on 'requests' in the manifest file as

    'external_dependencies' : {
        'python' : ['requests'],
    }

That would give a friendly error message upon installation in OpenERP if this module is not available.

l.988,991: Are the integer dictionary keys stringified on purpose? Judging by the docstring of push_document you also accept integers there, so I would find it more intuitive to use native integers here. May be a matter of style though.

review: Needs Fixing
19. By Guewen Baconnier @ Camptocamp <email address hidden>

[FIX] express the external dependency on the 'request' lib in the manifest file

Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

Oh yes you are right for the external_dependencies in the manifest file, that's fixed now.

Concerning the keys as str in the fields.selection, keys as int are just not supported (by the web client?). I think that OpenERP assumes that the keys are strings. I gave it a try ;-)

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Thanks for the fix!

About integer keys in the web client, that is odd given that this is used in Accounting -> Configuration -> Financial Accounting -> Account Reports -> Account Reports. The model of this action, account.financial.report contains the 'sign' field that has the following selection:

    [[-1,"Reverse balance sign"],[1,"Preserve balance sign"]]

But I ran a test and the problem is having an zero integer key, evaluating to false obviously somewhere in the client so that it shows no value at all in the dropdown. I'd say let's just leave it at this.

review: Approve
Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Guewen,

There has been a race condition between the branches for this project. I tried to merge your branch but it has no common anchestor with lp:report-print-send. Could you rebase your branch on the head branch?

20. By Guewen Baconnier @ Camptocamp <email address hidden>

[FIX] manifest typos

21. By Guewen Baconnier @ Camptocamp <email address hidden>

[MRG] from 6.1 main branch

Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

Stefan,

I updated my branch from the main branch, it should be merge-ready.

That's a good thing to know for this integer keys in the fields.selection, I did not noticed that it was due to the 0, but it makes sense.

Thanks for your review!

Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

Thanks for the merge

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== renamed file 'README' => 'README'
=== renamed directory 'base_report_to_printer' => 'base_report_to_printer'
=== added directory 'pingen'
=== added file 'pingen/__init__.py'
--- pingen/__init__.py 1970-01-01 00:00:00 +0000
+++ pingen/__init__.py 2012-12-07 13:35:25 +0000
@@ -0,0 +1,26 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Author: Guewen Baconnier
5# Copyright 2012 Camptocamp SA
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22import ir_attachment
23import pingen
24import pingen_document
25import res_company
26
027
=== added file 'pingen/__openerp__.py'
--- pingen/__openerp__.py 1970-01-01 00:00:00 +0000
+++ pingen/__openerp__.py 2012-12-07 13:35:25 +0000
@@ -0,0 +1,119 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Author: Guewen Baconnier
5# Copyright 2012 Camptocamp SA
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22{
23 'name': 'pingen.com integration',
24 'version': '1.0',
25 'author': 'Camptocamp',
26 'maintainer': 'Camptocamp',
27 'license': 'AGPL-3',
28 'category': 'Reporting',
29 'complexity': 'easy',
30 'depends': [],
31 'external_dependencies': {
32 'python': ['requests'],
33 },
34 'description': """
35Integration with pingen.com
36===========================
37
38What is pingen.com
39------------------
40
41Pingen.com is a paid online service.
42It sends uploaded documents by letter post.
43
44Scope of the integration
45------------------------
46
47One can decide, per document / attachment, if it should be pushed
48to pingen.com. The documents are pushed asynchronously.
49
50A second cron updates the informations of the documents from pingen.com, so we
51know which of them have been sent.
52
53Configuration
54-------------
55
56The authentication token is configured on the company's view. You can also
57tick a checkbox if the staging environment (https://stage-api.pingen.com)
58should be used.
59
60The setup of the 2 crons can be changed as well:
61
62 * Run Pingen Document Push
63 * Run Pingen Document Update
64
65Usage
66-----
67
68On the attachment view, a new pingen.com tab has been added.
69You can tick a box to push the document to pingen.com.
70
71There is 3 additional options:
72
73 * Send: the document will not be only uploaded, but will be also be sent
74 * Speed: priority or economy
75 * Type of print: color or black and white
76
77Once the configuration is done and the attachment saved, a Pingen Document
78is created. You can directly access to the latter on the Link on the right on
79the attachment view.
80
81You can find them in `Settings > Customization > Low Level Objets > Pingen
82Documents` or in the more convenient `Documents` menu if you have installed the
83`document` module.
84
85Errors
86------
87
88Sometimes, pingen.com will refuse to send a document because it does not meet
89its requirements. In such case, the document's state becomes "Pingen Error" and
90you will need to manually handle the case, either from the pingen.com backend,
91or by changing the document on OpenERP and resolving the error on the Pingen
92Document.
93
94When a connection error occurs, the action will be retried on the next scheduler
95run.
96
97Dependencies
98------------
99
100 * Require the Python library `requests <http://docs.python-requests.org/>`_
101 * The PDF files sent to pingen.com have to respect some `formatting rules
102 <https://stage-app.pingen.com/resources/pingen_requirements_v1_en.pdf>`_.
103 * The address must be in a format accepted by pingen.com: the last line
104 is the country in English or German.
105
106""",
107 'website': 'http://www.camptocamp.com',
108 'data': [
109 'ir_attachment_view.xml',
110 'pingen_document_view.xml',
111 'pingen_data.xml',
112 'res_company_view.xml',
113 'security/ir.model.access.csv',
114 ],
115 'tests': [],
116 'installable': True,
117 'auto_install': False,
118 'application': True,
119}
0120
=== added directory 'pingen/i18n'
=== added file 'pingen/i18n/fr.po'
--- pingen/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ pingen/i18n/fr.po 2012-12-07 13:35:25 +0000
@@ -0,0 +1,390 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * pingen
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 6.1\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2012-11-26 10:54+0000\n"
10"PO-Revision-Date: 2012-11-26 10:54+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: pingen
19#: code:addons/pingen/pingen_document.py:177
20#: code:addons/pingen/pingen_document.py:307
21#: code:addons/pingen/pingen_document.py:414
22#, python-format
23msgid "Unexcepted Error when updating the status of Document %s"
24msgstr "Erreur inattendue lors de la mise à jour du document %s"
25
26#. module: pingen
27#: field:pingen.document,push_date:0
28msgid "Push Date"
29msgstr "Date d'ajout"
30
31#. module: pingen
32#: view:pingen.document:0
33msgid "Errors"
34msgstr "Erreurs"
35
36#. module: pingen
37#: field:pingen.document,pingen_id:0
38msgid "Pingen ID"
39msgstr "ID Pingen"
40
41#. module: pingen
42#: constraint:res.company:0
43msgid "Error! You can not create recursive companies."
44msgstr "Error! You can not create recursive companies."
45
46#. module: pingen
47#: field:ir.attachment,pingen_send:0
48msgid "Send"
49msgstr "Envoyer"
50
51#. module: pingen
52#: code:addons/pingen/pingen_document.py:399
53#, python-format
54msgid "Connection Error when updating the status of Document %s from Pingen"
55msgstr "Erreur de connexion lors de la mise à jour de l'état du document %s depuis Pingen"
56
57#. module: pingen
58#: field:pingen.document,state:0
59msgid "State"
60msgstr "État"
61
62#. module: pingen
63#: field:ir.attachment,pingen_color:0
64msgid "Type of print"
65msgstr "Type d'impression"
66
67#. module: pingen
68#: view:pingen.document:0
69msgid "Attachment"
70msgstr "Attachement"
71
72#. module: pingen
73#: code:addons/pingen/pingen_document.py:405
74#, python-format
75msgid "Error when updating the status of Document %s from Pingen: \n"
76"%s"
77msgstr "Erreur lors de la mise à jour de l'état du document %s depuis Pingen: \n"
78"%s"
79
80#. module: pingen
81#: model:ir.actions.act_window,name:pingen.act_attachment_to_pingen_document
82#: field:ir.attachment,pingen_document_ids:0
83#: view:pingen.document:0
84msgid "Pingen Document"
85msgstr "Document Pingen"
86
87#. module: pingen
88#: field:pingen.document,attachment_id:0
89msgid "Document"
90msgstr "Document"
91
92#. module: pingen
93#: help:ir.attachment,pingen_send:0
94msgid "Defines if a document is merely uploaded or also sent"
95msgstr "Définit si un fichier est juste ajouté ou également envoyé"
96
97#. module: pingen
98#: view:pingen.document:0
99#: selection:pingen.document,state:0
100msgid "Pending"
101msgstr "En attente"
102
103#. module: pingen
104#: selection:ir.attachment,pingen_speed:0
105msgid "Economy"
106msgstr "Économique"
107
108#. module: pingen
109#: view:pingen.document:0
110msgid "Errors resolved"
111msgstr "Erreurs résolues"
112
113#. module: pingen
114#: sql_constraint:pingen.document:0
115msgid "Only one Pingen document is allowed per attachment."
116msgstr "Uniquement un document Pingen est autorisé par attachement."
117
118#. module: pingen
119#: code:addons/pingen/pingen_document.py:168
120#: code:addons/pingen/pingen_document.py:298
121#, python-format
122msgid "Error when asking Pingen to send the document %s: \n"
123"%s"
124msgstr "Erreurs lors de l'envoi du document par Pingen %s: \n"
125"%s"
126
127#. module: pingen
128#: view:pingen.document:0
129msgid "Update the letter's informations"
130msgstr "Mettre à jour les informations de la lettre"
131
132#. module: pingen
133#: view:pingen.document:0
134#: selection:pingen.document,state:0
135msgid "Canceled"
136msgstr "Annulé"
137
138#. module: pingen
139#: selection:pingen.document,state:0
140msgid "Connection Error"
141msgstr "Erreur de connexion"
142
143#. module: pingen
144#: model:ir.actions.act_window,name:pingen.action_pingen_document
145#: model:ir.ui.menu,name:pingen.menu_pingen_document
146msgid "Pingen Documents"
147msgstr "Documents Pingen"
148
149#. module: pingen
150#: field:pingen.document,last_error_message:0
151msgid "Error Message"
152msgstr "Message d'erreur"
153
154#. module: pingen
155#: selection:ir.attachment,pingen_color:0
156msgid "B/W"
157msgstr "N/B"
158
159#. module: pingen
160#: field:res.company,pingen_staging:0
161msgid "Pingen Staging"
162msgstr "Staging Pingen"
163
164#. module: pingen
165#: model:ir.model,name:pingen.model_ir_attachment
166msgid "ir.attachment"
167msgstr "ir.attachment"
168
169#. module: pingen
170#: view:pingen.document:0
171#: selection:pingen.document,state:0
172msgid "In Sendcenter"
173msgstr "Dans le Sendcenter"
174
175#. module: pingen
176#: view:pingen.document:0
177#: selection:pingen.document,state:0
178msgid "Sent"
179msgstr "Envoyé"
180
181#. module: pingen
182#: field:pingen.document,post_status:0
183msgid "Post Status"
184msgstr "État de la lettre"
185
186#. module: pingen
187#: code:addons/pingen/pingen_document.py:163
188#: code:addons/pingen/pingen_document.py:292
189#, python-format
190msgid "Connection Error when asking for sending the document %s to Pingen"
191msgstr "Erreur de connexion avec Pingen lors de l'envoi de %s"
192
193#. module: pingen
194#: view:res.company:0
195msgid "Configuration"
196msgstr "Configuration"
197
198#. module: pingen
199#: view:pingen.document:0
200msgid "Data"
201msgstr "Données"
202
203#. module: pingen
204#: view:pingen.document:0
205msgid "Options"
206msgstr "Options"
207
208#. module: pingen
209#: field:res.company,pingen_token:0
210msgid "Pingen Token"
211msgstr "Token Pingen"
212
213#. module: pingen
214#: field:ir.attachment,send_to_pingen:0
215msgid "Send to Pingen.com"
216msgstr "Ajouter sur Pingen.com"
217
218#. module: pingen
219#: model:ir.model,name:pingen.model_pingen_document
220msgid "pingen.document"
221msgstr "pingen.document"
222
223#. module: pingen
224#: view:pingen.document:0
225msgid "Dates"
226msgstr "Dates"
227
228#. module: pingen
229#: view:pingen.document:0
230msgid "Sendcenter"
231msgstr "Sendcenter"
232
233#. module: pingen
234#: sql_constraint:res.company:0
235msgid "The company name must be unique !"
236msgstr "The company name must be unique !"
237
238#. module: pingen
239#: field:pingen.document,parsed_address:0
240msgid "Parsed Address"
241msgstr "Adresse analysée"
242
243#. module: pingen
244#: view:ir.attachment:0
245#: view:pingen.document:0
246#: view:res.company:0
247msgid "Pingen.com"
248msgstr "Pingen.com"
249
250#. module: pingen
251#: field:pingen.document,country_id:0
252msgid "Country"
253msgstr "Pays"
254
255#. module: pingen
256#: view:ir.attachment:0
257msgid "Notes"
258msgstr "Notes"
259
260#. module: pingen
261#: view:pingen.document:0
262#: selection:pingen.document,state:0
263msgid "Pushed"
264msgstr "Ajouté"
265
266#. module: pingen
267#: model:ir.model,name:pingen.model_res_company
268msgid "Companies"
269msgstr "Compagnies"
270
271#. module: pingen
272#: code:addons/pingen/ir_attachment.py:90
273#, python-format
274msgid "The attachment %s is already pushed to pingen.com."
275msgstr "L'attachement %s est déjà envoyé sur pingen.com."
276
277#. module: pingen
278#: view:pingen.document:0
279msgid "Attached To"
280msgstr "Attaché à "
281
282#. module: pingen
283#: code:addons/pingen/pingen_document.py:136
284#, python-format
285msgid "The document does not meet the Pingen requirements."
286msgstr "Le document ne remplit pas les exigences de Pingen"
287
288#. module: pingen
289#: code:addons/pingen/ir_attachment.py:89
290#: code:addons/pingen/pingen_document.py:176
291#: code:addons/pingen/pingen_document.py:306
292#: code:addons/pingen/pingen_document.py:413
293#: view:pingen.document:0
294#, python-format
295msgid "Error"
296msgstr "Erreur"
297
298#. module: pingen
299#: code:addons/pingen/pingen_document.py:162
300#: code:addons/pingen/pingen_document.py:291
301#: code:addons/pingen/pingen_document.py:398
302#, python-format
303msgid "Pingen Connection Error"
304msgstr "Erreur de connexion avec Pingen"
305
306#. module: pingen
307#: field:pingen.document,send_date:0
308msgid "Date of sending"
309msgstr "Date d'envoi"
310
311#. module: pingen
312#: selection:ir.attachment,pingen_speed:0
313msgid "Priority"
314msgstr "Priorité"
315
316#. module: pingen
317#: selection:ir.attachment,pingen_color:0
318msgid "Color"
319msgstr "Color"
320
321#. module: pingen
322#: model:ir.model,name:pingen.model_pingen_task
323msgid "pingen.task"
324msgstr "pingen.task"
325
326#. module: pingen
327#: help:pingen.document,pingen_id:0
328msgid "ID of the document in the Pingen Documents"
329msgstr "ID du document sur Pingen"
330
331#. module: pingen
332#: code:addons/pingen/pingen_document.py:167
333#: code:addons/pingen/pingen_document.py:297
334#: code:addons/pingen/pingen_document.py:404
335#: view:pingen.document:0
336#: selection:pingen.document,state:0
337#, python-format
338msgid "Pingen Error"
339msgstr "Erreur Pingen"
340
341#. module: pingen
342#: view:pingen.document:0
343msgid "Actions"
344msgstr "Actions"
345
346#. module: pingen
347#: field:pingen.document,pages:0
348msgid "Pages"
349msgstr "Pages"
350
351#. module: pingen
352#: field:pingen.document,currency_id:0
353msgid "Currency"
354msgstr "Devise"
355
356#. module: pingen
357#: field:pingen.document,cost:0
358msgid "Cost"
359msgstr "Coût"
360
361#. module: pingen
362#: view:pingen.document:0
363msgid "Push to pingen.com"
364msgstr "Ajouter sur pingen.com"
365
366#. module: pingen
367#: view:pingen.document:0
368msgid "Ask pingen.com to send the document"
369msgstr "Demander à pingen.com d'envoyer le document"
370
371#. module: pingen
372#: help:pingen.document,post_id:0
373msgid "ID of the document in the Pingen Sendcenter"
374msgstr "ID du document dans le Sendcenter Pingen"
375
376#. module: pingen
377#: field:ir.attachment,pingen_speed:0
378msgid "Speed"
379msgstr "Vitesse"
380
381#. module: pingen
382#: field:pingen.document,post_id:0
383msgid "Pingen Post ID"
384msgstr "ID de lettre Pingen"
385
386#. module: pingen
387#: help:ir.attachment,pingen_speed:0
388msgid "Defines the sending speed if the document is automatically sent"
389msgstr "Définit la vitesse d'envoi si le document est automatiquement envoyé"
390
0391
=== added file 'pingen/i18n/pingen.pot'
--- pingen/i18n/pingen.pot 1970-01-01 00:00:00 +0000
+++ pingen/i18n/pingen.pot 2012-12-07 13:35:25 +0000
@@ -0,0 +1,388 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * pingen
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 6.1\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2012-11-26 10:55+0000\n"
10"PO-Revision-Date: 2012-11-26 10:55+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: pingen
19#: code:addons/pingen/pingen_document.py:177
20#: code:addons/pingen/pingen_document.py:307
21#: code:addons/pingen/pingen_document.py:414
22#, python-format
23msgid "Unexcepted Error when updating the status of Document %s"
24msgstr ""
25
26#. module: pingen
27#: field:pingen.document,push_date:0
28msgid "Push Date"
29msgstr ""
30
31#. module: pingen
32#: view:pingen.document:0
33msgid "Errors"
34msgstr ""
35
36#. module: pingen
37#: field:pingen.document,pingen_id:0
38msgid "Pingen ID"
39msgstr ""
40
41#. module: pingen
42#: constraint:res.company:0
43msgid "Error! You can not create recursive companies."
44msgstr ""
45
46#. module: pingen
47#: field:ir.attachment,pingen_send:0
48msgid "Send"
49msgstr ""
50
51#. module: pingen
52#: code:addons/pingen/pingen_document.py:399
53#, python-format
54msgid "Connection Error when updating the status of Document %s from Pingen"
55msgstr ""
56
57#. module: pingen
58#: field:pingen.document,state:0
59msgid "State"
60msgstr ""
61
62#. module: pingen
63#: field:ir.attachment,pingen_color:0
64msgid "Type of print"
65msgstr ""
66
67#. module: pingen
68#: view:pingen.document:0
69msgid "Attachment"
70msgstr ""
71
72#. module: pingen
73#: code:addons/pingen/pingen_document.py:405
74#, python-format
75msgid "Error when updating the status of Document %s from Pingen: \n"
76"%s"
77msgstr ""
78
79#. module: pingen
80#: model:ir.actions.act_window,name:pingen.act_attachment_to_pingen_document
81#: field:ir.attachment,pingen_document_ids:0
82#: view:pingen.document:0
83msgid "Pingen Document"
84msgstr ""
85
86#. module: pingen
87#: field:pingen.document,attachment_id:0
88msgid "Document"
89msgstr ""
90
91#. module: pingen
92#: help:ir.attachment,pingen_send:0
93msgid "Defines if a document is merely uploaded or also sent"
94msgstr ""
95
96#. module: pingen
97#: view:pingen.document:0
98#: selection:pingen.document,state:0
99msgid "Pending"
100msgstr ""
101
102#. module: pingen
103#: selection:ir.attachment,pingen_speed:0
104msgid "Economy"
105msgstr ""
106
107#. module: pingen
108#: view:pingen.document:0
109msgid "Errors resolved"
110msgstr ""
111
112#. module: pingen
113#: sql_constraint:pingen.document:0
114msgid "Only one Pingen document is allowed per attachment."
115msgstr ""
116
117#. module: pingen
118#: code:addons/pingen/pingen_document.py:168
119#: code:addons/pingen/pingen_document.py:298
120#, python-format
121msgid "Error when asking Pingen to send the document %s: \n"
122"%s"
123msgstr ""
124
125#. module: pingen
126#: view:pingen.document:0
127msgid "Update the letter's informations"
128msgstr ""
129
130#. module: pingen
131#: view:pingen.document:0
132#: selection:pingen.document,state:0
133msgid "Canceled"
134msgstr ""
135
136#. module: pingen
137#: selection:pingen.document,state:0
138msgid "Connection Error"
139msgstr ""
140
141#. module: pingen
142#: model:ir.actions.act_window,name:pingen.action_pingen_document
143#: model:ir.ui.menu,name:pingen.menu_pingen_document
144msgid "Pingen Documents"
145msgstr ""
146
147#. module: pingen
148#: field:pingen.document,last_error_message:0
149msgid "Error Message"
150msgstr ""
151
152#. module: pingen
153#: selection:ir.attachment,pingen_color:0
154msgid "B/W"
155msgstr ""
156
157#. module: pingen
158#: field:res.company,pingen_staging:0
159msgid "Pingen Staging"
160msgstr ""
161
162#. module: pingen
163#: model:ir.model,name:pingen.model_ir_attachment
164msgid "ir.attachment"
165msgstr ""
166
167#. module: pingen
168#: view:pingen.document:0
169#: selection:pingen.document,state:0
170msgid "In Sendcenter"
171msgstr ""
172
173#. module: pingen
174#: view:pingen.document:0
175#: selection:pingen.document,state:0
176msgid "Sent"
177msgstr ""
178
179#. module: pingen
180#: field:pingen.document,post_status:0
181msgid "Post Status"
182msgstr ""
183
184#. module: pingen
185#: code:addons/pingen/pingen_document.py:163
186#: code:addons/pingen/pingen_document.py:292
187#, python-format
188msgid "Connection Error when asking for sending the document %s to Pingen"
189msgstr ""
190
191#. module: pingen
192#: view:res.company:0
193msgid "Configuration"
194msgstr ""
195
196#. module: pingen
197#: view:pingen.document:0
198msgid "Data"
199msgstr ""
200
201#. module: pingen
202#: view:pingen.document:0
203msgid "Options"
204msgstr ""
205
206#. module: pingen
207#: field:res.company,pingen_token:0
208msgid "Pingen Token"
209msgstr ""
210
211#. module: pingen
212#: field:ir.attachment,send_to_pingen:0
213msgid "Send to Pingen.com"
214msgstr ""
215
216#. module: pingen
217#: model:ir.model,name:pingen.model_pingen_document
218msgid "pingen.document"
219msgstr ""
220
221#. module: pingen
222#: view:pingen.document:0
223msgid "Dates"
224msgstr ""
225
226#. module: pingen
227#: view:pingen.document:0
228msgid "Sendcenter"
229msgstr ""
230
231#. module: pingen
232#: sql_constraint:res.company:0
233msgid "The company name must be unique !"
234msgstr ""
235
236#. module: pingen
237#: field:pingen.document,parsed_address:0
238msgid "Parsed Address"
239msgstr ""
240
241#. module: pingen
242#: view:ir.attachment:0
243#: view:pingen.document:0
244#: view:res.company:0
245msgid "Pingen.com"
246msgstr ""
247
248#. module: pingen
249#: field:pingen.document,country_id:0
250msgid "Country"
251msgstr ""
252
253#. module: pingen
254#: view:ir.attachment:0
255msgid "Notes"
256msgstr ""
257
258#. module: pingen
259#: view:pingen.document:0
260#: selection:pingen.document,state:0
261msgid "Pushed"
262msgstr ""
263
264#. module: pingen
265#: model:ir.model,name:pingen.model_res_company
266msgid "Companies"
267msgstr ""
268
269#. module: pingen
270#: code:addons/pingen/ir_attachment.py:90
271#, python-format
272msgid "The attachment %s is already pushed to pingen.com."
273msgstr ""
274
275#. module: pingen
276#: view:pingen.document:0
277msgid "Attached To"
278msgstr ""
279
280#. module: pingen
281#: code:addons/pingen/pingen_document.py:136
282#, python-format
283msgid "The document does not meet the Pingen requirements."
284msgstr ""
285
286#. module: pingen
287#: code:addons/pingen/ir_attachment.py:89
288#: code:addons/pingen/pingen_document.py:176
289#: code:addons/pingen/pingen_document.py:306
290#: code:addons/pingen/pingen_document.py:413
291#: view:pingen.document:0
292#, python-format
293msgid "Error"
294msgstr ""
295
296#. module: pingen
297#: code:addons/pingen/pingen_document.py:162
298#: code:addons/pingen/pingen_document.py:291
299#: code:addons/pingen/pingen_document.py:398
300#, python-format
301msgid "Pingen Connection Error"
302msgstr ""
303
304#. module: pingen
305#: field:pingen.document,send_date:0
306msgid "Date of sending"
307msgstr ""
308
309#. module: pingen
310#: selection:ir.attachment,pingen_speed:0
311msgid "Priority"
312msgstr ""
313
314#. module: pingen
315#: selection:ir.attachment,pingen_color:0
316msgid "Color"
317msgstr ""
318
319#. module: pingen
320#: model:ir.model,name:pingen.model_pingen_task
321msgid "pingen.task"
322msgstr ""
323
324#. module: pingen
325#: help:pingen.document,pingen_id:0
326msgid "ID of the document in the Pingen Documents"
327msgstr ""
328
329#. module: pingen
330#: code:addons/pingen/pingen_document.py:167
331#: code:addons/pingen/pingen_document.py:297
332#: code:addons/pingen/pingen_document.py:404
333#: view:pingen.document:0
334#: selection:pingen.document,state:0
335#, python-format
336msgid "Pingen Error"
337msgstr ""
338
339#. module: pingen
340#: view:pingen.document:0
341msgid "Actions"
342msgstr ""
343
344#. module: pingen
345#: field:pingen.document,pages:0
346msgid "Pages"
347msgstr ""
348
349#. module: pingen
350#: field:pingen.document,currency_id:0
351msgid "Currency"
352msgstr ""
353
354#. module: pingen
355#: field:pingen.document,cost:0
356msgid "Cost"
357msgstr ""
358
359#. module: pingen
360#: view:pingen.document:0
361msgid "Push to pingen.com"
362msgstr ""
363
364#. module: pingen
365#: view:pingen.document:0
366msgid "Ask pingen.com to send the document"
367msgstr ""
368
369#. module: pingen
370#: help:pingen.document,post_id:0
371msgid "ID of the document in the Pingen Sendcenter"
372msgstr ""
373
374#. module: pingen
375#: field:ir.attachment,pingen_speed:0
376msgid "Speed"
377msgstr ""
378
379#. module: pingen
380#: field:pingen.document,post_id:0
381msgid "Pingen Post ID"
382msgstr ""
383
384#. module: pingen
385#: help:ir.attachment,pingen_speed:0
386msgid "Defines the sending speed if the document is automatically sent"
387msgstr ""
388
0389
=== added file 'pingen/ir_attachment.py'
--- pingen/ir_attachment.py 1970-01-01 00:00:00 +0000
+++ pingen/ir_attachment.py 2012-12-07 13:35:25 +0000
@@ -0,0 +1,124 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Author: Guewen Baconnier
5# Copyright 2012 Camptocamp SA
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22import requests
23import base64
24
25from openerp.osv import osv, orm, fields
26from openerp.tools.translate import _
27
28
29class ir_attachment(orm.Model):
30
31 _inherit = 'ir.attachment'
32
33 _columns = {
34 'send_to_pingen': fields.boolean('Send to Pingen.com'),
35 'pingen_document_ids': fields.one2many(
36 'pingen.document', 'attachment_id',
37 string='Pingen Document', readonly=True),
38 'pingen_send': fields.boolean(
39 'Send',
40 help="Defines if a document is merely uploaded or also sent"),
41 'pingen_speed': fields.selection(
42 [('1', 'Priority'), ('2', 'Economy')],
43 'Speed',
44 help="Defines the sending speed if the document is automatically sent"),
45 'pingen_color': fields.selection( [('0', 'B/W'), ('1', 'Color')], 'Type of print'),
46 }
47
48 _defaults = {
49 'pingen_send': True,
50 'pingen_color': '0',
51 'pingen_speed': '2',
52 }
53
54 def _prepare_pingen_document_vals(self, cr, uid, attachment, context=None):
55 return {'attachment_id': attachment.id,
56 'config': 'created from attachment'}
57
58 def _handle_pingen_document(self, cr, uid, attachment_id, context=None):
59 """ Reponsible of the related ``pingen.document`` when the ``send_to_pingen``
60 field is modified.
61
62 Only one pingen document can be created per attachment.
63
64 When ``send_to_pingen`` is activated:
65 * Create a ``pingen.document`` if it does not already exist
66 * Put the related ``pingen.document`` to ``pending`` if it already exist
67 When it is deactivated:
68 * Do nothing if no related ``pingen.document`` exists
69 * Or cancel it
70 * If it has already been pushed to pingen.com, raises
71 an `osv.except_osv` exception
72 """
73 pingen_document_obj = self.pool.get('pingen.document')
74 attachment = self.browse(cr, uid, attachment_id, context=context)
75 document = attachment.pingen_document_ids[0] if attachment.pingen_document_ids else None
76 if attachment.send_to_pingen:
77 if document:
78 document.write({'state': 'pending'}, context=context)
79 else:
80 pingen_document_obj.create(
81 cr, uid,
82 self._prepare_pingen_document_vals(
83 cr, uid, attachment, context=context),
84 context=context)
85 else:
86 if document:
87 if document.state == 'pushed':
88 raise osv.except_osv(
89 _('Error'),
90 _('The attachment %s is already pushed to pingen.com.') % \
91 attachment.name)
92 document.write({'state': 'canceled'}, context=context)
93 return
94
95 def create(self, cr, uid, vals, context=None):
96 attachment_id = super(ir_attachment, self).create(cr, uid, vals, context=context)
97 if 'send_to_pingen' in vals:
98 self._handle_pingen_document(cr, uid, attachment_id, context=context)
99 return attachment_id
100
101 def write(self, cr, uid, ids, vals, context=None):
102 res = super(ir_attachment, self).write(cr, uid, ids, vals, context=context)
103 if 'send_to_pingen' in vals:
104 for attachment_id in ids:
105 self._handle_pingen_document(cr, uid, attachment_id, context=context)
106 return res
107
108 def _decoded_content(self, cr, uid, attachment, context=None):
109 """ Returns the decoded content of an attachment (stored or url)
110
111 Returns None if the type is 'url' and the url is not reachable.
112 """
113 decoded_document = None
114 if attachment.type == 'binary':
115 decoded_document = base64.decodestring(attachment.datas)
116 elif attachment.type == 'url':
117 response = requests.get(attachment.url)
118 if response.ok:
119 decoded_document = requests.content
120 else:
121 raise Exception(
122 'The type of attachment %s is not handled' % attachment.type)
123 return decoded_document
124
0125
=== added file 'pingen/ir_attachment_view.xml'
--- pingen/ir_attachment_view.xml 1970-01-01 00:00:00 +0000
+++ pingen/ir_attachment_view.xml 2012-12-07 13:35:25 +0000
@@ -0,0 +1,31 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3 <data noupdate="0">
4
5 <record id="view_attachment_form" model="ir.ui.view">
6 <field name="name">ir.attachment.pingen.view</field>
7 <field name="model">ir.attachment</field>
8 <field name="type">form</field>
9 <field name="inherit_id" ref="base.view_attachment_form"/>
10 <field name="arch" type="xml">
11 <page string="Notes" position="before">
12 <page string="Pingen.com">
13 <field name="send_to_pingen"/>
14 <field name="pingen_send" attrs="{'required': [('send_to_pingen', '=', True)]}"/>
15 <field name="pingen_speed" attrs="{'required': [('pingen_send', '=', True)]}"/>
16 <field name="pingen_color" />
17 </page>
18 </page>
19 </field>
20 </record>
21
22 <act_window
23 context="{'search_default_attachment_id': [active_id], 'default_attachment_id': active_id}"
24 id="act_attachment_to_pingen_document"
25 name="Pingen Document"
26 groups=""
27 res_model="pingen.document"
28 src_model="ir.attachment"/>
29
30 </data>
31</openerp>
032
=== added file 'pingen/pingen.py'
--- pingen/pingen.py 1970-01-01 00:00:00 +0000
+++ pingen/pingen.py 2012-12-07 13:35:25 +0000
@@ -0,0 +1,209 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Author: Guewen Baconnier
5# Copyright 2012 Camptocamp SA
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22import requests
23import logging
24import urlparse
25import json
26
27from requests.packages.urllib3.filepost import encode_multipart_formdata
28
29_logger = logging.getLogger(__name__)
30
31POST_SENDING_STATUS = {
32 100: 'Ready/Pending',
33 101: 'Processing',
34 102: 'Waiting for confirmation',
35 200: 'Sent',
36 300: 'Some error occured and object wasn\'t sent',
37 400: 'Sending cancelled',
38}
39
40
41class PingenException(RuntimeError):
42 """There was an ambiguous exception that occurred while handling your
43 request."""
44
45
46class ConnectionError(PingenException):
47 """An Error occured with the pingen API"""
48
49
50class APIError(PingenException):
51 """An Error occured with the pingen API"""
52
53
54class Pingen(object):
55 """ Interface to the pingen.com API """
56
57 def __init__(self, token, staging=True):
58 self._token = token
59 self.staging = staging
60 self._session = None
61 super(Pingen, self).__init__()
62
63 @property
64 def url(self):
65 if self.staging:
66 return 'https://stage-api.pingen.com'
67 return 'https://api.pingen.com'
68
69 @property
70 def session(self):
71 """ Build a requests session """
72 if self._session is not None:
73 return self._session
74 self._session = requests.Session(
75 params={'token': self._token},
76 # with safe_mode, requests catch errors and
77 # returns a blank response with an error
78 config={'safe_mode': True},
79 # verify = False required for staging environment
80 # because the SSL certificate is wrong
81 verify=not self.staging)
82 return self._session
83
84 def __enter__(self):
85 return self
86
87 def __exit__(self, *args):
88 self.close()
89
90 def close(self):
91 """Dispose of any internal state. """
92 if self._session:
93 self._session.close()
94
95 def _send(self, method, endpoint, **kwargs):
96 """ Send a request to the pingen API using requests
97
98 Add necessary boilerplate to call pingen.com API
99 (authentication, configuration, ...)
100
101 :param boundmethod method: requests method to call
102 :param str endpoint: endpoint to call
103 :param kwargs: additional arguments forwarded to the requests method
104 """
105 complete_url = urlparse.urljoin(self.url, endpoint)
106
107 response = method(complete_url, **kwargs)
108
109 if not response.ok:
110 raise ConnectionError(
111 "%s: %s" % (response.json['errorcode'],
112 response.json['errormessage']))
113
114 if response.json['error']:
115 raise APIError(
116 "%s: %s" % (response.json['errorcode'], response.json['errormessage']))
117
118 return response
119
120 def push_document(self, filename, filestream, send=None, speed=None, color=None):
121 """ Upload a document to pingen.com and eventually ask to send it
122
123 :param str filename: name of the file to push
124 :param StringIO filestream: file to push
125 :param boolean send: if True, the document will be sent by pingen.com
126 :param int/str speed: sending speed of the document if it is send
127 1 = Priority, 2 = Economy
128 :param int/str color: type of print, 0 = B/W, 1 = Color
129 :return: tuple with 3 items:
130 1. document_id on pingen.com
131 2. post_id on pingen.com if it has been sent or None
132 3. dict of the created item on pingen (details)
133 """
134 data = {
135 'send': send,
136 'speed': speed,
137 'color': color,
138 }
139
140 # we cannot use the `files` param alongside
141 # with the `datas`param when data is a
142 # JSON-encoded data. We have to construct
143 # the entire body and send it to `data`
144 # https://github.com/kennethreitz/requests/issues/950
145 formdata = {
146 'file': (filename, filestream.read()),
147 'data': json.dumps(data),
148 }
149
150 multipart, content_type = encode_multipart_formdata(formdata)
151
152 response = self._send(
153 self.session.post,
154 'document/upload',
155 headers={'Content-Type': content_type},
156 data=multipart)
157
158 rjson = response.json
159
160 document_id = rjson['id']
161 if rjson.get('send'):
162 # confusing name but send_id is the posted id
163 posted_id = rjson['send'][0]['send_id']
164 item = rjson['item']
165
166 return document_id, posted_id, item
167
168 def send_document(self, document_id, speed=None, color=None):
169 """ Send a uploaded document to pingen.com
170
171 :param int document_id: id of the document to send
172 :param int/str speed: sending speed of the document if it is send
173 1 = Priority, 2 = Economy
174 :param int/str color: type of print, 0 = B/W, 1 = Color
175 :return: id of the post on pingen.com
176 """
177 data = {
178 'speed': speed,
179 'color': color,
180 }
181 response = self._send(
182 self.session.post,
183 'document/send',
184 params={'id': document_id},
185 data={'data': json.dumps(data)})
186
187 return response.json['id']
188
189 def post_infos(self, post_id):
190 """ Return the information of a post
191
192 :param int post_id: id of the document to send
193 :return: dict of infos of the post
194 """
195 response = self._send(
196 self.session.get,
197 'post/get',
198 params={'id': post_id})
199
200 return response.json['item']
201
202 @staticmethod
203 def is_posted(post_infos):
204 """ return True if the post has been sent
205
206 :param dict post_infos: post infos returned by `post_infos`
207 """
208 return post_infos['status'] == 200
209
0210
=== added file 'pingen/pingen_data.xml'
--- pingen/pingen_data.xml 1970-01-01 00:00:00 +0000
+++ pingen/pingen_data.xml 2012-12-07 13:35:25 +0000
@@ -0,0 +1,32 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3 <data noupdate="1">
4
5 <record forcecreate="True" id="ir_cron_push_pingen" model="ir.cron">
6 <field name="name">Run Pingen Document Push</field>
7 <field eval="True" name="active"/>
8 <field name="user_id" ref="base.user_root"/>
9 <field name="interval_number">1</field>
10 <field name="interval_type">hours</field>
11 <field name="numbercall">-1</field>
12 <field eval="False" name="doall"/>
13 <field name="model">pingen.document</field>
14 <field name="function">_push_and_send_to_pingen_cron</field>
15 <field name="args">(None,)</field>
16 </record>
17
18 <record forcecreate="True" id="ir_cron_update_pingen" model="ir.cron">
19 <field name="name">Run Pingen Document Update</field>
20 <field eval="True" name="active"/>
21 <field name="user_id" ref="base.user_root"/>
22 <field name="interval_number">1</field>
23 <field name="interval_type">days</field>
24 <field name="numbercall">-1</field>
25 <field eval="False" name="doall"/>
26 <field name="model">pingen.document</field>
27 <field name="function">_update_post_infos_cron</field>
28 <field name="args">(None,)</field>
29 </record>
30
31 </data>
32</openerp>
033
=== added file 'pingen/pingen_document.py'
--- pingen/pingen_document.py 1970-01-01 00:00:00 +0000
+++ pingen/pingen_document.py 2012-12-07 13:35:25 +0000
@@ -0,0 +1,420 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Author: Guewen Baconnier
5# Copyright 2012 Camptocamp SA
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22import logging
23
24from cStringIO import StringIO
25
26from contextlib import closing
27from openerp.osv import osv, orm, fields
28from openerp.tools.translate import _
29from openerp import pooler
30from .pingen import APIError, ConnectionError, POST_SENDING_STATUS
31
32_logger = logging.getLogger(__name__)
33
34
35class pingen_document(orm.Model):
36 """ A pingen document is the state of the synchronization of
37 an attachment with pingen.com
38
39 It stores the configuration and the current state of the synchronization.
40 It also serves as a queue of documents to push to pingen.com
41 """
42
43 _name = 'pingen.document'
44 _inherits = {'ir.attachment': 'attachment_id'}
45
46 _columns = {
47 'attachment_id': fields.many2one(
48 'ir.attachment', 'Document',
49 required=True, readonly=True,
50 ondelete='cascade'),
51 'state': fields.selection(
52 [('pending', 'Pending'),
53 ('pushed', 'Pushed'),
54 ('sendcenter', 'In Sendcenter'),
55 ('sent', 'Sent'),
56 ('error', 'Connection Error'),
57 ('pingen_error', 'Pingen Error'),
58 ('canceled', 'Canceled')],
59 string='State', readonly=True, required=True),
60 'push_date': fields.datetime('Push Date', readonly=True),
61
62 # for `error` and `pingen_error` states when we push
63 'last_error_message': fields.text('Error Message', readonly=True),
64
65 # pingen IDs
66 'pingen_id': fields.integer(
67 'Pingen ID', readonly=True,
68 help="ID of the document in the Pingen Documents"),
69 'post_id': fields.integer(
70 'Pingen Post ID', readonly=True,
71 help="ID of the document in the Pingen Sendcenter"),
72
73 # sendcenter infos
74 'post_status': fields.char('Post Status', size=128, readonly=True),
75 'parsed_address': fields.text('Parsed Address', readonly=True),
76 'cost': fields.float('Cost', readonly=True),
77 'currency_id': fields.many2one('res.currency', 'Currency', readonly=True),
78 'country_id': fields.many2one('res.country', 'Country', readonly=True),
79 'send_date': fields.datetime('Date of sending', readonly=True),
80 'pages': fields.integer('Pages', readonly=True),
81 }
82
83 _defaults = {
84 'state': 'pending',
85 }
86
87 _sql_constraints = [
88 ('pingen_document_attachment_uniq',
89 'unique (attachment_id)',
90 'Only one Pingen document is allowed per attachment.'),
91 ]
92
93 def _get_pingen_session(self, cr, uid, context=None):
94 """ Returns a pingen session for a user """
95 company = self.pool.get('res.users').browse(
96 cr, uid, uid, context=context).company_id
97 return self.pool.get('res.company')._pingen(cr, uid, company, context=context)
98
99 def _push_to_pingen(self, cr, uid, document, pingen=None, context=None):
100 """ Push a document to pingen.com
101
102 :param Pingen pingen: optional pingen object to reuse session
103 """
104 attachment_obj = self.pool.get('ir.attachment')
105
106 decoded_document = attachment_obj._decoded_content(
107 cr, uid, document.attachment_id, context=context)
108
109 if pingen is None:
110 pingen = self._get_pingen_session(cr, uid, context=context)
111 try:
112 doc_id, post_id, infos = pingen.push_document(
113 document.datas_fname,
114 StringIO(decoded_document),
115 document.pingen_send,
116 document.pingen_speed,
117 document.pingen_color)
118 except ConnectionError as e:
119 _logger.exception(
120 'Connection Error when pushing Pingen Document %s to %s.' %
121 (document.id, pingen.url))
122 raise
123
124 except APIError as e:
125 _logger.error(
126 'API Error when pushing Pingen Document %s to %s.' %
127 (document.id, pingen.url))
128 raise
129
130 error = False
131 state = 'pushed'
132 if post_id:
133 state = 'sendcenter'
134 elif infos['requirement_failure']:
135 state = 'pingen_error'
136 error = _('The document does not meet the Pingen requirements.')
137
138 document.write(
139 {'last_error_message': error,
140 'state': state,
141 'push_date': infos['date'],
142 'pingen_id': doc_id,
143 'post_id': post_id},
144 context=context)
145 _logger.info('Pingen Document %s: pushed to %s' % (document.id, pingen.url))
146
147 def push_to_pingen(self, cr, uid, ids, context=None):
148 """ Push a document to pingen.com
149
150 Convert errors to osv.except_osv to be handled by the client.
151
152 Wrapper method for multiple ids (when triggered from button for
153 instance) for public interface.
154 """
155 assert len(ids) == 1, "Only 1 id is allowed"
156 with self._get_pingen_session(cr, uid, context=context) as session:
157 for document in self.browse(cr, uid, ids, context=context):
158 try:
159 self._push_to_pingen(
160 cr, uid, document, pingen=session, context=context)
161 except ConnectionError as e:
162 raise osv.except_osv(
163 _('Pingen Connection Error'),
164 _('Connection Error when asking for sending the document %s to Pingen') % document.name)
165
166 except APIError as e:
167 raise osv.except_osv(
168 _('Pingen Error'),
169 _('Error when asking Pingen to send the document %s: '
170 '\n%s') % (document.name, e))
171
172 except:
173 _logger.exception(
174 'Unexcepted Error when updating the status of pingen.document %s: ' %
175 document.id)
176 raise osv.except_osv(
177 _('Error'),
178 _('Unexcepted Error when updating the status of Document %s') % document.name)
179 return True
180
181 def _push_and_send_to_pingen_cron(self, cr, uid, ids, context=None):
182 """ Push a document to pingen.com
183
184 Intended to be used in a cron.
185
186 Commit after each record
187
188 Instead of raising, store the error in the pingen.document
189 """
190 if not ids:
191 ids = self.search(
192 cr, uid,
193 # do not retry pingen_error, they should be treated manually
194 [('state', 'in', ['pending', 'pushed', 'error'])],
195 limit=100,
196 context=context)
197
198 with closing(pooler.get_db(cr.dbname).cursor()) as loc_cr, \
199 self._get_pingen_session(cr, uid, context=context) as session:
200 for document in self.browse(loc_cr, uid, ids, context=context):
201
202 if document.state == 'error':
203 self._resolve_error(loc_cr, uid, document, context=context)
204 document.refresh()
205
206 try:
207 if document.state == 'pending':
208 self._push_to_pingen(
209 loc_cr, uid, document, pingen=session, context=context)
210
211 elif document.state == 'pushed':
212 self._ask_pingen_send(
213 loc_cr, uid, document, pingen=session, context=context)
214 except ConnectionError as e:
215 document.write({'last_error_message': e,
216 'state': 'error'},
217 context=context)
218 except APIError as e:
219 document.write({'last_error_message': e,
220 'state': 'pingen_error'},
221 context=context)
222 except:
223 _logger.error('Unexcepted error in pingen cron')
224 loc_cr.rollback()
225 raise
226
227 else:
228 loc_cr.commit()
229
230 return True
231
232 def _resolve_error(self, cr, uid, document, context=None):
233 """ A document as resolved, put in the correct state """
234 if document.post_id:
235 state = 'sendcenter'
236 elif document.pingen_id:
237 state = 'pushed'
238 else:
239 state = 'pending'
240 document.write({'state': state}, context=context)
241
242 def resolve_error(self, cr, uid, ids, context=None):
243 """ A document as resolved, put in the correct state """
244 for document in self.browse(cr, uid, ids, context=context):
245 self._resolve_error(cr, uid, document, context=context)
246 return True
247
248 def _ask_pingen_send(self, cr, uid, document, pingen, context=None):
249 """ For a document already pushed to pingen, ask to send it.
250
251 :param Pingen pingen: pingen object to reuse
252 """
253 # sending has been explicitely asked so we change the option
254 # for consistency
255 if not document.pingen_send:
256 document.write({'pingen_send': True}, context=context)
257
258 try:
259 post_id = pingen.send_document(
260 document.pingen_id,
261 document.pingen_speed,
262 document.pingen_color)
263 except ConnectionError as e:
264 _logger.exception('Connection Error when asking for sending Pingen Document %s to %s.' %
265 (document.id, pingen.url))
266 raise
267 except APIError as e:
268 _logger.exception('API Error when asking for sending Pingen Document %s to %s.' %
269 (document.id, pingen.url))
270 raise
271
272 document.write(
273 {'last_error_message': False,
274 'state': 'sendcenter',
275 'post_id': post_id},
276 context=context)
277 _logger.info('Pingen Document %s: asked for sending to %s' % (document.id, pingen.url))
278
279 return True
280
281 def ask_pingen_send(self, cr, uid, ids, context=None):
282 """ For a document already pushed to pingen, ask to send it.
283
284 Wrapper method for multiple ids (when triggered from button for
285 instance) for public interface.
286 """
287 assert len(ids) == 1, "Only 1 id is allowed"
288 with self._get_pingen_session(cr, uid, context=context) as session:
289 for document in self.browse(cr, uid, ids, context=context):
290 try:
291 self._ask_pingen_send(cr, uid, document, pingen=session, context=context)
292 except ConnectionError as e:
293 raise osv.except_osv(
294 _('Pingen Connection Error'),
295 _('Connection Error when asking for '
296 'sending the document %s to Pingen') % document.name)
297
298 except APIError as e:
299 raise osv.except_osv(
300 _('Pingen Error'),
301 _('Error when asking Pingen to send the document %s: '
302 '\n%s') % (document.name, e))
303
304 except:
305 _logger.exception(
306 'Unexcepted Error when updating the status of pingen.document %s: ' %
307 document.id)
308 raise osv.except_osv(
309 _('Error'),
310 _('Unexcepted Error when updating the status of Document %s') % document.name)
311 return True
312
313 def _update_post_infos(self, cr, uid, document, pingen, context=None):
314 """ Update the informations from pingen of a document in the Sendcenter
315
316 :param Pingen pingen: pingen object to reuse
317 """
318 if not document.post_id:
319 return
320
321 try:
322 post_infos = pingen.post_infos(document.post_id)
323 except ConnectionError as e:
324 _logger.exception(
325 'Connection Error when asking for '
326 'sending Pingen Document %s to %s.' %
327 (document.id, pingen.url))
328 raise
329 except APIError as e:
330 _logger.exception(
331 'API Error when asking for sending Pingen Document %s to %s.' %
332 (document.id, pingen.url))
333 raise
334
335 currency_ids = self.pool.get('res.currency').search(
336 cr, uid, [('name', '=', post_infos['currency'])], context=context)
337 country_ids = self.pool.get('res.country').search(
338 cr, uid, [('code', '=', post_infos['country'])], context=context)
339 vals = {
340 'post_status': POST_SENDING_STATUS[post_infos['status']],
341 'cost': post_infos['cost'],
342 'currency_id': currency_ids[0] if currency_ids else False,
343 'parsed_address': post_infos['address'],
344 'country_id': country_ids[0] if country_ids else False,
345 'send_date': post_infos['date'],
346 'pages': post_infos['pages'],
347 'last_error_message': False,
348 }
349 if pingen.is_posted(post_infos):
350 vals['state'] = 'sent'
351
352 document.write(vals, context=context)
353 _logger.info('Pingen Document %s: status updated' % document.id)
354
355 def _update_post_infos_cron(self, cr, uid, ids, context=None):
356 """ Update the informations from pingen of a document in the Sendcenter
357
358 Intended to be used in a cron.
359
360 Commit after each record
361
362 Do not raise errors, only skip the update of the record.
363 """
364 if not ids:
365 ids = self.search(
366 cr, uid,
367 [('state', '=', 'sendcenter')],
368 context=context)
369
370 with closing(pooler.get_db(cr.dbname).cursor()) as loc_cr, \
371 self._get_pingen_session(cr, uid, context=context) as session:
372 for document in self.browse(loc_cr, uid, ids, context=context):
373 try:
374 self._update_post_infos(
375 loc_cr, uid, document, pingen=session, context=context)
376 except (ConnectionError, APIError):
377 # will be retried the next time
378 # In any case, the error has been logged by _update_post_infos
379 loc_cr.rollback()
380 except:
381 _logger.error('Unexcepted error in pingen cron')
382 loc_cr.rollback()
383 raise
384 else:
385 loc_cr.commit()
386 return True
387
388 def update_post_infos(self, cr, uid, ids, context=None):
389 """ Update the informations from pingen of a document in the Sendcenter
390
391 Wrapper method for multiple ids (when triggered from button for
392 instance) for public interface.
393 """
394 assert len(ids) == 1, "Only 1 id is allowed"
395 with self._get_pingen_session(cr, uid, context=context) as session:
396 for document in self.browse(cr, uid, ids, context=context):
397 try:
398 self._update_post_infos(
399 cr, uid, document, pingen=session, context=context)
400 except ConnectionError as e:
401 raise osv.except_osv(
402 _('Pingen Connection Error'),
403 _('Connection Error when updating the status of Document %s'
404 ' from Pingen') % document.name)
405
406 except APIError as e:
407 raise osv.except_osv(
408 _('Pingen Error'),
409 _('Error when updating the status of Document %s from Pingen: '
410 '\n%s') % (document.name, e))
411
412 except:
413 _logger.exception(
414 'Unexcepted Error when updating the status of pingen.document %s: ' %
415 document.id)
416 raise osv.except_osv(
417 _('Error'),
418 _('Unexcepted Error when updating the status of Document %s') % document.name)
419 return True
420
0421
=== added file 'pingen/pingen_document_view.xml'
--- pingen/pingen_document_view.xml 1970-01-01 00:00:00 +0000
+++ pingen/pingen_document_view.xml 2012-12-07 13:35:25 +0000
@@ -0,0 +1,161 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3 <data noupdate="0">
4
5 <record id="view_pingen_document_tree" model="ir.ui.view">
6 <field name="name">pingen.document.tree</field>
7 <field name="model">pingen.document</field>
8 <field name="type">tree</field>
9 <field name="arch" type="xml">
10 <tree string="Pingen Document">
11 <field name="name"/>
12 <field name="datas_fname"/>
13 <field name="pingen_send"/>
14 <field name="pingen_speed"/>
15 <field name="pingen_color"/>
16 <field name="state"/>
17 </tree>
18 </field>
19 </record>
20
21 <record id="view_pingen_document_form" model="ir.ui.view">
22 <field name="name">pingen.document.form</field>
23 <field name="model">pingen.document</field>
24 <field name="type">form</field>
25 <field name="arch" type="xml">
26 <form string="Pingen Document">
27 <group colspan="4" col="6">
28 <field name="name" readonly="True"/>
29 <field name="type" readonly="True"/>
30 <field name="company_id" readonly="True" groups="base.group_multi_company" widget="selection"/>
31 </group>
32 <notebook colspan="4">
33 <page string="Pingen.com">
34 <separator string="Options" colspan="4"/>
35 <newline />
36 <group col="2" colspan="2">
37 <field name="pingen_send" attrs="{'readonly': [('state', 'in', ['sendcenter', 'sent'])]}"/>
38 <field name="pingen_speed" attrs="{'readonly': [('state', 'in', ['sendcenter', 'sent'])], 'required': [('pingen_send', '=', True)]}"/>
39 <field name="pingen_color" attrs="{'readonly': [('state', 'in', ['sendcenter', 'sent'])]}"/>
40 </group>
41
42 <separator string="Dates" colspan="4"/>
43 <newline />
44 <group col="2" colspan="2">
45 <field name="push_date"/>
46 </group>
47
48 <group colspan="4" attrs="{'invisible': [('last_error_message', '=', False)]}">
49 <separator string="Errors" colspan="4"/>
50 <newline />
51 <group col="2" colspan="2">
52 <field nolabel="1" name="last_error_message"/>
53 </group>
54 </group>
55
56 <group colspan="4" attrs="{'invisible': [('state', 'not in', ['sendcenter', 'sent'])]}">
57 <separator string="Sendcenter" colspan="4"/>
58 <newline />
59 <group col="4" colspan="2">
60 <field colspan="4" name="post_status"/>
61 <group col="3" colspan="2">
62 <field name="cost"/>
63 <field colspan="1" nolabel="1" name="currency_id"/>
64 </group>
65 <newline/>
66 <field name="parsed_address"/>
67 <field name="country_id"/>
68 <field name="send_date"/>
69 <field name="pages"/>
70 </group>
71 </group>
72
73 <separator string="Actions" colspan="4"/>
74 <newline />
75 <group col="2" colspan="2">
76 <button name="push_to_pingen" type="object"
77 states="pending"
78 string="Push to pingen.com" icon="terp-stage"/>
79 <button name="ask_pingen_send" type="object"
80 states="pushed"
81 string="Ask pingen.com to send the document" icon="gtk-print"/>
82 <button name="resolve_error" type="object"
83 states="error,pingen_error"
84 string="Errors resolved" icon="gtk-redo"/>
85 <button name="update_post_infos" type="object"
86 states="sendcenter"
87 string="Update the letter's informations" icon="gtk-refresh"/>
88 </group>
89 </page>
90 <page string="Attachment">
91 <group col="4" colspan="4">
92 <separator string="Data" colspan="4"/>
93 <newline />
94 <group col="2" colspan="4" attrs="{'invisible':[('type','=','url')]}">
95 <field name="datas" filename="datas_fname" readonly="True"/>
96 <field name="datas_fname" select="1" readonly="True"/>
97 </group>
98 <group col="2" colspan="4" attrs="{'invisible':[('type','=','binary')]}">
99 <field name="url" widget="url" readonly="True"/>
100 </group>
101 </group>
102 <group col="2" colspan="4">
103 <separator string="Attached To" colspan="2"/>
104 <field name="attachment_id"/>
105 </group>
106 </page>
107 </notebook>
108
109 <field name="state" widget="statusbar"
110 statusbar_visible="pending,pushed,sent"
111 statusbar_colors='{"error":"red","pingen_error":"red","canceled":"grey","pushed":"blue","sent":"green"}'/>
112 </form>
113 </field>
114 </record>
115
116 <record id="view_pingen_document_search" model="ir.ui.view">
117 <field name="name">pingen.document.search</field>
118 <field name="model">pingen.document</field>
119 <field name="type">search</field>
120 <field name="arch" type="xml">
121 <search string="Pingen Document">
122 <filter icon="terp-project"
123 string="Pending"
124 domain="[('state','=','pending')]"/>
125 <filter icon="terp-stage"
126 string="Pushed"
127 domain="[('state','=','pushed')]"/>
128 <filter icon="gtk-print"
129 string="In Sendcenter"
130 domain="[('state','=','sendcenter')]"/>
131 <filter icon="kanban-apply"
132 string="Sent"
133 domain="[('state','=','sent')]"/>
134 <filter icon="kanban-stop"
135 string="Error"
136 domain="[('state','=','error')]"/>
137 <filter icon="STOCK_NO"
138 string="Pingen Error"
139 domain="[('state','=','pingen_error')]"/>
140 <filter icon="terp-dialog-close"
141 string="Canceled"
142 domain="[('state','=','canceled')]"/>
143 <separator orientation="vertical"/>
144 <field name="attachment_id" />
145 </search>
146 </field>
147 </record>
148
149 <record id="action_pingen_document" model="ir.actions.act_window">
150 <field name="name">Pingen Documents</field>
151 <field name="type">ir.actions.act_window</field>
152 <field name="res_model">pingen.document</field>
153 <field name="view_type">form</field>
154 <field name="view_mode">tree,form</field>
155 <field name="search_view_id" ref="view_pingen_document_search"/>
156 </record>
157
158 <menuitem action="action_pingen_document" id="menu_pingen_document" parent="base.next_id_4"/>
159
160 </data>
161</openerp>
0162
=== added file 'pingen/res_company.py'
--- pingen/res_company.py 1970-01-01 00:00:00 +0000
+++ pingen/res_company.py 2012-12-07 13:35:25 +0000
@@ -0,0 +1,42 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Author: Guewen Baconnier
5# Copyright 2012 Camptocamp SA
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22from openerp.osv import orm, fields
23from openerp.osv.orm import browse_record
24from .pingen import Pingen
25
26class res_company(orm.Model):
27
28 _inherit = 'res.company'
29
30 _columns = {
31 'pingen_token': fields.char('Pingen Token', size=32),
32 'pingen_staging': fields.boolean('Pingen Staging')
33 }
34
35 def _pingen(self, cr, uid, company, context=None):
36 """ Return a Pingen instance to work on """
37 assert isinstance(company, (int, long, browse_record)), \
38 "one id or browse_record expected"
39 if not isinstance(company, browse_record):
40 company = self.browse(cr, uid, company_id, context=context)
41 return Pingen(company.pingen_token, staging=company.pingen_staging)
42
043
=== added file 'pingen/res_company_view.xml'
--- pingen/res_company_view.xml 1970-01-01 00:00:00 +0000
+++ pingen/res_company_view.xml 2012-12-07 13:35:25 +0000
@@ -0,0 +1,20 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3 <data noupdate="0">
4
5 <record model="ir.ui.view" id="view_company_inherit_form">
6 <field name="name">res.company.form.inherit</field>
7 <field name="model">res.company</field>
8 <field name="type">form</field>
9 <field name="inherit_id" ref="base.view_company_form"/>
10 <field name="arch" type="xml">
11 <page string="Configuration" position="inside">
12 <separator string="Pingen.com" colspan="4"/>
13 <field name="pingen_token" groups="base.group_system"/>
14 <field name="pingen_staging" groups="base.group_system"/>
15 </page>
16 </field>
17 </record>
18
19 </data>
20</openerp>
021
=== added directory 'pingen/security'
=== added file 'pingen/security/ir.model.access.csv'
--- pingen/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
+++ pingen/security/ir.model.access.csv 2012-12-07 13:35:25 +0000
@@ -0,0 +1,3 @@
1"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
2"access_pingen_document_all","pingen_document all","model_pingen_document",,1,0,0,0
3"access_pingen_document_group_user","pingen_document group_user","model_pingen_document","base.group_user",1,1,1,1
04
=== added directory 'pingen_document'
=== added file 'pingen_document/__init__.py'
--- pingen_document/__init__.py 1970-01-01 00:00:00 +0000
+++ pingen_document/__init__.py 2012-12-07 13:35:25 +0000
@@ -0,0 +1,21 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Author: Guewen Baconnier
5# Copyright 2012 Camptocamp SA
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
022
=== added file 'pingen_document/__openerp__.py'
--- pingen_document/__openerp__.py 1970-01-01 00:00:00 +0000
+++ pingen_document/__openerp__.py 2012-12-07 13:35:25 +0000
@@ -0,0 +1,41 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Author: Guewen Baconnier
5# Copyright 2012 Camptocamp SA
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22{
23 'name' : 'pingen.com integration (document)',
24 'version' : '1.0',
25 'author' : 'Camptocamp',
26 'maintainer': 'Camptocamp',
27 'license': 'AGPL-3',
28 'category': 'Reporting',
29 'complexity': 'easy',
30 'depends' : ['document', 'pingen'],
31 'description': """
32Glue module between the `pingen` and the `document` modules.
33""",
34 'website': 'http://www.camptocamp.com',
35 'data': [
36 'pingen_document_view.xml',
37 ],
38 'tests': [],
39 'installable': True,
40 'auto_install': True,
41}
042
=== added directory 'pingen_document/i18n'
=== added file 'pingen_document/i18n/de.po'
--- pingen_document/i18n/de.po 1970-01-01 00:00:00 +0000
+++ pingen_document/i18n/de.po 2012-12-07 13:35:25 +0000
@@ -0,0 +1,32 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * pingen_document
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 6.1\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2012-11-26 10:54+0000\n"
10"PO-Revision-Date: 2012-11-26 10:54+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: pingen_document
19#: view:ir.attachment:0
20msgid "Notes"
21msgstr "Notes"
22
23#. module: pingen_document
24#: model:ir.ui.menu,name:pingen_document.menu_pingen_document_document
25msgid "Pingen Documents"
26msgstr "Pingen Documents"
27
28#. module: pingen_document
29#: view:ir.attachment:0
30msgid "Pingen.com"
31msgstr "Pingen.com"
32
033
=== added file 'pingen_document/i18n/en.po'
--- pingen_document/i18n/en.po 1970-01-01 00:00:00 +0000
+++ pingen_document/i18n/en.po 2012-12-07 13:35:25 +0000
@@ -0,0 +1,32 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * pingen_document
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 6.1\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2012-11-26 10:54+0000\n"
10"PO-Revision-Date: 2012-11-26 10:54+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: pingen_document
19#: view:ir.attachment:0
20msgid "Notes"
21msgstr "Notes"
22
23#. module: pingen_document
24#: model:ir.ui.menu,name:pingen_document.menu_pingen_document_document
25msgid "Pingen Documents"
26msgstr "Pingen Documents"
27
28#. module: pingen_document
29#: view:ir.attachment:0
30msgid "Pingen.com"
31msgstr "Pingen.com"
32
033
=== added file 'pingen_document/i18n/es.po'
--- pingen_document/i18n/es.po 1970-01-01 00:00:00 +0000
+++ pingen_document/i18n/es.po 2012-12-07 13:35:25 +0000
@@ -0,0 +1,32 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * pingen_document
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 6.1\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2012-11-26 10:54+0000\n"
10"PO-Revision-Date: 2012-11-26 10:54+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: pingen_document
19#: view:ir.attachment:0
20msgid "Notes"
21msgstr "Notes"
22
23#. module: pingen_document
24#: model:ir.ui.menu,name:pingen_document.menu_pingen_document_document
25msgid "Pingen Documents"
26msgstr "Pingen Documents"
27
28#. module: pingen_document
29#: view:ir.attachment:0
30msgid "Pingen.com"
31msgstr "Pingen.com"
32
033
=== added file 'pingen_document/i18n/fr.po'
--- pingen_document/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ pingen_document/i18n/fr.po 2012-12-07 13:35:25 +0000
@@ -0,0 +1,32 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * pingen_document
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 6.1\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2012-11-26 10:56+0000\n"
10"PO-Revision-Date: 2012-11-26 10:56+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: pingen_document
19#: view:ir.attachment:0
20msgid "Notes"
21msgstr "Notes"
22
23#. module: pingen_document
24#: model:ir.ui.menu,name:pingen_document.menu_pingen_document_document
25msgid "Pingen Documents"
26msgstr "Documents Pingen"
27
28#. module: pingen_document
29#: view:ir.attachment:0
30msgid "Pingen.com"
31msgstr "Pingen.com"
32
033
=== added file 'pingen_document/i18n/pingen_document.pot'
--- pingen_document/i18n/pingen_document.pot 1970-01-01 00:00:00 +0000
+++ pingen_document/i18n/pingen_document.pot 2012-12-07 13:35:25 +0000
@@ -0,0 +1,32 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * pingen_document
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 6.1\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2012-11-26 10:56+0000\n"
10"PO-Revision-Date: 2012-11-26 10:56+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: pingen_document
19#: view:ir.attachment:0
20msgid "Notes"
21msgstr ""
22
23#. module: pingen_document
24#: model:ir.ui.menu,name:pingen_document.menu_pingen_document_document
25msgid "Pingen Documents"
26msgstr ""
27
28#. module: pingen_document
29#: view:ir.attachment:0
30msgid "Pingen.com"
31msgstr ""
32
033
=== added file 'pingen_document/pingen_document_view.xml'
--- pingen_document/pingen_document_view.xml 1970-01-01 00:00:00 +0000
+++ pingen_document/pingen_document_view.xml 2012-12-07 13:35:25 +0000
@@ -0,0 +1,27 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3 <data noupdate="0">
4
5 <record id="view_document_file_form" model="ir.ui.view">
6 <field name="name">ir.attachment.document.pingen.view</field>
7 <field name="model">ir.attachment</field>
8 <field name="type">form</field>
9 <field name="inherit_id" ref="document.view_document_file_form"/>
10 <field name="arch" type="xml">
11 <page string="Notes" position="before">
12 <page string="Pingen.com">
13 <field name="send_to_pingen"/>
14 <field name="pingen_send" attrs="{'required': [('send_to_pingen', '=', True)]}"/>
15 <field name="pingen_speed" attrs="{'required': [('pingen_send', '=', True)]}"/>
16 <field name="pingen_color" />
17 </page>
18 </page>
19 </field>
20 </record>
21
22 <menuitem action="pingen.action_pingen_document"
23 id="menu_pingen_document_document"
24 parent="document.menu_document_doc"/>
25
26 </data>
27</openerp>

Subscribers

People subscribed via source and target branches