Merge lp:~camptocamp/report-print-send/6.1-pingen into lp:~report-print-send-core-editors/report-print-send/6.1
- 6.1-pingen
- Merge into 6.1
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Stefan Rijnhart (Opener) | Approve | ||
Review via email:
|
Commit message
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
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Stefan Rijnhart (Opener) (stefan-opener) wrote : | # |
- 19. By Guewen Baconnier @ Camptocamp <email address hidden>
-
[FIX] express the external dependency on the 'request' lib in the manifest file
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : | # |
Oh yes you are right for the external_
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 ;-)
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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.
[[-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.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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?
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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!
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : | # |
Thanks for the merge
Preview Diff
1 | === renamed file 'README' => 'README' |
2 | === renamed directory 'base_report_to_printer' => 'base_report_to_printer' |
3 | === added directory 'pingen' |
4 | === added file 'pingen/__init__.py' |
5 | --- pingen/__init__.py 1970-01-01 00:00:00 +0000 |
6 | +++ pingen/__init__.py 2012-12-07 13:35:25 +0000 |
7 | @@ -0,0 +1,26 @@ |
8 | +# -*- coding: utf-8 -*- |
9 | +############################################################################## |
10 | +# |
11 | +# Author: Guewen Baconnier |
12 | +# Copyright 2012 Camptocamp SA |
13 | +# |
14 | +# This program is free software: you can redistribute it and/or modify |
15 | +# it under the terms of the GNU Affero General Public License as |
16 | +# published by the Free Software Foundation, either version 3 of the |
17 | +# License, or (at your option) any later version. |
18 | +# |
19 | +# This program is distributed in the hope that it will be useful, |
20 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
21 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22 | +# GNU Affero General Public License for more details. |
23 | +# |
24 | +# You should have received a copy of the GNU Affero General Public License |
25 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
26 | +# |
27 | +############################################################################## |
28 | + |
29 | +import ir_attachment |
30 | +import pingen |
31 | +import pingen_document |
32 | +import res_company |
33 | + |
34 | |
35 | === added file 'pingen/__openerp__.py' |
36 | --- pingen/__openerp__.py 1970-01-01 00:00:00 +0000 |
37 | +++ pingen/__openerp__.py 2012-12-07 13:35:25 +0000 |
38 | @@ -0,0 +1,119 @@ |
39 | +# -*- coding: utf-8 -*- |
40 | +############################################################################## |
41 | +# |
42 | +# Author: Guewen Baconnier |
43 | +# Copyright 2012 Camptocamp SA |
44 | +# |
45 | +# This program is free software: you can redistribute it and/or modify |
46 | +# it under the terms of the GNU Affero General Public License as |
47 | +# published by the Free Software Foundation, either version 3 of the |
48 | +# License, or (at your option) any later version. |
49 | +# |
50 | +# This program is distributed in the hope that it will be useful, |
51 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
52 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
53 | +# GNU Affero General Public License for more details. |
54 | +# |
55 | +# You should have received a copy of the GNU Affero General Public License |
56 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
57 | +# |
58 | +############################################################################## |
59 | + |
60 | +{ |
61 | + 'name': 'pingen.com integration', |
62 | + 'version': '1.0', |
63 | + 'author': 'Camptocamp', |
64 | + 'maintainer': 'Camptocamp', |
65 | + 'license': 'AGPL-3', |
66 | + 'category': 'Reporting', |
67 | + 'complexity': 'easy', |
68 | + 'depends': [], |
69 | + 'external_dependencies': { |
70 | + 'python': ['requests'], |
71 | + }, |
72 | + 'description': """ |
73 | +Integration with pingen.com |
74 | +=========================== |
75 | + |
76 | +What is pingen.com |
77 | +------------------ |
78 | + |
79 | +Pingen.com is a paid online service. |
80 | +It sends uploaded documents by letter post. |
81 | + |
82 | +Scope of the integration |
83 | +------------------------ |
84 | + |
85 | +One can decide, per document / attachment, if it should be pushed |
86 | +to pingen.com. The documents are pushed asynchronously. |
87 | + |
88 | +A second cron updates the informations of the documents from pingen.com, so we |
89 | +know which of them have been sent. |
90 | + |
91 | +Configuration |
92 | +------------- |
93 | + |
94 | +The authentication token is configured on the company's view. You can also |
95 | +tick a checkbox if the staging environment (https://stage-api.pingen.com) |
96 | +should be used. |
97 | + |
98 | +The setup of the 2 crons can be changed as well: |
99 | + |
100 | + * Run Pingen Document Push |
101 | + * Run Pingen Document Update |
102 | + |
103 | +Usage |
104 | +----- |
105 | + |
106 | +On the attachment view, a new pingen.com tab has been added. |
107 | +You can tick a box to push the document to pingen.com. |
108 | + |
109 | +There is 3 additional options: |
110 | + |
111 | + * Send: the document will not be only uploaded, but will be also be sent |
112 | + * Speed: priority or economy |
113 | + * Type of print: color or black and white |
114 | + |
115 | +Once the configuration is done and the attachment saved, a Pingen Document |
116 | +is created. You can directly access to the latter on the Link on the right on |
117 | +the attachment view. |
118 | + |
119 | +You can find them in `Settings > Customization > Low Level Objets > Pingen |
120 | +Documents` or in the more convenient `Documents` menu if you have installed the |
121 | +`document` module. |
122 | + |
123 | +Errors |
124 | +------ |
125 | + |
126 | +Sometimes, pingen.com will refuse to send a document because it does not meet |
127 | +its requirements. In such case, the document's state becomes "Pingen Error" and |
128 | +you will need to manually handle the case, either from the pingen.com backend, |
129 | +or by changing the document on OpenERP and resolving the error on the Pingen |
130 | +Document. |
131 | + |
132 | +When a connection error occurs, the action will be retried on the next scheduler |
133 | +run. |
134 | + |
135 | +Dependencies |
136 | +------------ |
137 | + |
138 | + * Require the Python library `requests <http://docs.python-requests.org/>`_ |
139 | + * The PDF files sent to pingen.com have to respect some `formatting rules |
140 | + <https://stage-app.pingen.com/resources/pingen_requirements_v1_en.pdf>`_. |
141 | + * The address must be in a format accepted by pingen.com: the last line |
142 | + is the country in English or German. |
143 | + |
144 | +""", |
145 | + 'website': 'http://www.camptocamp.com', |
146 | + 'data': [ |
147 | + 'ir_attachment_view.xml', |
148 | + 'pingen_document_view.xml', |
149 | + 'pingen_data.xml', |
150 | + 'res_company_view.xml', |
151 | + 'security/ir.model.access.csv', |
152 | + ], |
153 | + 'tests': [], |
154 | + 'installable': True, |
155 | + 'auto_install': False, |
156 | + 'application': True, |
157 | +} |
158 | |
159 | === added directory 'pingen/i18n' |
160 | === added file 'pingen/i18n/fr.po' |
161 | --- pingen/i18n/fr.po 1970-01-01 00:00:00 +0000 |
162 | +++ pingen/i18n/fr.po 2012-12-07 13:35:25 +0000 |
163 | @@ -0,0 +1,390 @@ |
164 | +# Translation of OpenERP Server. |
165 | +# This file contains the translation of the following modules: |
166 | +# * pingen |
167 | +# |
168 | +msgid "" |
169 | +msgstr "" |
170 | +"Project-Id-Version: OpenERP Server 6.1\n" |
171 | +"Report-Msgid-Bugs-To: \n" |
172 | +"POT-Creation-Date: 2012-11-26 10:54+0000\n" |
173 | +"PO-Revision-Date: 2012-11-26 10:54+0000\n" |
174 | +"Last-Translator: <>\n" |
175 | +"Language-Team: \n" |
176 | +"MIME-Version: 1.0\n" |
177 | +"Content-Type: text/plain; charset=UTF-8\n" |
178 | +"Content-Transfer-Encoding: \n" |
179 | +"Plural-Forms: \n" |
180 | + |
181 | +#. module: pingen |
182 | +#: code:addons/pingen/pingen_document.py:177 |
183 | +#: code:addons/pingen/pingen_document.py:307 |
184 | +#: code:addons/pingen/pingen_document.py:414 |
185 | +#, python-format |
186 | +msgid "Unexcepted Error when updating the status of Document %s" |
187 | +msgstr "Erreur inattendue lors de la mise à jour du document %s" |
188 | + |
189 | +#. module: pingen |
190 | +#: field:pingen.document,push_date:0 |
191 | +msgid "Push Date" |
192 | +msgstr "Date d'ajout" |
193 | + |
194 | +#. module: pingen |
195 | +#: view:pingen.document:0 |
196 | +msgid "Errors" |
197 | +msgstr "Erreurs" |
198 | + |
199 | +#. module: pingen |
200 | +#: field:pingen.document,pingen_id:0 |
201 | +msgid "Pingen ID" |
202 | +msgstr "ID Pingen" |
203 | + |
204 | +#. module: pingen |
205 | +#: constraint:res.company:0 |
206 | +msgid "Error! You can not create recursive companies." |
207 | +msgstr "Error! You can not create recursive companies." |
208 | + |
209 | +#. module: pingen |
210 | +#: field:ir.attachment,pingen_send:0 |
211 | +msgid "Send" |
212 | +msgstr "Envoyer" |
213 | + |
214 | +#. module: pingen |
215 | +#: code:addons/pingen/pingen_document.py:399 |
216 | +#, python-format |
217 | +msgid "Connection Error when updating the status of Document %s from Pingen" |
218 | +msgstr "Erreur de connexion lors de la mise à jour de l'état du document %s depuis Pingen" |
219 | + |
220 | +#. module: pingen |
221 | +#: field:pingen.document,state:0 |
222 | +msgid "State" |
223 | +msgstr "État" |
224 | + |
225 | +#. module: pingen |
226 | +#: field:ir.attachment,pingen_color:0 |
227 | +msgid "Type of print" |
228 | +msgstr "Type d'impression" |
229 | + |
230 | +#. module: pingen |
231 | +#: view:pingen.document:0 |
232 | +msgid "Attachment" |
233 | +msgstr "Attachement" |
234 | + |
235 | +#. module: pingen |
236 | +#: code:addons/pingen/pingen_document.py:405 |
237 | +#, python-format |
238 | +msgid "Error when updating the status of Document %s from Pingen: \n" |
239 | +"%s" |
240 | +msgstr "Erreur lors de la mise à jour de l'état du document %s depuis Pingen: \n" |
241 | +"%s" |
242 | + |
243 | +#. module: pingen |
244 | +#: model:ir.actions.act_window,name:pingen.act_attachment_to_pingen_document |
245 | +#: field:ir.attachment,pingen_document_ids:0 |
246 | +#: view:pingen.document:0 |
247 | +msgid "Pingen Document" |
248 | +msgstr "Document Pingen" |
249 | + |
250 | +#. module: pingen |
251 | +#: field:pingen.document,attachment_id:0 |
252 | +msgid "Document" |
253 | +msgstr "Document" |
254 | + |
255 | +#. module: pingen |
256 | +#: help:ir.attachment,pingen_send:0 |
257 | +msgid "Defines if a document is merely uploaded or also sent" |
258 | +msgstr "Définit si un fichier est juste ajouté ou également envoyé" |
259 | + |
260 | +#. module: pingen |
261 | +#: view:pingen.document:0 |
262 | +#: selection:pingen.document,state:0 |
263 | +msgid "Pending" |
264 | +msgstr "En attente" |
265 | + |
266 | +#. module: pingen |
267 | +#: selection:ir.attachment,pingen_speed:0 |
268 | +msgid "Economy" |
269 | +msgstr "Économique" |
270 | + |
271 | +#. module: pingen |
272 | +#: view:pingen.document:0 |
273 | +msgid "Errors resolved" |
274 | +msgstr "Erreurs résolues" |
275 | + |
276 | +#. module: pingen |
277 | +#: sql_constraint:pingen.document:0 |
278 | +msgid "Only one Pingen document is allowed per attachment." |
279 | +msgstr "Uniquement un document Pingen est autorisé par attachement." |
280 | + |
281 | +#. module: pingen |
282 | +#: code:addons/pingen/pingen_document.py:168 |
283 | +#: code:addons/pingen/pingen_document.py:298 |
284 | +#, python-format |
285 | +msgid "Error when asking Pingen to send the document %s: \n" |
286 | +"%s" |
287 | +msgstr "Erreurs lors de l'envoi du document par Pingen %s: \n" |
288 | +"%s" |
289 | + |
290 | +#. module: pingen |
291 | +#: view:pingen.document:0 |
292 | +msgid "Update the letter's informations" |
293 | +msgstr "Mettre à jour les informations de la lettre" |
294 | + |
295 | +#. module: pingen |
296 | +#: view:pingen.document:0 |
297 | +#: selection:pingen.document,state:0 |
298 | +msgid "Canceled" |
299 | +msgstr "Annulé" |
300 | + |
301 | +#. module: pingen |
302 | +#: selection:pingen.document,state:0 |
303 | +msgid "Connection Error" |
304 | +msgstr "Erreur de connexion" |
305 | + |
306 | +#. module: pingen |
307 | +#: model:ir.actions.act_window,name:pingen.action_pingen_document |
308 | +#: model:ir.ui.menu,name:pingen.menu_pingen_document |
309 | +msgid "Pingen Documents" |
310 | +msgstr "Documents Pingen" |
311 | + |
312 | +#. module: pingen |
313 | +#: field:pingen.document,last_error_message:0 |
314 | +msgid "Error Message" |
315 | +msgstr "Message d'erreur" |
316 | + |
317 | +#. module: pingen |
318 | +#: selection:ir.attachment,pingen_color:0 |
319 | +msgid "B/W" |
320 | +msgstr "N/B" |
321 | + |
322 | +#. module: pingen |
323 | +#: field:res.company,pingen_staging:0 |
324 | +msgid "Pingen Staging" |
325 | +msgstr "Staging Pingen" |
326 | + |
327 | +#. module: pingen |
328 | +#: model:ir.model,name:pingen.model_ir_attachment |
329 | +msgid "ir.attachment" |
330 | +msgstr "ir.attachment" |
331 | + |
332 | +#. module: pingen |
333 | +#: view:pingen.document:0 |
334 | +#: selection:pingen.document,state:0 |
335 | +msgid "In Sendcenter" |
336 | +msgstr "Dans le Sendcenter" |
337 | + |
338 | +#. module: pingen |
339 | +#: view:pingen.document:0 |
340 | +#: selection:pingen.document,state:0 |
341 | +msgid "Sent" |
342 | +msgstr "Envoyé" |
343 | + |
344 | +#. module: pingen |
345 | +#: field:pingen.document,post_status:0 |
346 | +msgid "Post Status" |
347 | +msgstr "État de la lettre" |
348 | + |
349 | +#. module: pingen |
350 | +#: code:addons/pingen/pingen_document.py:163 |
351 | +#: code:addons/pingen/pingen_document.py:292 |
352 | +#, python-format |
353 | +msgid "Connection Error when asking for sending the document %s to Pingen" |
354 | +msgstr "Erreur de connexion avec Pingen lors de l'envoi de %s" |
355 | + |
356 | +#. module: pingen |
357 | +#: view:res.company:0 |
358 | +msgid "Configuration" |
359 | +msgstr "Configuration" |
360 | + |
361 | +#. module: pingen |
362 | +#: view:pingen.document:0 |
363 | +msgid "Data" |
364 | +msgstr "Données" |
365 | + |
366 | +#. module: pingen |
367 | +#: view:pingen.document:0 |
368 | +msgid "Options" |
369 | +msgstr "Options" |
370 | + |
371 | +#. module: pingen |
372 | +#: field:res.company,pingen_token:0 |
373 | +msgid "Pingen Token" |
374 | +msgstr "Token Pingen" |
375 | + |
376 | +#. module: pingen |
377 | +#: field:ir.attachment,send_to_pingen:0 |
378 | +msgid "Send to Pingen.com" |
379 | +msgstr "Ajouter sur Pingen.com" |
380 | + |
381 | +#. module: pingen |
382 | +#: model:ir.model,name:pingen.model_pingen_document |
383 | +msgid "pingen.document" |
384 | +msgstr "pingen.document" |
385 | + |
386 | +#. module: pingen |
387 | +#: view:pingen.document:0 |
388 | +msgid "Dates" |
389 | +msgstr "Dates" |
390 | + |
391 | +#. module: pingen |
392 | +#: view:pingen.document:0 |
393 | +msgid "Sendcenter" |
394 | +msgstr "Sendcenter" |
395 | + |
396 | +#. module: pingen |
397 | +#: sql_constraint:res.company:0 |
398 | +msgid "The company name must be unique !" |
399 | +msgstr "The company name must be unique !" |
400 | + |
401 | +#. module: pingen |
402 | +#: field:pingen.document,parsed_address:0 |
403 | +msgid "Parsed Address" |
404 | +msgstr "Adresse analysée" |
405 | + |
406 | +#. module: pingen |
407 | +#: view:ir.attachment:0 |
408 | +#: view:pingen.document:0 |
409 | +#: view:res.company:0 |
410 | +msgid "Pingen.com" |
411 | +msgstr "Pingen.com" |
412 | + |
413 | +#. module: pingen |
414 | +#: field:pingen.document,country_id:0 |
415 | +msgid "Country" |
416 | +msgstr "Pays" |
417 | + |
418 | +#. module: pingen |
419 | +#: view:ir.attachment:0 |
420 | +msgid "Notes" |
421 | +msgstr "Notes" |
422 | + |
423 | +#. module: pingen |
424 | +#: view:pingen.document:0 |
425 | +#: selection:pingen.document,state:0 |
426 | +msgid "Pushed" |
427 | +msgstr "Ajouté" |
428 | + |
429 | +#. module: pingen |
430 | +#: model:ir.model,name:pingen.model_res_company |
431 | +msgid "Companies" |
432 | +msgstr "Compagnies" |
433 | + |
434 | +#. module: pingen |
435 | +#: code:addons/pingen/ir_attachment.py:90 |
436 | +#, python-format |
437 | +msgid "The attachment %s is already pushed to pingen.com." |
438 | +msgstr "L'attachement %s est déjà envoyé sur pingen.com." |
439 | + |
440 | +#. module: pingen |
441 | +#: view:pingen.document:0 |
442 | +msgid "Attached To" |
443 | +msgstr "Attaché à " |
444 | + |
445 | +#. module: pingen |
446 | +#: code:addons/pingen/pingen_document.py:136 |
447 | +#, python-format |
448 | +msgid "The document does not meet the Pingen requirements." |
449 | +msgstr "Le document ne remplit pas les exigences de Pingen" |
450 | + |
451 | +#. module: pingen |
452 | +#: code:addons/pingen/ir_attachment.py:89 |
453 | +#: code:addons/pingen/pingen_document.py:176 |
454 | +#: code:addons/pingen/pingen_document.py:306 |
455 | +#: code:addons/pingen/pingen_document.py:413 |
456 | +#: view:pingen.document:0 |
457 | +#, python-format |
458 | +msgid "Error" |
459 | +msgstr "Erreur" |
460 | + |
461 | +#. module: pingen |
462 | +#: code:addons/pingen/pingen_document.py:162 |
463 | +#: code:addons/pingen/pingen_document.py:291 |
464 | +#: code:addons/pingen/pingen_document.py:398 |
465 | +#, python-format |
466 | +msgid "Pingen Connection Error" |
467 | +msgstr "Erreur de connexion avec Pingen" |
468 | + |
469 | +#. module: pingen |
470 | +#: field:pingen.document,send_date:0 |
471 | +msgid "Date of sending" |
472 | +msgstr "Date d'envoi" |
473 | + |
474 | +#. module: pingen |
475 | +#: selection:ir.attachment,pingen_speed:0 |
476 | +msgid "Priority" |
477 | +msgstr "Priorité" |
478 | + |
479 | +#. module: pingen |
480 | +#: selection:ir.attachment,pingen_color:0 |
481 | +msgid "Color" |
482 | +msgstr "Color" |
483 | + |
484 | +#. module: pingen |
485 | +#: model:ir.model,name:pingen.model_pingen_task |
486 | +msgid "pingen.task" |
487 | +msgstr "pingen.task" |
488 | + |
489 | +#. module: pingen |
490 | +#: help:pingen.document,pingen_id:0 |
491 | +msgid "ID of the document in the Pingen Documents" |
492 | +msgstr "ID du document sur Pingen" |
493 | + |
494 | +#. module: pingen |
495 | +#: code:addons/pingen/pingen_document.py:167 |
496 | +#: code:addons/pingen/pingen_document.py:297 |
497 | +#: code:addons/pingen/pingen_document.py:404 |
498 | +#: view:pingen.document:0 |
499 | +#: selection:pingen.document,state:0 |
500 | +#, python-format |
501 | +msgid "Pingen Error" |
502 | +msgstr "Erreur Pingen" |
503 | + |
504 | +#. module: pingen |
505 | +#: view:pingen.document:0 |
506 | +msgid "Actions" |
507 | +msgstr "Actions" |
508 | + |
509 | +#. module: pingen |
510 | +#: field:pingen.document,pages:0 |
511 | +msgid "Pages" |
512 | +msgstr "Pages" |
513 | + |
514 | +#. module: pingen |
515 | +#: field:pingen.document,currency_id:0 |
516 | +msgid "Currency" |
517 | +msgstr "Devise" |
518 | + |
519 | +#. module: pingen |
520 | +#: field:pingen.document,cost:0 |
521 | +msgid "Cost" |
522 | +msgstr "Coût" |
523 | + |
524 | +#. module: pingen |
525 | +#: view:pingen.document:0 |
526 | +msgid "Push to pingen.com" |
527 | +msgstr "Ajouter sur pingen.com" |
528 | + |
529 | +#. module: pingen |
530 | +#: view:pingen.document:0 |
531 | +msgid "Ask pingen.com to send the document" |
532 | +msgstr "Demander à pingen.com d'envoyer le document" |
533 | + |
534 | +#. module: pingen |
535 | +#: help:pingen.document,post_id:0 |
536 | +msgid "ID of the document in the Pingen Sendcenter" |
537 | +msgstr "ID du document dans le Sendcenter Pingen" |
538 | + |
539 | +#. module: pingen |
540 | +#: field:ir.attachment,pingen_speed:0 |
541 | +msgid "Speed" |
542 | +msgstr "Vitesse" |
543 | + |
544 | +#. module: pingen |
545 | +#: field:pingen.document,post_id:0 |
546 | +msgid "Pingen Post ID" |
547 | +msgstr "ID de lettre Pingen" |
548 | + |
549 | +#. module: pingen |
550 | +#: help:ir.attachment,pingen_speed:0 |
551 | +msgid "Defines the sending speed if the document is automatically sent" |
552 | +msgstr "Définit la vitesse d'envoi si le document est automatiquement envoyé" |
553 | + |
554 | |
555 | === added file 'pingen/i18n/pingen.pot' |
556 | --- pingen/i18n/pingen.pot 1970-01-01 00:00:00 +0000 |
557 | +++ pingen/i18n/pingen.pot 2012-12-07 13:35:25 +0000 |
558 | @@ -0,0 +1,388 @@ |
559 | +# Translation of OpenERP Server. |
560 | +# This file contains the translation of the following modules: |
561 | +# * pingen |
562 | +# |
563 | +msgid "" |
564 | +msgstr "" |
565 | +"Project-Id-Version: OpenERP Server 6.1\n" |
566 | +"Report-Msgid-Bugs-To: \n" |
567 | +"POT-Creation-Date: 2012-11-26 10:55+0000\n" |
568 | +"PO-Revision-Date: 2012-11-26 10:55+0000\n" |
569 | +"Last-Translator: <>\n" |
570 | +"Language-Team: \n" |
571 | +"MIME-Version: 1.0\n" |
572 | +"Content-Type: text/plain; charset=UTF-8\n" |
573 | +"Content-Transfer-Encoding: \n" |
574 | +"Plural-Forms: \n" |
575 | + |
576 | +#. module: pingen |
577 | +#: code:addons/pingen/pingen_document.py:177 |
578 | +#: code:addons/pingen/pingen_document.py:307 |
579 | +#: code:addons/pingen/pingen_document.py:414 |
580 | +#, python-format |
581 | +msgid "Unexcepted Error when updating the status of Document %s" |
582 | +msgstr "" |
583 | + |
584 | +#. module: pingen |
585 | +#: field:pingen.document,push_date:0 |
586 | +msgid "Push Date" |
587 | +msgstr "" |
588 | + |
589 | +#. module: pingen |
590 | +#: view:pingen.document:0 |
591 | +msgid "Errors" |
592 | +msgstr "" |
593 | + |
594 | +#. module: pingen |
595 | +#: field:pingen.document,pingen_id:0 |
596 | +msgid "Pingen ID" |
597 | +msgstr "" |
598 | + |
599 | +#. module: pingen |
600 | +#: constraint:res.company:0 |
601 | +msgid "Error! You can not create recursive companies." |
602 | +msgstr "" |
603 | + |
604 | +#. module: pingen |
605 | +#: field:ir.attachment,pingen_send:0 |
606 | +msgid "Send" |
607 | +msgstr "" |
608 | + |
609 | +#. module: pingen |
610 | +#: code:addons/pingen/pingen_document.py:399 |
611 | +#, python-format |
612 | +msgid "Connection Error when updating the status of Document %s from Pingen" |
613 | +msgstr "" |
614 | + |
615 | +#. module: pingen |
616 | +#: field:pingen.document,state:0 |
617 | +msgid "State" |
618 | +msgstr "" |
619 | + |
620 | +#. module: pingen |
621 | +#: field:ir.attachment,pingen_color:0 |
622 | +msgid "Type of print" |
623 | +msgstr "" |
624 | + |
625 | +#. module: pingen |
626 | +#: view:pingen.document:0 |
627 | +msgid "Attachment" |
628 | +msgstr "" |
629 | + |
630 | +#. module: pingen |
631 | +#: code:addons/pingen/pingen_document.py:405 |
632 | +#, python-format |
633 | +msgid "Error when updating the status of Document %s from Pingen: \n" |
634 | +"%s" |
635 | +msgstr "" |
636 | + |
637 | +#. module: pingen |
638 | +#: model:ir.actions.act_window,name:pingen.act_attachment_to_pingen_document |
639 | +#: field:ir.attachment,pingen_document_ids:0 |
640 | +#: view:pingen.document:0 |
641 | +msgid "Pingen Document" |
642 | +msgstr "" |
643 | + |
644 | +#. module: pingen |
645 | +#: field:pingen.document,attachment_id:0 |
646 | +msgid "Document" |
647 | +msgstr "" |
648 | + |
649 | +#. module: pingen |
650 | +#: help:ir.attachment,pingen_send:0 |
651 | +msgid "Defines if a document is merely uploaded or also sent" |
652 | +msgstr "" |
653 | + |
654 | +#. module: pingen |
655 | +#: view:pingen.document:0 |
656 | +#: selection:pingen.document,state:0 |
657 | +msgid "Pending" |
658 | +msgstr "" |
659 | + |
660 | +#. module: pingen |
661 | +#: selection:ir.attachment,pingen_speed:0 |
662 | +msgid "Economy" |
663 | +msgstr "" |
664 | + |
665 | +#. module: pingen |
666 | +#: view:pingen.document:0 |
667 | +msgid "Errors resolved" |
668 | +msgstr "" |
669 | + |
670 | +#. module: pingen |
671 | +#: sql_constraint:pingen.document:0 |
672 | +msgid "Only one Pingen document is allowed per attachment." |
673 | +msgstr "" |
674 | + |
675 | +#. module: pingen |
676 | +#: code:addons/pingen/pingen_document.py:168 |
677 | +#: code:addons/pingen/pingen_document.py:298 |
678 | +#, python-format |
679 | +msgid "Error when asking Pingen to send the document %s: \n" |
680 | +"%s" |
681 | +msgstr "" |
682 | + |
683 | +#. module: pingen |
684 | +#: view:pingen.document:0 |
685 | +msgid "Update the letter's informations" |
686 | +msgstr "" |
687 | + |
688 | +#. module: pingen |
689 | +#: view:pingen.document:0 |
690 | +#: selection:pingen.document,state:0 |
691 | +msgid "Canceled" |
692 | +msgstr "" |
693 | + |
694 | +#. module: pingen |
695 | +#: selection:pingen.document,state:0 |
696 | +msgid "Connection Error" |
697 | +msgstr "" |
698 | + |
699 | +#. module: pingen |
700 | +#: model:ir.actions.act_window,name:pingen.action_pingen_document |
701 | +#: model:ir.ui.menu,name:pingen.menu_pingen_document |
702 | +msgid "Pingen Documents" |
703 | +msgstr "" |
704 | + |
705 | +#. module: pingen |
706 | +#: field:pingen.document,last_error_message:0 |
707 | +msgid "Error Message" |
708 | +msgstr "" |
709 | + |
710 | +#. module: pingen |
711 | +#: selection:ir.attachment,pingen_color:0 |
712 | +msgid "B/W" |
713 | +msgstr "" |
714 | + |
715 | +#. module: pingen |
716 | +#: field:res.company,pingen_staging:0 |
717 | +msgid "Pingen Staging" |
718 | +msgstr "" |
719 | + |
720 | +#. module: pingen |
721 | +#: model:ir.model,name:pingen.model_ir_attachment |
722 | +msgid "ir.attachment" |
723 | +msgstr "" |
724 | + |
725 | +#. module: pingen |
726 | +#: view:pingen.document:0 |
727 | +#: selection:pingen.document,state:0 |
728 | +msgid "In Sendcenter" |
729 | +msgstr "" |
730 | + |
731 | +#. module: pingen |
732 | +#: view:pingen.document:0 |
733 | +#: selection:pingen.document,state:0 |
734 | +msgid "Sent" |
735 | +msgstr "" |
736 | + |
737 | +#. module: pingen |
738 | +#: field:pingen.document,post_status:0 |
739 | +msgid "Post Status" |
740 | +msgstr "" |
741 | + |
742 | +#. module: pingen |
743 | +#: code:addons/pingen/pingen_document.py:163 |
744 | +#: code:addons/pingen/pingen_document.py:292 |
745 | +#, python-format |
746 | +msgid "Connection Error when asking for sending the document %s to Pingen" |
747 | +msgstr "" |
748 | + |
749 | +#. module: pingen |
750 | +#: view:res.company:0 |
751 | +msgid "Configuration" |
752 | +msgstr "" |
753 | + |
754 | +#. module: pingen |
755 | +#: view:pingen.document:0 |
756 | +msgid "Data" |
757 | +msgstr "" |
758 | + |
759 | +#. module: pingen |
760 | +#: view:pingen.document:0 |
761 | +msgid "Options" |
762 | +msgstr "" |
763 | + |
764 | +#. module: pingen |
765 | +#: field:res.company,pingen_token:0 |
766 | +msgid "Pingen Token" |
767 | +msgstr "" |
768 | + |
769 | +#. module: pingen |
770 | +#: field:ir.attachment,send_to_pingen:0 |
771 | +msgid "Send to Pingen.com" |
772 | +msgstr "" |
773 | + |
774 | +#. module: pingen |
775 | +#: model:ir.model,name:pingen.model_pingen_document |
776 | +msgid "pingen.document" |
777 | +msgstr "" |
778 | + |
779 | +#. module: pingen |
780 | +#: view:pingen.document:0 |
781 | +msgid "Dates" |
782 | +msgstr "" |
783 | + |
784 | +#. module: pingen |
785 | +#: view:pingen.document:0 |
786 | +msgid "Sendcenter" |
787 | +msgstr "" |
788 | + |
789 | +#. module: pingen |
790 | +#: sql_constraint:res.company:0 |
791 | +msgid "The company name must be unique !" |
792 | +msgstr "" |
793 | + |
794 | +#. module: pingen |
795 | +#: field:pingen.document,parsed_address:0 |
796 | +msgid "Parsed Address" |
797 | +msgstr "" |
798 | + |
799 | +#. module: pingen |
800 | +#: view:ir.attachment:0 |
801 | +#: view:pingen.document:0 |
802 | +#: view:res.company:0 |
803 | +msgid "Pingen.com" |
804 | +msgstr "" |
805 | + |
806 | +#. module: pingen |
807 | +#: field:pingen.document,country_id:0 |
808 | +msgid "Country" |
809 | +msgstr "" |
810 | + |
811 | +#. module: pingen |
812 | +#: view:ir.attachment:0 |
813 | +msgid "Notes" |
814 | +msgstr "" |
815 | + |
816 | +#. module: pingen |
817 | +#: view:pingen.document:0 |
818 | +#: selection:pingen.document,state:0 |
819 | +msgid "Pushed" |
820 | +msgstr "" |
821 | + |
822 | +#. module: pingen |
823 | +#: model:ir.model,name:pingen.model_res_company |
824 | +msgid "Companies" |
825 | +msgstr "" |
826 | + |
827 | +#. module: pingen |
828 | +#: code:addons/pingen/ir_attachment.py:90 |
829 | +#, python-format |
830 | +msgid "The attachment %s is already pushed to pingen.com." |
831 | +msgstr "" |
832 | + |
833 | +#. module: pingen |
834 | +#: view:pingen.document:0 |
835 | +msgid "Attached To" |
836 | +msgstr "" |
837 | + |
838 | +#. module: pingen |
839 | +#: code:addons/pingen/pingen_document.py:136 |
840 | +#, python-format |
841 | +msgid "The document does not meet the Pingen requirements." |
842 | +msgstr "" |
843 | + |
844 | +#. module: pingen |
845 | +#: code:addons/pingen/ir_attachment.py:89 |
846 | +#: code:addons/pingen/pingen_document.py:176 |
847 | +#: code:addons/pingen/pingen_document.py:306 |
848 | +#: code:addons/pingen/pingen_document.py:413 |
849 | +#: view:pingen.document:0 |
850 | +#, python-format |
851 | +msgid "Error" |
852 | +msgstr "" |
853 | + |
854 | +#. module: pingen |
855 | +#: code:addons/pingen/pingen_document.py:162 |
856 | +#: code:addons/pingen/pingen_document.py:291 |
857 | +#: code:addons/pingen/pingen_document.py:398 |
858 | +#, python-format |
859 | +msgid "Pingen Connection Error" |
860 | +msgstr "" |
861 | + |
862 | +#. module: pingen |
863 | +#: field:pingen.document,send_date:0 |
864 | +msgid "Date of sending" |
865 | +msgstr "" |
866 | + |
867 | +#. module: pingen |
868 | +#: selection:ir.attachment,pingen_speed:0 |
869 | +msgid "Priority" |
870 | +msgstr "" |
871 | + |
872 | +#. module: pingen |
873 | +#: selection:ir.attachment,pingen_color:0 |
874 | +msgid "Color" |
875 | +msgstr "" |
876 | + |
877 | +#. module: pingen |
878 | +#: model:ir.model,name:pingen.model_pingen_task |
879 | +msgid "pingen.task" |
880 | +msgstr "" |
881 | + |
882 | +#. module: pingen |
883 | +#: help:pingen.document,pingen_id:0 |
884 | +msgid "ID of the document in the Pingen Documents" |
885 | +msgstr "" |
886 | + |
887 | +#. module: pingen |
888 | +#: code:addons/pingen/pingen_document.py:167 |
889 | +#: code:addons/pingen/pingen_document.py:297 |
890 | +#: code:addons/pingen/pingen_document.py:404 |
891 | +#: view:pingen.document:0 |
892 | +#: selection:pingen.document,state:0 |
893 | +#, python-format |
894 | +msgid "Pingen Error" |
895 | +msgstr "" |
896 | + |
897 | +#. module: pingen |
898 | +#: view:pingen.document:0 |
899 | +msgid "Actions" |
900 | +msgstr "" |
901 | + |
902 | +#. module: pingen |
903 | +#: field:pingen.document,pages:0 |
904 | +msgid "Pages" |
905 | +msgstr "" |
906 | + |
907 | +#. module: pingen |
908 | +#: field:pingen.document,currency_id:0 |
909 | +msgid "Currency" |
910 | +msgstr "" |
911 | + |
912 | +#. module: pingen |
913 | +#: field:pingen.document,cost:0 |
914 | +msgid "Cost" |
915 | +msgstr "" |
916 | + |
917 | +#. module: pingen |
918 | +#: view:pingen.document:0 |
919 | +msgid "Push to pingen.com" |
920 | +msgstr "" |
921 | + |
922 | +#. module: pingen |
923 | +#: view:pingen.document:0 |
924 | +msgid "Ask pingen.com to send the document" |
925 | +msgstr "" |
926 | + |
927 | +#. module: pingen |
928 | +#: help:pingen.document,post_id:0 |
929 | +msgid "ID of the document in the Pingen Sendcenter" |
930 | +msgstr "" |
931 | + |
932 | +#. module: pingen |
933 | +#: field:ir.attachment,pingen_speed:0 |
934 | +msgid "Speed" |
935 | +msgstr "" |
936 | + |
937 | +#. module: pingen |
938 | +#: field:pingen.document,post_id:0 |
939 | +msgid "Pingen Post ID" |
940 | +msgstr "" |
941 | + |
942 | +#. module: pingen |
943 | +#: help:ir.attachment,pingen_speed:0 |
944 | +msgid "Defines the sending speed if the document is automatically sent" |
945 | +msgstr "" |
946 | + |
947 | |
948 | === added file 'pingen/ir_attachment.py' |
949 | --- pingen/ir_attachment.py 1970-01-01 00:00:00 +0000 |
950 | +++ pingen/ir_attachment.py 2012-12-07 13:35:25 +0000 |
951 | @@ -0,0 +1,124 @@ |
952 | +# -*- coding: utf-8 -*- |
953 | +############################################################################## |
954 | +# |
955 | +# Author: Guewen Baconnier |
956 | +# Copyright 2012 Camptocamp SA |
957 | +# |
958 | +# This program is free software: you can redistribute it and/or modify |
959 | +# it under the terms of the GNU Affero General Public License as |
960 | +# published by the Free Software Foundation, either version 3 of the |
961 | +# License, or (at your option) any later version. |
962 | +# |
963 | +# This program is distributed in the hope that it will be useful, |
964 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
965 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
966 | +# GNU Affero General Public License for more details. |
967 | +# |
968 | +# You should have received a copy of the GNU Affero General Public License |
969 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
970 | +# |
971 | +############################################################################## |
972 | + |
973 | +import requests |
974 | +import base64 |
975 | + |
976 | +from openerp.osv import osv, orm, fields |
977 | +from openerp.tools.translate import _ |
978 | + |
979 | + |
980 | +class ir_attachment(orm.Model): |
981 | + |
982 | + _inherit = 'ir.attachment' |
983 | + |
984 | + _columns = { |
985 | + 'send_to_pingen': fields.boolean('Send to Pingen.com'), |
986 | + 'pingen_document_ids': fields.one2many( |
987 | + 'pingen.document', 'attachment_id', |
988 | + string='Pingen Document', readonly=True), |
989 | + 'pingen_send': fields.boolean( |
990 | + 'Send', |
991 | + help="Defines if a document is merely uploaded or also sent"), |
992 | + 'pingen_speed': fields.selection( |
993 | + [('1', 'Priority'), ('2', 'Economy')], |
994 | + 'Speed', |
995 | + help="Defines the sending speed if the document is automatically sent"), |
996 | + 'pingen_color': fields.selection( [('0', 'B/W'), ('1', 'Color')], 'Type of print'), |
997 | + } |
998 | + |
999 | + _defaults = { |
1000 | + 'pingen_send': True, |
1001 | + 'pingen_color': '0', |
1002 | + 'pingen_speed': '2', |
1003 | + } |
1004 | + |
1005 | + def _prepare_pingen_document_vals(self, cr, uid, attachment, context=None): |
1006 | + return {'attachment_id': attachment.id, |
1007 | + 'config': 'created from attachment'} |
1008 | + |
1009 | + def _handle_pingen_document(self, cr, uid, attachment_id, context=None): |
1010 | + """ Reponsible of the related ``pingen.document`` when the ``send_to_pingen`` |
1011 | + field is modified. |
1012 | + |
1013 | + Only one pingen document can be created per attachment. |
1014 | + |
1015 | + When ``send_to_pingen`` is activated: |
1016 | + * Create a ``pingen.document`` if it does not already exist |
1017 | + * Put the related ``pingen.document`` to ``pending`` if it already exist |
1018 | + When it is deactivated: |
1019 | + * Do nothing if no related ``pingen.document`` exists |
1020 | + * Or cancel it |
1021 | + * If it has already been pushed to pingen.com, raises |
1022 | + an `osv.except_osv` exception |
1023 | + """ |
1024 | + pingen_document_obj = self.pool.get('pingen.document') |
1025 | + attachment = self.browse(cr, uid, attachment_id, context=context) |
1026 | + document = attachment.pingen_document_ids[0] if attachment.pingen_document_ids else None |
1027 | + if attachment.send_to_pingen: |
1028 | + if document: |
1029 | + document.write({'state': 'pending'}, context=context) |
1030 | + else: |
1031 | + pingen_document_obj.create( |
1032 | + cr, uid, |
1033 | + self._prepare_pingen_document_vals( |
1034 | + cr, uid, attachment, context=context), |
1035 | + context=context) |
1036 | + else: |
1037 | + if document: |
1038 | + if document.state == 'pushed': |
1039 | + raise osv.except_osv( |
1040 | + _('Error'), |
1041 | + _('The attachment %s is already pushed to pingen.com.') % \ |
1042 | + attachment.name) |
1043 | + document.write({'state': 'canceled'}, context=context) |
1044 | + return |
1045 | + |
1046 | + def create(self, cr, uid, vals, context=None): |
1047 | + attachment_id = super(ir_attachment, self).create(cr, uid, vals, context=context) |
1048 | + if 'send_to_pingen' in vals: |
1049 | + self._handle_pingen_document(cr, uid, attachment_id, context=context) |
1050 | + return attachment_id |
1051 | + |
1052 | + def write(self, cr, uid, ids, vals, context=None): |
1053 | + res = super(ir_attachment, self).write(cr, uid, ids, vals, context=context) |
1054 | + if 'send_to_pingen' in vals: |
1055 | + for attachment_id in ids: |
1056 | + self._handle_pingen_document(cr, uid, attachment_id, context=context) |
1057 | + return res |
1058 | + |
1059 | + def _decoded_content(self, cr, uid, attachment, context=None): |
1060 | + """ Returns the decoded content of an attachment (stored or url) |
1061 | + |
1062 | + Returns None if the type is 'url' and the url is not reachable. |
1063 | + """ |
1064 | + decoded_document = None |
1065 | + if attachment.type == 'binary': |
1066 | + decoded_document = base64.decodestring(attachment.datas) |
1067 | + elif attachment.type == 'url': |
1068 | + response = requests.get(attachment.url) |
1069 | + if response.ok: |
1070 | + decoded_document = requests.content |
1071 | + else: |
1072 | + raise Exception( |
1073 | + 'The type of attachment %s is not handled' % attachment.type) |
1074 | + return decoded_document |
1075 | + |
1076 | |
1077 | === added file 'pingen/ir_attachment_view.xml' |
1078 | --- pingen/ir_attachment_view.xml 1970-01-01 00:00:00 +0000 |
1079 | +++ pingen/ir_attachment_view.xml 2012-12-07 13:35:25 +0000 |
1080 | @@ -0,0 +1,31 @@ |
1081 | +<?xml version="1.0" encoding="utf-8"?> |
1082 | +<openerp> |
1083 | + <data noupdate="0"> |
1084 | + |
1085 | + <record id="view_attachment_form" model="ir.ui.view"> |
1086 | + <field name="name">ir.attachment.pingen.view</field> |
1087 | + <field name="model">ir.attachment</field> |
1088 | + <field name="type">form</field> |
1089 | + <field name="inherit_id" ref="base.view_attachment_form"/> |
1090 | + <field name="arch" type="xml"> |
1091 | + <page string="Notes" position="before"> |
1092 | + <page string="Pingen.com"> |
1093 | + <field name="send_to_pingen"/> |
1094 | + <field name="pingen_send" attrs="{'required': [('send_to_pingen', '=', True)]}"/> |
1095 | + <field name="pingen_speed" attrs="{'required': [('pingen_send', '=', True)]}"/> |
1096 | + <field name="pingen_color" /> |
1097 | + </page> |
1098 | + </page> |
1099 | + </field> |
1100 | + </record> |
1101 | + |
1102 | + <act_window |
1103 | + context="{'search_default_attachment_id': [active_id], 'default_attachment_id': active_id}" |
1104 | + id="act_attachment_to_pingen_document" |
1105 | + name="Pingen Document" |
1106 | + groups="" |
1107 | + res_model="pingen.document" |
1108 | + src_model="ir.attachment"/> |
1109 | + |
1110 | + </data> |
1111 | +</openerp> |
1112 | |
1113 | === added file 'pingen/pingen.py' |
1114 | --- pingen/pingen.py 1970-01-01 00:00:00 +0000 |
1115 | +++ pingen/pingen.py 2012-12-07 13:35:25 +0000 |
1116 | @@ -0,0 +1,209 @@ |
1117 | +# -*- coding: utf-8 -*- |
1118 | +############################################################################## |
1119 | +# |
1120 | +# Author: Guewen Baconnier |
1121 | +# Copyright 2012 Camptocamp SA |
1122 | +# |
1123 | +# This program is free software: you can redistribute it and/or modify |
1124 | +# it under the terms of the GNU Affero General Public License as |
1125 | +# published by the Free Software Foundation, either version 3 of the |
1126 | +# License, or (at your option) any later version. |
1127 | +# |
1128 | +# This program is distributed in the hope that it will be useful, |
1129 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1130 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1131 | +# GNU Affero General Public License for more details. |
1132 | +# |
1133 | +# You should have received a copy of the GNU Affero General Public License |
1134 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1135 | +# |
1136 | +############################################################################## |
1137 | + |
1138 | +import requests |
1139 | +import logging |
1140 | +import urlparse |
1141 | +import json |
1142 | + |
1143 | +from requests.packages.urllib3.filepost import encode_multipart_formdata |
1144 | + |
1145 | +_logger = logging.getLogger(__name__) |
1146 | + |
1147 | +POST_SENDING_STATUS = { |
1148 | + 100: 'Ready/Pending', |
1149 | + 101: 'Processing', |
1150 | + 102: 'Waiting for confirmation', |
1151 | + 200: 'Sent', |
1152 | + 300: 'Some error occured and object wasn\'t sent', |
1153 | + 400: 'Sending cancelled', |
1154 | +} |
1155 | + |
1156 | + |
1157 | +class PingenException(RuntimeError): |
1158 | + """There was an ambiguous exception that occurred while handling your |
1159 | + request.""" |
1160 | + |
1161 | + |
1162 | +class ConnectionError(PingenException): |
1163 | + """An Error occured with the pingen API""" |
1164 | + |
1165 | + |
1166 | +class APIError(PingenException): |
1167 | + """An Error occured with the pingen API""" |
1168 | + |
1169 | + |
1170 | +class Pingen(object): |
1171 | + """ Interface to the pingen.com API """ |
1172 | + |
1173 | + def __init__(self, token, staging=True): |
1174 | + self._token = token |
1175 | + self.staging = staging |
1176 | + self._session = None |
1177 | + super(Pingen, self).__init__() |
1178 | + |
1179 | + @property |
1180 | + def url(self): |
1181 | + if self.staging: |
1182 | + return 'https://stage-api.pingen.com' |
1183 | + return 'https://api.pingen.com' |
1184 | + |
1185 | + @property |
1186 | + def session(self): |
1187 | + """ Build a requests session """ |
1188 | + if self._session is not None: |
1189 | + return self._session |
1190 | + self._session = requests.Session( |
1191 | + params={'token': self._token}, |
1192 | + # with safe_mode, requests catch errors and |
1193 | + # returns a blank response with an error |
1194 | + config={'safe_mode': True}, |
1195 | + # verify = False required for staging environment |
1196 | + # because the SSL certificate is wrong |
1197 | + verify=not self.staging) |
1198 | + return self._session |
1199 | + |
1200 | + def __enter__(self): |
1201 | + return self |
1202 | + |
1203 | + def __exit__(self, *args): |
1204 | + self.close() |
1205 | + |
1206 | + def close(self): |
1207 | + """Dispose of any internal state. """ |
1208 | + if self._session: |
1209 | + self._session.close() |
1210 | + |
1211 | + def _send(self, method, endpoint, **kwargs): |
1212 | + """ Send a request to the pingen API using requests |
1213 | + |
1214 | + Add necessary boilerplate to call pingen.com API |
1215 | + (authentication, configuration, ...) |
1216 | + |
1217 | + :param boundmethod method: requests method to call |
1218 | + :param str endpoint: endpoint to call |
1219 | + :param kwargs: additional arguments forwarded to the requests method |
1220 | + """ |
1221 | + complete_url = urlparse.urljoin(self.url, endpoint) |
1222 | + |
1223 | + response = method(complete_url, **kwargs) |
1224 | + |
1225 | + if not response.ok: |
1226 | + raise ConnectionError( |
1227 | + "%s: %s" % (response.json['errorcode'], |
1228 | + response.json['errormessage'])) |
1229 | + |
1230 | + if response.json['error']: |
1231 | + raise APIError( |
1232 | + "%s: %s" % (response.json['errorcode'], response.json['errormessage'])) |
1233 | + |
1234 | + return response |
1235 | + |
1236 | + def push_document(self, filename, filestream, send=None, speed=None, color=None): |
1237 | + """ Upload a document to pingen.com and eventually ask to send it |
1238 | + |
1239 | + :param str filename: name of the file to push |
1240 | + :param StringIO filestream: file to push |
1241 | + :param boolean send: if True, the document will be sent by pingen.com |
1242 | + :param int/str speed: sending speed of the document if it is send |
1243 | + 1 = Priority, 2 = Economy |
1244 | + :param int/str color: type of print, 0 = B/W, 1 = Color |
1245 | + :return: tuple with 3 items: |
1246 | + 1. document_id on pingen.com |
1247 | + 2. post_id on pingen.com if it has been sent or None |
1248 | + 3. dict of the created item on pingen (details) |
1249 | + """ |
1250 | + data = { |
1251 | + 'send': send, |
1252 | + 'speed': speed, |
1253 | + 'color': color, |
1254 | + } |
1255 | + |
1256 | + # we cannot use the `files` param alongside |
1257 | + # with the `datas`param when data is a |
1258 | + # JSON-encoded data. We have to construct |
1259 | + # the entire body and send it to `data` |
1260 | + # https://github.com/kennethreitz/requests/issues/950 |
1261 | + formdata = { |
1262 | + 'file': (filename, filestream.read()), |
1263 | + 'data': json.dumps(data), |
1264 | + } |
1265 | + |
1266 | + multipart, content_type = encode_multipart_formdata(formdata) |
1267 | + |
1268 | + response = self._send( |
1269 | + self.session.post, |
1270 | + 'document/upload', |
1271 | + headers={'Content-Type': content_type}, |
1272 | + data=multipart) |
1273 | + |
1274 | + rjson = response.json |
1275 | + |
1276 | + document_id = rjson['id'] |
1277 | + if rjson.get('send'): |
1278 | + # confusing name but send_id is the posted id |
1279 | + posted_id = rjson['send'][0]['send_id'] |
1280 | + item = rjson['item'] |
1281 | + |
1282 | + return document_id, posted_id, item |
1283 | + |
1284 | + def send_document(self, document_id, speed=None, color=None): |
1285 | + """ Send a uploaded document to pingen.com |
1286 | + |
1287 | + :param int document_id: id of the document to send |
1288 | + :param int/str speed: sending speed of the document if it is send |
1289 | + 1 = Priority, 2 = Economy |
1290 | + :param int/str color: type of print, 0 = B/W, 1 = Color |
1291 | + :return: id of the post on pingen.com |
1292 | + """ |
1293 | + data = { |
1294 | + 'speed': speed, |
1295 | + 'color': color, |
1296 | + } |
1297 | + response = self._send( |
1298 | + self.session.post, |
1299 | + 'document/send', |
1300 | + params={'id': document_id}, |
1301 | + data={'data': json.dumps(data)}) |
1302 | + |
1303 | + return response.json['id'] |
1304 | + |
1305 | + def post_infos(self, post_id): |
1306 | + """ Return the information of a post |
1307 | + |
1308 | + :param int post_id: id of the document to send |
1309 | + :return: dict of infos of the post |
1310 | + """ |
1311 | + response = self._send( |
1312 | + self.session.get, |
1313 | + 'post/get', |
1314 | + params={'id': post_id}) |
1315 | + |
1316 | + return response.json['item'] |
1317 | + |
1318 | + @staticmethod |
1319 | + def is_posted(post_infos): |
1320 | + """ return True if the post has been sent |
1321 | + |
1322 | + :param dict post_infos: post infos returned by `post_infos` |
1323 | + """ |
1324 | + return post_infos['status'] == 200 |
1325 | + |
1326 | |
1327 | === added file 'pingen/pingen_data.xml' |
1328 | --- pingen/pingen_data.xml 1970-01-01 00:00:00 +0000 |
1329 | +++ pingen/pingen_data.xml 2012-12-07 13:35:25 +0000 |
1330 | @@ -0,0 +1,32 @@ |
1331 | +<?xml version="1.0" encoding="utf-8"?> |
1332 | +<openerp> |
1333 | + <data noupdate="1"> |
1334 | + |
1335 | + <record forcecreate="True" id="ir_cron_push_pingen" model="ir.cron"> |
1336 | + <field name="name">Run Pingen Document Push</field> |
1337 | + <field eval="True" name="active"/> |
1338 | + <field name="user_id" ref="base.user_root"/> |
1339 | + <field name="interval_number">1</field> |
1340 | + <field name="interval_type">hours</field> |
1341 | + <field name="numbercall">-1</field> |
1342 | + <field eval="False" name="doall"/> |
1343 | + <field name="model">pingen.document</field> |
1344 | + <field name="function">_push_and_send_to_pingen_cron</field> |
1345 | + <field name="args">(None,)</field> |
1346 | + </record> |
1347 | + |
1348 | + <record forcecreate="True" id="ir_cron_update_pingen" model="ir.cron"> |
1349 | + <field name="name">Run Pingen Document Update</field> |
1350 | + <field eval="True" name="active"/> |
1351 | + <field name="user_id" ref="base.user_root"/> |
1352 | + <field name="interval_number">1</field> |
1353 | + <field name="interval_type">days</field> |
1354 | + <field name="numbercall">-1</field> |
1355 | + <field eval="False" name="doall"/> |
1356 | + <field name="model">pingen.document</field> |
1357 | + <field name="function">_update_post_infos_cron</field> |
1358 | + <field name="args">(None,)</field> |
1359 | + </record> |
1360 | + |
1361 | + </data> |
1362 | +</openerp> |
1363 | |
1364 | === added file 'pingen/pingen_document.py' |
1365 | --- pingen/pingen_document.py 1970-01-01 00:00:00 +0000 |
1366 | +++ pingen/pingen_document.py 2012-12-07 13:35:25 +0000 |
1367 | @@ -0,0 +1,420 @@ |
1368 | +# -*- coding: utf-8 -*- |
1369 | +############################################################################## |
1370 | +# |
1371 | +# Author: Guewen Baconnier |
1372 | +# Copyright 2012 Camptocamp SA |
1373 | +# |
1374 | +# This program is free software: you can redistribute it and/or modify |
1375 | +# it under the terms of the GNU Affero General Public License as |
1376 | +# published by the Free Software Foundation, either version 3 of the |
1377 | +# License, or (at your option) any later version. |
1378 | +# |
1379 | +# This program is distributed in the hope that it will be useful, |
1380 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1381 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1382 | +# GNU Affero General Public License for more details. |
1383 | +# |
1384 | +# You should have received a copy of the GNU Affero General Public License |
1385 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1386 | +# |
1387 | +############################################################################## |
1388 | + |
1389 | +import logging |
1390 | + |
1391 | +from cStringIO import StringIO |
1392 | + |
1393 | +from contextlib import closing |
1394 | +from openerp.osv import osv, orm, fields |
1395 | +from openerp.tools.translate import _ |
1396 | +from openerp import pooler |
1397 | +from .pingen import APIError, ConnectionError, POST_SENDING_STATUS |
1398 | + |
1399 | +_logger = logging.getLogger(__name__) |
1400 | + |
1401 | + |
1402 | +class pingen_document(orm.Model): |
1403 | + """ A pingen document is the state of the synchronization of |
1404 | + an attachment with pingen.com |
1405 | + |
1406 | + It stores the configuration and the current state of the synchronization. |
1407 | + It also serves as a queue of documents to push to pingen.com |
1408 | + """ |
1409 | + |
1410 | + _name = 'pingen.document' |
1411 | + _inherits = {'ir.attachment': 'attachment_id'} |
1412 | + |
1413 | + _columns = { |
1414 | + 'attachment_id': fields.many2one( |
1415 | + 'ir.attachment', 'Document', |
1416 | + required=True, readonly=True, |
1417 | + ondelete='cascade'), |
1418 | + 'state': fields.selection( |
1419 | + [('pending', 'Pending'), |
1420 | + ('pushed', 'Pushed'), |
1421 | + ('sendcenter', 'In Sendcenter'), |
1422 | + ('sent', 'Sent'), |
1423 | + ('error', 'Connection Error'), |
1424 | + ('pingen_error', 'Pingen Error'), |
1425 | + ('canceled', 'Canceled')], |
1426 | + string='State', readonly=True, required=True), |
1427 | + 'push_date': fields.datetime('Push Date', readonly=True), |
1428 | + |
1429 | + # for `error` and `pingen_error` states when we push |
1430 | + 'last_error_message': fields.text('Error Message', readonly=True), |
1431 | + |
1432 | + # pingen IDs |
1433 | + 'pingen_id': fields.integer( |
1434 | + 'Pingen ID', readonly=True, |
1435 | + help="ID of the document in the Pingen Documents"), |
1436 | + 'post_id': fields.integer( |
1437 | + 'Pingen Post ID', readonly=True, |
1438 | + help="ID of the document in the Pingen Sendcenter"), |
1439 | + |
1440 | + # sendcenter infos |
1441 | + 'post_status': fields.char('Post Status', size=128, readonly=True), |
1442 | + 'parsed_address': fields.text('Parsed Address', readonly=True), |
1443 | + 'cost': fields.float('Cost', readonly=True), |
1444 | + 'currency_id': fields.many2one('res.currency', 'Currency', readonly=True), |
1445 | + 'country_id': fields.many2one('res.country', 'Country', readonly=True), |
1446 | + 'send_date': fields.datetime('Date of sending', readonly=True), |
1447 | + 'pages': fields.integer('Pages', readonly=True), |
1448 | + } |
1449 | + |
1450 | + _defaults = { |
1451 | + 'state': 'pending', |
1452 | + } |
1453 | + |
1454 | + _sql_constraints = [ |
1455 | + ('pingen_document_attachment_uniq', |
1456 | + 'unique (attachment_id)', |
1457 | + 'Only one Pingen document is allowed per attachment.'), |
1458 | + ] |
1459 | + |
1460 | + def _get_pingen_session(self, cr, uid, context=None): |
1461 | + """ Returns a pingen session for a user """ |
1462 | + company = self.pool.get('res.users').browse( |
1463 | + cr, uid, uid, context=context).company_id |
1464 | + return self.pool.get('res.company')._pingen(cr, uid, company, context=context) |
1465 | + |
1466 | + def _push_to_pingen(self, cr, uid, document, pingen=None, context=None): |
1467 | + """ Push a document to pingen.com |
1468 | + |
1469 | + :param Pingen pingen: optional pingen object to reuse session |
1470 | + """ |
1471 | + attachment_obj = self.pool.get('ir.attachment') |
1472 | + |
1473 | + decoded_document = attachment_obj._decoded_content( |
1474 | + cr, uid, document.attachment_id, context=context) |
1475 | + |
1476 | + if pingen is None: |
1477 | + pingen = self._get_pingen_session(cr, uid, context=context) |
1478 | + try: |
1479 | + doc_id, post_id, infos = pingen.push_document( |
1480 | + document.datas_fname, |
1481 | + StringIO(decoded_document), |
1482 | + document.pingen_send, |
1483 | + document.pingen_speed, |
1484 | + document.pingen_color) |
1485 | + except ConnectionError as e: |
1486 | + _logger.exception( |
1487 | + 'Connection Error when pushing Pingen Document %s to %s.' % |
1488 | + (document.id, pingen.url)) |
1489 | + raise |
1490 | + |
1491 | + except APIError as e: |
1492 | + _logger.error( |
1493 | + 'API Error when pushing Pingen Document %s to %s.' % |
1494 | + (document.id, pingen.url)) |
1495 | + raise |
1496 | + |
1497 | + error = False |
1498 | + state = 'pushed' |
1499 | + if post_id: |
1500 | + state = 'sendcenter' |
1501 | + elif infos['requirement_failure']: |
1502 | + state = 'pingen_error' |
1503 | + error = _('The document does not meet the Pingen requirements.') |
1504 | + |
1505 | + document.write( |
1506 | + {'last_error_message': error, |
1507 | + 'state': state, |
1508 | + 'push_date': infos['date'], |
1509 | + 'pingen_id': doc_id, |
1510 | + 'post_id': post_id}, |
1511 | + context=context) |
1512 | + _logger.info('Pingen Document %s: pushed to %s' % (document.id, pingen.url)) |
1513 | + |
1514 | + def push_to_pingen(self, cr, uid, ids, context=None): |
1515 | + """ Push a document to pingen.com |
1516 | + |
1517 | + Convert errors to osv.except_osv to be handled by the client. |
1518 | + |
1519 | + Wrapper method for multiple ids (when triggered from button for |
1520 | + instance) for public interface. |
1521 | + """ |
1522 | + assert len(ids) == 1, "Only 1 id is allowed" |
1523 | + with self._get_pingen_session(cr, uid, context=context) as session: |
1524 | + for document in self.browse(cr, uid, ids, context=context): |
1525 | + try: |
1526 | + self._push_to_pingen( |
1527 | + cr, uid, document, pingen=session, context=context) |
1528 | + except ConnectionError as e: |
1529 | + raise osv.except_osv( |
1530 | + _('Pingen Connection Error'), |
1531 | + _('Connection Error when asking for sending the document %s to Pingen') % document.name) |
1532 | + |
1533 | + except APIError as e: |
1534 | + raise osv.except_osv( |
1535 | + _('Pingen Error'), |
1536 | + _('Error when asking Pingen to send the document %s: ' |
1537 | + '\n%s') % (document.name, e)) |
1538 | + |
1539 | + except: |
1540 | + _logger.exception( |
1541 | + 'Unexcepted Error when updating the status of pingen.document %s: ' % |
1542 | + document.id) |
1543 | + raise osv.except_osv( |
1544 | + _('Error'), |
1545 | + _('Unexcepted Error when updating the status of Document %s') % document.name) |
1546 | + return True |
1547 | + |
1548 | + def _push_and_send_to_pingen_cron(self, cr, uid, ids, context=None): |
1549 | + """ Push a document to pingen.com |
1550 | + |
1551 | + Intended to be used in a cron. |
1552 | + |
1553 | + Commit after each record |
1554 | + |
1555 | + Instead of raising, store the error in the pingen.document |
1556 | + """ |
1557 | + if not ids: |
1558 | + ids = self.search( |
1559 | + cr, uid, |
1560 | + # do not retry pingen_error, they should be treated manually |
1561 | + [('state', 'in', ['pending', 'pushed', 'error'])], |
1562 | + limit=100, |
1563 | + context=context) |
1564 | + |
1565 | + with closing(pooler.get_db(cr.dbname).cursor()) as loc_cr, \ |
1566 | + self._get_pingen_session(cr, uid, context=context) as session: |
1567 | + for document in self.browse(loc_cr, uid, ids, context=context): |
1568 | + |
1569 | + if document.state == 'error': |
1570 | + self._resolve_error(loc_cr, uid, document, context=context) |
1571 | + document.refresh() |
1572 | + |
1573 | + try: |
1574 | + if document.state == 'pending': |
1575 | + self._push_to_pingen( |
1576 | + loc_cr, uid, document, pingen=session, context=context) |
1577 | + |
1578 | + elif document.state == 'pushed': |
1579 | + self._ask_pingen_send( |
1580 | + loc_cr, uid, document, pingen=session, context=context) |
1581 | + except ConnectionError as e: |
1582 | + document.write({'last_error_message': e, |
1583 | + 'state': 'error'}, |
1584 | + context=context) |
1585 | + except APIError as e: |
1586 | + document.write({'last_error_message': e, |
1587 | + 'state': 'pingen_error'}, |
1588 | + context=context) |
1589 | + except: |
1590 | + _logger.error('Unexcepted error in pingen cron') |
1591 | + loc_cr.rollback() |
1592 | + raise |
1593 | + |
1594 | + else: |
1595 | + loc_cr.commit() |
1596 | + |
1597 | + return True |
1598 | + |
1599 | + def _resolve_error(self, cr, uid, document, context=None): |
1600 | + """ A document as resolved, put in the correct state """ |
1601 | + if document.post_id: |
1602 | + state = 'sendcenter' |
1603 | + elif document.pingen_id: |
1604 | + state = 'pushed' |
1605 | + else: |
1606 | + state = 'pending' |
1607 | + document.write({'state': state}, context=context) |
1608 | + |
1609 | + def resolve_error(self, cr, uid, ids, context=None): |
1610 | + """ A document as resolved, put in the correct state """ |
1611 | + for document in self.browse(cr, uid, ids, context=context): |
1612 | + self._resolve_error(cr, uid, document, context=context) |
1613 | + return True |
1614 | + |
1615 | + def _ask_pingen_send(self, cr, uid, document, pingen, context=None): |
1616 | + """ For a document already pushed to pingen, ask to send it. |
1617 | + |
1618 | + :param Pingen pingen: pingen object to reuse |
1619 | + """ |
1620 | + # sending has been explicitely asked so we change the option |
1621 | + # for consistency |
1622 | + if not document.pingen_send: |
1623 | + document.write({'pingen_send': True}, context=context) |
1624 | + |
1625 | + try: |
1626 | + post_id = pingen.send_document( |
1627 | + document.pingen_id, |
1628 | + document.pingen_speed, |
1629 | + document.pingen_color) |
1630 | + except ConnectionError as e: |
1631 | + _logger.exception('Connection Error when asking for sending Pingen Document %s to %s.' % |
1632 | + (document.id, pingen.url)) |
1633 | + raise |
1634 | + except APIError as e: |
1635 | + _logger.exception('API Error when asking for sending Pingen Document %s to %s.' % |
1636 | + (document.id, pingen.url)) |
1637 | + raise |
1638 | + |
1639 | + document.write( |
1640 | + {'last_error_message': False, |
1641 | + 'state': 'sendcenter', |
1642 | + 'post_id': post_id}, |
1643 | + context=context) |
1644 | + _logger.info('Pingen Document %s: asked for sending to %s' % (document.id, pingen.url)) |
1645 | + |
1646 | + return True |
1647 | + |
1648 | + def ask_pingen_send(self, cr, uid, ids, context=None): |
1649 | + """ For a document already pushed to pingen, ask to send it. |
1650 | + |
1651 | + Wrapper method for multiple ids (when triggered from button for |
1652 | + instance) for public interface. |
1653 | + """ |
1654 | + assert len(ids) == 1, "Only 1 id is allowed" |
1655 | + with self._get_pingen_session(cr, uid, context=context) as session: |
1656 | + for document in self.browse(cr, uid, ids, context=context): |
1657 | + try: |
1658 | + self._ask_pingen_send(cr, uid, document, pingen=session, context=context) |
1659 | + except ConnectionError as e: |
1660 | + raise osv.except_osv( |
1661 | + _('Pingen Connection Error'), |
1662 | + _('Connection Error when asking for ' |
1663 | + 'sending the document %s to Pingen') % document.name) |
1664 | + |
1665 | + except APIError as e: |
1666 | + raise osv.except_osv( |
1667 | + _('Pingen Error'), |
1668 | + _('Error when asking Pingen to send the document %s: ' |
1669 | + '\n%s') % (document.name, e)) |
1670 | + |
1671 | + except: |
1672 | + _logger.exception( |
1673 | + 'Unexcepted Error when updating the status of pingen.document %s: ' % |
1674 | + document.id) |
1675 | + raise osv.except_osv( |
1676 | + _('Error'), |
1677 | + _('Unexcepted Error when updating the status of Document %s') % document.name) |
1678 | + return True |
1679 | + |
1680 | + def _update_post_infos(self, cr, uid, document, pingen, context=None): |
1681 | + """ Update the informations from pingen of a document in the Sendcenter |
1682 | + |
1683 | + :param Pingen pingen: pingen object to reuse |
1684 | + """ |
1685 | + if not document.post_id: |
1686 | + return |
1687 | + |
1688 | + try: |
1689 | + post_infos = pingen.post_infos(document.post_id) |
1690 | + except ConnectionError as e: |
1691 | + _logger.exception( |
1692 | + 'Connection Error when asking for ' |
1693 | + 'sending Pingen Document %s to %s.' % |
1694 | + (document.id, pingen.url)) |
1695 | + raise |
1696 | + except APIError as e: |
1697 | + _logger.exception( |
1698 | + 'API Error when asking for sending Pingen Document %s to %s.' % |
1699 | + (document.id, pingen.url)) |
1700 | + raise |
1701 | + |
1702 | + currency_ids = self.pool.get('res.currency').search( |
1703 | + cr, uid, [('name', '=', post_infos['currency'])], context=context) |
1704 | + country_ids = self.pool.get('res.country').search( |
1705 | + cr, uid, [('code', '=', post_infos['country'])], context=context) |
1706 | + vals = { |
1707 | + 'post_status': POST_SENDING_STATUS[post_infos['status']], |
1708 | + 'cost': post_infos['cost'], |
1709 | + 'currency_id': currency_ids[0] if currency_ids else False, |
1710 | + 'parsed_address': post_infos['address'], |
1711 | + 'country_id': country_ids[0] if country_ids else False, |
1712 | + 'send_date': post_infos['date'], |
1713 | + 'pages': post_infos['pages'], |
1714 | + 'last_error_message': False, |
1715 | + } |
1716 | + if pingen.is_posted(post_infos): |
1717 | + vals['state'] = 'sent' |
1718 | + |
1719 | + document.write(vals, context=context) |
1720 | + _logger.info('Pingen Document %s: status updated' % document.id) |
1721 | + |
1722 | + def _update_post_infos_cron(self, cr, uid, ids, context=None): |
1723 | + """ Update the informations from pingen of a document in the Sendcenter |
1724 | + |
1725 | + Intended to be used in a cron. |
1726 | + |
1727 | + Commit after each record |
1728 | + |
1729 | + Do not raise errors, only skip the update of the record. |
1730 | + """ |
1731 | + if not ids: |
1732 | + ids = self.search( |
1733 | + cr, uid, |
1734 | + [('state', '=', 'sendcenter')], |
1735 | + context=context) |
1736 | + |
1737 | + with closing(pooler.get_db(cr.dbname).cursor()) as loc_cr, \ |
1738 | + self._get_pingen_session(cr, uid, context=context) as session: |
1739 | + for document in self.browse(loc_cr, uid, ids, context=context): |
1740 | + try: |
1741 | + self._update_post_infos( |
1742 | + loc_cr, uid, document, pingen=session, context=context) |
1743 | + except (ConnectionError, APIError): |
1744 | + # will be retried the next time |
1745 | + # In any case, the error has been logged by _update_post_infos |
1746 | + loc_cr.rollback() |
1747 | + except: |
1748 | + _logger.error('Unexcepted error in pingen cron') |
1749 | + loc_cr.rollback() |
1750 | + raise |
1751 | + else: |
1752 | + loc_cr.commit() |
1753 | + return True |
1754 | + |
1755 | + def update_post_infos(self, cr, uid, ids, context=None): |
1756 | + """ Update the informations from pingen of a document in the Sendcenter |
1757 | + |
1758 | + Wrapper method for multiple ids (when triggered from button for |
1759 | + instance) for public interface. |
1760 | + """ |
1761 | + assert len(ids) == 1, "Only 1 id is allowed" |
1762 | + with self._get_pingen_session(cr, uid, context=context) as session: |
1763 | + for document in self.browse(cr, uid, ids, context=context): |
1764 | + try: |
1765 | + self._update_post_infos( |
1766 | + cr, uid, document, pingen=session, context=context) |
1767 | + except ConnectionError as e: |
1768 | + raise osv.except_osv( |
1769 | + _('Pingen Connection Error'), |
1770 | + _('Connection Error when updating the status of Document %s' |
1771 | + ' from Pingen') % document.name) |
1772 | + |
1773 | + except APIError as e: |
1774 | + raise osv.except_osv( |
1775 | + _('Pingen Error'), |
1776 | + _('Error when updating the status of Document %s from Pingen: ' |
1777 | + '\n%s') % (document.name, e)) |
1778 | + |
1779 | + except: |
1780 | + _logger.exception( |
1781 | + 'Unexcepted Error when updating the status of pingen.document %s: ' % |
1782 | + document.id) |
1783 | + raise osv.except_osv( |
1784 | + _('Error'), |
1785 | + _('Unexcepted Error when updating the status of Document %s') % document.name) |
1786 | + return True |
1787 | + |
1788 | |
1789 | === added file 'pingen/pingen_document_view.xml' |
1790 | --- pingen/pingen_document_view.xml 1970-01-01 00:00:00 +0000 |
1791 | +++ pingen/pingen_document_view.xml 2012-12-07 13:35:25 +0000 |
1792 | @@ -0,0 +1,161 @@ |
1793 | +<?xml version="1.0" encoding="utf-8"?> |
1794 | +<openerp> |
1795 | + <data noupdate="0"> |
1796 | + |
1797 | + <record id="view_pingen_document_tree" model="ir.ui.view"> |
1798 | + <field name="name">pingen.document.tree</field> |
1799 | + <field name="model">pingen.document</field> |
1800 | + <field name="type">tree</field> |
1801 | + <field name="arch" type="xml"> |
1802 | + <tree string="Pingen Document"> |
1803 | + <field name="name"/> |
1804 | + <field name="datas_fname"/> |
1805 | + <field name="pingen_send"/> |
1806 | + <field name="pingen_speed"/> |
1807 | + <field name="pingen_color"/> |
1808 | + <field name="state"/> |
1809 | + </tree> |
1810 | + </field> |
1811 | + </record> |
1812 | + |
1813 | + <record id="view_pingen_document_form" model="ir.ui.view"> |
1814 | + <field name="name">pingen.document.form</field> |
1815 | + <field name="model">pingen.document</field> |
1816 | + <field name="type">form</field> |
1817 | + <field name="arch" type="xml"> |
1818 | + <form string="Pingen Document"> |
1819 | + <group colspan="4" col="6"> |
1820 | + <field name="name" readonly="True"/> |
1821 | + <field name="type" readonly="True"/> |
1822 | + <field name="company_id" readonly="True" groups="base.group_multi_company" widget="selection"/> |
1823 | + </group> |
1824 | + <notebook colspan="4"> |
1825 | + <page string="Pingen.com"> |
1826 | + <separator string="Options" colspan="4"/> |
1827 | + <newline /> |
1828 | + <group col="2" colspan="2"> |
1829 | + <field name="pingen_send" attrs="{'readonly': [('state', 'in', ['sendcenter', 'sent'])]}"/> |
1830 | + <field name="pingen_speed" attrs="{'readonly': [('state', 'in', ['sendcenter', 'sent'])], 'required': [('pingen_send', '=', True)]}"/> |
1831 | + <field name="pingen_color" attrs="{'readonly': [('state', 'in', ['sendcenter', 'sent'])]}"/> |
1832 | + </group> |
1833 | + |
1834 | + <separator string="Dates" colspan="4"/> |
1835 | + <newline /> |
1836 | + <group col="2" colspan="2"> |
1837 | + <field name="push_date"/> |
1838 | + </group> |
1839 | + |
1840 | + <group colspan="4" attrs="{'invisible': [('last_error_message', '=', False)]}"> |
1841 | + <separator string="Errors" colspan="4"/> |
1842 | + <newline /> |
1843 | + <group col="2" colspan="2"> |
1844 | + <field nolabel="1" name="last_error_message"/> |
1845 | + </group> |
1846 | + </group> |
1847 | + |
1848 | + <group colspan="4" attrs="{'invisible': [('state', 'not in', ['sendcenter', 'sent'])]}"> |
1849 | + <separator string="Sendcenter" colspan="4"/> |
1850 | + <newline /> |
1851 | + <group col="4" colspan="2"> |
1852 | + <field colspan="4" name="post_status"/> |
1853 | + <group col="3" colspan="2"> |
1854 | + <field name="cost"/> |
1855 | + <field colspan="1" nolabel="1" name="currency_id"/> |
1856 | + </group> |
1857 | + <newline/> |
1858 | + <field name="parsed_address"/> |
1859 | + <field name="country_id"/> |
1860 | + <field name="send_date"/> |
1861 | + <field name="pages"/> |
1862 | + </group> |
1863 | + </group> |
1864 | + |
1865 | + <separator string="Actions" colspan="4"/> |
1866 | + <newline /> |
1867 | + <group col="2" colspan="2"> |
1868 | + <button name="push_to_pingen" type="object" |
1869 | + states="pending" |
1870 | + string="Push to pingen.com" icon="terp-stage"/> |
1871 | + <button name="ask_pingen_send" type="object" |
1872 | + states="pushed" |
1873 | + string="Ask pingen.com to send the document" icon="gtk-print"/> |
1874 | + <button name="resolve_error" type="object" |
1875 | + states="error,pingen_error" |
1876 | + string="Errors resolved" icon="gtk-redo"/> |
1877 | + <button name="update_post_infos" type="object" |
1878 | + states="sendcenter" |
1879 | + string="Update the letter's informations" icon="gtk-refresh"/> |
1880 | + </group> |
1881 | + </page> |
1882 | + <page string="Attachment"> |
1883 | + <group col="4" colspan="4"> |
1884 | + <separator string="Data" colspan="4"/> |
1885 | + <newline /> |
1886 | + <group col="2" colspan="4" attrs="{'invisible':[('type','=','url')]}"> |
1887 | + <field name="datas" filename="datas_fname" readonly="True"/> |
1888 | + <field name="datas_fname" select="1" readonly="True"/> |
1889 | + </group> |
1890 | + <group col="2" colspan="4" attrs="{'invisible':[('type','=','binary')]}"> |
1891 | + <field name="url" widget="url" readonly="True"/> |
1892 | + </group> |
1893 | + </group> |
1894 | + <group col="2" colspan="4"> |
1895 | + <separator string="Attached To" colspan="2"/> |
1896 | + <field name="attachment_id"/> |
1897 | + </group> |
1898 | + </page> |
1899 | + </notebook> |
1900 | + |
1901 | + <field name="state" widget="statusbar" |
1902 | + statusbar_visible="pending,pushed,sent" |
1903 | + statusbar_colors='{"error":"red","pingen_error":"red","canceled":"grey","pushed":"blue","sent":"green"}'/> |
1904 | + </form> |
1905 | + </field> |
1906 | + </record> |
1907 | + |
1908 | + <record id="view_pingen_document_search" model="ir.ui.view"> |
1909 | + <field name="name">pingen.document.search</field> |
1910 | + <field name="model">pingen.document</field> |
1911 | + <field name="type">search</field> |
1912 | + <field name="arch" type="xml"> |
1913 | + <search string="Pingen Document"> |
1914 | + <filter icon="terp-project" |
1915 | + string="Pending" |
1916 | + domain="[('state','=','pending')]"/> |
1917 | + <filter icon="terp-stage" |
1918 | + string="Pushed" |
1919 | + domain="[('state','=','pushed')]"/> |
1920 | + <filter icon="gtk-print" |
1921 | + string="In Sendcenter" |
1922 | + domain="[('state','=','sendcenter')]"/> |
1923 | + <filter icon="kanban-apply" |
1924 | + string="Sent" |
1925 | + domain="[('state','=','sent')]"/> |
1926 | + <filter icon="kanban-stop" |
1927 | + string="Error" |
1928 | + domain="[('state','=','error')]"/> |
1929 | + <filter icon="STOCK_NO" |
1930 | + string="Pingen Error" |
1931 | + domain="[('state','=','pingen_error')]"/> |
1932 | + <filter icon="terp-dialog-close" |
1933 | + string="Canceled" |
1934 | + domain="[('state','=','canceled')]"/> |
1935 | + <separator orientation="vertical"/> |
1936 | + <field name="attachment_id" /> |
1937 | + </search> |
1938 | + </field> |
1939 | + </record> |
1940 | + |
1941 | + <record id="action_pingen_document" model="ir.actions.act_window"> |
1942 | + <field name="name">Pingen Documents</field> |
1943 | + <field name="type">ir.actions.act_window</field> |
1944 | + <field name="res_model">pingen.document</field> |
1945 | + <field name="view_type">form</field> |
1946 | + <field name="view_mode">tree,form</field> |
1947 | + <field name="search_view_id" ref="view_pingen_document_search"/> |
1948 | + </record> |
1949 | + |
1950 | + <menuitem action="action_pingen_document" id="menu_pingen_document" parent="base.next_id_4"/> |
1951 | + |
1952 | + </data> |
1953 | +</openerp> |
1954 | |
1955 | === added file 'pingen/res_company.py' |
1956 | --- pingen/res_company.py 1970-01-01 00:00:00 +0000 |
1957 | +++ pingen/res_company.py 2012-12-07 13:35:25 +0000 |
1958 | @@ -0,0 +1,42 @@ |
1959 | +# -*- coding: utf-8 -*- |
1960 | +############################################################################## |
1961 | +# |
1962 | +# Author: Guewen Baconnier |
1963 | +# Copyright 2012 Camptocamp SA |
1964 | +# |
1965 | +# This program is free software: you can redistribute it and/or modify |
1966 | +# it under the terms of the GNU Affero General Public License as |
1967 | +# published by the Free Software Foundation, either version 3 of the |
1968 | +# License, or (at your option) any later version. |
1969 | +# |
1970 | +# This program is distributed in the hope that it will be useful, |
1971 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1972 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1973 | +# GNU Affero General Public License for more details. |
1974 | +# |
1975 | +# You should have received a copy of the GNU Affero General Public License |
1976 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1977 | +# |
1978 | +############################################################################## |
1979 | + |
1980 | +from openerp.osv import orm, fields |
1981 | +from openerp.osv.orm import browse_record |
1982 | +from .pingen import Pingen |
1983 | + |
1984 | +class res_company(orm.Model): |
1985 | + |
1986 | + _inherit = 'res.company' |
1987 | + |
1988 | + _columns = { |
1989 | + 'pingen_token': fields.char('Pingen Token', size=32), |
1990 | + 'pingen_staging': fields.boolean('Pingen Staging') |
1991 | + } |
1992 | + |
1993 | + def _pingen(self, cr, uid, company, context=None): |
1994 | + """ Return a Pingen instance to work on """ |
1995 | + assert isinstance(company, (int, long, browse_record)), \ |
1996 | + "one id or browse_record expected" |
1997 | + if not isinstance(company, browse_record): |
1998 | + company = self.browse(cr, uid, company_id, context=context) |
1999 | + return Pingen(company.pingen_token, staging=company.pingen_staging) |
2000 | + |
2001 | |
2002 | === added file 'pingen/res_company_view.xml' |
2003 | --- pingen/res_company_view.xml 1970-01-01 00:00:00 +0000 |
2004 | +++ pingen/res_company_view.xml 2012-12-07 13:35:25 +0000 |
2005 | @@ -0,0 +1,20 @@ |
2006 | +<?xml version="1.0" encoding="utf-8"?> |
2007 | +<openerp> |
2008 | + <data noupdate="0"> |
2009 | + |
2010 | + <record model="ir.ui.view" id="view_company_inherit_form"> |
2011 | + <field name="name">res.company.form.inherit</field> |
2012 | + <field name="model">res.company</field> |
2013 | + <field name="type">form</field> |
2014 | + <field name="inherit_id" ref="base.view_company_form"/> |
2015 | + <field name="arch" type="xml"> |
2016 | + <page string="Configuration" position="inside"> |
2017 | + <separator string="Pingen.com" colspan="4"/> |
2018 | + <field name="pingen_token" groups="base.group_system"/> |
2019 | + <field name="pingen_staging" groups="base.group_system"/> |
2020 | + </page> |
2021 | + </field> |
2022 | + </record> |
2023 | + |
2024 | + </data> |
2025 | +</openerp> |
2026 | |
2027 | === added directory 'pingen/security' |
2028 | === added file 'pingen/security/ir.model.access.csv' |
2029 | --- pingen/security/ir.model.access.csv 1970-01-01 00:00:00 +0000 |
2030 | +++ pingen/security/ir.model.access.csv 2012-12-07 13:35:25 +0000 |
2031 | @@ -0,0 +1,3 @@ |
2032 | +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" |
2033 | +"access_pingen_document_all","pingen_document all","model_pingen_document",,1,0,0,0 |
2034 | +"access_pingen_document_group_user","pingen_document group_user","model_pingen_document","base.group_user",1,1,1,1 |
2035 | |
2036 | === added directory 'pingen_document' |
2037 | === added file 'pingen_document/__init__.py' |
2038 | --- pingen_document/__init__.py 1970-01-01 00:00:00 +0000 |
2039 | +++ pingen_document/__init__.py 2012-12-07 13:35:25 +0000 |
2040 | @@ -0,0 +1,21 @@ |
2041 | +# -*- coding: utf-8 -*- |
2042 | +############################################################################## |
2043 | +# |
2044 | +# Author: Guewen Baconnier |
2045 | +# Copyright 2012 Camptocamp SA |
2046 | +# |
2047 | +# This program is free software: you can redistribute it and/or modify |
2048 | +# it under the terms of the GNU Affero General Public License as |
2049 | +# published by the Free Software Foundation, either version 3 of the |
2050 | +# License, or (at your option) any later version. |
2051 | +# |
2052 | +# This program is distributed in the hope that it will be useful, |
2053 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2054 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2055 | +# GNU Affero General Public License for more details. |
2056 | +# |
2057 | +# You should have received a copy of the GNU Affero General Public License |
2058 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2059 | +# |
2060 | +############################################################################## |
2061 | + |
2062 | |
2063 | === added file 'pingen_document/__openerp__.py' |
2064 | --- pingen_document/__openerp__.py 1970-01-01 00:00:00 +0000 |
2065 | +++ pingen_document/__openerp__.py 2012-12-07 13:35:25 +0000 |
2066 | @@ -0,0 +1,41 @@ |
2067 | +# -*- coding: utf-8 -*- |
2068 | +############################################################################## |
2069 | +# |
2070 | +# Author: Guewen Baconnier |
2071 | +# Copyright 2012 Camptocamp SA |
2072 | +# |
2073 | +# This program is free software: you can redistribute it and/or modify |
2074 | +# it under the terms of the GNU Affero General Public License as |
2075 | +# published by the Free Software Foundation, either version 3 of the |
2076 | +# License, or (at your option) any later version. |
2077 | +# |
2078 | +# This program is distributed in the hope that it will be useful, |
2079 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2080 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2081 | +# GNU Affero General Public License for more details. |
2082 | +# |
2083 | +# You should have received a copy of the GNU Affero General Public License |
2084 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2085 | +# |
2086 | +############################################################################## |
2087 | + |
2088 | +{ |
2089 | + 'name' : 'pingen.com integration (document)', |
2090 | + 'version' : '1.0', |
2091 | + 'author' : 'Camptocamp', |
2092 | + 'maintainer': 'Camptocamp', |
2093 | + 'license': 'AGPL-3', |
2094 | + 'category': 'Reporting', |
2095 | + 'complexity': 'easy', |
2096 | + 'depends' : ['document', 'pingen'], |
2097 | + 'description': """ |
2098 | +Glue module between the `pingen` and the `document` modules. |
2099 | +""", |
2100 | + 'website': 'http://www.camptocamp.com', |
2101 | + 'data': [ |
2102 | + 'pingen_document_view.xml', |
2103 | + ], |
2104 | + 'tests': [], |
2105 | + 'installable': True, |
2106 | + 'auto_install': True, |
2107 | +} |
2108 | |
2109 | === added directory 'pingen_document/i18n' |
2110 | === added file 'pingen_document/i18n/de.po' |
2111 | --- pingen_document/i18n/de.po 1970-01-01 00:00:00 +0000 |
2112 | +++ pingen_document/i18n/de.po 2012-12-07 13:35:25 +0000 |
2113 | @@ -0,0 +1,32 @@ |
2114 | +# Translation of OpenERP Server. |
2115 | +# This file contains the translation of the following modules: |
2116 | +# * pingen_document |
2117 | +# |
2118 | +msgid "" |
2119 | +msgstr "" |
2120 | +"Project-Id-Version: OpenERP Server 6.1\n" |
2121 | +"Report-Msgid-Bugs-To: \n" |
2122 | +"POT-Creation-Date: 2012-11-26 10:54+0000\n" |
2123 | +"PO-Revision-Date: 2012-11-26 10:54+0000\n" |
2124 | +"Last-Translator: <>\n" |
2125 | +"Language-Team: \n" |
2126 | +"MIME-Version: 1.0\n" |
2127 | +"Content-Type: text/plain; charset=UTF-8\n" |
2128 | +"Content-Transfer-Encoding: \n" |
2129 | +"Plural-Forms: \n" |
2130 | + |
2131 | +#. module: pingen_document |
2132 | +#: view:ir.attachment:0 |
2133 | +msgid "Notes" |
2134 | +msgstr "Notes" |
2135 | + |
2136 | +#. module: pingen_document |
2137 | +#: model:ir.ui.menu,name:pingen_document.menu_pingen_document_document |
2138 | +msgid "Pingen Documents" |
2139 | +msgstr "Pingen Documents" |
2140 | + |
2141 | +#. module: pingen_document |
2142 | +#: view:ir.attachment:0 |
2143 | +msgid "Pingen.com" |
2144 | +msgstr "Pingen.com" |
2145 | + |
2146 | |
2147 | === added file 'pingen_document/i18n/en.po' |
2148 | --- pingen_document/i18n/en.po 1970-01-01 00:00:00 +0000 |
2149 | +++ pingen_document/i18n/en.po 2012-12-07 13:35:25 +0000 |
2150 | @@ -0,0 +1,32 @@ |
2151 | +# Translation of OpenERP Server. |
2152 | +# This file contains the translation of the following modules: |
2153 | +# * pingen_document |
2154 | +# |
2155 | +msgid "" |
2156 | +msgstr "" |
2157 | +"Project-Id-Version: OpenERP Server 6.1\n" |
2158 | +"Report-Msgid-Bugs-To: \n" |
2159 | +"POT-Creation-Date: 2012-11-26 10:54+0000\n" |
2160 | +"PO-Revision-Date: 2012-11-26 10:54+0000\n" |
2161 | +"Last-Translator: <>\n" |
2162 | +"Language-Team: \n" |
2163 | +"MIME-Version: 1.0\n" |
2164 | +"Content-Type: text/plain; charset=UTF-8\n" |
2165 | +"Content-Transfer-Encoding: \n" |
2166 | +"Plural-Forms: \n" |
2167 | + |
2168 | +#. module: pingen_document |
2169 | +#: view:ir.attachment:0 |
2170 | +msgid "Notes" |
2171 | +msgstr "Notes" |
2172 | + |
2173 | +#. module: pingen_document |
2174 | +#: model:ir.ui.menu,name:pingen_document.menu_pingen_document_document |
2175 | +msgid "Pingen Documents" |
2176 | +msgstr "Pingen Documents" |
2177 | + |
2178 | +#. module: pingen_document |
2179 | +#: view:ir.attachment:0 |
2180 | +msgid "Pingen.com" |
2181 | +msgstr "Pingen.com" |
2182 | + |
2183 | |
2184 | === added file 'pingen_document/i18n/es.po' |
2185 | --- pingen_document/i18n/es.po 1970-01-01 00:00:00 +0000 |
2186 | +++ pingen_document/i18n/es.po 2012-12-07 13:35:25 +0000 |
2187 | @@ -0,0 +1,32 @@ |
2188 | +# Translation of OpenERP Server. |
2189 | +# This file contains the translation of the following modules: |
2190 | +# * pingen_document |
2191 | +# |
2192 | +msgid "" |
2193 | +msgstr "" |
2194 | +"Project-Id-Version: OpenERP Server 6.1\n" |
2195 | +"Report-Msgid-Bugs-To: \n" |
2196 | +"POT-Creation-Date: 2012-11-26 10:54+0000\n" |
2197 | +"PO-Revision-Date: 2012-11-26 10:54+0000\n" |
2198 | +"Last-Translator: <>\n" |
2199 | +"Language-Team: \n" |
2200 | +"MIME-Version: 1.0\n" |
2201 | +"Content-Type: text/plain; charset=UTF-8\n" |
2202 | +"Content-Transfer-Encoding: \n" |
2203 | +"Plural-Forms: \n" |
2204 | + |
2205 | +#. module: pingen_document |
2206 | +#: view:ir.attachment:0 |
2207 | +msgid "Notes" |
2208 | +msgstr "Notes" |
2209 | + |
2210 | +#. module: pingen_document |
2211 | +#: model:ir.ui.menu,name:pingen_document.menu_pingen_document_document |
2212 | +msgid "Pingen Documents" |
2213 | +msgstr "Pingen Documents" |
2214 | + |
2215 | +#. module: pingen_document |
2216 | +#: view:ir.attachment:0 |
2217 | +msgid "Pingen.com" |
2218 | +msgstr "Pingen.com" |
2219 | + |
2220 | |
2221 | === added file 'pingen_document/i18n/fr.po' |
2222 | --- pingen_document/i18n/fr.po 1970-01-01 00:00:00 +0000 |
2223 | +++ pingen_document/i18n/fr.po 2012-12-07 13:35:25 +0000 |
2224 | @@ -0,0 +1,32 @@ |
2225 | +# Translation of OpenERP Server. |
2226 | +# This file contains the translation of the following modules: |
2227 | +# * pingen_document |
2228 | +# |
2229 | +msgid "" |
2230 | +msgstr "" |
2231 | +"Project-Id-Version: OpenERP Server 6.1\n" |
2232 | +"Report-Msgid-Bugs-To: \n" |
2233 | +"POT-Creation-Date: 2012-11-26 10:56+0000\n" |
2234 | +"PO-Revision-Date: 2012-11-26 10:56+0000\n" |
2235 | +"Last-Translator: <>\n" |
2236 | +"Language-Team: \n" |
2237 | +"MIME-Version: 1.0\n" |
2238 | +"Content-Type: text/plain; charset=UTF-8\n" |
2239 | +"Content-Transfer-Encoding: \n" |
2240 | +"Plural-Forms: \n" |
2241 | + |
2242 | +#. module: pingen_document |
2243 | +#: view:ir.attachment:0 |
2244 | +msgid "Notes" |
2245 | +msgstr "Notes" |
2246 | + |
2247 | +#. module: pingen_document |
2248 | +#: model:ir.ui.menu,name:pingen_document.menu_pingen_document_document |
2249 | +msgid "Pingen Documents" |
2250 | +msgstr "Documents Pingen" |
2251 | + |
2252 | +#. module: pingen_document |
2253 | +#: view:ir.attachment:0 |
2254 | +msgid "Pingen.com" |
2255 | +msgstr "Pingen.com" |
2256 | + |
2257 | |
2258 | === added file 'pingen_document/i18n/pingen_document.pot' |
2259 | --- pingen_document/i18n/pingen_document.pot 1970-01-01 00:00:00 +0000 |
2260 | +++ pingen_document/i18n/pingen_document.pot 2012-12-07 13:35:25 +0000 |
2261 | @@ -0,0 +1,32 @@ |
2262 | +# Translation of OpenERP Server. |
2263 | +# This file contains the translation of the following modules: |
2264 | +# * pingen_document |
2265 | +# |
2266 | +msgid "" |
2267 | +msgstr "" |
2268 | +"Project-Id-Version: OpenERP Server 6.1\n" |
2269 | +"Report-Msgid-Bugs-To: \n" |
2270 | +"POT-Creation-Date: 2012-11-26 10:56+0000\n" |
2271 | +"PO-Revision-Date: 2012-11-26 10:56+0000\n" |
2272 | +"Last-Translator: <>\n" |
2273 | +"Language-Team: \n" |
2274 | +"MIME-Version: 1.0\n" |
2275 | +"Content-Type: text/plain; charset=UTF-8\n" |
2276 | +"Content-Transfer-Encoding: \n" |
2277 | +"Plural-Forms: \n" |
2278 | + |
2279 | +#. module: pingen_document |
2280 | +#: view:ir.attachment:0 |
2281 | +msgid "Notes" |
2282 | +msgstr "" |
2283 | + |
2284 | +#. module: pingen_document |
2285 | +#: model:ir.ui.menu,name:pingen_document.menu_pingen_document_document |
2286 | +msgid "Pingen Documents" |
2287 | +msgstr "" |
2288 | + |
2289 | +#. module: pingen_document |
2290 | +#: view:ir.attachment:0 |
2291 | +msgid "Pingen.com" |
2292 | +msgstr "" |
2293 | + |
2294 | |
2295 | === added file 'pingen_document/pingen_document_view.xml' |
2296 | --- pingen_document/pingen_document_view.xml 1970-01-01 00:00:00 +0000 |
2297 | +++ pingen_document/pingen_document_view.xml 2012-12-07 13:35:25 +0000 |
2298 | @@ -0,0 +1,27 @@ |
2299 | +<?xml version="1.0" encoding="utf-8"?> |
2300 | +<openerp> |
2301 | + <data noupdate="0"> |
2302 | + |
2303 | + <record id="view_document_file_form" model="ir.ui.view"> |
2304 | + <field name="name">ir.attachment.document.pingen.view</field> |
2305 | + <field name="model">ir.attachment</field> |
2306 | + <field name="type">form</field> |
2307 | + <field name="inherit_id" ref="document.view_document_file_form"/> |
2308 | + <field name="arch" type="xml"> |
2309 | + <page string="Notes" position="before"> |
2310 | + <page string="Pingen.com"> |
2311 | + <field name="send_to_pingen"/> |
2312 | + <field name="pingen_send" attrs="{'required': [('send_to_pingen', '=', True)]}"/> |
2313 | + <field name="pingen_speed" attrs="{'required': [('pingen_send', '=', True)]}"/> |
2314 | + <field name="pingen_color" /> |
2315 | + </page> |
2316 | + </page> |
2317 | + </field> |
2318 | + </record> |
2319 | + |
2320 | + <menuitem action="pingen.action_pingen_document" |
2321 | + id="menu_pingen_document_document" |
2322 | + parent="document.menu_document_doc"/> |
2323 | + |
2324 | + </data> |
2325 | +</openerp> |
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.