Merge lp:~ssebastian/openerp-usa/shipping_api_usps into lp:openerp-usa/6.1.x
- shipping_api_usps
- Merge into US_Localization_v6
Proposed by
Sinoj Sebastin
Status: | Merged |
---|---|
Merged at revision: | 69 |
Proposed branch: | lp:~ssebastian/openerp-usa/shipping_api_usps |
Merge into: | lp:openerp-usa/6.1.x |
Diff against target: |
1347 lines (+1274/-0) 13 files modified
shipping_api_usps/Change Log.txt (+23/-0) shipping_api_usps/__init__.py (+28/-0) shipping_api_usps/__openerp__.py (+44/-0) shipping_api_usps/logistic_company_view.xml (+31/-0) shipping_api_usps/sale.py (+149/-0) shipping_api_usps/sale_view.xml (+36/-0) shipping_api_usps/stock.py (+459/-0) shipping_api_usps/stock_view.xml (+48/-0) shipping_api_usps/wizard/__init__.py (+26/-0) shipping_api_usps/wizard/wizard_shipping_rate_calculation.py (+306/-0) shipping_api_usps/wizard/wizard_shipping_rate_view.xml (+36/-0) shipping_api_usps/wizard/xml2dic.py (+44/-0) shipping_api_usps/xml2dic.py (+44/-0) |
To merge this branch: | bzr merge lp:~ssebastian/openerp-usa/shipping_api_usps |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
npg | Pending | ||
Review via email: mp+116398@code.launchpad.net |
Commit message
Description of the change
Added module shipping_api_usps
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory 'shipping_api_usps' |
2 | === added file 'shipping_api_usps/Change Log.txt' |
3 | --- shipping_api_usps/Change Log.txt 1970-01-01 00:00:00 +0000 |
4 | +++ shipping_api_usps/Change Log.txt 2012-07-24 04:29:18 +0000 |
5 | @@ -0,0 +1,23 @@ |
6 | +=============================================================================== |
7 | + Version Change Log (shipping_api_usps) |
8 | +=============================================================================== |
9 | +@TODO : SECURITY |
10 | + |
11 | +1.6 on 2011-12-29 by Arif |
12 | + * Shipment details from Sales Order to Delivery Order |
13 | + |
14 | +1.5 - 2011-12-27 by Arif |
15 | + * Added required fields in sales order, stock and wizard for ship charge |
16 | + * Ship rate request and response |
17 | + |
18 | +1.4 - 2011-12-23 by Arif |
19 | + * Ship rate request - Ship charge calculation in Sales Order |
20 | + |
21 | +1.3 - 2011-12-12 by Arif |
22 | + * Fixed bug on Label printing |
23 | + |
24 | +1.2 - 2011-12-12 by Arif |
25 | + * Fixed bug on Process shipment |
26 | + |
27 | +1.0 (2011-10-17) by Arif |
28 | + * Basic functions for USPS |
29 | |
30 | === added file 'shipping_api_usps/__init__.py' |
31 | --- shipping_api_usps/__init__.py 1970-01-01 00:00:00 +0000 |
32 | +++ shipping_api_usps/__init__.py 2012-07-24 04:29:18 +0000 |
33 | @@ -0,0 +1,28 @@ |
34 | +# -*- coding: utf-8 -*- |
35 | +############################################################################## |
36 | +# |
37 | +# OpenERP, Open Source Management Solution |
38 | +# Copyright (C) 2011 NovaPoint Group LLC (<http://www.novapointgroup.com>) |
39 | +# Copyright (C) 2004-2010 OpenERP SA (<http://www.openerp.com>) |
40 | +# |
41 | +# This program is free software: you can redistribute it and/or modify |
42 | +# it under the terms of the GNU General Public License as published by |
43 | +# the Free Software Foundation, either version 3 of the License, or |
44 | +# (at your option) any later version. |
45 | +# |
46 | +# This program is distributed in the hope that it will be useful, |
47 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
48 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
49 | +# GNU General Public License for more details. |
50 | +# |
51 | +# You should have received a copy of the GNU General Public License |
52 | +# along with this program. If not, see <http://www.gnu.org/licenses/> |
53 | +# |
54 | +############################################################################## |
55 | + |
56 | +import stock |
57 | +import sale |
58 | +import wizard |
59 | + |
60 | + |
61 | +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
62 | \ No newline at end of file |
63 | |
64 | === added file 'shipping_api_usps/__openerp__.py' |
65 | --- shipping_api_usps/__openerp__.py 1970-01-01 00:00:00 +0000 |
66 | +++ shipping_api_usps/__openerp__.py 2012-07-24 04:29:18 +0000 |
67 | @@ -0,0 +1,44 @@ |
68 | +# -*- coding: utf-8 -*- |
69 | +############################################################################## |
70 | +# |
71 | +# OpenERP, Open Source Management Solution |
72 | +# Copyright (C) 2011 NovaPoint Group LLC (<http://www.novapointgroup.com>) |
73 | +# Copyright (C) 2004-2010 OpenERP SA (<http://www.openerp.com>) |
74 | +# |
75 | +# This program is free software: you can redistribute it and/or modify |
76 | +# it under the terms of the GNU General Public License as published by |
77 | +# the Free Software Foundation, either version 3 of the License, or |
78 | +# (at your option) any later version. |
79 | +# |
80 | +# This program is distributed in the hope that it will be useful, |
81 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
82 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
83 | +# GNU General Public License for more details. |
84 | +# |
85 | +# You should have received a copy of the GNU General Public License |
86 | +# along with this program. If not, see <http://www.gnu.org/licenses/> |
87 | +# |
88 | +############################################################################## |
89 | + |
90 | +{ |
91 | + 'name': 'Shipping API USPS', |
92 | + 'version': '1.6', |
93 | + 'category': 'Generic Modules/Others', |
94 | + 'description': """ |
95 | + """, |
96 | + 'author': 'NovaPoint Group LLC', |
97 | + 'website': ' http://www.novapointgroup.com', |
98 | + 'depends': ['shipping_api'], |
99 | + 'init_xml': [], |
100 | + 'update_xml': [ |
101 | + 'logistic_company_view.xml', |
102 | + 'stock_view.xml', |
103 | + 'sale_view.xml', |
104 | + 'wizard/wizard_shipping_rate_view.xml' |
105 | + ], |
106 | + 'demo_xml': [ |
107 | + ], |
108 | + 'installable': True, |
109 | + 'active': False, |
110 | +} |
111 | +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
112 | |
113 | === added file 'shipping_api_usps/logistic_company_view.xml' |
114 | --- shipping_api_usps/logistic_company_view.xml 1970-01-01 00:00:00 +0000 |
115 | +++ shipping_api_usps/logistic_company_view.xml 2012-07-24 04:29:18 +0000 |
116 | @@ -0,0 +1,31 @@ |
117 | +<?xml version="1.0" encoding="UTF-8"?> |
118 | +<openerp> |
119 | + <data> |
120 | + |
121 | + <record id="logistic_company_form_usps" model="ir.ui.view"> |
122 | + <field name="name">logistic_company_form_usps</field> |
123 | + <field name="model">logistic.company</field> |
124 | + <field name="type">form</field> |
125 | + <field name="inherit_id" ref="shipping_api.view_form_logistic_company" /> |
126 | + <field name="arch" type="xml"> |
127 | + <xpath expr="/form/notebook/page[@string='Notes']" position="before"> |
128 | + <page string="USPS" attrs="{'invisible':[('ship_company_code','!=','usps')]}" > |
129 | + <!-- field name="ups_shipping_account_ids" nolabel='1' colspan="4"/ --> |
130 | + |
131 | + <field name='usps_userid' attrs="{'required':[('ship_company_code','=','usps')]}"/> |
132 | + <newline /> |
133 | + |
134 | + <field name='usps_url_test' attrs="{'required':[('ship_company_code','=','usps'),('test_mode','=',True)]}"/> |
135 | + <field name='usps_url_secure_test' attrs="{'required':[('ship_company_code','=','usps'),('test_mode','=',True)]}"/> |
136 | + <field name='usps_url' attrs="{'required':[('ship_company_code','=','usps'),('test_mode','=', False)]}"/> |
137 | + <field name='usps_url_secure' attrs="{'required':[('ship_company_code','=','usps'),('test_mode','=',False)]}"/> |
138 | + |
139 | + |
140 | + </page> |
141 | + </xpath> |
142 | + </field> |
143 | + </record> |
144 | + |
145 | + </data> |
146 | +</openerp> |
147 | + |
148 | \ No newline at end of file |
149 | |
150 | === added file 'shipping_api_usps/sale.py' |
151 | --- shipping_api_usps/sale.py 1970-01-01 00:00:00 +0000 |
152 | +++ shipping_api_usps/sale.py 2012-07-24 04:29:18 +0000 |
153 | @@ -0,0 +1,149 @@ |
154 | +# -*- coding: utf-8 -*- |
155 | +############################################################################## |
156 | +# |
157 | +# OpenERP, Open Source Management Solution |
158 | +# Copyright (C) 2011 NovaPoint Group LLC (<http://www.novapointgroup.com>) |
159 | +# Copyright (C) 2004-2010 OpenERP SA (<http://www.openerp.com>) |
160 | +# |
161 | +# This program is free software: you can redistribute it and/or modify |
162 | +# it under the terms of the GNU General Public License as published by |
163 | +# the Free Software Foundation, either version 3 of the License, or |
164 | +# (at your option) any later version. |
165 | +# |
166 | +# This program is distributed in the hope that it will be useful, |
167 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
168 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
169 | +# GNU General Public License for more details. |
170 | +# |
171 | +# You should have received a copy of the GNU General Public License |
172 | +# along with this program. If not, see <http://www.gnu.org/licenses/> |
173 | +# |
174 | +############################################################################## |
175 | +from osv import fields,osv |
176 | + |
177 | +class sale_order(osv.osv): |
178 | + _inherit="sale.order" |
179 | + |
180 | + def _get_company_code(self, cr, user, context=None): |
181 | + res = super(sale_order, self)._get_company_code(cr, user, context=context) |
182 | + res.append(('usps', 'USPS')) |
183 | + return res |
184 | + def _get_service_type_usps(self, cr, uid, context=None): |
185 | + return [ |
186 | + ('First Class', 'First Class'), |
187 | + ('First Class HFP Commercial', 'First Class HFP Commercial'), |
188 | + ('FirstClassMailInternational', 'First Class Mail International'), |
189 | + ('Priority', 'Priority'), |
190 | + ('Priority Commercial', 'Priority Commercial'), |
191 | + ('Priority HFP Commercial', 'Priority HFP Commercial'), |
192 | + ('PriorityMailInternational', 'Priority Mail International'), |
193 | + ('Express', 'Express'), |
194 | + ('Express Commercial', 'Express Commercial'), |
195 | + ('Express SH', 'Express SH'), |
196 | + ('Express SH Commercial', 'Express SH Commercial'), |
197 | + ('Express HFP', 'Express HFP'), |
198 | + ('Express HFP Commercial', 'Express HFP Commercial'), |
199 | + ('ExpressMailInternational', 'Express Mail International'), |
200 | + ('ParcelPost', 'Parcel Post'), |
201 | + ('ParcelSelect', 'Parcel Select'), |
202 | + ('StandardMail', 'Standard Mail'), |
203 | + ('CriticalMail', 'Critical Mail'), |
204 | + ('Media', 'Media'), |
205 | + ('Library', 'Library'), |
206 | + ('All', 'All'), |
207 | + ('Online', 'Online'), |
208 | + ] |
209 | + |
210 | + def _get_first_class_mail_type_usps(self, cr, uid, context=None): |
211 | + return [ |
212 | + ('Letter', 'Letter'), |
213 | + ('Flat', 'Flat'), |
214 | + ('Parcel', 'Parcel'), |
215 | + ('Postcard', 'Postcard'), |
216 | + ] |
217 | + |
218 | + def _get_container_usps(self, cr, uid, context=None): |
219 | + return [ |
220 | + ('Variable', 'Variable'), |
221 | + ('Card', 'Card'), |
222 | + ('Letter', 'Letter'), |
223 | + ('Flat', 'Flat'), |
224 | + ('Parcel', 'Parcel'), |
225 | + ('Large Parcel', 'Large Parcel'), |
226 | + ('Irregular Parcel', 'Irregular Parcel'), |
227 | + ('Oversized Parcel', 'Oversized Parcel'), |
228 | + ('Flat Rate Envelope', 'Flat Rate Envelope'), |
229 | + ('Padded Flat Rate Envelope', 'Padded Flat Rate Envelope'), |
230 | + ('Legal Flat Rate Envelope', 'Legal Flat Rate Envelope'), |
231 | + ('SM Flat Rate Envelope', 'SM Flat Rate Envelope'), |
232 | + ('Window Flat Rate Envelope', 'Window Flat Rate Envelope'), |
233 | + ('Gift Card Flat Rate Envelope', 'Gift Card Flat Rate Envelope'), |
234 | + ('Cardboard Flat Rate Envelope', 'Cardboard Flat Rate Envelope'), |
235 | + ('Flat Rate Box', 'Flat Rate Box'), |
236 | + ('SM Flat Rate Box', 'SM Flat Rate Box'), |
237 | + ('MD Flat Rate Box', 'MD Flat Rate Box'), |
238 | + ('LG Flat Rate Box', 'LG Flat Rate Box'), |
239 | + ('RegionalRateBoxA', 'RegionalRateBoxA'), |
240 | + ('RegionalRateBoxB', 'RegionalRateBoxB'), |
241 | + ('Rectangular', 'Rectangular'), |
242 | + ('Non-Rectangular', 'Non-Rectangular'), |
243 | + ] |
244 | + |
245 | + def _get_size_usps(self, cr, uid, context=None): |
246 | + return [ |
247 | + ('REGULAR', 'Regular'), |
248 | + ('LARGE', 'Large'), |
249 | + ] |
250 | + def action_ship_create(self, cr, uid, ids, *args): |
251 | + result = super(sale_order, self).action_ship_create(cr, uid, ids, *args) |
252 | + if result: |
253 | + for sale in self.browse(cr, uid, ids, context=None): |
254 | + if sale.ship_company_code=='usps': |
255 | + pick_ids = self.pool.get('stock.picking').search(cr, uid, [('sale_id','=',sale.id),('type','=','out')], context=None) |
256 | + if pick_ids: |
257 | + vals = { |
258 | + 'ship_company_code' : 'usps', |
259 | + 'logis_company' : sale.logis_company and sale.logis_company.id or False, |
260 | + 'usps_service_type' : sale.usps_service_type, |
261 | + 'usps_package_location' : sale.usps_package_location, |
262 | + 'usps_first_class_mail_type' : sale.usps_first_class_mail_type, |
263 | + 'usps_container' : sale.usps_container, |
264 | + 'usps_size' : sale.usps_size, |
265 | + 'usps_length' : sale.usps_length, |
266 | + 'usps_width' : sale.usps_width, |
267 | + 'usps_height' : sale.usps_height, |
268 | + 'usps_girth' : sale.usps_girth |
269 | + } |
270 | + self.pool.get('stock.picking').write(cr, uid, pick_ids,vals, context=None) |
271 | + return result |
272 | + _columns= { |
273 | + 'ship_company_code': fields.selection(_get_company_code, 'Ship Company', method=True, size=64), |
274 | + 'usps_service_type' : fields.selection(_get_service_type_usps, 'Service Type', size=100), |
275 | + 'usps_package_location' : fields.selection([ |
276 | + ('Front Door','Front Door'), |
277 | + ('Back Door','Back Door'), |
278 | + ('Side Door','Side Door'), |
279 | + ('Knock on Door/Ring Bell','Knock on Door/Ring Bell'), |
280 | + ('Mail Room','Mail Room'), |
281 | + ('Office','Office'), |
282 | + ('Reception','Reception'), |
283 | + ('In/At Mailbox','In/At Mailbox'), |
284 | + ('Other','Other'), |
285 | + ],'Package Location', size=64), |
286 | + 'usps_first_class_mail_type' : fields.selection(_get_first_class_mail_type_usps, 'First Class Mail Type', size=50), |
287 | + 'usps_container' : fields.selection(_get_container_usps,'Container', size=100), |
288 | + 'usps_size' : fields.selection(_get_size_usps,'Size'), |
289 | + 'usps_length' : fields.float('Length'), |
290 | + 'usps_width' : fields.float('Width'), |
291 | + 'usps_height' : fields.float('Height'), |
292 | + 'usps_girth' : fields.float('Girth'), |
293 | + } |
294 | + _defaults = { |
295 | + 'usps_service_type' : 'Priority', |
296 | + 'usps_package_location' : 'Front Door', |
297 | + 'usps_first_class_mail_type': 'Parcel', |
298 | + 'usps_size' : 'REGULAR', |
299 | + 'usps_container' : 'Variable', |
300 | + |
301 | + } |
302 | +sale_order() |
303 | \ No newline at end of file |
304 | |
305 | === added file 'shipping_api_usps/sale_view.xml' |
306 | --- shipping_api_usps/sale_view.xml 1970-01-01 00:00:00 +0000 |
307 | +++ shipping_api_usps/sale_view.xml 2012-07-24 04:29:18 +0000 |
308 | @@ -0,0 +1,36 @@ |
309 | +<?xml version="1.0" encoding="utf-8"?> |
310 | +<openerp> |
311 | + <data> |
312 | + <record model="ir.ui.view" id="sale_order_form_usps"> |
313 | + <field name="name">sale.order.view_form.usps</field> |
314 | + <field name="model">sale.order</field> |
315 | + <field name="inherit_id" ref="sale.view_order_form" /> |
316 | + <field name="type">form</field> |
317 | + <field name="priority" eval="30" /> |
318 | + <field name="arch" type="xml"> |
319 | + <xpath expr="//separator[@string='Notes']" position="before" > |
320 | + <newline /> |
321 | + <group colspan="4" col="4" attrs="{'invisible':[('ship_company_code','!=','usps')]}" > |
322 | + <separator string="USPS" colspan="4" /> |
323 | + <field name='usps_service_type' attrs="{'required': [('ship_company_code','=','usps')]}" /> |
324 | + |
325 | + <field name='usps_package_location' invisible="1" attrs="{'required': [('ship_company_code','=','usps')]}" /> |
326 | + <field name="usps_container" /> |
327 | + <field name="usps_size" invisible="1"/> |
328 | + |
329 | + <field name="usps_first_class_mail_type" attrs="{'required':[('usps_service_type','in',('First Class','First Class HFP Commercial'))], 'invisible':[('usps_service_type','not in',('First Class','First Class HFP Commercial'))]}" /> |
330 | + <!-- group colspan="4" col="4" attrs="{'invisible':[('usps_size','!=','LARGE')]}" > |
331 | + <separator string = "USPS Dimension" colspan="4" /> |
332 | + <field name="usps_width" /> |
333 | + <field name="usps_length" /> |
334 | + <field name="usps_height" /> |
335 | + <field name="usps_girth" attrs="{'invisible':['|', ('usps_container','!=','Non-Rectangular'), ('usps_container','!=','Variable'), ('usps_container','!=','')]}" /> |
336 | + </group --> |
337 | + </group> |
338 | + </xpath> |
339 | + |
340 | + </field> |
341 | + </record> |
342 | + </data> |
343 | +</openerp> |
344 | + |
345 | \ No newline at end of file |
346 | |
347 | === added file 'shipping_api_usps/stock.py' |
348 | --- shipping_api_usps/stock.py 1970-01-01 00:00:00 +0000 |
349 | +++ shipping_api_usps/stock.py 2012-07-24 04:29:18 +0000 |
350 | @@ -0,0 +1,459 @@ |
351 | +# -*- coding: utf-8 -*- |
352 | +############################################################################## |
353 | +# |
354 | +# OpenERP, Open Source Management Solution |
355 | +# Copyright (C) 2011 NovaPoint Group LLC (<http://www.novapointgroup.com>) |
356 | +# Copyright (C) 2004-2010 OpenERP SA (<http://www.openerp.com>) |
357 | +# |
358 | +# This program is free software: you can redistribute it and/or modify |
359 | +# it under the terms of the GNU General Public License as published by |
360 | +# the Free Software Foundation, either version 3 of the License, or |
361 | +# (at your option) any later version. |
362 | +# |
363 | +# This program is distributed in the hope that it will be useful, |
364 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
365 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
366 | +# GNU General Public License for more details. |
367 | +# |
368 | +# You should have received a copy of the GNU General Public License |
369 | +# along with this program. If not, see <http://www.gnu.org/licenses/> |
370 | +# |
371 | +############################################################################## |
372 | + |
373 | + |
374 | +from osv import fields,osv |
375 | +from xml.dom.minidom import Document |
376 | +from tools.translate import _ |
377 | +import httplib |
378 | +import xml2dic |
379 | + |
380 | +import time |
381 | +import datetime |
382 | +from urlparse import urlparse |
383 | +import Image |
384 | +import tempfile |
385 | +import re |
386 | + |
387 | + |
388 | +import netsvc |
389 | +import base64 |
390 | +import logging |
391 | +import tools |
392 | + |
393 | +from base64 import b64decode |
394 | +import binascii |
395 | + |
396 | + |
397 | +class logistic_company(osv.osv): |
398 | + _inherit="logistic.company" |
399 | + def _get_company_code(self, cr, user, context=None): |
400 | + res = super(logistic_company, self)._get_company_code(cr, user, context=context) |
401 | + res.append(('usps', 'USPS')) |
402 | + |
403 | + return res |
404 | + _columns = { |
405 | + |
406 | + 'ship_company_code' : fields.selection(_get_company_code, 'Ship Company', method=True, required=True, size=64), |
407 | + 'usps_userid' : fields.char('User ID', size=128), |
408 | + 'usps_url_test' : fields.char('Test Url', size=512), |
409 | + 'usps_url' : fields.char('Production URL', size=512), |
410 | + 'usps_url_secure_test' : fields.char('Test Url SSL', size=512), |
411 | + 'usps_url_secure' : fields.char('Production URL SSL', size=512), |
412 | + |
413 | + } |
414 | + |
415 | +logistic_company() |
416 | +class stock_packages(osv.osv): |
417 | + _inherit = "stock.packages" |
418 | + _columns = { |
419 | + 'usps_confirmation_number': fields.char('USPS Confirm Number', size=64, readonly=True), |
420 | + } |
421 | + |
422 | +stock_packages() |
423 | + |
424 | +class stock_picking(osv.osv): |
425 | + |
426 | + |
427 | + _inherit = "stock.picking" |
428 | + def _get_company_code(self, cr, user, context=None): |
429 | + res = super(stock_picking, self)._get_company_code(cr, user, context=context) |
430 | + res.append(('usps', 'USPS')) |
431 | + |
432 | + return res |
433 | + def _get_service_type_usps(self, cr, uid, context=None): |
434 | + return [ |
435 | + ('First Class', 'First Class'), |
436 | + ('First Class HFP Commercial', 'First Class HFP Commercial'), |
437 | + ('FirstClassMailInternational', 'First Class Mail International'), |
438 | + ('Priority', 'Priority'), |
439 | + ('Priority Commercial', 'Priority Commercial'), |
440 | + ('Priority HFP Commercial', 'Priority HFP Commercial'), |
441 | + ('PriorityMailInternational', 'Priority Mail International'), |
442 | + ('Express', 'Express'), |
443 | + ('Express Commercial', 'Express Commercial'), |
444 | + ('Express SH', 'Express SH'), |
445 | + ('Express SH Commercial', 'Express SH Commercial'), |
446 | + ('Express HFP', 'Express HFP'), |
447 | + ('Express HFP Commercial', 'Express HFP Commercial'), |
448 | + ('ExpressMailInternational', 'Express Mail International'), |
449 | + ('ParcelPost', 'Parcel Post'), |
450 | + ('ParcelSelect', 'Parcel Select'), |
451 | + ('StandardMail', 'Standard Mail'), |
452 | + ('CriticalMail', 'Critical Mail'), |
453 | + ('Media', 'Media'), |
454 | + ('Library', 'Library'), |
455 | + ('All', 'All'), |
456 | + ('Online', 'Online'), |
457 | + ] |
458 | + |
459 | + def _get_first_class_mail_type_usps(self, cr, uid, context=None): |
460 | + return [ |
461 | + ('Letter', 'Letter'), |
462 | + ('Flat', 'Flat'), |
463 | + ('Parcel', 'Parcel'), |
464 | + ('Postcard', 'Postcard'), |
465 | + ] |
466 | + |
467 | + def _get_container_usps(self, cr, uid, context=None): |
468 | + return [ |
469 | + ('Variable', 'Variable'), |
470 | + ('Card', 'Card'), |
471 | + ('Letter', 'Letter'), |
472 | + ('Flat', 'Flat'), |
473 | + ('Parcel', 'Parcel'), |
474 | + ('Large Parcel', 'Large Parcel'), |
475 | + ('Irregular Parcel', 'Irregular Parcel'), |
476 | + ('Oversized Parcel', 'Oversized Parcel'), |
477 | + ('Flat Rate Envelope', 'Flat Rate Envelope'), |
478 | + ('Padded Flat Rate Envelope', 'Padded Flat Rate Envelope'), |
479 | + ('Legal Flat Rate Envelope', 'Legal Flat Rate Envelope'), |
480 | + ('SM Flat Rate Envelope', 'SM Flat Rate Envelope'), |
481 | + ('Window Flat Rate Envelope', 'Window Flat Rate Envelope'), |
482 | + ('Gift Card Flat Rate Envelope', 'Gift Card Flat Rate Envelope'), |
483 | + ('Cardboard Flat Rate Envelope', 'Cardboard Flat Rate Envelope'), |
484 | + ('Flat Rate Box', 'Flat Rate Box'), |
485 | + ('SM Flat Rate Box', 'SM Flat Rate Box'), |
486 | + ('MD Flat Rate Box', 'MD Flat Rate Box'), |
487 | + ('LG Flat Rate Box', 'LG Flat Rate Box'), |
488 | + ('RegionalRateBoxA', 'RegionalRateBoxA'), |
489 | + ('RegionalRateBoxB', 'RegionalRateBoxB'), |
490 | + ('Rectangular', 'Rectangular'), |
491 | + ('Non-Rectangular', 'Non-Rectangular'), |
492 | + ] |
493 | + |
494 | + def _get_size_usps(self, cr, uid, context=None): |
495 | + return [ |
496 | + ('REGULAR', 'Regular'), |
497 | + ('LARGE', 'Large'), |
498 | + ] |
499 | + _columns = { |
500 | + 'ship_company_code': fields.selection(_get_company_code, 'Ship Company', method=True, size=64), |
501 | + 'usps_confirmation_number' : fields.char('Confirmation Number', size=64, readonly=True), |
502 | + 'usps_service_type' : fields.selection(_get_service_type_usps, 'Service Type', size=100), |
503 | + 'usps_package_location' : fields.selection([ |
504 | + ('Front Door','Front Door'), |
505 | + ('Back Door','Back Door'), |
506 | + ('Side Door','Side Door'), |
507 | + ('Knock on Door/Ring Bell','Knock on Door/Ring Bell'), |
508 | + ('Mail Room','Mail Room'), |
509 | + ('Office','Office'), |
510 | + ('Reception','Reception'), |
511 | + ('In/At Mailbox','In/At Mailbox'), |
512 | + ('Other','Other'), |
513 | + ],'Package Location'), |
514 | + 'usps_first_class_mail_type' : fields.selection(_get_first_class_mail_type_usps, 'First Class Mail Type', size=50), |
515 | + 'usps_container' : fields.selection(_get_container_usps,'Container', size=100), |
516 | + 'usps_size' : fields.selection(_get_size_usps,'Size'), |
517 | + 'usps_length' : fields.float('Length'), |
518 | + 'usps_width' : fields.float('Width'), |
519 | + 'usps_height' : fields.float('Height'), |
520 | + 'usps_girth' : fields.float('Girth'), |
521 | + } |
522 | + _defaults = { |
523 | + 'usps_service_type' : 'Priority', |
524 | + 'usps_package_location' : 'Front Door', |
525 | + 'usps_first_class_mail_type': 'Parcel', |
526 | + 'usps_size' : 'REGULAR', |
527 | + 'usps_container' : 'Variable', |
528 | + } |
529 | + |
530 | + def process_ship(self,cr, uid, ids, context=None): |
531 | + do = self.browse(cr, uid, type(ids)==type([]) and ids[0] or ids, context=context) |
532 | + user = self.pool.get('res.users').browse(cr, uid, uid, context=context) |
533 | + if do.ship_company_code != 'usps': |
534 | + return super(stock_picking, self).process_ship(cr, uid, ids, context=context) |
535 | + |
536 | + if not (do.logis_company and do.logis_company.ship_company_code=='usps'): |
537 | + return super(stock_picking, self).process_ship(cr, uid, ids, context=context) |
538 | + userid = do.logis_company.usps_userid |
539 | + url = do.logis_company.test_mode and do.logis_company.usps_url_secure_test or do.logis_company.usps_url_secure |
540 | + url_prd = do.logis_company.usps_url |
541 | + url_prd_secure = do.logis_company.usps_url_secure |
542 | + test=do.logis_company.test_mode |
543 | + str_error = '' |
544 | + ship_message = '' |
545 | + error = False |
546 | + for package in do.packages_ids: |
547 | + str_error = '' |
548 | + #if do.packages_ids: |
549 | + #@Changing to production URL SINCE DelivConfirmCertifyV3.0Request works only with production url and test data |
550 | + url = do.logis_company.usps_url_secure |
551 | + if test: |
552 | + request_xml = """<DelivConfirmCertifyV3.0Request USERID="%(user_id)s"> |
553 | + <Option>1</Option> |
554 | + <ImageParameters></ImageParameters> |
555 | + <FromName>Joe Smith</FromName> |
556 | + <FromFirm>ABD Corp.</FromFirm> |
557 | + <FromAddress1>Apt. 3C</FromAddress1> |
558 | + <FromAddress2>6406 Ivy Lane</FromAddress2> |
559 | + <FromCity>Greenbelt</FromCity> |
560 | + <FromState>MD</FromState> |
561 | + <FromZip5>20770</FromZip5> |
562 | + <FromZip4>1234</FromZip4> |
563 | + <ToName>Tom Collins</ToName> |
564 | + <ToFirm>XYZ Corp.</ToFirm> |
565 | + <ToAddress1>Suite 4D</ToAddress1> |
566 | + <ToAddress2>8 Wildwood Drive</ToAddress2> |
567 | + <ToCity>Old Lyme</ToCity> |
568 | + <ToState>CT</ToState> |
569 | + <ToZip5>06371</ToZip5> |
570 | + <ToZip4></ToZip4> |
571 | + <WeightInOunces>1</WeightInOunces> |
572 | + <ServiceType>Priority</ServiceType> |
573 | + <SeparateReceiptPage></SeparateReceiptPage> |
574 | + <POZipCode></POZipCode> |
575 | + <ImageType>TIF</ImageType> |
576 | + <LabelDate></LabelDate> |
577 | + <CustomerRefNo></CustomerRefNo> |
578 | + <AddressServiceRequested></AddressServiceRequested> |
579 | + <SenderName></SenderName> |
580 | + <SenderEMail></SenderEMail> |
581 | + <RecipientName></RecipientName> |
582 | + <RecipientEMail></RecipientEMail> |
583 | + </DelivConfirmCertifyV3.0Request> |
584 | + """%{ |
585 | + 'user_id' : userid, |
586 | + } |
587 | + request_url = url + '?API=DelivConfirmCertifyV3&XML=' + request_xml |
588 | + elif do.company_id.partner_id.address: |
589 | + from_address = do.company_id.partner_id.address[0] |
590 | + request_xml = """<DeliveryConfirmationV3.0Request USERID="%(user_id)s"> |
591 | + <Option>1</Option> |
592 | + <ImageParameters /> |
593 | + <FromName>%(from_name)s</FromName> |
594 | + <FromFirm>%(from_firm)s</FromFirm> |
595 | + <FromAddress1 /> |
596 | + <FromAddress2>%(from_address2)s</FromAddress2> |
597 | + <FromCity>%(from_city)s</FromCity> |
598 | + <FromState>%(from_state)s</FromState> |
599 | + <FromZip5>%(from_zip5)s</FromZip5> |
600 | + <FromZip4>%(from_zip4)s</FromZip4> |
601 | + <ToName>%(to_name)s</ToName> |
602 | + <ToFirm>%(to_firm)s</ToFirm> |
603 | + <ToAddress1>%(to_address1)s</ToAddress1> |
604 | + <ToAddress2>%(to_address2)s</ToAddress2> |
605 | + <ToCity>%(to_city)s</ToCity> |
606 | + <ToState>%(to_state)s</ToState> |
607 | + <ToZip5>%(to_zip5)s</ToZip5> |
608 | + <ToZip4>%(to_zip4)s</ToZip4> |
609 | + <WeightInOunces>%(weight)s</WeightInOunces> |
610 | + <ServiceType>%(service_type)s</ServiceType> |
611 | + <POZipCode></POZipCode> |
612 | + <ImageType>TIF</ImageType> |
613 | + <LabelDate></LabelDate> |
614 | + <CustomerRefNo></CustomerRefNo> |
615 | + <AddressServiceRequested>TRUE</AddressServiceRequested> |
616 | + </DeliveryConfirmationV3.0Request> |
617 | + """%{ |
618 | + 'user_id' : userid, |
619 | + 'from_name' : from_address.name, |
620 | + 'from_firm' : '', |
621 | + 'from_address2' : from_address.street or '', |
622 | + 'from_city' : from_address.city or '', |
623 | + 'from_state' : from_address.state_id and from_address.state_id.code or '', |
624 | + 'from_zip5' : from_address.zip_id and from_address.zip_id.zipcode or '', |
625 | + 'from_zip4' : from_address.zip or '', |
626 | + 'to_name' : do.address_id.name , |
627 | + 'to_firm' : '', |
628 | + 'to_address1' : do.address_id.street, |
629 | + 'to_address2' : do.address_id.street2, |
630 | + 'to_city' : do.address_id.city, |
631 | + 'to_state' : do.address_id.state_id and do.address_id.state_id.code or '', |
632 | + 'to_zip5' : do.address_id.zip_id and do.address_id.zip_id.zipcode or '', |
633 | + 'to_zip4' : do.address_id.zip, |
634 | + 'weight' : package.weight, |
635 | + 'service_type' : do.usps_service_type, |
636 | + } |
637 | + request_url = url + '?API=DeliveryConfirmationV3&XML=' + request_xml |
638 | + try : |
639 | + import urllib |
640 | + f = urllib.urlopen(request_url) |
641 | + from xml.dom.minidom import parse, parseString |
642 | + import xml2dic |
643 | + |
644 | + str_response = f.read() |
645 | + xml_response = parseString(str_response) |
646 | + xml_dic = xml2dic.main(str_response) |
647 | + |
648 | + if 'Error' in xml_dic.keys(): |
649 | + error = True |
650 | + for item in xml_dic.get('Error'): |
651 | + |
652 | + if item.get('Number'): |
653 | + if str_error: |
654 | + str_error = str_error+ "\n----------------------" |
655 | + str_error= str_error + "\nNumber : " + item['Number'] |
656 | + if item.get('Description'): |
657 | + str_error = str_error + "\nDescription : " + item['Description'] |
658 | + |
659 | + else: |
660 | + confirmation_number = xml_dic['DelivConfirmCertifyV3.0Response'][0]['DeliveryConfirmationNumber'] |
661 | + label_data = xml_dic['DelivConfirmCertifyV3.0Response'][1]['DeliveryConfirmationLabel'] |
662 | + #logo = binascii.b2a_base64(str(b64decode(label_data))) |
663 | + #logo = str(b64decode(label_data)) |
664 | + |
665 | + logo=base64.decodestring(label_data) |
666 | + |
667 | + import os |
668 | + import tempfile |
669 | + dir_temp = tempfile.gettempdir() |
670 | + |
671 | + f = open(dir_temp + '/usps.tif', 'w+') |
672 | + f.write(logo) |
673 | + f.close() |
674 | + label_image='' |
675 | + |
676 | + cp=False |
677 | + if os.name == 'posix' or 'nt': |
678 | + try: |
679 | + os.system("tiffcp -c none "+ dir_temp +"/usps.tif " + dir_temp +"/usps_temp.tif") |
680 | + cp=True |
681 | + except Exception, e: |
682 | + str_error = "Please install tiffcp." |
683 | + if cp: |
684 | + im = Image.open(dir_temp + '/usps_temp.tif') |
685 | + im.thumbnail(im.size) |
686 | + im.save(dir_temp+'/usps_temp.jpg', "JPEG", quality=100) |
687 | + label_from_file=open(dir_temp+'/usps_temp.jpg','rb') |
688 | + label_image=base64.encodestring(label_from_file.read()) |
689 | + |
690 | + self.pool.get('stock.packages').write(cr, uid, [package.id], {'logo': label_image, 'tracking_no': confirmation_number, 'usps_confirmation_number': confirmation_number,'ship_message': 'Shipment has processed'}) |
691 | + |
692 | + except Exception, e: |
693 | + str_error = str(e) |
694 | + |
695 | + cr.commit() |
696 | + if str_error: |
697 | + self.pool.get('stock.packages').write(cr, uid, do.id, {'ship_message': str_error}, context=context) |
698 | + |
699 | + |
700 | + |
701 | + if not error: |
702 | + self.write(cr, uid, do.id, {'ship_state':'ready_pick','ship_message': 'Shipment has been processed.'}, context=context) |
703 | + return { |
704 | + 'type': 'ir.actions.report.xml', |
705 | + 'report_name':'multiple.label.print', |
706 | + 'datas': { |
707 | + 'model':'stock.picking', |
708 | + 'id': ids and ids[0] or False, |
709 | + 'ids': ids and ids or [], |
710 | + 'report_type': 'pdf' |
711 | + }, |
712 | + 'nodestroy': True |
713 | + } |
714 | + else: |
715 | + self.write(cr, uid, do.id, {'ship_message': 'Error occured on processing some of packages, for details please see the status packages.'}, context=context) |
716 | + #@todo: raise appropriate error msg |
717 | + raise osv.except_osv(_('Error'), _('%s' % ('No package lines are created for shippment process.'))) |
718 | + |
719 | + return True |
720 | + |
721 | + def process_void(self,cr, uid, ids, context=None): |
722 | + |
723 | + do = self.browse(cr, uid, type(ids)==type([]) and ids[0] or ids, context=context) |
724 | + if do.ship_company_code != 'usps': |
725 | + return super(stock_picking, self).process_void(cr, uid, ids, context=context) |
726 | + |
727 | + if not (do.logis_company and do.logis_company.ship_company_code=='usps'): |
728 | + return super(stock_picking, self).process_void(cr, uid, ids, context=context) |
729 | + |
730 | + userid = do.logis_company.usps_userid |
731 | + url = do.logis_company.test_mode and do.logis_company.usps_url_secure_test or do.logis_company.usps_url_secure |
732 | + url_prd = do.logis_company.usps_url |
733 | + url_prd_secure = do.logis_company.usps_url_secure |
734 | + test=do.logis_company.test_mode |
735 | + |
736 | + error = False |
737 | + str_error = '' |
738 | + |
739 | + for pack in do.packages_ids: |
740 | + if pack.tracking_no: |
741 | + url = test and do.logis_company.usps_url_secure_test or do.logis_company.usps_url_secure |
742 | + url_sec = test and do.logis_company.usps_url_secure_test or do.logis_company.usps_url_secure |
743 | + if test: |
744 | + request_xml = """<CarrierPickupCancelRequest USERID="%(user_id)s"> |
745 | + <FirmName>ABC Corp.</FirmName> |
746 | + <SuiteOrApt>Suite 777</SuiteOrApt> |
747 | + <Address2>1390 Market Street</Address2> |
748 | + <Urbanization></Urbanization> |
749 | + <City>Houston</City> |
750 | + <State>TX</State> |
751 | + <ZIP5>77058</ZIP5> |
752 | + <ZIP4>1234</ZIP4> |
753 | + <ConfirmationNumber>WTC123456789</ConfirmationNumber> |
754 | + </CarrierPickupCancelRequest> |
755 | + """%{'user_id': do.logis_company.usps_userid} |
756 | + else: |
757 | + request_xml = """<CarrierPickupCancelRequest USERID="%(user_id)"> |
758 | + <FirmName>ABC Corp.</FirmName> |
759 | + <SuiteOrApt>Suite 777</SuiteOrApt> |
760 | + <Address2>1390 Market Street</Address2> |
761 | + <Urbanization></Urbanization> |
762 | + <City>Houston</City> |
763 | + <State>TX</State> |
764 | + <ZIP5>77058</ZIP5> |
765 | + <ZIP4>1234</ZIP4> |
766 | + <ConfirmationNumber>%(confirmation_number)</ConfirmationNumber> |
767 | + </CarrierPickupCancelRequest> |
768 | + """%{ |
769 | + 'user_id': do.logis_company.usps_userid, |
770 | + 'confirmation_number' : pack.tracking_no, |
771 | + } |
772 | + request_url = url + '?API=CarrierPickupCancel&XML=' + request_xml |
773 | + try : |
774 | + import urllib |
775 | + f = urllib.urlopen(request_url) |
776 | + from xml.dom.minidom import parse, parseString |
777 | + import xml2dic |
778 | + |
779 | + str_response = f.read() |
780 | + except Exception: |
781 | + self.pool.get('stock.packages').write(cr, uid, pack.id, {'ship_message': str(Exception)}, context=context) |
782 | + |
783 | + print "Shipment Cancel response :", str_response |
784 | + |
785 | + xml_response = parseString(str_response) |
786 | + xml_dic = xml2dic.main(str_response) |
787 | + |
788 | + if 'Error' in xml_dic.keys(): |
789 | + error = True |
790 | + for item in xml_dic.get('Error'): |
791 | + self.pool.get('stock.packages').write(cr, uid, pack.id, {'ship_message': str_error}, context=context) |
792 | + break |
793 | + else: |
794 | + self.pool.get('stock.packages').write(cr, uid, pack.id, { |
795 | + 'negotiated_rates' : 0.00, |
796 | + 'shipment_identific_no' :'', |
797 | + 'tracking_no': '', |
798 | + 'tracking_url': '', |
799 | + 'logo' : '', |
800 | + 'ship_message' : 'Shipment Cancelled'}, context=context) |
801 | + |
802 | + if not error: |
803 | + self.write(cr, uid, do.id, {'ship_state' :'draft', 'ship_message' : 'Shipment has been cancelled.'}, context=context) |
804 | + else : |
805 | + self.write(cr, uid, do.id, { 'ship_message' : 'Cancellation of some of shipment has failed, please check the status of pakages.'}, context=context) |
806 | + return True |
807 | +stock_picking() |
808 | + |
809 | + |
810 | |
811 | === added file 'shipping_api_usps/stock_view.xml' |
812 | --- shipping_api_usps/stock_view.xml 1970-01-01 00:00:00 +0000 |
813 | +++ shipping_api_usps/stock_view.xml 2012-07-24 04:29:18 +0000 |
814 | @@ -0,0 +1,48 @@ |
815 | +<?xml version="1.0" encoding="UTF-8"?> |
816 | +<openerp> |
817 | + <data> |
818 | + <record id="view_picking_shipping_usps" model="ir.ui.view"> |
819 | + <field name="name">stock.picking.shipping.usps</field> |
820 | + <field name="model">stock.picking</field> |
821 | + <field name="inherit_id" ref="stock.view_picking_out_form" /> |
822 | + <field name="type">form</field> |
823 | + <field name="priority" eval="20" /> |
824 | + <field name="arch" type="xml"> |
825 | + <xpath expr="//separator[@string='Shipment']" position="before"> |
826 | + <group colspan="4" col="4" attrs="{'invisible':[('ship_company_code','!=','usps')]}" > |
827 | + <separator string="USPS" colspan="4" /> |
828 | + <field name='usps_service_type' attrs="{'required': [('ship_company_code','=','usps')]}" /> |
829 | + |
830 | + <field name='usps_package_location' attrs="{'required': [('ship_company_code','=','usps')]}" /> |
831 | + <field name='usps_confirmation_number' invisible="1" /> |
832 | + |
833 | + <field name="usps_container" /> |
834 | + <field name="usps_size" invisible="1" /> |
835 | + |
836 | + <field name="usps_first_class_mail_type" attrs="{'required':[('usps_service_type','in',('First Class','First Class HFP Commercial'))], 'invisible':[('usps_service_type','not in',('First Class','First Class HFP Commercial'))]}" /> |
837 | + <!-- group colspan="4" col="4" attrs="{'invisible':[('usps_size','!=','LARGE')]}" > |
838 | + <separator string = "USPS Dimension" colspan="4" /> |
839 | + <field name="usps_width" /> |
840 | + <field name="usps_length" /> |
841 | + <field name="usps_height" /> |
842 | + <field name="usps_girth" attrs="{'invisible':['|', ('usps_container','!=','Non-Rectangular'), ('usps_container','!=','Variable'), ('usps_container','!=','')]}" /> |
843 | + </group --> |
844 | + </group> |
845 | + </xpath> |
846 | + </field> |
847 | + </record> |
848 | + |
849 | + <record id="stock_packages_form_usps" model="ir.ui.view"> |
850 | + <field name="name">stock.packages.form.usps</field> |
851 | + <field name="model">stock.packages</field> |
852 | + <field name="type">form</field> |
853 | + <field name= "priority" ref="shipping_api.stock_packages_form" /> |
854 | + <field name="arch" type="xml"> |
855 | + <field name="tracking_url" position="after" > |
856 | + <field name="usps_confirmation_number" invisible="1"/> |
857 | + </field> |
858 | + </field> |
859 | + </record> |
860 | + </data> |
861 | +</openerp> |
862 | + |
863 | |
864 | === added directory 'shipping_api_usps/wizard' |
865 | === added file 'shipping_api_usps/wizard/__init__.py' |
866 | --- shipping_api_usps/wizard/__init__.py 1970-01-01 00:00:00 +0000 |
867 | +++ shipping_api_usps/wizard/__init__.py 2012-07-24 04:29:18 +0000 |
868 | @@ -0,0 +1,26 @@ |
869 | +# -*- coding: utf-8 -*- |
870 | +############################################################################## |
871 | +# |
872 | +# OpenERP, Open Source Management Solution |
873 | +# Copyright (C) 2011 NovaPoint Group LLC (<http://www.novapointgroup.com>) |
874 | +# Copyright (C) 2004-2010 OpenERP SA (<http://www.openerp.com>) |
875 | +# |
876 | +# This program is free software: you can redistribute it and/or modify |
877 | +# it under the terms of the GNU General Public License as published by |
878 | +# the Free Software Foundation, either version 3 of the License, or |
879 | +# (at your option) any later version. |
880 | +# |
881 | +# This program is distributed in the hope that it will be useful, |
882 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
883 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
884 | +# GNU General Public License for more details. |
885 | +# |
886 | +# You should have received a copy of the GNU General Public License |
887 | +# along with this program. If not, see <http://www.gnu.org/licenses/> |
888 | +# |
889 | +############################################################################## |
890 | + |
891 | +import wizard_shipping_rate_calculation |
892 | + |
893 | + |
894 | +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
895 | \ No newline at end of file |
896 | |
897 | === added file 'shipping_api_usps/wizard/wizard_shipping_rate_calculation.py' |
898 | --- shipping_api_usps/wizard/wizard_shipping_rate_calculation.py 1970-01-01 00:00:00 +0000 |
899 | +++ shipping_api_usps/wizard/wizard_shipping_rate_calculation.py 2012-07-24 04:29:18 +0000 |
900 | @@ -0,0 +1,306 @@ |
901 | +# -*- coding: utf-8 -*- |
902 | +############################################################################## |
903 | +# |
904 | +# OpenERP, Open Source Management Solution |
905 | +# Copyright (C) 2011 NovaPoint Group LLC (<http://www.novapointgroup.com>) |
906 | +# Copyright (C) 2004-2010 OpenERP SA (<http://www.openerp.com>) |
907 | +# |
908 | +# This program is free software: you can redistribute it and/or modify |
909 | +# it under the terms of the GNU General Public License as published by |
910 | +# the Free Software Foundation, either version 3 of the License, or |
911 | +# (at your option) any later version. |
912 | +# |
913 | +# This program is distributed in the hope that it will be useful, |
914 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
915 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
916 | +# GNU General Public License for more details. |
917 | +# |
918 | +# You should have received a copy of the GNU General Public License |
919 | +# along with this program. If not, see <http://www.gnu.org/licenses/> |
920 | +# |
921 | +############################################################################## |
922 | +from osv import fields,osv |
923 | +from xml.dom.minidom import Document |
924 | +from tools.translate import _ |
925 | +import httplib |
926 | + |
927 | +import time |
928 | +import datetime |
929 | +from urlparse import urlparse |
930 | +import Image |
931 | +import tempfile |
932 | +import re |
933 | +import math |
934 | + |
935 | +from mako.template import Template |
936 | +from mako import exceptions |
937 | +import netsvc |
938 | +import base64 |
939 | +import logging |
940 | +import tools |
941 | + |
942 | +from base64 import b64decode |
943 | +import binascii |
944 | + |
945 | + |
946 | +class shipping_rate_wizard(osv.osv_memory): |
947 | + _inherit = 'shipping.rate.wizard' |
948 | + |
949 | + def _get_company_code(self, cr, user, context=None): |
950 | + res = super(shipping_rate_wizard, self)._get_company_code(cr, user, context=context) |
951 | + res.append(('usps', 'USPS')) |
952 | + return res |
953 | + |
954 | + def default_get(self, cr, uid, fields, context={}): |
955 | + res = super(shipping_rate_wizard, self).default_get(cr, uid, fields, context=context) |
956 | + if context.get('active_model',False) == 'sale.order': |
957 | + sale_id = context.get('active_id',False) |
958 | + if sale_id: |
959 | + sale = self.pool.get('sale.order').browse(cr, uid, sale_id, context=context) |
960 | + if 'usps_service_type' in fields and sale.usps_service_type: |
961 | + res['usps_service_type'] = sale.usps_service_type |
962 | + |
963 | + if 'usps_first_class_mail_type' in fields and sale.usps_first_class_mail_type: |
964 | + res['usps_first_class_mail_type'] = sale.usps_first_class_mail_type |
965 | + |
966 | + if 'usps_container' in fields and sale.usps_container: |
967 | + res['usps_container'] = sale.usps_container |
968 | + |
969 | + if 'usps_package_location' in fields and sale.usps_package_location: |
970 | + res['usps_package_location'] = sale.usps_package_location |
971 | + |
972 | + if 'usps_size' in fields and sale.usps_size: |
973 | + res['usps_size'] = sale.usps_size |
974 | + |
975 | + if 'usps_length' in fields and sale.usps_length: |
976 | + res['usps_length'] = sale.usps_length |
977 | + |
978 | + if 'usps_width' in fields and sale.usps_width: |
979 | + res['usps_width'] = sale.usps_width |
980 | + |
981 | + if 'usps_height' in fields and sale.usps_height: |
982 | + res['usps_height'] = sale.usps_height |
983 | + |
984 | + if 'usps_girth' in fields and sale.usps_girth: |
985 | + res['usps_girth'] = sale.usps_girth |
986 | + |
987 | + return res |
988 | + |
989 | + def update_sale_order(self, cr, uid, ids, context={}): |
990 | + data = self.browse(cr, uid, ids[0], context=context) |
991 | + if not (data['rate_selection'] == 'rate_request' and data['ship_company_code']=='usps'): |
992 | + return super(shipping_rate_wizard, self).update_sale_order(cr, uid, ids, context) |
993 | + if context.get('active_model',False) == 'sale.order': |
994 | + sale_id = context.get('active_id',False) |
995 | + sale_id and self.pool.get('sale.order').write(cr,uid,[sale_id],{'shipcharge':data.shipping_cost, |
996 | + 'ship_method':data.usps_service_type, |
997 | + 'sale_account_id':data.logis_company and data.logis_company.ship_account_id and data.logis_company.ship_account_id.id or False, |
998 | + 'ship_company_code' :data.ship_company_code, |
999 | + 'logis_company' : data.logis_company and data.logis_company.id or False, |
1000 | + 'usps_service_type' : data.usps_service_type, |
1001 | + 'usps_package_location' : data.usps_package_location, |
1002 | + 'usps_first_class_mail_type' : data.usps_first_class_mail_type , |
1003 | + 'usps_container' : data.usps_container , |
1004 | + 'usps_size' : data.usps_size , |
1005 | + 'usps_length' : data.usps_length , |
1006 | + 'usps_width' : data.usps_width , |
1007 | + 'usps_height' : data.usps_height , |
1008 | + 'usps_girth' : data.usps_girth , |
1009 | + 'rate_selection' : data.rate_selection |
1010 | + }) |
1011 | + self.pool.get('sale.order').button_dummy(cr, uid, [sale_id], context=context) |
1012 | + return {'nodestroy':False,'type': 'ir.actions.act_window_close'} |
1013 | + |
1014 | + return True |
1015 | + |
1016 | + def get_rate(self, cr, uid, ids, context={}): |
1017 | + data = self.browse(cr, uid, ids[0], context=context) |
1018 | + if not ( data['rate_selection'] == 'rate_request' and data['ship_company_code']=='usps'): |
1019 | + return super(shipping_rate_wizard, self).get_rate(cr, uid, ids, context) |
1020 | + |
1021 | + if context.get('active_model',False) == 'sale.order': |
1022 | + sale_id = context.get('active_id',False) |
1023 | + sale = self.pool.get('sale.order').browse(cr, uid, sale_id, context=context) |
1024 | + test = data.logis_company.test_mode or False |
1025 | + url = '' |
1026 | + url_sec = '' |
1027 | + request_xml = '' |
1028 | + |
1029 | + if data.logis_company: |
1030 | + url = test and data.logis_company.usps_url_test or data.logis_company.usps_url |
1031 | + url_sec = test and data.logis_company.usps_url_secure_test or data.logis_company.usps_url_secure |
1032 | + url_prd = data.logis_company.usps_url |
1033 | + url_prd_sec = data.logis_company.usps_url_secure |
1034 | + |
1035 | + address_from = sale.company_id.partner_id.address and sale.company_id.partner_id.address[0] |
1036 | + zip_origin = '' |
1037 | + if address_from: |
1038 | + zip_origin = address_from.zip_id and address_from.zip_id.zipcode or '' |
1039 | + zip_destination=sale.partner_shipping_id.zip_id and sale.partner_shipping_id.zip_id.zipcode or '' |
1040 | + weight = math.modf(sale.total_weight_net) |
1041 | + pounds = int(weight[1]) |
1042 | + ounces = round(weight[0],2) * 16 |
1043 | + request_xml = """<RateV4Request USERID="%(user_id)s"> |
1044 | + <Revision/> |
1045 | + <Package ID="1ST"> |
1046 | + <Service>%(service_type)s</Service> |
1047 | + <FirstClassMailType>%(first_class_mail_type)s</FirstClassMailType> |
1048 | + <ZipOrigination>%(zip_origin)s</ZipOrigination> |
1049 | + <ZipDestination>%(zip_desitination)s</ZipDestination> |
1050 | + <Pounds>%(pounds)s</Pounds> |
1051 | + <Ounces>%(ounces)s</Ounces> |
1052 | + <Container>%(container)s</Container> |
1053 | + <Size>REGULAR</Size> |
1054 | + <Machinable>true</Machinable> |
1055 | + </Package> |
1056 | + </RateV4Request>"""%{ |
1057 | + 'user_id' : data.logis_company and data.logis_company.usps_userid, |
1058 | + 'service_type' : data.usps_service_type , |
1059 | + 'first_class_mail_type' : data.usps_first_class_mail_type, |
1060 | + 'zip_origin' : zip_origin, |
1061 | + 'zip_desitination' : zip_destination, |
1062 | + 'pounds' : str(pounds), |
1063 | + 'ounces' : str(ounces), |
1064 | + 'container' : str(data.usps_container) , |
1065 | + } |
1066 | + |
1067 | + request_url = url_prd + '?API=RateV4&XML=' + request_xml |
1068 | + |
1069 | + str_response = '' |
1070 | + error = False |
1071 | + try : |
1072 | + import urllib |
1073 | + f = urllib.urlopen(request_url) |
1074 | + from xml.dom.minidom import parse, parseString |
1075 | + import xml2dic |
1076 | + |
1077 | + str_response = f.read() |
1078 | + except Exception, e: |
1079 | + self.write(cr, uid, [data.id], {'status_message': str(e)}, context=context) |
1080 | + |
1081 | + |
1082 | + if str_response: |
1083 | + xml_response = parseString(str_response) |
1084 | + xml_dic = xml2dic.main(str_response) |
1085 | + if 'Error' in xml_dic.keys(): |
1086 | + error = True |
1087 | + for item in xml_dic.get('Error'): |
1088 | + if 'Description' in item: |
1089 | + self.write(cr, uid, [data.id], {'status_message': 'Error : ' + item['Description'] }, context=context) |
1090 | + break |
1091 | + else: |
1092 | + for pack in xml_dic['RateV4Response']: |
1093 | + if 'Package' in pack: |
1094 | + for item in pack['Package']: |
1095 | + if 'Error' in item: |
1096 | + error = True |
1097 | + for i in item['Error']: |
1098 | + if 'Description' in i: |
1099 | + self.write(cr, uid, [data.id], {'status_message': 'Error : ' + i['Description'] }, context=context) |
1100 | + break |
1101 | + if error: |
1102 | + break |
1103 | + if error: |
1104 | + break |
1105 | + if not error: |
1106 | + for pack in xml_dic['RateV4Response']: |
1107 | + if 'Package' in pack: |
1108 | + for item in pack['Package']: |
1109 | + if 'Postage' in item: |
1110 | + for i in item['Postage']: |
1111 | + if 'Rate' in i: |
1112 | + self.write(cr, uid, [data.id], {'status_message': '', 'shipping_cost': i['Rate'] }, context=context) |
1113 | + break |
1114 | + |
1115 | + return True |
1116 | + |
1117 | + def _get_service_type_usps(self, cr, uid, context=None): |
1118 | + return [ |
1119 | + ('First Class', 'First Class'), |
1120 | + ('First Class HFP Commercial', 'First Class HFP Commercial'), |
1121 | + ('FirstClassMailInternational', 'First Class Mail International'), |
1122 | + ('Priority', 'Priority'), |
1123 | + ('Priority Commercial', 'Priority Commercial'), |
1124 | + ('Priority HFP Commercial', 'Priority HFP Commercial'), |
1125 | + ('PriorityMailInternational', 'Priority Mail International'), |
1126 | + ('Express', 'Express'), |
1127 | + ('Express Commercial', 'Express Commercial'), |
1128 | + ('Express SH', 'Express SH'), |
1129 | + ('Express SH Commercial', 'Express SH Commercial'), |
1130 | + ('Express HFP', 'Express HFP'), |
1131 | + ('Express HFP Commercial', 'Express HFP Commercial'), |
1132 | + ('ExpressMailInternational', 'Express Mail International'), |
1133 | + ('ParcelPost', 'Parcel Post'), |
1134 | + ('ParcelSelect', 'Parcel Select'), |
1135 | + ('StandardMail', 'Standard Mail'), |
1136 | + ('CriticalMail', 'Critical Mail'), |
1137 | + ('Media', 'Media'), |
1138 | + ('Library', 'Library'), |
1139 | + ('All', 'All'), |
1140 | + ('Online', 'Online'), |
1141 | + ] |
1142 | + |
1143 | + def _get_first_class_mail_type_usps(self, cr, uid, context=None): |
1144 | + return [ |
1145 | + ('Letter', 'Letter'), |
1146 | + ('Flat', 'Flat'), |
1147 | + ('Parcel', 'Parcel'), |
1148 | + ('Postcard', 'Postcard'), |
1149 | + ] |
1150 | + |
1151 | + def _get_container_usps(self, cr, uid, context=None): |
1152 | + return [ |
1153 | + ('Variable', 'Variable'), |
1154 | + ('Card', 'Card'), |
1155 | + ('Letter', 'Letter'), |
1156 | + ('Flat', 'Flat'), |
1157 | + ('Parcel', 'Parcel'), |
1158 | + ('Large Parcel', 'Large Parcel'), |
1159 | + ('Irregular Parcel', 'Irregular Parcel'), |
1160 | + ('Oversized Parcel', 'Oversized Parcel'), |
1161 | + ('Flat Rate Envelope', 'Flat Rate Envelope'), |
1162 | + ('Padded Flat Rate Envelope', 'Padded Flat Rate Envelope'), |
1163 | + ('Legal Flat Rate Envelope', 'Legal Flat Rate Envelope'), |
1164 | + ('SM Flat Rate Envelope', 'SM Flat Rate Envelope'), |
1165 | + ('Window Flat Rate Envelope', 'Window Flat Rate Envelope'), |
1166 | + ('Gift Card Flat Rate Envelope', 'Gift Card Flat Rate Envelope'), |
1167 | + ('Cardboard Flat Rate Envelope', 'Cardboard Flat Rate Envelope'), |
1168 | + ('Flat Rate Box', 'Flat Rate Box'), |
1169 | + ('SM Flat Rate Box', 'SM Flat Rate Box'), |
1170 | + ('MD Flat Rate Box', 'MD Flat Rate Box'), |
1171 | + ('LG Flat Rate Box', 'LG Flat Rate Box'), |
1172 | + ('RegionalRateBoxA', 'RegionalRateBoxA'), |
1173 | + ('RegionalRateBoxB', 'RegionalRateBoxB'), |
1174 | + ('Rectangular', 'Rectangular'), |
1175 | + ('Non-Rectangular', 'Non-Rectangular'), |
1176 | + ] |
1177 | + |
1178 | + def _get_size_usps(self, cr, uid, context=None): |
1179 | + return [ |
1180 | + ('REGULAR', 'Regular'), |
1181 | + ('LARGE', 'Large'), |
1182 | + ] |
1183 | + _columns= { |
1184 | + 'ship_company_code': fields.selection(_get_company_code, 'Ship Company', method=True, size=64), |
1185 | + 'usps_service_type' : fields.selection(_get_service_type_usps, 'Service Type', size=100), |
1186 | + 'usps_package_location' : fields.selection([ |
1187 | + ('Front Door','Front Door'), |
1188 | + ('Back Door','Back Door'), |
1189 | + ('Side Door','Side Door'), |
1190 | + ('Knock on Door/Ring Bell','Knock on Door/Ring Bell'), |
1191 | + ('Mail Room','Mail Room'), |
1192 | + ('Office','Office'), |
1193 | + ('Reception','Reception'), |
1194 | + ('In/At Mailbox','In/At Mailbox'), |
1195 | + ('Other','Other'), |
1196 | + ],'Package Location'), |
1197 | + 'usps_first_class_mail_type' : fields.selection(_get_first_class_mail_type_usps, 'First Class Mail Type', size=50), |
1198 | + 'usps_container' : fields.selection(_get_container_usps,'Container', size=100), |
1199 | + 'usps_size' : fields.selection(_get_size_usps,'Size'), |
1200 | + 'usps_length' : fields.float('Length'), |
1201 | + 'usps_width' : fields.float('Width'), |
1202 | + 'usps_height' : fields.float('Height'), |
1203 | + 'usps_girth' : fields.float('Girth'), |
1204 | + } |
1205 | +shipping_rate_wizard() |
1206 | +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
1207 | \ No newline at end of file |
1208 | |
1209 | === added file 'shipping_api_usps/wizard/wizard_shipping_rate_view.xml' |
1210 | --- shipping_api_usps/wizard/wizard_shipping_rate_view.xml 1970-01-01 00:00:00 +0000 |
1211 | +++ shipping_api_usps/wizard/wizard_shipping_rate_view.xml 2012-07-24 04:29:18 +0000 |
1212 | @@ -0,0 +1,36 @@ |
1213 | +<?xml version="1.0" encoding="utf-8"?> |
1214 | +<openerp> |
1215 | + <data> |
1216 | + <!-- Shipping rate wizard --> |
1217 | + <record id="view_for_shipping_rate_wizard_usps" model="ir.ui.view"> |
1218 | + <field name="name">action_for_shipping_rate_wizard_usps</field> |
1219 | + <field name="model">shipping.rate.wizard</field> |
1220 | + <field name="type">form</field> |
1221 | + <field name="priority" eval="30" /> |
1222 | + <field name="inherit_id" ref="sale_negotiated_shipping.view_for_shipping_rate_wizard" /> |
1223 | + <field name="arch" type="xml"> |
1224 | + <xpath expr="//field[@name='rate_select']" position="before" > |
1225 | + <group colspan="4" col="4" attrs="{'invisible':['|',('rate_selection','=','rate_card'),('ship_company_code','!=','usps') ]}" > |
1226 | + <separator string="USPS" colspan="4" /> |
1227 | + <field name='usps_service_type' attrs="{'required': [('ship_company_code','=','usps')]}" /> |
1228 | + |
1229 | + <field name='usps_package_location' invisible="1" attrs="{'required': [('ship_company_code','=','usps')]}" /> |
1230 | + |
1231 | + <field name="usps_container" /> |
1232 | + <field name="usps_size" invisible="1" /> |
1233 | + |
1234 | + <field name="usps_first_class_mail_type" attrs="{'required':[('usps_service_type','in',('First Class','First Class HFP Commercial'))], 'invisible':[('usps_service_type','not in',('First Class','First Class HFP Commercial'))]}" /> |
1235 | + <!-- group colspan="4" col="4" attrs="{'invisible':[('usps_size','!=','LARGE')]}" > |
1236 | + <separator string = "USPS Dimension" colspan="4" /> |
1237 | + <field name="usps_width" /> |
1238 | + <field name="usps_length" /> |
1239 | + <field name="usps_height" /> |
1240 | + <field name="usps_girth" attrs="{'invisible':['|', ('usps_container','!=','Non-Rectangular'), ('usps_container','!=','Variable'), ('usps_container','!=','')]}" /> |
1241 | + </group --> |
1242 | + </group> |
1243 | + </xpath> |
1244 | + </field> |
1245 | + </record> |
1246 | + |
1247 | + </data> |
1248 | +</openerp> |
1249 | \ No newline at end of file |
1250 | |
1251 | === added file 'shipping_api_usps/wizard/xml2dic.py' |
1252 | --- shipping_api_usps/wizard/xml2dic.py 1970-01-01 00:00:00 +0000 |
1253 | +++ shipping_api_usps/wizard/xml2dic.py 2012-07-24 04:29:18 +0000 |
1254 | @@ -0,0 +1,44 @@ |
1255 | +##Module that converts the Xml response to dictionary |
1256 | +from lxml import etree |
1257 | + |
1258 | + |
1259 | +def dictlist(node): |
1260 | + res = {} |
1261 | + res[node.tag] = [] |
1262 | + xmltodict(node,res[node.tag]) |
1263 | + reply = {} |
1264 | + reply[node.tag] =res[node.tag] |
1265 | + |
1266 | + return reply |
1267 | + |
1268 | +def xmltodict(node,res): |
1269 | + rep = {} |
1270 | + |
1271 | + if len(node): |
1272 | + #n = 0 |
1273 | + for n in list(node): |
1274 | + rep[node.tag] = [] |
1275 | + value = xmltodict(n,rep[node.tag]) |
1276 | + if len(n): |
1277 | + |
1278 | + value = rep[node.tag] |
1279 | + res.append({n.tag:value}) |
1280 | + else : |
1281 | + |
1282 | + res.append(rep[node.tag][0]) |
1283 | + |
1284 | + else: |
1285 | + value = {} |
1286 | + value = node.text |
1287 | + res.append({node.tag:value}) |
1288 | + |
1289 | + return |
1290 | + |
1291 | +def main(xml_string): |
1292 | + tree = etree.fromstring(xml_string) |
1293 | + res = dictlist(tree) |
1294 | + return res |
1295 | + |
1296 | + |
1297 | +if __name__ == '__main__' : |
1298 | + main() |
1299 | |
1300 | === added file 'shipping_api_usps/xml2dic.py' |
1301 | --- shipping_api_usps/xml2dic.py 1970-01-01 00:00:00 +0000 |
1302 | +++ shipping_api_usps/xml2dic.py 2012-07-24 04:29:18 +0000 |
1303 | @@ -0,0 +1,44 @@ |
1304 | +##Module that converts the Xml response to dictionary |
1305 | +from lxml import etree |
1306 | + |
1307 | + |
1308 | +def dictlist(node): |
1309 | + res = {} |
1310 | + res[node.tag] = [] |
1311 | + xmltodict(node,res[node.tag]) |
1312 | + reply = {} |
1313 | + reply[node.tag] =res[node.tag] |
1314 | + |
1315 | + return reply |
1316 | + |
1317 | +def xmltodict(node,res): |
1318 | + rep = {} |
1319 | + |
1320 | + if len(node): |
1321 | + #n = 0 |
1322 | + for n in list(node): |
1323 | + rep[node.tag] = [] |
1324 | + value = xmltodict(n,rep[node.tag]) |
1325 | + if len(n): |
1326 | + |
1327 | + value = rep[node.tag] |
1328 | + res.append({n.tag:value}) |
1329 | + else : |
1330 | + |
1331 | + res.append(rep[node.tag][0]) |
1332 | + |
1333 | + else: |
1334 | + value = {} |
1335 | + value = node.text |
1336 | + res.append({node.tag:value}) |
1337 | + |
1338 | + return |
1339 | + |
1340 | +def main(xml_string): |
1341 | + tree = etree.fromstring(xml_string) |
1342 | + res = dictlist(tree) |
1343 | + return res |
1344 | + |
1345 | + |
1346 | +if __name__ == '__main__' : |
1347 | + main() |