~faisal-basar/openerp-usa/BistaShipping

« back to all changes in this revision

Viewing changes to shipping_bista/stock.py

  • Committer: Girish Joshi
  • Date: 2011-09-19 05:30:03 UTC
  • Revision ID: girish.joshi@bistasolutions.com-20110919053003-nkyjpzyod45iqy1c
Second Commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
##############################################################################
 
3
#
 
4
#    OpenERP, Open Source Management Solution
 
5
#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
 
6
#
 
7
#    This program is free software: you can redistribute it and/or modify
 
8
#    it under the terms of the GNU Affero General Public License as
 
9
#    published by the Free Software Foundation, either version 3 of the
 
10
#    License, or (at your option) any later version.
 
11
#
 
12
#    This program is distributed in the hope that it will be useful,
 
13
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
#    GNU Affero General Public License for more details.
 
16
#
 
17
#    You should have received a copy of the GNU Affero General Public License
 
18
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
#
 
20
##############################################################################
 
21
 
 
22
from osv import fields, osv
 
23
 
 
24
import decimal_precision as dp
 
25
import urllib2
 
26
import urllib
 
27
from base64 import b64decode
 
28
import binascii
 
29
import decimal_precision as dp
 
30
import time
 
31
import webbrowser
 
32
 
 
33
import HTMLParser
 
34
h = HTMLParser.HTMLParser()
 
35
import httplib
 
36
import shippingservice
 
37
from miscellaneous import Address
 
38
 
 
39
from .xml_dict import dict_to_xml, xml_to_dict
 
40
 
 
41
from fedex.services.rate_service import FedexRateServiceRequest
 
42
from fedex.services.ship_service import FedexProcessShipmentRequest
 
43
from fedex.config import FedexConfig
 
44
import suds
 
45
from suds.client import Client
 
46
 
 
47
from tools.translate import _
 
48
import netsvc
 
49
logger = netsvc.Logger()
 
50
import math
 
51
import socket
 
52
import urllib2
 
53
 
 
54
def get_partner_details(firm_name, partneradd_lnk, context=None):
 
55
        result = {}
 
56
        if partneradd_lnk:
 
57
            result['name'] = partneradd_lnk.name
 
58
            result['firm'] = firm_name or partneradd_lnk.name
 
59
            result['add1'] = partneradd_lnk.street or ''
 
60
            result['add2'] = partneradd_lnk.street2 or ''
 
61
            result['city'] = partneradd_lnk.city or ''
 
62
            result['state_code'] = partneradd_lnk.state_id.code or ''
 
63
            result['zip5'] = ''
 
64
            result['zip4'] = ''
 
65
            print "zip: ",partneradd_lnk.zip
 
66
            if len(partneradd_lnk.zip.strip()) == 5:
 
67
                result['zip5'] = partneradd_lnk.zip
 
68
                result['zip4'] = ''
 
69
            elif len(partneradd_lnk.zip.strip()) == 4:
 
70
                result['zip4'] = partneradd_lnk.zip
 
71
                result['zip5'] = ''
 
72
            elif str(partneradd_lnk.zip).find('-'):
 
73
                zips = str(partneradd_lnk.zip).split('-')
 
74
                if len(zips[0]) == 5 and len(zips[1]) == 4:
 
75
                    result['zip5'] = zips[0]
 
76
                    result['zip4'] = zips[1]
 
77
                elif len(zips[0]) == 4 and len(zips[1]) == 5:
 
78
                    result['zip4'] = zips[0]
 
79
                    result['zip5'] = zips[1]
 
80
            else:
 
81
                result['zip4'] = result['zip5'] = ''
 
82
                
 
83
            result['email'] = partneradd_lnk.email or ''
 
84
            result['country_code'] = partneradd_lnk.country_id.code or ''
 
85
            result['phone'] = partneradd_lnk.phone or ''
 
86
        return result
 
87
 
 
88
class shipping_response(osv.osv):
 
89
    _name = 'shipping.response'
 
90
 
 
91
    def generate_tracking_no(self, cr, uid, ids, context={}, error=True):
 
92
        print "generate_tracking_no ids: ",ids
 
93
#        import subprocess as sp
 
94
#        url = 'http://www.python.org'
 
95
#        child = sp.Popen("firefox %s" % url, shell=True)
 
96
 
 
97
        def get_usps_servicename(service):
 
98
            if 'First-Class' in service:
 
99
                return 'First Class'
 
100
            elif 'Express Mail' in service:
 
101
                return 'Express Mail'
 
102
            elif 'Priority Mail' in service:
 
103
                return 'Priority Mail'
 
104
            elif 'Library Mail' in service:
 
105
                return 'Library Mail'
 
106
            elif 'Parcel Post' in service:
 
107
                return 'Parcel Post'
 
108
            elif 'Media Mail' in service:
 
109
                return 'Media Mail'
 
110
            
 
111
        logger.notifyChannel('init', netsvc.LOG_WARNING, 'generate_tracking_no called')
 
112
        saleorder_obj = self.pool.get('sale.order')
 
113
        stockmove_obj = self.pool.get('stock.move')
 
114
        stockpicking_obj = self.pool.get('stock.picking')
 
115
        shippingresp_lnk = self.browse(cr,uid,ids[0])
 
116
        
 
117
        move_ids = stockmove_obj.search(cr,uid,[('picking_id','=',shippingresp_lnk.picking_id.id)])
 
118
 
 
119
        move_lines = stockmove_obj.browse(cr,uid,move_ids)
 
120
        for move_line in move_lines:
 
121
            real_stock  = move_line.product_id.qty_available
 
122
            print "real_stock: ",real_stock
 
123
            res = self.pool.get('stock.location')._product_reserve(cr, uid, [move_line.location_id.id], move_line.product_id.id, move_line.product_qty, {'uom': move_line.product_uom.id}, lock=True)
 
124
#            if not res:
 
125
#                saleorder_obj.write(cr,uid,shippingresp_lnk.picking_id.sale_id.id,{'state':'shipping_except'})
 
126
#                if error:
 
127
#                    raise osv.except_osv(_('Error'), _('Not enough stock in inventory'))
 
128
#                return False
 
129
        partneradd_lnk = shippingresp_lnk.picking_id.sale_id.shop_id.cust_address
 
130
        if not partneradd_lnk:
 
131
           raise osv.except_osv(_('Error'), _('Shop Address not defined!'),)
 
132
        result_from = get_partner_details(shippingresp_lnk.picking_id.sale_id.shop_id.name,partneradd_lnk,context)
 
133
 
 
134
        partner_lnk = shippingresp_lnk.picking_id.partner_id
 
135
        address = self.pool.get('res.partner').address_get(cr,uid,[partner_lnk.id])
 
136
        partneradd_lnk = self.pool.get('res.partner.address').browse(cr,uid,address['default'])
 
137
        result_to = get_partner_details(partner_lnk.name,partneradd_lnk,context)
 
138
        ### Shipper
 
139
        cust_address = shippingresp_lnk.picking_id.sale_id.shop_id.cust_address
 
140
        if not cust_address:
 
141
            if error:
 
142
                raise osv.except_osv(_('Error'), _('Shop Address not defined!'),)
 
143
            else:
 
144
                return False
 
145
        shipper = Address(cust_address.name or cust_address.partner_id.name, cust_address.street, cust_address.city, cust_address.state_id.code or '', cust_address.zip, cust_address.country_id.code, cust_address.street2 or '', cust_address.phone or '', cust_address.email, cust_address.partner_id.name)
 
146
 
 
147
        ### Recipient
 
148
        cust_address = shippingresp_lnk.picking_id.address_id
 
149
        receipient = Address(cust_address.name or cust_address.partner_id.name, cust_address.street, cust_address.city, cust_address.state_id.code or '', cust_address.zip, cust_address.country_id.code, cust_address.street2 or '', cust_address.phone or '', cust_address.email, cust_address.partner_id.name)
 
150
 
 
151
        weight = shippingresp_lnk.weight
 
152
        rate = shippingresp_lnk.rate
 
153
        tracking_no = False
 
154
 
 
155
        if shippingresp_lnk.type.lower() == 'usps' and ('usps_active' in context.keys() and context.get('usps_active')):
 
156
 
 
157
            shippingusps_obj = self.pool.get('shipping.usps')
 
158
            shippingusps_id = shippingusps_obj.search(cr,uid,[('active','=',True)])
 
159
            if not shippingusps_id:
 
160
                if error:
 
161
                    raise osv.except_osv(_('Error'), _('Default USPS settings not defined'))
 
162
                return False
 
163
            else:
 
164
                shippingusps_id = shippingusps_id[0]
 
165
            shippingusps_ptr = shippingusps_obj.browse(cr,uid,shippingusps_id)
 
166
            user_id = shippingusps_ptr.user_id
 
167
 
 
168
            
 
169
            url = "https://testing.shippingapis.com/ShippingAPITest.dll?API=DeliveryConfirmationV3&" if shippingusps_ptr.test else "https://secure.shippingapis.com/ShippingAPI.dll?API=DeliveryConfirmationV3&"
 
170
            
 
171
            weight = math.modf(weight)
 
172
            pounds = int(weight[1])
 
173
            ounces = round(weight[0],4) * 16
 
174
            final_weight = pounds*16 + ounces
 
175
            print "usps weight pounds: ",pounds
 
176
            print "usps weight ounces: ",ounces
 
177
            
 
178
            service_type = get_usps_servicename(shippingresp_lnk.name)
 
179
            print "service_type: ",service_type
 
180
            
 
181
            values = {}
 
182
            values['XML'] = '<DeliveryConfirmationV3.0Request USERID="' + user_id + '"><Option>1</Option><ImageParameters></ImageParameters><FromName>' + result_from['name'] + '</FromName><FromFirm>' + result_from['firm'] + '</FromFirm><FromAddress1>' + result_from['add2'] + '</FromAddress1><FromAddress2>' + result_from['add1'] + '</FromAddress2><FromCity>' + result_from['city'] + '</FromCity><FromState>' + result_from['state_code'] + '</FromState><FromZip5>' + result_from['zip5'] + '</FromZip5><FromZip4>' + result_from['zip4'] + '</FromZip4><ToName>' + result_to['name'] + '</ToName><ToFirm>' + result_to['firm'] + '</ToFirm><ToAddress1>' + result_to['add2'] + '</ToAddress1><ToAddress2>' + result_to['add1'] + '</ToAddress2><ToCity>' + result_to['city'] + '</ToCity><ToState>' + result_to['state_code'] + '</ToState><ToZip5>' + result_to['zip5'] + '</ToZip5><ToZip4>' + result_to['zip4'] + '</ToZip4><WeightInOunces>' + str(final_weight) + '</WeightInOunces><ServiceType>' + service_type + '</ServiceType><SeparateReceiptPage>TRUE</SeparateReceiptPage><POZipCode></POZipCode><ImageType>TIF</ImageType><LabelDate></LabelDate><CustomerRefNo></CustomerRefNo><AddressServiceRequested></AddressServiceRequested><SenderName></SenderName><SenderEMail></SenderEMail><RecipientName></RecipientName><RecipientEMail></RecipientEMail></DeliveryConfirmationV3.0Request>'
 
183
            url = url + urllib.urlencode(values)
 
184
            print "usps url: ",url
 
185
            #logger.notifyChannel('init', netsvc.LOG_WARNING, 'shipping url is %s'%(url,))
 
186
            #req = urllib2.Request(url)
 
187
            #opener = urllib2.build_opener()
 
188
            #f = opener.open(req)
 
189
            #response = f.read()
 
190
            
 
191
            try:
 
192
                f = urllib2.urlopen(url)
 
193
                response = f.read()
 
194
                print "usps response: ",response
 
195
            except Exception, e:
 
196
                #print e
 
197
                if error:
 
198
                    raise osv.except_osv(_('Error'), _('%s' % (e)))
 
199
                return False
 
200
            #print "after exception"
 
201
            
 
202
            if response.find('<Error>') != -1:
 
203
                sIndex = response.find('<Description>')
 
204
                eIndex = response.find('</Description>')
 
205
                if error:
 
206
                    raise osv.except_osv(_('Error'), _('%s') % (response[int(sIndex)+13:int(eIndex)],))
 
207
                return False
 
208
 
 
209
            i = sIndex = eIndex = 0
 
210
            sIndex = response.find('<DeliveryConfirmationNumber>',i)
 
211
            eIndex = response.find('</DeliveryConfirmationNumber>',i)
 
212
            tracking_no = response[int(sIndex) + 36:int(eIndex)]
 
213
 
 
214
            sIndex = response.find('<DeliveryConfirmationLabel>',i)
 
215
            eIndex = response.find('</DeliveryConfirmationLabel>',i)
 
216
            s_label = response[int(sIndex) + 27:int(eIndex)]
 
217
 
 
218
            s_label = s_label.replace('\n','')
 
219
            s_label = s_label.replace('\r','')
 
220
            #shipping_label = b64decode(s_label).encode('UTF-8')
 
221
            #logger.notifyChannel('init', netsvc.LOG_WARNING, '!!!!!!shipping_label is %s'%(s_label,))
 
222
 
 
223
            """filename = "Label1.tif"
 
224
            FILE = open(filename,"w")
 
225
            FILE.write(b64decode(s_label))"""
 
226
 
 
227
            attachment_pool = self.pool.get('ir.attachment')
 
228
            data_attach = {
 
229
                'name': 'PackingList.tif',
 
230
                'datas': binascii.b2a_base64(str(b64decode(s_label))),
 
231
                'description': 'Packing List',
 
232
                'res_name': shippingresp_lnk.picking_id.name,
 
233
                'res_model': 'stock.picking',
 
234
                'res_id': shippingresp_lnk.picking_id.id,
 
235
            }
 
236
            attach_id = attachment_pool.search(cr,uid,[('res_id','=',shippingresp_lnk.picking_id.id),('res_name','=',shippingresp_lnk.picking_id.name)])
 
237
            if not attach_id:
 
238
                attach_id = attachment_pool.create(cr, uid, data_attach)
 
239
                print "attach_id: ",attach_id
 
240
            else:
 
241
                attach_result = attachment_pool.write(cr, uid, attach_id, data_attach)
 
242
                attach_id = attach_id[0]
 
243
                print "attach_result: ",attach_result
 
244
            context['attach_id'] = attach_id
 
245
            
 
246
            if tracking_no:
 
247
                stockpicking_obj.write(cr,uid,shippingresp_lnk.picking_id.id,{'carrier_tracking_ref':tracking_no, 'shipping_label':binascii.b2a_base64(str(b64decode(s_label))), 'shipping_rate': rate})
 
248
                context['track_success'] = True
 
249
        
 
250
        elif shippingresp_lnk.type.lower() == 'fedex':
 
251
            print "Inside Fedex Shipping"
 
252
            #raise osv.except_osv(_('Error'), _('FedEx shipment request under construction'))
 
253
 
 
254
            shippingfedex_obj = self.pool.get('shipping.fedex')
 
255
            shippingfedex_id = shippingfedex_obj.search(cr,uid,[('active','=',True)])
 
256
            if not shippingfedex_id:
 
257
                raise osv.except_osv(_('Error'), _('Default Fedex settings not defined'))
 
258
            else:
 
259
                shippingfedex_id = shippingfedex_id[0]
 
260
                
 
261
            shippingfedex_ptr = shippingfedex_obj.browse(cr,uid,shippingfedex_id)
 
262
            account_no = shippingfedex_ptr.account_no
 
263
            key = shippingfedex_ptr.key
 
264
            password = shippingfedex_ptr.password
 
265
            meter_no = shippingfedex_ptr.meter_no
 
266
            is_test = shippingfedex_ptr.test
 
267
            CONFIG_OBJ = FedexConfig(key=key, password=password, account_number=account_no, meter_number=meter_no, use_test_server=is_test)
 
268
       
 
269
            # This is the object that will be handling our tracking request.
 
270
            # We're using the FedexConfig object from example_config.py in this dir.
 
271
            shipment = FedexProcessShipmentRequest(CONFIG_OBJ)
 
272
 
 
273
            # This is very generalized, top-level information.
 
274
            # REGULAR_PICKUP, REQUEST_COURIER, DROP_BOX, BUSINESS_SERVICE_CENTER or STATION
 
275
#            print "DROPOFF TYPE: ",shippingresp_lnk.dropoff_type_fedex
 
276
            fedex_servicedetails = stockpicking_obj.browse(cr,uid,shippingresp_lnk.picking_id.id)
 
277
            
 
278
            shipment.RequestedShipment.DropoffType = fedex_servicedetails.dropoff_type_fedex #'REGULAR_PICKUP'
 
279
            print "DROP OFF TYPE: ",fedex_servicedetails.dropoff_type_fedex
 
280
            # See page 355 in WS_ShipService.pdf for a full list. Here are the common ones:
 
281
            # STANDARD_OVERNIGHT, PRIORITY_OVERNIGHT, FEDEX_GROUND, FEDEX_EXPRESS_SAVER
 
282
            shipment.RequestedShipment.ServiceType = fedex_servicedetails.service_type_fedex #'PRIORITY_OVERNIGHT'
 
283
 
 
284
            # What kind of package this will be shipped in.
 
285
            # FEDEX_BOX, FEDEX_PAK, FEDEX_TUBE, YOUR_PACKAGING
 
286
            shipment.RequestedShipment.PackagingType = fedex_servicedetails.packaging_type_fedex  #'FEDEX_PAK'
 
287
 
 
288
            # No idea what this is.
 
289
            # INDIVIDUAL_PACKAGES, PACKAGE_GROUPS, PACKAGE_SUMMARY
 
290
            shipment.RequestedShipment.PackageDetail = fedex_servicedetails.package_detail_fedex #'INDIVIDUAL_PACKAGES'
 
291
 
 
292
            # Shipper contact info.
 
293
            shipment.RequestedShipment.Shipper.Contact.PersonName = shipper.name #'Sender Name'
 
294
            shipment.RequestedShipment.Shipper.Contact.CompanyName = shipper.company_name #'Some Company'
 
295
            shipment.RequestedShipment.Shipper.Contact.PhoneNumber = shipper.phone #'9012638716'
 
296
 
 
297
            # Shipper address.
 
298
            shipment.RequestedShipment.Shipper.Address.StreetLines = shipper.address1 #['Address Line 1']
 
299
            shipment.RequestedShipment.Shipper.Address.City =  shipper.city #'Herndon'
 
300
            shipment.RequestedShipment.Shipper.Address.StateOrProvinceCode = shipper.state_code #'VA'
 
301
            shipment.RequestedShipment.Shipper.Address.PostalCode = shipper.zip #'20171'
 
302
            shipment.RequestedShipment.Shipper.Address.CountryCode = shipper.country_code #'US'
 
303
            shipment.RequestedShipment.Shipper.Address.Residential = False
 
304
 
 
305
            # Recipient contact info.
 
306
            shipment.RequestedShipment.Recipient.Contact.PersonName = receipient.name #'Recipient Name'
 
307
            shipment.RequestedShipment.Recipient.Contact.CompanyName = receipient.company_name #'Recipient Company'
 
308
            shipment.RequestedShipment.Recipient.Contact.PhoneNumber = receipient.phone #'9012637906'
 
309
 
 
310
            # Recipient address
 
311
            shipment.RequestedShipment.Recipient.Address.StreetLines = receipient.address1 #['Address Line 1']
 
312
            shipment.RequestedShipment.Recipient.Address.City = receipient.city #'Herndon'
 
313
            shipment.RequestedShipment.Recipient.Address.StateOrProvinceCode = receipient.state_code #'VA'
 
314
            shipment.RequestedShipment.Recipient.Address.PostalCode = receipient.zip #'20171'
 
315
            shipment.RequestedShipment.Recipient.Address.CountryCode = receipient.country_code #'US'
 
316
            # This is needed to ensure an accurate rate quote with the response.
 
317
            shipment.RequestedShipment.Recipient.Address.Residential = False
 
318
 
 
319
            # Who pays for the shipment?
 
320
            # RECIPIENT, SENDER or THIRD_PARTY
 
321
            shipment.RequestedShipment.ShippingChargesPayment.PaymentType = fedex_servicedetails.payment_type_fedex #'SENDER'
 
322
 
 
323
            # Specifies the label type to be returned.
 
324
            # LABEL_DATA_ONLY or COMMON2D
 
325
            shipment.RequestedShipment.LabelSpecification.LabelFormatType = 'COMMON2D'
 
326
 
 
327
            # Specifies which format the label file will be sent to you in.
 
328
            # DPL, EPL2, PDF, PNG, ZPLII
 
329
            shipment.RequestedShipment.LabelSpecification.ImageType = 'PNG'
 
330
 
 
331
            # To use doctab stocks, you must change ImageType above to one of the
 
332
            # label printer formats (ZPLII, EPL2, DPL).
 
333
            # See documentation for paper types, there quite a few.
 
334
            shipment.RequestedShipment.LabelSpecification.LabelStockType = 'PAPER_4X6'
 
335
 
 
336
            # This indicates if the top or bottom of the label comes out of the
 
337
            # printer first.
 
338
            # BOTTOM_EDGE_OF_TEXT_FIRST or TOP_EDGE_OF_TEXT_FIRST
 
339
            shipment.RequestedShipment.LabelSpecification.LabelPrintingOrientation = 'BOTTOM_EDGE_OF_TEXT_FIRST'
 
340
 
 
341
            package1_weight = shipment.create_wsdl_object_of_type('Weight')
 
342
            # Weight, in pounds.
 
343
            package1_weight.Value = fedex_servicedetails.weight_package #1.0
 
344
            package1_weight.Units = "LB"
 
345
 
 
346
            package1 = shipment.create_wsdl_object_of_type('RequestedPackageLineItem')
 
347
            package1.Weight = package1_weight
 
348
            # Un-comment this to see the other variables you may set on a package.
 
349
            #print package1
 
350
 
 
351
            # This adds the RequestedPackageLineItem WSDL object to the shipment. It
 
352
            # increments the package count and total weight of the shipment for you.
 
353
            shipment.add_package(package1)
 
354
 
 
355
            # If you'd like to see some documentation on the ship service WSDL, un-comment
 
356
            # this line. (Spammy).
 
357
            #print shipment.client
 
358
 
 
359
            # Un-comment this to see your complete, ready-to-send request as it stands
 
360
            # before it is actually sent. This is useful for seeing what values you can
 
361
            # change.
 
362
            #print shipment.RequestedShipment
 
363
 
 
364
            # If you want to make sure that all of your entered details are valid, you
 
365
            # can call this and parse it just like you would via send_request(). If
 
366
            # shipment.response.HighestSeverity == "SUCCESS", your shipment is valid.
 
367
            #shipment.send_validation_request()
 
368
 
 
369
            # Fires off the request, sets the 'response' attribute on the object.
 
370
            try:
 
371
                shipment.send_request()
 
372
            except Exception, e:
 
373
                if error:
 
374
                        if e.reason.strerror == 'Name or service not known':
 
375
                            errormessage = "Connection Error: Please check your internet connection!"
 
376
                        else:
 
377
                            errormessage = e
 
378
                    
 
379
                        print "EXception: ",errormessage        
 
380
                        raise osv.except_osv(_('Error'), _('%s' % (errormessage,)))                
 
381
                
 
382
            # This will show the reply to your shipment being sent. You can access the
 
383
            # attributes through the response attribute on the request object. This is
 
384
            # good to un-comment to see the variables returned by the Fedex reply.
 
385
            #print shipment.response
 
386
            
 
387
            # Here is the overall end result of the query.
 
388
            print "HighestSeverity:", shipment.response.HighestSeverity
 
389
            # Getting the tracking number from the new shipment.
 
390
            fedexTrackingNumber = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[0].TrackingIds[0].TrackingNumber 
 
391
            print "Fedex Tracking#:",fedexTrackingNumber 
 
392
            # Net shipping costs.
 
393
            fedexshippingrate = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[0].PackageRating.PackageRateDetails[0].NetCharge.Amount
 
394
            print "Net Shipping Cost (US$):",fedexshippingrate
 
395
 
 
396
            # Get the label image in ASCII format from the reply. Note the list indices
 
397
            # we're using. You'll need to adjust or iterate through these if your shipment
 
398
            # has multiple packages.
 
399
            ascii_label_data = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[0].Label.Parts[0].Image
 
400
            # Convert the ASCII data to binary.
 
401
#            label_binary_data = binascii.a2b_base64(ascii_label_data)
 
402
#            print"LABEL: ",label_binary_data
 
403
            """
 
404
            #This is an example of how to dump a label to a PNG file.
 
405
            """
 
406
            # This will be the file we write the label out to.
 
407
#            png_file = open('example_shipment_label.png', 'wb')
 
408
#            png_file.write(b64decode(label_binary_data))
 
409
#            png_file.close()
 
410
            
 
411
            
 
412
            fedex_attachment_pool = self.pool.get('ir.attachment')
 
413
            fedex_data_attach = {
 
414
                'name': 'PackingList.png',
 
415
                'datas': binascii.b2a_base64(str(b64decode(ascii_label_data))),
 
416
                'description': 'Packing List',
 
417
                'res_name': shippingresp_lnk.picking_id.name,
 
418
                'res_model': 'stock.picking',
 
419
                'res_id': shippingresp_lnk.picking_id.id,
 
420
            }
 
421
            
 
422
            fedex_attach_id = fedex_attachment_pool.search(cr,uid,[('res_id','=',shippingresp_lnk.picking_id.id),('res_name','=',shippingresp_lnk.picking_id.name)])
 
423
            if not fedex_attach_id:
 
424
                fedex_attach_id = fedex_attachment_pool.create(cr, uid, fedex_data_attach)
 
425
                print "attach_id: ",fedex_attach_id
 
426
            else:
 
427
                fedex_attach_result = fedex_attachment_pool.write(cr, uid, fedex_attach_id, fedex_data_attach)
 
428
                fedex_attach_id = fedex_attach_id[0]
 
429
                print "attach_result: ",fedex_attach_result
 
430
                
 
431
            context['attach_id'] = fedex_attach_id
 
432
            context['tracking_no'] = fedexTrackingNumber
 
433
            """
 
434
            #This is an example of how to print the label to a serial printer. This will not
 
435
            #work for all label printers, consult your printer's documentation for more
 
436
            #details on what formats it can accept.
 
437
            """
 
438
            # Pipe the binary directly to the label printer. Works under Linux
 
439
            # without requiring PySerial. This WILL NOT work on other platforms.
 
440
            #label_printer = open("/dev/ttyS0", "w")
 
441
            #label_printer.write(label_binary_data)
 
442
            #label_printer.close()
 
443
 
 
444
            """
 
445
            #This is a potential cross-platform solution using pySerial. This has not been
 
446
            #tested in a long time and may or may not work. For Windows, Mac, and other
 
447
            #platforms, you may want to go this route.
 
448
            """
 
449
            #import serial
 
450
            #label_printer = serial.Serial(0)
 
451
            #print "SELECTED SERIAL PORT: "+ label_printer.portstr
 
452
            #label_printer.write(label_binary_data)
 
453
            #label_printer.close()
 
454
#
 
455
#            if shipment.response.CompletedShipmentDetail.CompletedPackageDetails[0].TrackingIds[0].TrackingNumber:
 
456
#                track_success = True
 
457
            if fedexTrackingNumber:
 
458
                stockpickingwrite_result = stockpicking_obj.write(cr,uid,shippingresp_lnk.picking_id.id,{'carrier_tracking_ref':fedexTrackingNumber, 'shipping_label':binascii.b2a_base64(str(b64decode(ascii_label_data))), 'shipping_rate': fedexshippingrate})
 
459
                context['track_success'] = True    
 
460
 
 
461
        elif shippingresp_lnk.type.lower() == 'ups':
 
462
            ups_info = self.pool.get('shipping.ups').get_ups_info(cr,uid,context)
 
463
 
 
464
            stockpicking_obj = self.pool.get('stock.picking')
 
465
            pickup_type_ups = shippingresp_lnk.picking_id.pickup_type_ups
 
466
            service_type_ups = shippingresp_lnk.picking_id.service_type_ups
 
467
            packaging_type_ups = shippingresp_lnk.picking_id.packaging_type_ups
 
468
            ups = shippingservice.UPSShipmentConfirmRequest(ups_info, pickup_type_ups, service_type_ups, packaging_type_ups, weight, shipper, receipient)
 
469
            try:
 
470
                ups_response = ups.send()
 
471
            except Exception, e:
 
472
                if error:
 
473
                        if e.reason.strerror == 'Name or service not known':
 
474
                            errormessage = "Connection Error: Please check your internet connection!"
 
475
                        else:
 
476
                            errormessage = e
 
477
                    
 
478
                        print "EXception: ",errormessage        
 
479
                        raise osv.except_osv(_('Error'), _('%s' % (errormessage,)))
 
480
                        
 
481
            ups = shippingservice.UPSShipmentAcceptRequest(ups_info, ups_response.shipment_digest)
 
482
            ups_response = ups.send()
 
483
            
 
484
            context['attach_id'] = stockpicking_obj.create_attachment(cr,uid,[shippingresp_lnk.picking_id.id],ups_response,context)
 
485
            stockpickingwrite_result = stockpicking_obj.write(cr,uid,shippingresp_lnk.picking_id.id,{'carrier_tracking_ref':ups_response.tracking_number, 'shipping_label':binascii.b2a_base64(str(b64decode(ups_response.graphic_image))), 'shipping_rate': rate})
 
486
            context['track_success'] = True
 
487
            context['tracking_no'] = ups_response.tracking_number
 
488
        
 
489
        ### Check Availability; Confirm; Validate : Automate Process Now step
 
490
        if context.get('track_success',False):
 
491
            ### Assign Carrier to Delivery carrier if user has not chosen
 
492
#            carrier_lnk = stockpicking_obj.browse(cr,uid,shippingresp_lnk.picking_id.id).carrier_id
 
493
#            if not carrier_lnk:
 
494
            type_fieldname = ''
 
495
            if shippingresp_lnk.type.lower() == 'usps':
 
496
                type_fieldname = 'is_usps'
 
497
            elif shippingresp_lnk.type.lower() == 'ups':
 
498
                type_fieldname = 'is_ups'
 
499
            elif shippingresp_lnk.type.lower() == 'fedex':
 
500
                type_fieldname = 'is_fedex'
 
501
                
 
502
            carrier_ids = self.pool.get('delivery.carrier').search(cr,uid,[('service_output','=',shippingresp_lnk.name),(type_fieldname,'=',True)])
 
503
            if not carrier_ids:
 
504
                if error:
 
505
                    raise osv.except_osv(_('Error'), _('Shipping service output settings not defined'))
 
506
                return False
 
507
#            print "selected carrier ids: ",carrier_ids
 
508
            self.pool.get('stock.picking').write(cr,uid,shippingresp_lnk.picking_id.id,{'carrier_id':carrier_ids[0]})
 
509
            
 
510
            ### Check Availabiity
 
511
            actionassign_result = stockpicking_obj.action_assign_new(cr,uid,[shippingresp_lnk.picking_id.id])
 
512
            print "actionassign_result: ",actionassign_result
 
513
            if not actionassign_result:
 
514
                ### Force Availability
 
515
#                forceassign_result = stockpicking_obj.force_assign(cr,uid,[shippingresp_lnk.picking_id.id])
 
516
                saleorder_obj.write(cr,uid,shippingresp_lnk.picking_id.sale_id.id,{'state':'shipping_except'})
 
517
                return False
 
518
            
 
519
            current_time = time.strftime('%Y-%m-%d %H:%M:%S')
 
520
            partial_datas = {
 
521
                'delivery_date' : current_time
 
522
            }
 
523
 
 
524
            for move in move_lines:
 
525
                if move.state in ('done', 'cancel'):
 
526
                    continue
 
527
 
 
528
                partial_datas['move%s' % (move.id)] = {
 
529
                    'product_id' : move.product_id.id,
 
530
                    'product_qty' : move.product_qty,
 
531
                    'product_uom' :move.product_uom.id,
 
532
                    'prodlot_id' : move.prodlot_id.id,
 
533
                }
 
534
 
 
535
            #print "partial_datas: ",partial_datas
 
536
            res = stockpicking_obj.do_partial(cr,uid,[shippingresp_lnk.picking_id.id],partial_datas,context)
 
537
 
 
538
            wf_service = netsvc.LocalService("workflow")
 
539
            wf_service.trg_write(uid, 'stock.picking', shippingresp_lnk.picking_id.id, cr)
 
540
            wf_service.trg_write(uid, 'sale.order', shippingresp_lnk.picking_id.sale_id.id, cr)
 
541
            saleorder_obj.write(cr,uid,shippingresp_lnk.picking_id.sale_id.id,{'client_order_ref':context['tracking_no'], 'carrier_id':carrier_ids[0]})
 
542
 
 
543
            ### Write this shipping respnse is selected
 
544
            self.write(cr,uid,ids[0],{'selected':True})
 
545
 
 
546
            if context.get('batch_printing',False):
 
547
                return True
 
548
            
 
549
            
 
550
            #serverip = socket.gethostbyname(socket.gethostname())
 
551
            try:
 
552
                serverip = urllib2.urlopen('http://whatismyip.org').read()
 
553
            except Exception, e:                
 
554
                if error:
 
555
                    raise osv.except_osv(_('Error'), _('%s' % (e))) 
 
556
                
 
557
            print "IP ADDRESS IS: ",serverip
 
558
            
 
559
            return {'type': 'ir.actions.act_url',
 
560
                'url': 'http://'+serverip+':8080/openerp/attachment/get?record=' + str(context['attach_id']),
 
561
                'target': 'new'}
 
562
 
 
563
#            datas = {'ids': [shippingresp_lnk.picking_id.id],
 
564
#                     'model': 'stock.picking'}
 
565
 
 
566
#            return {'type': 'ir.actions.report.xml',
 
567
#                    'report_name': 'webkitstock.picking.label',
 
568
#                    'datas': datas}
 
569
#            return True
 
570
        else:
 
571
            return False 
 
572
    _order = 'sr_no'
 
573
 
 
574
    _columns = {
 
575
        'name': fields.char('Service Type', size=100, readonly=True),
 
576
        'type': fields.char('Shipping Type', size=64, readonly=True),
 
577
        'rate': fields.char('Rate', size=64, readonly=True),
 
578
        #'tracking_no' : fields.char('Tracking No.', size=100),
 
579
        'weight' : fields.float('Weight'),
 
580
        'cust_default' : fields.boolean('Customer Default'),
 
581
        'sys_default' : fields.boolean('System Default'),
 
582
        'sr_no' : fields.integer('Sr. No'),
 
583
        'selected' : fields.boolean('Selected'),
 
584
        'picking_id' : fields.many2one('stock.picking','Picking')
 
585
    }
 
586
    _defaults = {
 
587
        'sr_no': 9,
 
588
        'selected': False
 
589
    }
 
590
shipping_response()
 
591
 
 
592
def _get_shipping_type(self, cr, uid, context=None):
 
593
    return [
 
594
        ('Fedex','Fedex'),
 
595
        ('UPS','UPS'),
 
596
        ('USPS','USPS'),
 
597
        ('All','All'),
 
598
    ]
 
599
def _get_service_type_usps(self, cr, uid, context=None):
 
600
    return [
 
601
        ('First Class', 'First Class'),
 
602
        ('First Class HFP Commercial', 'First Class HFP Commercial'),
 
603
        ('FirstClassMailInternational', 'First Class Mail International'),
 
604
        ('Priority', 'Priority'),
 
605
        ('Priority Commercial', 'Priority Commercial'),
 
606
        ('Priority HFP Commercial', 'Priority HFP Commercial'),
 
607
        ('PriorityMailInternational', 'Priority Mail International'),
 
608
        ('Express', 'Express'),
 
609
        ('Express Commercial', 'Express Commercial'),
 
610
        ('Express SH', 'Express SH'),
 
611
        ('Express SH Commercial', 'Express SH Commercial'),
 
612
        ('Express HFP', 'Express HFP'),
 
613
        ('Express HFP Commercial', 'Express HFP Commercial'),
 
614
        ('ExpressMailInternational', 'Express Mail International'),
 
615
        ('ParcelPost', 'Parcel Post'),
 
616
        ('ParcelSelect', 'Parcel Select'),
 
617
        ('StandardMail', 'Standard Mail'),
 
618
        ('CriticalMail', 'Critical Mail'),
 
619
        ('Media', 'Media'),
 
620
        ('Library', 'Library'),
 
621
        ('All', 'All'),
 
622
        ('Online', 'Online'),
 
623
    ]
 
624
 
 
625
def _get_first_class_mail_type_usps(self, cr, uid, context=None):
 
626
    return [
 
627
        ('Letter', 'Letter'),
 
628
        ('Flat', 'Flat'),
 
629
        ('Parcel', 'Parcel'),
 
630
        ('Postcard', 'Postcard'),
 
631
    ]
 
632
 
 
633
def _get_container_usps(self, cr, uid, context=None):
 
634
    return [
 
635
        ('Variable', 'Variable'),
 
636
        ('Card', 'Card'),
 
637
        ('Letter', 'Letter'),
 
638
        ('Flat', 'Flat'),
 
639
        ('Parcel', 'Parcel'),
 
640
        ('Large Parcel', 'Large Parcel'),
 
641
        ('Irregular Parcel', 'Irregular Parcel'),
 
642
        ('Oversized Parcel', 'Oversized Parcel'),
 
643
        ('Flat Rate Envelope', 'Flat Rate Envelope'),
 
644
        ('Padded Flat Rate Envelope', 'Padded Flat Rate Envelope'),
 
645
        ('Legal Flat Rate Envelope', 'Legal Flat Rate Envelope'),
 
646
        ('SM Flat Rate Envelope', 'SM Flat Rate Envelope'),
 
647
        ('Window Flat Rate Envelope', 'Window Flat Rate Envelope'),
 
648
        ('Gift Card Flat Rate Envelope', 'Gift Card Flat Rate Envelope'),
 
649
        ('Cardboard Flat Rate Envelope', 'Cardboard Flat Rate Envelope'),
 
650
        ('Flat Rate Box', 'Flat Rate Box'),
 
651
        ('SM Flat Rate Box', 'SM Flat Rate Box'),
 
652
        ('MD Flat Rate Box', 'MD Flat Rate Box'),
 
653
        ('LG Flat Rate Box', 'LG Flat Rate Box'),
 
654
        ('RegionalRateBoxA', 'RegionalRateBoxA'),
 
655
        ('RegionalRateBoxB', 'RegionalRateBoxB'),
 
656
        ('Rectangular', 'Rectangular'),
 
657
        ('Non-Rectangular', 'Non-Rectangular'),
 
658
     ]
 
659
 
 
660
def _get_size_usps(self, cr, uid, context=None):
 
661
    return [
 
662
        ('REGULAR', 'Regular'),
 
663
        ('LARGE', 'Large'),
 
664
     ]
 
665
 
 
666
class stock_picking(osv.osv):
 
667
    _name = "stock.picking"
 
668
    _inherit = "stock.picking"
 
669
 
 
670
    def action_assign_new(self, cr, uid, ids, *args):
 
671
        """ Changes state of picking to available if all moves are confirmed.
 
672
        @return: True
 
673
        """
 
674
        for pick in self.browse(cr, uid, ids):
 
675
            move_ids = [x.id for x in pick.move_lines if x.state == 'confirmed']
 
676
            print "move_ids in action_assign_new: ",move_ids
 
677
            if not move_ids:
 
678
                return False
 
679
            self.pool.get('stock.move').action_assign(cr, uid, move_ids)
 
680
        return True
 
681
 
 
682
    def get_ups_servicetype_name(self, cr, uid, ids, code, mag_code=False):
 
683
        if code:
 
684
            if code == '01':
 
685
                return 'Next Day Air'
 
686
            elif code == '02':
 
687
                return 'Second Day Air'
 
688
            elif code == '03':
 
689
                return 'Ground'
 
690
            elif code == '07':
 
691
                return 'Worldwide Express'
 
692
            elif code == '08':
 
693
                return 'Worldwide Expedited'
 
694
            elif code == '11':
 
695
                return 'Standard'
 
696
            elif code == '12':
 
697
                return 'Three-Day Select'
 
698
            elif code == '13':
 
699
                return 'Next Day Air Saver'
 
700
            elif code == '14':
 
701
                return 'Next Day Air Early AM'
 
702
            elif code == '54':
 
703
                return 'Worldwide Express Plus'
 
704
            elif code == '59':
 
705
                return 'Second Day Air AM'
 
706
            elif code == '65':
 
707
                return 'Saver'
 
708
            else:
 
709
                return False
 
710
        elif mag_code:
 
711
            if mag_code == 'ups_3DS':
 
712
                return 'Three-Day Select'
 
713
            elif mag_code == 'ups_GND':
 
714
                return 'Ground'
 
715
            elif mag_code == 'ups_2DA':
 
716
                return 'Second Day Air'
 
717
            elif mag_code == 'ups_1DP':
 
718
                return 'Next Day Air Saver'
 
719
            elif mag_code == 'ups_1DA':
 
720
                return 'Next Day Air'
 
721
            elif mag_code == 'ups_1DM':
 
722
                return 'Next Day Air Early AM'
 
723
        else:
 
724
            return False
 
725
 
 
726
    def generate_fedex_shipping(self, cr, uid, ids, dropoff_type_fedex, service_type_fedex, packaging_type_fedex, package_detail_fedex, payment_type_fedex, physical_packaging_fedex, weight, shipper_postal_code,shipper_country_code,customer_postal_code,customer_country_code, sys_default=False,cust_default=False, error=True, context=None):
 
727
        if 'fedex_active' in context.keys() and context['fedex_active'] == False:
 
728
            return True
 
729
        shippingfedex_obj = self.pool.get('shipping.fedex')
 
730
        shippingfedex_id = shippingfedex_obj.search(cr,uid,[('active','=',True)])
 
731
        if not shippingfedex_id:
 
732
            if error:
 
733
                raise osv.except_osv(_('Error'), _('Default FedEx settings not defined'))
 
734
            else:
 
735
                return False
 
736
        else:
 
737
            shippingfedex_id = shippingfedex_id[0]
 
738
 
 
739
        shippingfedex_ptr = shippingfedex_obj.browse(cr,uid,shippingfedex_id)
 
740
        account_no = shippingfedex_ptr.account_no
 
741
        key = shippingfedex_ptr.key
 
742
        password = shippingfedex_ptr.password
 
743
        meter_no = shippingfedex_ptr.meter_no
 
744
        is_test = shippingfedex_ptr.test
 
745
        CONFIG_OBJ = FedexConfig(key=key, password=password, account_number=account_no, meter_number=meter_no, use_test_server=is_test)
 
746
        rate_request = FedexRateServiceRequest(CONFIG_OBJ)
 
747
 
 
748
        stockpicking_lnk = self.browse(cr,uid,ids[0])
 
749
 
 
750
        #print "dropoff_type_fedex: ",dropoff_type_fedex
 
751
        #print "service_type_fedex: ",service_type_fedex
 
752
        #print "packaging_type_fedex: ",packaging_type_fedex
 
753
        # This is very generalized, top-level information.
 
754
        # REGULAR_PICKUP, REQUEST_COURIER, DROP_BOX, BUSINESS_SERVICE_CENTER or STATION
 
755
        rate_request.RequestedShipment.DropoffType = dropoff_type_fedex
 
756
 
 
757
        # See page 355 in WS_ShipService.pdf for a full list. Here are the common ones:
 
758
        # STANDARD_OVERNIGHT, PRIORITY_OVERNIGHT, FEDEX_GROUND, FEDEX_EXPRESS_SAVER
 
759
        rate_request.RequestedShipment.ServiceType = service_type_fedex
 
760
 
 
761
        # What kind of package this will be shipped in.
 
762
        # FEDEX_BOX, FEDEX_PAK, FEDEX_TUBE, YOUR_PACKAGING
 
763
        rate_request.RequestedShipment.PackagingType = packaging_type_fedex
 
764
 
 
765
        # No idea what this is.
 
766
        # INDIVIDUAL_PACKAGES, PACKAGE_GROUPS, PACKAGE_SUMMARY
 
767
        rate_request.RequestedShipment.PackageDetail = package_detail_fedex
 
768
 
 
769
        rate_request.RequestedShipment.Shipper.Address.PostalCode = shipper_postal_code
 
770
        rate_request.RequestedShipment.Shipper.Address.CountryCode = shipper_country_code
 
771
        rate_request.RequestedShipment.Shipper.Address.Residential = False
 
772
 
 
773
        rate_request.RequestedShipment.Recipient.Address.PostalCode = customer_postal_code
 
774
        rate_request.RequestedShipment.Recipient.Address.CountryCode = customer_country_code
 
775
        # This is needed to ensure an accurate rate quote with the response.
 
776
        #rate_request.RequestedShipment.Recipient.Address.Residential = True
 
777
        #include estimated duties and taxes in rate quote, can be ALL or NONE
 
778
        rate_request.RequestedShipment.EdtRequestType = 'NONE'
 
779
 
 
780
        # Who pays for the rate_request?
 
781
        # RECIPIENT, SENDER or THIRD_PARTY
 
782
        rate_request.RequestedShipment.ShippingChargesPayment.PaymentType = payment_type_fedex
 
783
 
 
784
        package1_weight = rate_request.create_wsdl_object_of_type('Weight')
 
785
        package1_weight.Value = weight
 
786
        package1_weight.Units = "LB"
 
787
 
 
788
        package1 = rate_request.create_wsdl_object_of_type('RequestedPackageLineItem')
 
789
        package1.Weight = package1_weight
 
790
        #can be other values this is probably the most common
 
791
        package1.PhysicalPackaging = physical_packaging_fedex
 
792
        # Un-comment this to see the other variables you may set on a package.
 
793
        #print package1
 
794
 
 
795
        # This adds the RequestedPackageLineItem WSDL object to the rate_request. It
 
796
        # increments the package count and total weight of the rate_request for you.
 
797
        rate_request.add_package(package1)
 
798
 
 
799
        # If you'd like to see some documentation on the ship service WSDL, un-comment
 
800
        # this line. (Spammy).
 
801
        #print rate_request.client
 
802
 
 
803
        # Un-comment this to see your complete, ready-to-send request as it stands
 
804
        # before it is actually sent. This is useful for seeing what values you can
 
805
        # change.
 
806
        #print rate_request.RequestedShipment
 
807
 
 
808
        # Fires off the request, sets the 'response' attribute on the object.
 
809
        try:
 
810
            rate_request.send_request()
 
811
 
 
812
        except Exception, e:
 
813
            if error:
 
814
                raise Exception('%s' % (e))
 
815
            return False
 
816
 
 
817
        # This will show the reply to your rate_request being sent. You can access the
 
818
        # attributes through the response attribute on the request object. This is
 
819
        # good to un-comment to see the variables returned by the FedEx reply.
 
820
        #print 'response: ', rate_request.response
 
821
 
 
822
        # Here is the overall end result of the query.
 
823
        #print "HighestSeverity:", rate_request.response.HighestSeverity
 
824
 
 
825
        for detail in rate_request.response.RateReplyDetails[0].RatedShipmentDetails:
 
826
            for surcharge in detail.ShipmentRateDetail.Surcharges:
 
827
                if surcharge.SurchargeType == 'OUT_OF_DELIVERY_AREA':
 
828
                    print "ODA rate_request charge %s" % surcharge.Amount.Amount
 
829
 
 
830
        for rate_detail in rate_request.response.RateReplyDetails[0].RatedShipmentDetails:
 
831
            print "Net FedEx Charge %s %s" % (rate_detail.ShipmentRateDetail.TotalNetFedExCharge.Currency,rate_detail.ShipmentRateDetail.TotalNetFedExCharge.Amount)
 
832
 
 
833
        sr_no = 9
 
834
        sys_default_value = False
 
835
        cust_default_value = False
 
836
        if sys_default:
 
837
            sys_default_vals = sys_default.split('/')
 
838
            #print "sys_default_vals: ",sys_default_vals
 
839
            if sys_default_vals[0] == 'FedEx':
 
840
                sys_default_value = True
 
841
                sr_no = 2
 
842
 
 
843
        if cust_default:
 
844
            cust_default_vals = cust_default.split('/')
 
845
            #print "sys_default_vals: ",sys_default_vals
 
846
            if cust_default_vals[0] == 'FedEx':
 
847
                cust_default_value = True
 
848
                sr_no = 1
 
849
 
 
850
        fedex_res_vals = {
 
851
            'name' : service_type_fedex,
 
852
            'type' : 'FedEx',
 
853
            'rate' : rate_detail.ShipmentRateDetail.TotalNetFedExCharge.Amount,
 
854
            'picking_id' : ids[0], #Change the ids[0] when switch to create
 
855
            'weight' : weight,
 
856
            'sys_default' : sys_default_value,
 
857
            'cust_default' : cust_default_value,
 
858
            'sr_no' : sr_no
 
859
        }
 
860
        fedex_res_id = self.pool.get('shipping.response').create(cr,uid,fedex_res_vals)
 
861
        #print "fedex_res_id: ",fedex_res_id
 
862
        if fedex_res_id:
 
863
            return True
 
864
        else:
 
865
            return False
 
866
 
 
867
 
 
868
    def generate_usps_shipping(self, cr, uid, ids,service_type_usps,first_class_mail_type_usps,container,size_usps,weight,zip_origination,zip_destination,sys_default=False,cust_default=False,error=True,context=None):
 
869
        #service_type = {}
 
870
        ### Shift the code to def create
 
871
        ### Check if it is in delivery orders - Done
 
872
        ### Deleting all that exist if user is generating shipping again - Done
 
873
        ### Defaults values of types
 
874
        ### New link to do Generate Shipping
 
875
 
 
876
        
 
877
        #logger.notifyChannel('init', netsvc.LOG_WARNING, 'service_type_usps is %s'%(urllib.urlencode(service_type),))
 
878
        if 'usps_active' in context.keys() and context['usps_active'] == False:
 
879
            return True
 
880
 
 
881
        stockpicking_lnk = self.browse(cr,uid,ids[0])
 
882
        usps_res_id = False
 
883
        
 
884
        shippingusps_obj = self.pool.get('shipping.usps')
 
885
        shippingusps_id = shippingusps_obj.search(cr,uid,[('active','=',True)])
 
886
        if not shippingusps_id:
 
887
            ### This is required because when picking is created when saleorder is confirmed and if the default parameter has some error then it should not stop as the order is getting imported from external sites
 
888
            if error:
 
889
                raise osv.except_osv(_('Error'), _('Active USPS settings not defined'))
 
890
            else:
 
891
                return False
 
892
        else:
 
893
            shippingusps_id = shippingusps_id[0]
 
894
        shippingusps_ptr = shippingusps_obj.browse(cr,uid,shippingusps_id)
 
895
        user_id = shippingusps_ptr.user_id
 
896
 
 
897
        url = "http://testing.shippingapis.com/ShippingAPITest.dll?API=RateV4&" if shippingusps_ptr.test else "http://production.shippingapis.com/ShippingAPI.dll?API=RateV4&"
 
898
 
 
899
        ## <Service></Service>
 
900
        service_type = '<Service>' + service_type_usps + '</Service>'
 
901
 
 
902
        if service_type_usps == 'First Class':
 
903
            service_type += '<FirstClassMailType>' + first_class_mail_type_usps + '</FirstClassMailType>'
 
904
        #logger.notifyChannel('init', netsvc.LOG_WARNING, 'service_type is %s'%(service_type,))
 
905
        ### <Container />
 
906
        container = container and '<Container>' + container + '</Container>' or '<Container/>'
 
907
        #logger.notifyChannel('init', netsvc.LOG_WARNING, 'container is %s'%(container,))
 
908
        ### <Size />
 
909
        size = '<Size>' + size_usps + '</Size>'
 
910
        if size_usps == 'LARGE':
 
911
            size += '<Width>' + str(stockpicking_lnk.width_usps) + '</Width>'
 
912
            size += '<Length>' + str(stockpicking_lnk.length_usps) + '</Length>'
 
913
            size += '<Height>' + str(stockpicking_lnk.height_usps) + '</Height>'
 
914
 
 
915
            if stockpicking_lnk.container_usps == 'Non-Rectangular' or stockpicking_lnk.container_usps == 'Variable' or stockpicking_lnk.container_usps == '':
 
916
                size += '<Girth>' + str(stockpicking_lnk.height_usps) + '</Girth>'
 
917
        #logger.notifyChannel('init', netsvc.LOG_WARNING, 'size is %s'%(size,))
 
918
 
 
919
        weight_org = weight
 
920
        weight = math.modf(weight)
 
921
        pounds = int(weight[1])
 
922
        ounces = round(weight[0],2) * 16
 
923
 
 
924
        #logger.notifyChannel('init', netsvc.LOG_WARNING, 'pounds is %s'%(pounds,))
 
925
        #logger.notifyChannel('init', netsvc.LOG_WARNING, 'ounces is %s'%(ounces,))
 
926
 
 
927
        values = {}
 
928
        values['XML'] = '<RateV4Request USERID="' + user_id + '"><Revision/><Package ID="1ST">' + service_type + '<ZipOrigination>' + zip_origination + '</ZipOrigination><ZipDestination>' + zip_destination + '</ZipDestination><Pounds>' + str(pounds) + '</Pounds><Ounces>' + str(ounces) + '</Ounces>' + container + size + '<Machinable>true</Machinable></Package></RateV4Request>'
 
929
        logger.notifyChannel('init', netsvc.LOG_WARNING, 'values is %s'%(urllib.urlencode(values),))
 
930
        url = url + urllib.urlencode(values)
 
931
        logger.notifyChannel('init', netsvc.LOG_WARNING, 'shipping url is %s'%(url,))
 
932
        try:
 
933
            f = urllib2.urlopen(url)
 
934
            response = f.read()
 
935
            logger.notifyChannel('init', netsvc.LOG_WARNING, '!!!!!!shipping response is %s'%(response,))
 
936
        except Exception, e:
 
937
            raise Exception('%s' % (e))
 
938
            return False
 
939
 
 
940
 
 
941
        if response.find('<Error>') != -1:
 
942
            sIndex = response.find('<Description>')
 
943
            eIndex = response.find('</Description>')
 
944
            if error:
 
945
                raise Exception('%s' % (response[int(sIndex)+13:int(eIndex)],))
 
946
            else:
 
947
                return False
 
948
 
 
949
        
 
950
 
 
951
        i = sIndex = eIndex = 0
 
952
        sIndex = response.find('<MailService>',i)
 
953
        eIndex = response.find('</MailService>',i)
 
954
        rsIndex = response.find('<Rate>',i)
 
955
        reIndex = response.find('</Rate>',i)
 
956
        while (sIndex != -1):
 
957
            i = reIndex + 7
 
958
            mail_service = response[int(sIndex) + 13:int(eIndex)]
 
959
            tm = chr(174)
 
960
#            mail_service = mail_service.replace("&amp;lt;sup&amp;gt;&amp;amp;reg;&amp;lt;/sup&amp;gt;",str(tm))
 
961
            mail_service = mail_service.replace("&amp;lt;sup&amp;gt;&amp;amp;reg;&amp;lt;/sup&amp;gt;","")
 
962
            rate = response[int(rsIndex)+6:int(reIndex)]
 
963
            sIndex = response.find('<MailService>',i)
 
964
            eIndex = response.find('</MailService>',i)
 
965
            rsIndex = response.find('<Rate>',i)
 
966
            reIndex = response.find('</Rate>',i)
 
967
            #logger.notifyChannel('init', netsvc.LOG_WARNING, 'sIndex is %s'%(sIndex,))
 
968
            #logger.notifyChannel('init', netsvc.LOG_WARNING, 'eIndex is %s'%(eIndex,))
 
969
            #logger.notifyChannel('init', netsvc.LOG_WARNING, '!!!!!!shipping mail_service is %s'%(mail_service,))
 
970
            #logger.notifyChannel('init', netsvc.LOG_WARNING, '!!!!!!shipping rate is %s'%(h.unescape(rate),))
 
971
 
 
972
            
 
973
            """if sys_default:
 
974
                if mail_service.lower().find(def_service_type.lower()) != -1:
 
975
                    #print "Testng condition: ",mail_service.lower().find(def_service_type.lower())
 
976
                    if mail_service.lower().find(def_firstclass_type.lower()) != -1:
 
977
                        if def_container:
 
978
                            if mail_service.lower().find(def_container.lower()) != -1:
 
979
                                sys_default_value = True
 
980
                                sr_no = 1
 
981
                        else:
 
982
                            sys_default_value = True
 
983
                            sr_no = 1"""
 
984
 
 
985
            sys_default_value = False
 
986
            cust_default_value = False
 
987
            sr_no = 9
 
988
            print "sys_default: ",sys_default
 
989
 
 
990
            if cust_default and cust_default.split('/')[0] == 'USPS':
 
991
                cust_default_value = True
 
992
                sr_no = 1
 
993
                    
 
994
            elif sys_default and sys_default.split('/')[0] == 'USPS':
 
995
                sys_default_value = True
 
996
                sr_no = 2
 
997
                    
 
998
            usps_res_vals = {
 
999
                'name' : mail_service,
 
1000
                'type' : 'USPS',
 
1001
                'rate' : rate,
 
1002
                'picking_id' : ids[0], #Change the ids[0] when switch to create
 
1003
                'weight' : weight_org,
 
1004
                'sys_default' : sys_default_value,
 
1005
                'cust_default' : cust_default_value,
 
1006
                'sr_no' : sr_no,
 
1007
            }
 
1008
            usps_res_id = self.pool.get('shipping.response').create(cr,uid,usps_res_vals)
 
1009
            logger.notifyChannel('init', netsvc.LOG_WARNING, 'usps_res_id is %s'%(usps_res_id,))
 
1010
        if usps_res_id:
 
1011
            return True
 
1012
        else:
 
1013
            return False
 
1014
 
 
1015
    def create_quotes(self, cr, uid, ids, vals, context={}):
 
1016
        quotes_vals = {
 
1017
            'name' : vals.service_type,
 
1018
            'type' : context['type'],
 
1019
            'rate' : vals.rate,
 
1020
            'picking_id' : ids[0], #Change the ids[0] when switch to create
 
1021
            'weight' : vals.weight,
 
1022
            'sys_default' : False,
 
1023
            'cust_default' : False,
 
1024
            'sr_no' : vals.sr_no,
 
1025
        }
 
1026
        res_id = self.pool.get('shipping.response').create(cr,uid,quotes_vals)
 
1027
        logger.notifyChannel('init', netsvc.LOG_WARNING, 'res_id is %s'%(res_id,))
 
1028
        if res_id:
 
1029
            return True
 
1030
        else:
 
1031
            return False
 
1032
 
 
1033
    def create_attachment(self, cr, uid, ids, vals, context={}):
 
1034
        attachment_pool = self.pool.get('ir.attachment')
 
1035
        data_attach = {
 
1036
            'name': 'PackingList.' + vals.image_format.lower() ,
 
1037
            'datas': binascii.b2a_base64(str(b64decode(vals.graphic_image))),
 
1038
            'description': 'Packing List',
 
1039
            'res_name': self.browse(cr,uid,ids[0]).name,
 
1040
            'res_model': 'stock.picking',
 
1041
            'res_id': ids[0],
 
1042
        }
 
1043
        attach_id = attachment_pool.search(cr,uid,[('res_id','=',ids[0]),('res_name','=',self.browse(cr,uid,ids[0]).name)])
 
1044
        if not attach_id:
 
1045
            attach_id = attachment_pool.create(cr, uid, data_attach)
 
1046
            print "attach_id: ",attach_id
 
1047
        else:
 
1048
            attach_id = attach_id[0]
 
1049
            attach_result = attachment_pool.write(cr, uid, attach_id, data_attach)
 
1050
            print "attach_result: ",attach_result
 
1051
        return attach_id
 
1052
 
 
1053
 
 
1054
    ## This function is called when the button is clicked
 
1055
    def generate_shipping(self, cr, uid, ids, context={}):
 
1056
        print"IDS IS:",ids
 
1057
        print"rajivcontext",context
 
1058
        if context is None:
 
1059
            context = {}
 
1060
#        logger.notifyChannel('init', netsvc.LOG_WARNING, 'inside generate_shipping context: %s'%(context,))
 
1061
        for id in ids:
 
1062
            print"ID IS:",id
 
1063
            try:
 
1064
                stockpicking = self.browse(cr,uid,id)
 
1065
                shipping_type = stockpicking.shipping_type
 
1066
                print"shipping_type@@@",shipping_type
 
1067
 
 
1068
                weight = stockpicking.weight_package if stockpicking.weight_package else stockpicking.weight_net
 
1069
                if not weight:
 
1070
                    if context.get('error',False):
 
1071
                        raise Exception('Package Weight Invalid!')
 
1072
                    else:
 
1073
                        return False
 
1074
                shop_id = stockpicking.sale_id.shop_id
 
1075
                print"shop_id@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",shop_id
 
1076
                cust_address = stockpicking.sale_id.shop_id.cust_address
 
1077
                print "CUST ADDRESS: ",cust_address
 
1078
                if not cust_address:
 
1079
                    if context.get('error',False):
 
1080
                        raise Exception('Shop Address not defined!')
 
1081
                    else:
 
1082
                        return False
 
1083
 
 
1084
                shipper = Address(cust_address.name or cust_address.partner_id.name, cust_address.street, cust_address.city, cust_address.state_id.code or '', cust_address.zip, cust_address.country_id.code, cust_address.street2 or '', cust_address.phone or '', cust_address.email, cust_address.partner_id.name)
 
1085
                
 
1086
                ### Recipient
 
1087
                cust_address = stockpicking.address_id
 
1088
                cust_default=False
 
1089
                sys_default=False
 
1090
                stockpicking_lnk = self.browse(cr,uid,ids[0])
 
1091
                receipient = Address(cust_address.name or cust_address.partner_id.name, cust_address.street, cust_address.city, cust_address.state_id.code or '', cust_address.zip, cust_address.country_id.code, cust_address.street2 or '', cust_address.phone or '', cust_address.email, cust_address.partner_id.name)
 
1092
 
 
1093
                # Deleting previous quotes
 
1094
                shipping_res_obj = self.pool.get('shipping.response')
 
1095
                shipping_res_ids = shipping_res_obj.search(cr,uid,[('picking_id','=',ids[0])])
 
1096
                if shipping_res_ids:
 
1097
                    shipping_res_obj.unlink(cr,uid,shipping_res_ids)
 
1098
 
 
1099
                if 'usps_active' not in context.keys() and (shipping_type == 'USPS' or shipping_type == 'All'):
 
1100
                    print"Asif inside usps"
 
1101
                    usps_info = self.pool.get('shipping.usps').get_usps_info(cr,uid,context)
 
1102
                    service_type_usps = stockpicking.service_type_usps
 
1103
                    first_class_mail_type_usps = stockpicking.first_class_mail_type_usps or ''
 
1104
                    container_usps = stockpicking.container_usps or ''
 
1105
                    size_usps = stockpicking.size_usps
 
1106
                    width_usps = stockpicking.width_usps
 
1107
                    length_usps = stockpicking.length_usps
 
1108
                    height_usps = stockpicking.height_usps
 
1109
                    girth_usps = stockpicking.girth_usps
 
1110
                    usps = shippingservice.USPSRateRequest(usps_info, service_type_usps, first_class_mail_type_usps, container_usps, size_usps, width_usps, length_usps, height_usps, girth_usps, weight, shipper, receipient, cust_default, sys_default)
 
1111
                    usps_response = usps.send()
 
1112
                    context['type'] = 'USPS'
 
1113
                    self.create_quotes(cr,uid,ids,usps_response,context)
 
1114
#                    shipping_res = self.generate_usps_shipping(cr,uid,[id],service_type_usps,first_class_mail_type_usps,container_usps,size_usps,weight,shipper_postal_code,customer_postal_code,sys_default,cust_default,error_required,context)
 
1115
 
 
1116
                if 'ups_active' not in context.keys() or (shipping_type == 'UPS' or shipping_type == 'All'):
 
1117
                    print"Rajiv.S.Singh"
 
1118
                    ups_info = self.pool.get('shipping.ups').get_ups_info(cr,uid,context)
 
1119
                    pickup_type_ups = stockpicking.pickup_type_ups
 
1120
                    service_type_ups = stockpicking.service_type_ups
 
1121
                    packaging_type_ups = stockpicking.packaging_type_ups
 
1122
                    ups = shippingservice.UPSRateRequest(ups_info, pickup_type_ups, service_type_ups, packaging_type_ups, weight, shipper, receipient, cust_default, sys_default)
 
1123
                    ups_response = ups.send()
 
1124
                    context['type'] = 'UPS'
 
1125
                    self.create_quotes(cr,uid,ids,ups_response,context)
 
1126
#                    shipping_res = self.generate_ups_shipping(cr,uid,[id],pickup_type_ups,service_type_ups,packaging_type_ups,weight,shipper_postal_code,shipper_country_code,customer_postal_code,customer_country_code,sys_default,cust_default,error_required,context)
 
1127
 
 
1128
                if shipping_type == 'Fedex' or shipping_type == 'All':
 
1129
                    dropoff_type_fedex = stockpicking.dropoff_type_fedex
 
1130
                    service_type_fedex = stockpicking.service_type_fedex
 
1131
                    packaging_type_fedex = stockpicking.packaging_type_fedex
 
1132
                    package_detail_fedex = stockpicking.package_detail_fedex
 
1133
                    payment_type_fedex = stockpicking.payment_type_fedex
 
1134
                    physical_packaging_fedex = stockpicking.physical_packaging_fedex
 
1135
                    shipper_postal_code = shipper.zip
 
1136
                    shipper_country_code = shipper.country_code
 
1137
                    customer_postal_code = receipient.zip
 
1138
                    customer_country_code = receipient.country_code
 
1139
                    error_required = True
 
1140
                    shipping_res = self.generate_fedex_shipping(cr,uid,[id],dropoff_type_fedex,service_type_fedex,packaging_type_fedex,package_detail_fedex,payment_type_fedex,physical_packaging_fedex,weight,shipper_postal_code,shipper_country_code,customer_postal_code,customer_country_code,sys_default,cust_default,error_required,context)
 
1141
            except Exception, exc:
 
1142
                raise osv.except_osv(_('Error!'),_('%s' % (exc,)))
 
1143
            return True
 
1144
 
 
1145
    def _get_cust_default_shipping(self,cr,uid,carrier_id,context={}):
 
1146
        if carrier_id:
 
1147
            carrier_obj = self.pool.get('delivery.carrier')             
 
1148
            carrier_lnk = carrier_obj.browse(cr,uid,carrier_id)
 
1149
            cust_default = ''
 
1150
            if carrier_lnk.is_ups:
 
1151
                cust_default = 'UPS'
 
1152
                service_type_ups = carrier_lnk.service_code or '03'
 
1153
                cust_default += '/' + service_type_ups
 
1154
            elif carrier_lnk.is_fedex:
 
1155
                cust_default = 'FedEx'
 
1156
                service_type_fedex = carrier_lnk.service_code or 'FEDEX_GROUND'
 
1157
                cust_default += '/' + service_type_fedex
 
1158
            elif carrier_lnk.is_usps:
 
1159
                cust_default = 'USPS'
 
1160
                service_type_usps = carrier_lnk.service_code or 'All'
 
1161
                cust_default += '/' + service_type_usps
 
1162
        else:
 
1163
            cust_default = False
 
1164
        return cust_default
 
1165
 
 
1166
    def _get_sys_default_shipping(self,cr,uid,saleorderline_ids,weight,context={}):
 
1167
        print "SIJO:inside _get_sys_default_shipping"
 
1168
        sys_default = False
 
1169
        if len(saleorderline_ids) <= 2:
 
1170
            product_obj = self.pool.get('product.product')
 
1171
            saleorderline_obj = self.pool.get('sale.order.line')
 
1172
            product_shipping_obj = self.pool.get('product.product.shipping')
 
1173
            product_categ_shipping_obj = self.pool.get('product.category.shipping')
 
1174
 
 
1175
            product_id = False
 
1176
            ### Making sure product is not Shipping and Handling
 
1177
            for line in saleorderline_obj.browse(cr,uid,saleorderline_ids):
 
1178
                if line.product_id.type == 'service':
 
1179
                    continue
 
1180
                product_id = line.product_id.id
 
1181
                
 
1182
            if not product_id:
 
1183
                return False
 
1184
 
 
1185
            product_shipping_ids = product_shipping_obj.search(cr,uid,[('product_id','=',product_id)])
 
1186
 
 
1187
            if not product_shipping_ids:
 
1188
                categ_id = product_obj.browse(cr,uid,product_id).product_tmpl_id.categ_id.id
 
1189
                product_categ_shipping_ids = product_categ_shipping_obj.search(cr,uid,[('product_categ_id','=',categ_id)])
 
1190
                if not product_categ_shipping_ids:
 
1191
                    ### Assume the default
 
1192
                    if (weight*16) > 14.0:
 
1193
                        sys_default = 'USPS/Priority/Parcel/REGULAR'
 
1194
                    else:
 
1195
                        sys_default = 'USPS/First Class/Parcel/REGULAR'
 
1196
                    return sys_default
 
1197
 
 
1198
            if product_shipping_ids:
 
1199
                cr.execute(
 
1200
                    'SELECT * '
 
1201
                    'FROM product_product_shipping '
 
1202
                    'WHERE weight <= %s ' +
 
1203
                    'and product_id=%s ' +
 
1204
                    'order by sequence desc limit 1',
 
1205
                    (weight,product_id))
 
1206
            else:
 
1207
                cr.execute(
 
1208
                    'SELECT * '
 
1209
                    'FROM product_category_shipping '
 
1210
                    'WHERE weight <= %s '+
 
1211
                    'and product_categ_id=%s '+
 
1212
                    'order by sequence desc limit 1',
 
1213
                    (weight,categ_id))
 
1214
            res = cr.dictfetchall()
 
1215
            print "res: ",res
 
1216
            ## res:  [{'create_uid': 1, 'create_date': '2011-06-28 01:43:49.017306', 'product_id': 187, 'weight': 3.0, 'sequence': 3, 'container_usps': u'Letter', 'service_type_usps': u'First Class', 'write_uid': None, 'first_class_mail_type_usps': u'Letter', 'size_usps': u'REGULAR', 'write_date': None, 'shipping_type': u'USPS', 'id': 14}]
 
1217
            ### Format- USPS/First Class/Letter
 
1218
            sys_default = res[0]['shipping_type'] + '/' + res[0]['service_type_usps'] + '/' + res[0]['container_usps'] + '/' + res[0]['size_usps']
 
1219
        return sys_default
 
1220
 
 
1221
 
 
1222
    def create(self, cr, uid, vals, context=None):
 
1223
        #print "create vals: ",vals
 
1224
        #create vals:  {'origin': u'SO009', 'note': False, 'state': 'auto', 'name': u'OUT/00007', 'sale_id': 9, 'move_type': u'direct', 'type': 'out', 'address_id': 3, 'invoice_state': 'none', 'company_id': 1}
 
1225
        if context is None:
 
1226
            context={}
 
1227
        if vals.get('type',False) and vals['type'] == 'out':
 
1228
            try:
 
1229
                vals['shipping_type'] = 'All'
 
1230
                cust_default = False
 
1231
                saleorder_lnk = self.pool.get('sale.order') .browse(cr,uid,vals['sale_id'])
 
1232
                saleorderline_obj = self.pool.get('sale.order.line')
 
1233
                saleorderline_ids = saleorderline_obj.search(cr,uid,[('order_id','=',vals['sale_id'])])
 
1234
                #logger.notifyChannel('init', netsvc.LOG_WARNING, 'saleorderline_ids is %s'%(saleorderline_ids),)
 
1235
                weight = 0.0
 
1236
                for saleorderline_id in saleorderline_ids:
 
1237
                    saleorderline_lnk = saleorderline_obj.browse(cr,uid,saleorderline_id)
 
1238
                    weight += (saleorderline_lnk.product_id.product_tmpl_id.weight_net * saleorderline_lnk.product_uom_qty)
 
1239
                vals['weight_net'] = weight
 
1240
 
 
1241
                dropoff_type_fedex = 'REGULAR_PICKUP'
 
1242
                service_type_fedex = 'FEDEX_GROUND'
 
1243
                packaging_type_fedex = 'YOUR_PACKAGING'
 
1244
                package_detail_fedex = 'INDIVIDUAL_PACKAGES'
 
1245
                payment_type_fedex = 'SENDER'
 
1246
                physical_packaging_fedex = 'BOX'
 
1247
                vals['dropoff_type_fedex'] = dropoff_type_fedex
 
1248
                vals['service_type_fedex'] = service_type_fedex
 
1249
                vals['packaging_type_fedex'] = packaging_type_fedex
 
1250
                vals['package_detail_fedex'] = package_detail_fedex
 
1251
                vals['payment_type_fedex'] = payment_type_fedex
 
1252
                vals['physical_packaging_fedex'] = physical_packaging_fedex
 
1253
 
 
1254
                pickup_type_ups = '01'
 
1255
                service_type_ups = '03'
 
1256
                packaging_type_ups = '02'
 
1257
                vals['pickup_type_ups'] = pickup_type_ups
 
1258
                vals['service_type_ups'] = service_type_ups
 
1259
                vals['packaging_type_ups'] = packaging_type_ups
 
1260
 
 
1261
                carrier_id = saleorder_lnk.carrier_id and saleorder_lnk.carrier_id.id or False
 
1262
                if carrier_id:
 
1263
                    ## Find which carrier has been selected :- cust_default
 
1264
                    vals['carrier_id'] = carrier_id
 
1265
                    cust_default = self._get_cust_default_shipping(cr,uid,carrier_id,context)
 
1266
                    carrier_obj = self.pool.get('delivery.carrier')
 
1267
                    carrier_lnk = carrier_obj.browse(cr,uid,carrier_id)
 
1268
                    if carrier_lnk.is_ups:
 
1269
                        service_type_ups = carrier_lnk.service_code or '03'
 
1270
                        vals['service_type_ups'] = service_type_ups
 
1271
                    elif carrier_lnk.is_fedex:
 
1272
                        service_type_fedex = carrier_lnk.service_code or 'FEDEX_GROUND'
 
1273
                        vals['service_type_fedex'] = service_type_fedex
 
1274
                    elif carrier_lnk.is_usps:
 
1275
                        service_type_usps = carrier_lnk.service_code or 'All'
 
1276
                        first_class_mail_type_usps = carrier_lnk.first_class_mail_type_usps or 'Parcel'
 
1277
                        container_usps = carrier_lnk.container_usps or 'Parcel'
 
1278
                        size_usps = carrier_lnk.size_usps or 'REGULAR'
 
1279
                        vals['service_type_usps'] = service_type_usps
 
1280
                        vals['first_class_mail_type_usps'] = first_class_mail_type_usps
 
1281
                        vals['container_usps'] = container_usps
 
1282
                        vals['size_usps'] = size_usps
 
1283
               
 
1284
                ### Sys default applicable only for simple orders
 
1285
                sys_default = False
 
1286
#                if len(saleorderline_ids) <= 2:
 
1287
 
 
1288
                ## We consider the Gross Weight
 
1289
                    
 
1290
                sys_default = self._get_sys_default_shipping(cr,uid,saleorderline_ids,weight,context)
 
1291
                print "sys_default in create: ",sys_default
 
1292
#                   Output: USPS/First Class/Letter/Reqular
 
1293
#                   If the customer default is not there, ONLY then it goes for system default
 
1294
                if not (cust_default and cust_default.split("/")[0] == 'USPS') and sys_default and sys_default.split('/')[0] == 'USPS':
 
1295
                    vals['service_type_usps'] = sys_default.split('/')[1] or ''
 
1296
#                        vals['first_class_mail_type_usps'] = first_class_mail_type_usps
 
1297
                    vals['container_usps'] = sys_default.split('/')[2] or ''
 
1298
                    vals['size_usps'] = sys_default.split('/')[3] or ''
 
1299
 
 
1300
#                if not (cust_default or sys_default):
 
1301
#                    if (weight*16) > 14.0:
 
1302
#                        vals['service_type_usps'] = 'Priority'
 
1303
#                        vals['first_class_mail_type_usps'] = 'Parcel'
 
1304
#                        vals['container_usps'] = 'Parcel'
 
1305
#                        vals['size_usps'] = 'REGULAR'
 
1306
#                    else:
 
1307
#                        vals['service_type_usps'] = 'First Class'
 
1308
#                        vals['first_class_mail_type_usps'] = 'Parcel'
 
1309
#                        vals['container_usps'] = 'Parcel'
 
1310
#                        vals['size_usps'] = 'REGULAR'
 
1311
 
 
1312
                print "vals: ",vals
 
1313
                new_id = super(stock_picking, self).create(cr, uid, vals, context)
 
1314
                print "new_id: ",new_id
 
1315
#                error_required = False
 
1316
                
 
1317
                context['cust_default'] = cust_default
 
1318
                context['sys_default'] = sys_default
 
1319
                context['error'] = False
 
1320
                res = self.generate_shipping(cr,uid,[new_id],context)
 
1321
                print "shipping response: ",res
 
1322
#                print "error" + 1
 
1323
 
 
1324
            except Exception, e:
 
1325
                print "Exception: ",e
 
1326
                new_id = super(stock_picking, self).create(cr, uid, vals, context)
 
1327
        else:
 
1328
            new_id = super(stock_picking, self).create(cr, uid, vals, context)
 
1329
        #print "new_id: ",new_id
 
1330
#        print "error" + 1
 
1331
        return new_id
 
1332
 
 
1333
 
 
1334
    def _cal_weight_usps(self, cr, uid, ids, name, args, context=None):
 
1335
        res = {}
 
1336
        uom_obj = self.pool.get('product.uom')
 
1337
        for picking in self.browse(cr, uid, ids, context=context):
 
1338
            weight_net = picking.weight_net or 0.00
 
1339
            weight_net_usps = weight_net / 2.2
 
1340
 
 
1341
 
 
1342
            res[picking.id] = {
 
1343
                                'weight_net_usps': weight_net_usps,
 
1344
                              }
 
1345
        return res
 
1346
 
 
1347
    def _get_picking_line(self, cr, uid, ids, context=None):
 
1348
        result = {}
 
1349
        for line in self.pool.get('stock.move').browse(cr, uid, ids, context=context):
 
1350
            result[line.picking_id.id] = True
 
1351
        return result.keys()
 
1352
 
 
1353
    _columns = {
 
1354
        'use_shipping' : fields.boolean('Use Shipping'),
 
1355
        'shipping_type' : fields.selection(_get_shipping_type,'Shipping Type'),
 
1356
        'weight_package' : fields.float('Package Weight', digits_compute= dp.get_precision('Stock Weight'), help="Package weight which comes from weighinig machine in pounds"),
 
1357
        'service_type_usps' : fields.selection(_get_service_type_usps, 'Service Type', size=100),
 
1358
        'first_class_mail_type_usps' : fields.selection(_get_first_class_mail_type_usps, 'First Class Mail Type', size=50),
 
1359
        'container_usps' : fields.selection(_get_container_usps,'Container', size=100),
 
1360
        'size_usps' : fields.selection(_get_size_usps,'Size'),
 
1361
        'width_usps' : fields.float('Width', digits_compute= dp.get_precision('Stock Weight')),
 
1362
        'length_usps' : fields.float('Length', digits_compute= dp.get_precision('Stock Weight')),
 
1363
        'height_usps' : fields.float('Height', digits_compute= dp.get_precision('Stock Weight')),
 
1364
        'girth_usps' : fields.float('Girth', digits_compute= dp.get_precision('Stock Weight')),
 
1365
        #'machinable_usps' : fields.boolean('Machinable', domain=[('service_type_usps', 'in', ('first_class','parcel','all','online')), '|', ('first_class_mail_type_usps', 'in', ('letter','flat'))]),
 
1366
        #'ship_date_usps' : fields.date('Ship Date', help="Date Package Will Be Mailed. Ship date may be today plus 0 to 3 days in advance."),
 
1367
        'dropoff_type_fedex' : fields.selection([
 
1368
                ('REGULAR_PICKUP','REGULAR PICKUP'),
 
1369
                ('REQUEST_COURIER','REQUEST COURIER'),
 
1370
                ('DROP_BOX','DROP BOX'),
 
1371
                ('BUSINESS_SERVICE_CENTER','BUSINESS SERVICE CENTER'),
 
1372
                ('STATION','STATION'),
 
1373
            ],'Dropoff Type'),
 
1374
        'service_type_fedex' : fields.selection([
 
1375
                ('EUROPE_FIRST_INTERNATIONAL_PRIORITY','EUROPE_FIRST_INTERNATIONAL_PRIORITY'),
 
1376
                ('FEDEX_1_DAY_FREIGHT','FEDEX_1_DAY_FREIGHT'),
 
1377
                ('FEDEX_2_DAY','FEDEX_2_DAY'),
 
1378
                ('FEDEX_2_DAY_FREIGHT','FEDEX_2_DAY_FREIGHT'),
 
1379
                ('FEDEX_3_DAY_FREIGHT','FEDEX_3_DAY_FREIGHT'),
 
1380
                ('FEDEX_EXPRESS_SAVER','FEDEX_EXPRESS_SAVER'),
 
1381
                ('STANDARD_OVERNIGHT','STANDARD_OVERNIGHT'),
 
1382
                ('PRIORITY_OVERNIGHT','PRIORITY_OVERNIGHT'),
 
1383
                ('FEDEX_GROUND','FEDEX_GROUND'),
 
1384
           ],'Service Type'),
 
1385
        'packaging_type_fedex' : fields.selection([
 
1386
                ('FEDEX_BOX','FEDEX BOX'),
 
1387
                ('FEDEX_PAK','FEDEX PAK'),
 
1388
                ('FEDEX_TUBE','FEDEX_TUBE'),
 
1389
                ('YOUR_PACKAGING','YOUR_PACKAGING'),
 
1390
            ],'Packaging Type', help="What kind of package this will be shipped in"),
 
1391
        'package_detail_fedex' : fields.selection([
 
1392
                ('INDIVIDUAL_PACKAGES','INDIVIDUAL_PACKAGES'),
 
1393
                ('PACKAGE_GROUPS','PACKAGE_GROUPS'),
 
1394
                ('PACKAGE_SUMMARY','PACKAGE_SUMMARY'),
 
1395
            ],'Package Detail'),
 
1396
        'payment_type_fedex' : fields.selection([
 
1397
                ('RECIPIENT','RECIPIENT'),
 
1398
                ('SENDER','SENDER'),
 
1399
                ('THIRD_PARTY','THIRD_PARTY'),
 
1400
            ],'Payment Type', help="Who pays for the rate_request?"),
 
1401
        'physical_packaging_fedex' : fields.selection([
 
1402
                ('BAG','BAG'),
 
1403
                ('BARREL','BARREL'),
 
1404
                ('BOX','BOX'),
 
1405
                ('BUCKET','BUCKET'),
 
1406
                ('BUNDLE','BUNDLE'),
 
1407
                ('CARTON','CARTON'),
 
1408
                ('TANK','TANK'),
 
1409
                ('TUBE','TUBE'),
 
1410
            ],'Physical Packaging'),
 
1411
        'pickup_type_ups' : fields.selection([
 
1412
                ('01','Daily Pickup'),
 
1413
                ('03','Customer Counter'),
 
1414
                ('06','One Time Pickup'),
 
1415
                ('07','On Call Air'),
 
1416
                ('11','Suggested Retail Rates'),
 
1417
                ('19','Letter Center'),
 
1418
                ('20','Air Service Center'),
 
1419
            ],'Pickup Type'),
 
1420
        'service_type_ups' : fields.selection([
 
1421
                ('01','Next Day Air'),
 
1422
                ('02','Second Day Air'),
 
1423
                ('03','Ground'),
 
1424
                ('07','Worldwide Express'),
 
1425
                ('08','Worldwide Expedited'),
 
1426
                ('11','Standard'),
 
1427
                ('12','Three-Day Select'),
 
1428
                ('13','Next Day Air Saver'),
 
1429
                ('14','Next Day Air Early AM'),
 
1430
                ('54','Worldwide Express Plus'),
 
1431
                ('59','Second Day Air AM'),
 
1432
                ('65','Saver'),
 
1433
            ],'Service Type'),
 
1434
        'packaging_type_ups' : fields.selection([
 
1435
                ('00','Unknown'),
 
1436
                ('01','Letter'),
 
1437
                ('02','Package'),
 
1438
                ('03','Tube'),
 
1439
                ('04','Pack'),
 
1440
                ('21','Express Box'),
 
1441
                ('24','25Kg Box'),
 
1442
                ('25','10Kg Box'),
 
1443
                ('30','Pallet'),
 
1444
                ('2a','Small Express Box'),
 
1445
                ('2b','Medium Express Box'),
 
1446
                ('2c','Large Express Box'),
 
1447
            ],'Packaging Type'),
 
1448
        'shipping_label' : fields.binary('Logo'),
 
1449
        'shipping_rate': fields.float('Shipping Rate'),
 
1450
        'response_usps_ids' : fields.one2many('shipping.response','picking_id','Shipping Response')
 
1451
    }
 
1452
 
 
1453
    _defaults = {
 
1454
        'use_shipping' : True,
 
1455
        'shipping_type' : 'All',
 
1456
        'service_type_usps' : 'All',
 
1457
        'size_usps' : 'REGULAR',
 
1458
        'dropoff_type_fedex' : 'REGULAR_PICKUP',
 
1459
        'service_type_fedex' : 'FEDEX_GROUND',
 
1460
        'packaging_type_fedex' : 'YOUR_PACKAGING',
 
1461
        'package_detail_fedex' : 'INDIVIDUAL_PACKAGES',
 
1462
        'payment_type_fedex' : 'SENDER',
 
1463
        'physical_packaging_fedex' : 'BOX',
 
1464
        'pickup_type_ups' : '01',
 
1465
        'service_type_ups' : '03',
 
1466
        'packaging_type_ups' : '02'
 
1467
    }
 
1468
 
 
1469
stock_picking()
 
1470
 
 
1471
class stock_move(osv.osv):
 
1472
    _inherit = 'stock.move'
 
1473
 
 
1474
    def _cal_move_weight_new(self, cr, uid, ids, name, args, context=None):
 
1475
        res = {}
 
1476
        uom_obj = self.pool.get('product.uom')
 
1477
        for move in self.browse(cr, uid, ids, context=context):
 
1478
            weight = weight_net = 0.00
 
1479
            
 
1480
            converted_qty = move.product_qty
 
1481
            if move.product_uom.id <> move.product_id.uom_id.id:
 
1482
                converted_qty = uom_obj._compute_qty(cr, uid, move.product_uom.id, move.product_qty, move.product_id.uom_id.id)
 
1483
 
 
1484
            if move.product_id.weight > 0.00:
 
1485
                weight = (converted_qty * move.product_id.weight)
 
1486
 
 
1487
            if move.product_id.weight_net > 0.00:
 
1488
                    weight_net = (converted_qty * move.product_id.weight_net)
 
1489
 
 
1490
            res[move.id] =  {
 
1491
                            'weight': weight,
 
1492
                            'weight_net': weight_net,
 
1493
                            }
 
1494
        return res
 
1495
 
 
1496
    _columns = {
 
1497
        'weight': fields.function(_cal_move_weight_new, method=True, type='float', string='Weight', digits_compute= dp.get_precision('Stock Weight'), multi='_cal_move_weight',
 
1498
                  store={
 
1499
                 'stock.move': (lambda self, cr, uid, ids, c=None: ids, ['product_id', 'product_qty', 'product_uom'], 20),
 
1500
                 }),
 
1501
        'weight_net': fields.function(_cal_move_weight_new, method=True, type='float', string='Net weight', digits_compute= dp.get_precision('Stock Weight'), multi='_cal_move_weight',
 
1502
                  store={
 
1503
                 'stock.move': (lambda self, cr, uid, ids, c=None: ids, ['product_id', 'product_qty', 'product_uom'], 20),
 
1504
                 }),
 
1505
        }
 
1506
 
 
1507
stock_move()