Merge lp:~ssebastian/openerp-usa/shipping_api_usps into lp:openerp-usa/6.1.x

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
Reviewer Review Type Date Requested Status
npg Pending
Review via email: mp+116398@code.launchpad.net

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()