1
# -*- coding: utf-8 -*-
2
##############################################################################
4
# OpenERP, Open Source Management Solution
5
# Copyright (C) 2011 NovaPoint Group LLC (<http://www.novapointgroup.com>)
6
# Copyright (C) 2004-2010 OpenERP SA (<http://www.openerp.com>)
8
# This program is free software: you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation, either version 3 of the License, or
11
# (at your option) any later version.
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
18
# You should have received a copy of the GNU General Public License
19
# along with this program. If not, see <http://www.gnu.org/licenses/>
21
##############################################################################
23
from xml.dom.minidom import Document
29
from urlparse import urlparse
32
from mako.template import Template
36
from tools.translate import _
37
from osv import fields, osv
39
class shipping_move(osv.osv):
40
_inherit = "shipping.move"
42
'shipment_identific_no': fields.char('ShipmentIdentificationNumber', size=64, ),
43
'logo': fields.binary('Logo'),
44
'tracking_url': fields.char('Tracking URL', size=512, ),
45
'service': fields.many2one('ups.shipping.service.type', 'Shipping Service'),
47
def print_label(self, cr, uid, ids, context=None):
51
'type': 'ir.actions.report.xml',
52
'report_name': 'ship.log.label.print',
54
'model':'shipping.move',
55
'id': ids and ids[0] or False,
56
'ids': ids and ids or [],
62
def getTrackingUrl(self, cr, uid, ids, context=None):
63
ship_log_obj = self.browse(cr, uid, ids[0], context=context)
64
if ship_log_obj.tracking_no:
65
tracking_url = "http://wwwapps.ups.com/WebTracking/processInputRequest?sort_by=status&tracknums_displayed=1&\
66
TypeOfInquiryNumber=T&loc=en_US&InquiryNumber1=%s&track.x=0&track.y=0" %ship_log_obj.tracking_no
70
class stock_picking(osv.osv):
71
_inherit = "stock.picking"
73
def _get_company_code(self, cr, user, context=None):
74
res = super(stock_picking, self)._get_company_code(cr, user, context=context)
75
res.append(('ups', 'UPS'))
79
'ups_service': fields.many2one('ups.shipping.service.type', 'Service', help='The specific shipping service offered'),
80
'shipper': fields.many2one('ups.account.shipping', 'Shipper', help='The specific user ID and shipper. Setup in the company configuration.'),
81
'shipment_digest': fields.text('ShipmentDigest'),
82
'negotiated_rates': fields.float('NegotiatedRates'),
83
'shipment_identific_no': fields.char('ShipmentIdentificationNumber', size=64, ),
84
'tracking_no': fields.char('TrackingNumber', size=64, ),
85
'trade_mark': fields.related('shipper','trademark', type='char', size=1024, string='Trademark'),
86
'ship_company_code': fields.selection(_get_company_code, 'Ship Company', method=True, size=64),
87
'ups_pickup_type': fields.selection([
88
('01', 'Daily Pickup'),
89
('03', 'Customer Counter'),
90
('06', 'One Time Pickup'),
91
('07', 'On Call Air'),
92
('11', 'Suggested Retail Rates'),
93
('19', 'Letter Center'),
94
('20', 'Air Service Center'),
96
'ups_packaging_type': fields.many2one('shipping.package.type','Packaging Type'),
97
'ups_use_cc': fields.boolean('Credit Card Payment'),
98
'ups_cc_type': fields.selection([
99
('01', 'American Express'),
101
('04', 'MasterCard'),
105
('08', 'Diners Club')
107
'ups_cc_number': fields.char('Credit Card Number', size=32),
108
'ups_cc_expiaration_date': fields.char('Expiaration Date', size=6, help="Format is 'MMYYYY'"),
109
'ups_cc_security_code': fields.char('Security Code', size=4,),
110
'ups_cc_address_id': fields.many2one('res.partner.address', 'Address'),
111
'ups_third_party_account': fields.char('Third Party Account Number', size=32),
112
'ups_third_party_address_id': fields.many2one('res.partner.address', 'Third Party Address'),
113
'ups_third_party_type': fields.selection([('shipper', 'Shipper'), ('consignee', 'Consignee')], 'Third Party Type'),
114
'ups_bill_receiver_account': fields.char('Receiver Account', size=32, help="The UPS account number of Freight Collect"),
115
'ups_bill_receiver_address_id': fields.many2one('res.partner.address', 'Receiver Address')
118
def onchange_bill_shipping(self, cr, uid, ids, bill_shipping, ups_use_cc, ups_cc_address_id, ups_bill_receiver_address_id, address_id,
119
shipper, context=None):
121
if bill_shipping == 'shipper':
122
if not ups_cc_address_id and shipper:
123
ship_address = self.pool.get('ups.account.shipping').read(cr,uid, shipper, ['address'], context=context )['address']
125
vals['ups_cc_address_id'] = ship_address[0]
127
vals['ups_use_cc'] = False
128
if not ups_bill_receiver_address_id:
129
vals['ups_bill_receiver_address_id'] = address_id
130
return {'value' : vals}
132
def action_process(self, cr, uid, ids, context=None):
133
deliv_order = self.browse(cr, uid, ids, context=context)
134
if isinstance(deliv_order, list):
135
deliv_order = deliv_order[0]
136
do_transaction = True
137
sale = deliv_order.sale_id
138
if sale and sale.payment_method == 'cc_pre_auth' and not sale.invoiced:
139
rel_voucher = sale.rel_account_voucher_id
140
rel_voucher_id = rel_voucher and rel_voucher.id or False
141
if rel_voucher_id and rel_voucher.state != 'posted' and rel_voucher.cc_auth_code:
142
do_transaction = False
143
self.pool.get('account.voucher').write(cr, uid, [rel_voucher_id], {'cc_p_authorize': False, 'cc_charge': True})
144
do_transaction = self.pool.get('account.voucher').authorize(cr, uid, [rel_voucher_id], context=context)
145
if not do_transaction:
146
self.write(cr, uid, ids,{'ship_state': 'hold', 'ship_message': 'Unable to process creditcard payment.'})
148
raise osv.except_osv(_('Final credit card charge cannot be completed!'),_("Please hold shipment and contact customer service..") )
149
return super(stock_picking, self).action_process(cr, uid, ids, context=context)
151
def action_done(self, cr, uid, ids, context=None):
152
res = super(stock_picking, self).action_done(cr, uid, ids, context=context)
154
for picking in self.browse(cr, uid, ids, context=context):
156
service_type_obj = self.pool.get('ups.shipping.service.type')
157
ship_method = picking.sale_id and picking.sale_id.ship_method
159
service_type_ids = service_type_obj.search(cr,uid,[('description', 'like', ship_method)], context=context)
161
vals['ups_service'] = service_type_ids[0]
162
service_type = service_type_obj.browse(cr, uid, service_type_ids[0], context=context)
163
if service_type.ups_account_id:
164
vals['shipper'] = service_type.ups_account_id.id
165
if service_type.ups_account_id.logistic_company_id:
166
vals['logis_company'] = service_type_obj.ups_account_id.logistic_company_id.id
169
def on_change_sale_id(self, cr, uid, ids, sale_id=False, state=False, context=None):
172
sale_obj = self.pool.get('sale.order').browse(cr, uid, sale_id)
173
service_type_obj = self.pool.get('ups.shipping.service.type')
174
ups_shipping_service_ids = service_type_obj.search(cr, uid, [('description', '=', sale_obj.ship_method)], context=context)
175
if ups_shipping_service_ids:
176
vals['ups_service'] = ups_shipping_service_ids[0]
177
shipping_obj = self.pool.get('ups.account.shipping')
178
ups_shipping_ids = shipping_obj.search(cr, uid, [('ups_shipping_service_ids', 'in', ups_shipping_service_ids[0])], context=context)
180
vals['shipper'] = ups_shipping_ids[0]
181
log_company_obj = self.pool.get('logistic.company')
182
logistic_company_ids = log_company_obj.search(cr, uid, [('ups_shipping_account_ids', 'in', ups_shipping_ids[0])], context=context)
183
if logistic_company_ids:
184
vals['logis_company'] = logistic_company_ids[0]
187
def process_void(self, cr, uid, ids, context=None):
188
if isinstance(ids, list):
190
do = picking_obj.browse(cr, uid, ids)
191
if do.ship_company_code != 'ups':
192
return super(stock_picking, self).process_void(cr, uid, ids, context=context)
193
picking_obj = self.pool.get('stock.picking')
194
data_for_Access_Request = {
195
'AccessLicenseNumber': do.shipper.id and do.shipper.accesslicensenumber or '',
196
'UserId': do.shipper.id and do.shipper.userid or '',
197
'Password': do.shipper.id and do.shipper.password or ''
201
data_for_void_shipment = {
202
'VoidShipmentRequest': {
204
'RequestAction': "1",
205
'TransactionReference': {'CustomerContext': ""},
207
'ShipmentIdentificationNumber': do.logis_company.test_mode and '1Z12345E0193081456' or do.shipment_identific_no or '',
208
'ExpandedVoidShipment': {
209
'ShipmentIdentificationNumber': do.logis_company.test_mode and '1ZISDE016691676846' or do.shipment_identific_no or '',
216
VoidShipmentRequest = doc2.createElement("VoidShipmentRequest")
217
doc2.appendChild(VoidShipmentRequest)
219
Request = doc2.createElement("Request")
220
VoidShipmentRequest.appendChild(Request)
223
RequestAction = doc2.createElement("RequestAction")
224
ptext = doc2.createTextNode(data_for_void_shipment["VoidShipmentRequest"]['Request']['RequestAction'])
225
RequestAction.appendChild(ptext)
226
Request.appendChild(RequestAction)
228
TransactionReference = doc2.createElement("TransactionReference")
229
Request.appendChild(TransactionReference)
231
CustomerContext = doc2.createElement("CustomerContext")
232
ptext = doc2.createTextNode(data_for_void_shipment["VoidShipmentRequest"]['Request']['TransactionReference']['CustomerContext'])
233
CustomerContext.appendChild(ptext)
234
TransactionReference.appendChild(CustomerContext)
236
ExpandedVoidShipment = doc2.createElement("ExpandedVoidShipment")
237
VoidShipmentRequest.appendChild(ExpandedVoidShipment)
239
ShipmentIdentificationNumber = doc2.createElement("ShipmentIdentificationNumber")
240
ptext = doc2.createTextNode(data_for_void_shipment["VoidShipmentRequest"]['ExpandedVoidShipment']['ShipmentIdentificationNumber'])
241
ShipmentIdentificationNumber.appendChild(ptext)
242
ExpandedVoidShipment.appendChild(ShipmentIdentificationNumber)
244
TrackingNumber = doc2.createElement("TrackingNumber")
245
ptext = doc2.createTextNode(data_for_void_shipment["VoidShipmentRequest"]['ExpandedVoidShipment']['TrackingNumber'])
246
TrackingNumber.appendChild(ptext)
248
Request_string2 =doc2.toprettyxml()
251
AccessRequest = doc1.createElement("AccessRequest")
252
AccessRequest.setAttribute("xml:lang", "en-US")
253
doc1.appendChild(AccessRequest)
255
AccessLicenseNumber = doc1.createElement("AccessLicenseNumber")
256
ptext = doc1.createTextNode(data_for_Access_Request["AccessLicenseNumber"])
257
AccessLicenseNumber.appendChild(ptext)
258
AccessRequest.appendChild(AccessLicenseNumber)
260
UserId = doc1.createElement("UserId")
261
ptext = doc1.createTextNode(data_for_Access_Request["UserId"])
262
UserId.appendChild(ptext)
263
AccessRequest.appendChild(UserId)
265
Password = doc1.createElement("Password")
266
ptext = doc1.createTextNode(data_for_Access_Request["Password"])
267
Password.appendChild(ptext)
268
AccessRequest.appendChild(Password)
270
Request_string1 = doc1.toprettyxml()
271
Request_string = Request_string1 + Request_string2
273
if do.logis_company.test_mode:
274
void_web = do.logis_company.ship_void_test_web or ''
275
void_port = do.logis_company.ship_void_test_port
277
void_web = do.logis_company.ship_void_web or ''
278
void_port = do.logis_company.ship_void_port
280
parse_url = urlparse(void_web)
281
serv = parse_url.netloc
282
serv_path = parse_url.path
284
raise osv.except_osv(_('Unable to find Shipping URL!'), _("Please configure the shipping company with websites.") )
285
conn = httplib.HTTPSConnection(serv, void_port)
286
res = conn.request("POST", serv_path, Request_string)
287
res = conn.getresponse()
289
response_dic = xml2dic.main(result)
291
status_description = ''
292
error_description = ''
293
for elm in response_dic['VoidShipmentResponse']:
294
if 'Response' in elm:
295
for item in elm['Response']:
296
if 'ResponseStatusCode' in item:
297
if item['ResponseStatusCode'] == '1':
301
'negotiated_rates' : 0.00,
302
'shipment_identific_no' :'',
307
self.pool.get('stock.packages').write(cr, uid, [package.id for package in do.packages_ids], clear_vals, context=context)
308
picking_obj.write(cr, uid, do.id,
309
{'ship_state': 'draft', 'ship_message': 'Shipment has been cancelled.'}, context=context)
311
if 'ResponseStatusDescription' in item:
312
status_description = item['ResponseStatusDescription']
315
for i in item['Error']:
316
if 'ErrorDescription' in i:
317
error_description = i['ErrorDescription']
318
picking_obj.write(cr, uid, do.id, {'ship_message': status_description + ': ' + error_description }, context=context)
323
def fill_addr(self, addr_id):
325
'AddressLine1': addr_id and addr_id.street or '',
326
'AddressLine2': addr_id and addr_id.street2 or '',
328
'City': addr_id and addr_id.city or '',
329
'StateProvinceCode': addr_id and addr_id.state_id.id and addr_id.state_id.code or '',
330
'PostalCode': addr_id and addr_id.zip or '',
331
'CountryCode': addr_id and addr_id.country_id.id and addr_id.country_id.code or '',
332
'PostalCode': addr_id.zip_id and addr_id.zip_id.zipcode or ''
334
if addr_id and addr_id.classification == '2':
335
ret.update({'ResidentialAddress': ""})
339
def create_ship_accept_request_new(self, cr, uid, do, context=None):
343
xml_ship_accept_request="""<?xml version="1.0" ?>
344
<AccessRequest xml:lang='en-US'>
345
<AccessLicenseNumber>%(access_l_no)s</AccessLicenseNumber>
346
<UserId>%(user_id)s</UserId>
347
<Password>%(password)s</Password>
350
'access_l_no': do.shipper.accesslicensenumber or '',
351
'user_id': do.shipper.userid or '',
352
'password': do.shipper.password,
355
xml_ship_accept_request += """<?xml version="1.0" ?>
356
<ShipmentAcceptRequest>
358
<TransactionReference>
359
<CustomerContext>%(customer_context)s</CustomerContext>
360
<XpciVersion>1.0001</XpciVersion>
361
</TransactionReference>
362
<RequestAction>ShipAccept</RequestAction>
364
<ShipmentDigest>%(shipment_digest)s</ShipmentDigest>
365
</ShipmentAcceptRequest>
367
'customer_context': do.name or '',
368
'shipment_digest': do.shipment_digest,
370
return xml_ship_accept_request
372
def process_ship_accept(self, cr, uid, do, context=None):
373
shipment_accept_request_xml = self.create_ship_accept_request_new(cr, uid, do, context=context)
374
if do.logis_company.test_mode:
375
acce_web = do.logis_company.ship_accpt_test_web or ''
376
acce_port = do.logis_company.ship_accpt_test_port
378
acce_web = do.logis_company.ship_accpt_web or ''
379
acce_port = do.logis_company.ship_accpt_port
381
parse_url = urlparse(acce_web)
382
serv = parse_url.netloc
383
serv_path = parse_url.path
385
raise osv.except_osv(_('Unable to find Shipping URL!'), _("Please configure the shipping company with websites.") )
387
conn = httplib.HTTPSConnection(serv, acce_port)
388
res = conn.request("POST", serv_path, shipment_accept_request_xml)
389
res = conn.getresponse()
392
response_dic = xml2dic.main(result)
394
ShipmentIdentificationNumber = ''
397
control_log_image = ''
399
status_description = ''
400
for response in response_dic['ShipmentAcceptResponse']:
401
if response.get('Response'):
402
for resp_items in response['Response']:
403
if resp_items.get('ResponseStatusCode') and resp_items['ResponseStatusCode'] == '1':
405
if resp_items.get('ResponseStatusDescription'):
406
status_description = resp_items['ResponseStatusDescription']
407
if resp_items.get('Error'):
408
for err in resp_items['Error']:
409
if err.get('ErrorSeverity'):
410
status_description += '\n' + err.get('ErrorSeverity')
411
if err.get('ErrorDescription'):
412
status_description += '\n' + err.get('ErrorDescription')
413
do.write({'ship_message': status_description})
415
packages_ids = [package.id for package in do.packages_ids]
417
shipment_identific_number = ''
418
for shipmentresult in response_dic['ShipmentAcceptResponse']:
419
if shipmentresult.get('ShipmentResults'):
421
package_obj = self.pool.get('stock.packages')
422
for package in response['ShipmentResults']:
423
if package.get('ShipmentIdentificationNumber'):
424
shipment_identific_number = package['ShipmentIdentificationNumber']
426
if package.get('PackageResults'):
429
tracking_url = do.logis_company.ship_tracking_url or ''
430
for tracks in package['PackageResults']:
431
if tracks.get('TrackingNumber'):
432
tracking_number = tracks['TrackingNumber']
435
tracking_url = tracking_url%tracking_number
437
tracking_url = "Invalid tracking url on shipping company"
438
if tracks.get('LabelImage'):
439
for label in tracks['LabelImage']:
440
if label.get('GraphicImage'):
441
label_image = label['GraphicImage']
442
im_in_raw = base64.decodestring(label_image)
443
path = tempfile.mktemp()
444
temp = file(path, 'wb')
445
temp.write(im_in_raw)
447
new_im = Image.open(path)
448
new_im = new_im.rotate(270)
449
new_im.save(path, 'JPEG')
450
label_from_file = open(path,'rb')
451
label_image = base64.encodestring(label_from_file.read())
452
label_from_file.close()
453
package_obj.write(cr, uid, packages_ids[i], {
454
'tracking_no': tracking_number,
455
'shipment_identific_no': shipment_identific_number,
457
'ship_state': 'in_process',
458
'tracking_url': tracking_url
461
if int(time.strftime("%w")) in range(1, 6) or (time.strftime("%w") == '6' and do.sat_delivery):
462
next_pic_date = time.strftime("%Y-%m-%d")
464
timedelta = datetime.timedelta(7 - int(time.strftime("%w")))
465
next_pic_date = (datetime.datetime.today() + timedelta).strftime("%Y-%m-%d")
467
package_data = package_obj.read(cr, uid, packages_ids[i], ['weight', 'description'], context=context)
469
ship_move_obj = self.pool.get('shipping.move')
470
ship_move_obj.create(cr, uid, {
472
'package_weight': package_data['weight'],
473
'partner_id': do.address_id.id and do.address_id.partner_id.id,
474
'service': do.ups_service.id,
475
'ship_to': do.address_id.id,
476
'ship_from': do.ship_from and do.ship_from_address.id or \
477
do.shipper and do.shipper.address and do.shipper.address.id,
478
'tracking_no': tracking_number,
479
'shipment_identific_no': shipment_identific_number,
481
'state': 'ready_pick',
482
'tracking_url': tracking_url,
483
'package': package_data['description'] and str(package_data['description'])[:126],
484
'pic_date': next_pic_date,
485
'sale_id': do.sale_id.id and do.sale_id.id or False,
488
if package.get('ControlLogReceipt'):
489
for items in package['ControlLogReceipt']:
490
if items.get('GraphicImage'):
491
control_log_image = items['GraphicImage']
492
im_in_raw = base64.decodestring(control_log_image)
493
file_name = tempfile.mktemp()
494
path = file_name = '.html'
495
temp = file(path, 'wb')
496
temp.write(im_in_raw)
498
label_from_file = open(path,'rb')
499
control_log_image = base64.encodestring(label_from_file.read())
500
label_from_file.close()
501
package_obj.write(cr, uid, packages_ids, {'control_log_receipt': control_log_image}, context=context)
502
do.write({'ship_state': 'ready_pick'}, context=context)
505
def add_product(self, cr, uid, package_obj):
508
for pkg in package_obj.pick_id.packages_ids:
509
tot_weight += pkg.weight
510
for move_lines in package_obj.pick_id.move_lines:
511
product_id = move_lines.product_id
512
if move_lines.product_id.supply_method == 'produce':
517
'Description': move_lines.product_id.description or " ",
519
'Number': str(int(move_lines.product_qty) or 0),
520
'Value': str((move_lines.product_id.list_price * move_lines.product_qty) or 0),
521
'UnitOfMeasurement': {'Code': "LBS", 'Description': "Pounds"}
523
'CommodityCode': package_obj.pick_id.comm_code or "",
525
'OriginCountryCode': package_obj.pick_id.address_id and package_obj.pick_id.address_id.country_id and \
526
package_obj.pick_id.address_id.country_id.code or "",
527
'JointProductionIndicator': "",
529
'PreferenceCriteria': "B",
530
'ProducerInfo': produce,
531
'MarksAndNumbers': "",
532
'NumberOfPackagesPerCommodity': str(len(package_obj.pick_id.packages_ids)),
534
'UnitOfMeasurement': {'Code': "LBS", 'Description': "Pounds"},
535
'Weight': "%.1f"%(tot_weight or 0.0)
539
prods.append(product)
542
def create_comm_inv(self, cr, uid, package_obj):
544
if package_obj.pick_id.sale_id:
545
if package_obj.pick_id.sale_id.invoice_ids:
546
invoice_id = package_obj.pick_id.sale_id.invoice_ids[0]
547
user = self.pool.get('res.users').browse(cr, uid, uid)
550
'Product': [],#Placed out of this dictionary for common use
553
'PurchaseOrderNumber': "",
554
'TermsOfShipment': "",
555
'ReasonForExport': "SALE",
557
'DeclarationStatement': "I hereby certify that the good covered by this shipment qualifies as an originating good for purposes of \
558
preferential tariff treatment under the NAFTA.",
559
'CurrencyCode': user.company_id.currency_id.name or "",
562
comm_inv['InvoiceNumber'] = invoice_id.number or '/'
563
if invoice_id.date_invoice:
564
d = invoice_id.date_invoice
565
comm_inv['InvoiceDate'] = d[:4] + d[5:7] + d[8:10]
566
if not comm_inv['InvoiceDate']:
567
comm_inv['InvoiceDate'] = time.strftime("%Y%m%d")
571
def create_cer_orig(self, cr, uid, package_obj):
574
'Product': [],#Placed out of this dictionary for common use
575
'ExportDate': time.strftime("%Y%m%d"),
576
'ExportingCarrier': package_obj.pick_id.exp_carrier or "",
580
def get_value(self, cr, uid, object, message=None, context=None):
586
from mako.template import Template as MakoTemplate
587
message = tools.ustr(message)
589
'user':self.pool.get('res.users').browse(cr, uid, uid, context=context),
592
templ = MakoTemplate(message, input_encoding='utf-8')
593
reply = MakoTemplate(message).render_unicode(object=object, peobject=object, env=env, format_exceptions=True)
594
return reply or False
596
logging.exception("Can't render %r", message)
601
def create_ship_confirm_request_new(self, cr, uid, do):
605
xml_ship_confirm_request="""<?xml version="1.0" ?>
606
<AccessRequest xml:lang='en-US'>
607
<AccessLicenseNumber>%(access_l_no)s</AccessLicenseNumber>
608
<UserId>%(user_id)s</UserId>
609
<Password>%(password)s</Password>
612
'access_l_no': do.shipper.accesslicensenumber or '',
613
'user_id': do.shipper.userid or '',
614
'password': do.shipper.password,
616
shipper_address_lines = ['', '', '']
618
if do.shipper.address:
619
if do.shipper.address.street:
620
shipper_address_lines[j] = do.shipper.address.street
622
if do.shipper.address.street2:
623
shipper_address_lines[j] = do.shipper.address.street2
625
shipto_address_lines = ['','','']
628
if do.address_id.name:
629
shipto_address_lines[j] = do.address_id.name
631
if do.address_id.street:
632
shipto_address_lines[j] = do.address_id.street
634
if do.address_id.street2:
635
shipto_address_lines[j] = do.address_id.street2
638
xml_ship_confirm_request += """<?xml version="1.0"?>
639
<ShipmentConfirmRequest>
641
<TransactionReference>
642
<CustomerContext>%(customer_context)s</CustomerContext>
643
<XpciVersion>1.0001</XpciVersion>
644
</TransactionReference>
645
<RequestAction>ShipConfirm</RequestAction>
646
<RequestOption>%(address_validate)s</RequestOption>
650
<Description>%(shipment_description)s</Description>
651
<!--InvoiceLineTotal>
652
<CurrencyCode>%(invoice_currency_code)s</CurrencyCode>
653
<MonetaryValue>%(invoice_value)s</MonetaryValue>
654
</InvoiceLineTotal-->
656
<Name>%(shipper_name)s</Name>
657
<AttentionName>%(shipper_attention_name)s</AttentionName>
659
<AddressLine1>%(shipper_address_line1)s</AddressLine1>
660
<AddressLine2>%(shipper_address_line2)s</AddressLine2>
661
<AddressLine3>%(shipper_address_line3)s</AddressLine3>
662
<City>%(shipper_city)s</City>
663
<StateProvinceCode>%(shipper_state)s</StateProvinceCode>
664
<CountryCode>%(shipper_country)s</CountryCode>
665
<PostalCode>%(shipper_postal)s</PostalCode>
667
<PhoneNumber>%(shipper_phone_number)s</PhoneNumber>
668
<ShipperNumber>%(shipper_number)s</ShipperNumber>
669
<TaxIdentificationNumber>%(shipper_tax_id_number)s</TaxIdentificationNumber>
670
<FaxNumber>%(shipper_fax)s</FaxNumber>
671
<EMailAddress>%(shipper_email)s</EMailAddress>
674
<CompanyName>%(shipto_company)s</CompanyName>
675
<AttentionName>%(shipto_attention_name)s</AttentionName>
677
<AddressLine1>%(shipto_address_line1)s</AddressLine1>
678
<AddressLine2>%(shipto_address_line2)s</AddressLine2>
679
<AddressLine3>%(shipto_address_line3)s</AddressLine3>
680
<City>%(shipto_city)s</City>
681
<StateProvinceCode>%(shipto_state)s</StateProvinceCode>
682
<CountryCode>%(shipto_country)s</CountryCode>
683
<PostalCode>%(shipto_postal)s</PostalCode>
684
%(residential_address)s
686
<PhoneNumber>%(shipto_phone_number)s</PhoneNumber>
687
<FaxNumber>%(shipto_fax)s</FaxNumber>
688
<EMailAddress>%(shipto_email)s</EMailAddress>
689
<TaxIdentificationNumber>%(shipto_tax_id_number)s</TaxIdentificationNumber>
690
<LocationID></LocationID>
693
<Code>%(service_code)s</Code>
694
<Description>%(service_description)s</Description>
697
'customer_context': do.name or '',
698
'address_validate': do.address_validate or 'nonvalidate',
699
'shipment_description': do.note or do.name or so.origin,
700
'shipper_name': do.shipper.name or '',
701
'shipper_attention_name': do.shipper.atten_name or '',
702
'shipper_phone_number': do.shipper.address and do.shipper.address.phone or '',
703
'shipper_number': do.shipper.acc_no or '',
704
'shipper_tax_id_number': do.shipper.tax_id_no or '',
705
'shipper_fax': do.shipper.address and do.shipper.address.fax or '' ,
706
'shipper_email': do.shipper.address and do.shipper.address.email or '',
707
'shipper_address_line1': shipper_address_lines[0],
708
'shipper_address_line2': shipper_address_lines[1],
709
'shipper_address_line3': shipper_address_lines[2],
710
'shipper_city': do.shipper.address and do.shipper.address.city or '',
711
'shipper_state': do.shipper.address and do.shipper.address.state_id and do.shipper.address.state_id.code or '',
712
'shipper_country': do.shipper.address and do.shipper.address.country_id and do.shipper.address.country_id.code or '',
713
'shipper_postal': do.shipper.address and do.shipper.address.zip_id and do.shipper.address.zip_id.zipcode or '',
714
'shipto_company': do.partner_id.name or '',
715
'shipto_attention_name': do.inv_att_name or '',
716
'shipto_phone_number': do.address_id.phone or '',
717
'shipto_fax': do.address_id.fax or '',
718
'shipto_email': do.address_id.email or '' ,
719
'shipto_tax_id_number': '',
720
'shipto_address_line1': shipto_address_lines[0],
721
'shipto_address_line2': shipto_address_lines[1],
722
'shipto_address_line3': shipto_address_lines[2],
723
'shipto_city': do.address_id.city or '',
724
'shipto_state': do.address_id.state_id and do.address_id.state_id.code or '',
725
'shipto_country': do.address_id.country_id and do.address_id.country_id.code or '',
726
'shipto_postal': do.address_id.zip_id and do.address_id.zip_id.zipcode or '',
727
'residential_address': do.address_id.classification and do.address_id.classification == '2' and '<ResidentialAddress/>' or '',
728
'service_code': do.ups_service and do.ups_service.shipping_service_code or '',
729
'service_description': do.ups_service and do.ups_service.description or '',
730
'invoice_currency_code': do.sale_id and do.sale_id.pricelist_id.currency_id.name or 'USD',
731
'invoice_value': do.sale_id and str(int(do.sale_id.amount_total)) or '',
734
if (do.ship_from and do.ship_from_address and do.ship_from_address.country_id.code == 'US' or do.shipper and \
735
do.shipper.address and do.shipper.address.country_id and do.shipper.address.country_id.code == 'US') and \
736
do.address_id and do.address_id.country_id.code in ('PR', 'CA'):
737
xml_ship_confirm_request += """
739
<CurrencyCode>%(invoice_currency_code)s</CurrencyCode>
740
<MonetaryValue>%(invoice_value)s</MonetaryValue>
743
'invoice_currency_code': do.sale_id and do.sale_id.pricelist_id.currency_id.name or 'USD',
744
'invoice_value': do.sale_id and str(int(do.sale_id.amount_untaxed)) or '',
747
xml_ship_confirm_request += """
748
<ShipmentServiceOptions>
750
</ShipmentServiceOptions>
753
shipfrom_address_lines = ['', '', '']
755
if do.ship_from_address:
756
if do.ship_from_address.name:
757
shipfrom_address_lines[j] = do.ship_from_address.name
759
if do.ship_from_address.street:
760
shipfrom_address_lines[j] = do.ship_from_address.street
762
if do.ship_from_address.street2:
763
shipfrom_address_lines[j] = do.ship_from_address.street2
765
xml_ship_confirm_request += """
767
<CompanyName>%(shipfrom_company)s</CompanyName>
768
<AttentionName>%(shipfrom_attention_name)s</AttentionName>
770
<AddressLine1>%(shipfrom_address_line1)s</AddressLine1>
771
<AddressLine2>%(shipfrom_address_line2)s</AddressLine2>
772
<AddressLine3>%(shipfrom_address_line3)s</AddressLine3>
773
<City>%(shipfrom_city)s</City>
774
<StateProvinceCode>%(shipfrom_state)s</StateProvinceCode>
775
<CountryCode>%(shipfrom_country)s</CountryCode>
776
<PostalCode>%(shipfrom_postal)s</PostalCode>
778
<PhoneNumber>%(shipfrom_phone_number)s</PhoneNumber>
779
<FaxNumber>%(shipfrom_fax)s</FaxNumber>
780
<EMailAddress>%(shipfrom_email)s</EMailAddress>
781
<TaxIdentificationNumber>%(shipfrom_tax_id_number)s</TaxIdentificationNumber>
785
'shipfrom_company': do.ship_from_address and do.ship_from_address.partner_id and do.ship_from_address.partner_id.name or '',
786
'shipfrom_attention_name': '',
787
'shipfrom_phone_number': do.ship_from_address and do.ship_from_address.phone or '',
788
'shipfrom_fax': do.ship_from_address and do.ship_from_address.fax or '',
789
'shipfrom_email': do.ship_from_address and do.ship_from_address.email or '',
790
'shipfrom_tax_id_number': do.ship_from_tax_id_no or '',
791
'shipfrom_address_line1': shipfrom_address_lines[0],
792
'shipfrom_address_line2': shipfrom_address_lines[1],
793
'shipfrom_address_line3': shipfrom_address_lines[2],
794
'shipfrom_city': do.ship_from_address and do.ship_from_address.city or '',
795
'shipfrom_state': do.ship_from_address and do.ship_from_address.state_id and do.ship_from_address.state_id.code or '',
796
'shipfrom_country': do.ship_from_address and do.ship_from_address.country_id and do.ship_from_address.country_id.code or '',
797
'shipfrom_postal': do.ship_from_address and do.ship_from_address.zip_id and do.ship_from_address.zip_id.zipcode or '',
800
soldto_address_lines = ['', '', '']
802
if do.inv_address_id:
803
if do.inv_address_id.name:
804
soldto_address_lines[j] = do.inv_address_id.name
806
if do.inv_address_id.street:
807
soldto_address_lines[j] = do.inv_address_id.street
809
if do.inv_address_id.street2:
810
soldto_address_lines[j] = do.inv_address_id.street2
812
xml_ship_confirm_request += """
814
<Option>%(soldto_option)s</Option>
815
<CompanyName>%(soldto_company)s</CompanyName>
816
<AttentionName>%(soldto_attention_name)s</AttentionName>
817
<PhoneNumber>%(soldto_phone_number)s</PhoneNumber>
818
<TaxIdentificationNumber>%(soldto_tax_id_number)s</TaxIdentificationNumber>
820
<AddressLine1>%(soldto_address_line1)s</AddressLine1>
821
<AddressLine2>%(soldto_address_line2)s</AddressLine2>
822
<AddressLine3>%(soldto_address_line3)s</AddressLine3>
823
<City>%(soldto_city)s</City>
824
<StateProvinceCode>%(soldto_state)s</StateProvinceCode>
825
<CountryCode>%(soldto_country)s</CountryCode>
826
<PostalCode>%(soldto_postal)s</PostalCode>
830
'soldto_option': do.inv_option or '',
831
'soldto_company': do.inv_company or '',
832
'soldto_attention_name': do.inv_att_name or '',
833
'soldto_phone_number': do.inv_address_id.phone or '',
834
'soldto_tax_id_number': do.inv_tax_id_no or '',
835
'soldto_address_line1': soldto_address_lines[0],
836
'soldto_address_line2': soldto_address_lines[1],
837
'soldto_address_line3': soldto_address_lines[2],
838
'soldto_city': do.inv_address_id.city or '',
839
'soldto_state': do.inv_address_id.state_id and do.inv_address_id.state_id.code or '',
840
'soldto_country': do.inv_address_id.country_id and do.inv_address_id.country_id.code or '',
841
'soldto_postal': do.inv_address_id.zip_id and do.inv_address_id.zip_id.zipcode or '',
843
if not do.bill_shipping or do.bill_shipping == 'shipper':
844
if not do.ups_use_cc:
845
xml_ship_confirm_request += """
849
<AccountNumber>%(bill_shipper_account_number)s</AccountNumber>
852
</PaymentInformation>
854
'bill_shipper_account_number': do.shipper.acc_no or '',
857
cc_address_lines = ['', '', '']
859
if do.ups_cc_address_id:
860
if do.ups_cc_address_id.name:
861
cc_address_lines[j] = do.ups_cc_address_id.name
863
if do.ups_cc_address_id.street:
864
cc_address_lines[j] = do.ups_cc_address_id.street
866
if do.ups_cc_address_id.street2:
867
cc_address_lines[j] = do.ups_cc_address_id.street2
868
xml_ship_confirm_request += """
873
<Type>%(cc_type)s</Type>
874
<Number>%(cc_number)s</Number>
875
<ExpirationDate>%(cc_exp_date)s</ExpirationDate>
876
<SecurityCode>%(cc_security_code)s</SecurityCode>
878
<AddressLine1>%(cc_address_line1)s</AddressLine1>
879
<AddressLine2>%(cc_address_line2)s</AddressLine2>
880
<AddressLine3>%(cc_address_line3)s</AddressLine3>
881
<City>%(cc_city)s</City>
882
<StateProvinceCode>%(cc_state)s</StateProvinceCode>
883
<CountryCode>%(cc_country)s</CountryCode>
884
<PostalCode>%(cc_postal)s</PostalCode>
889
</PaymentInformation>
891
'cc_type': do.ups_cc_type or '',
892
'cc_number': do.ups_cc_number or '',
893
'cc_exp_date': do.ups_cc_expiaration_date or '',
894
'cc_security_code': do.ups_cc_security_code or '',
895
'cc_address_line1': cc_address_lines[0],
896
'cc_address_line2': cc_address_lines[1],
897
'cc_address_line3': cc_address_lines[2],
898
'cc_city': do.ups_cc_address_id.city or '',
899
'cc_state': do.ups_cc_address_id.state_id and do.ups_cc_address_id.state_id.code or '',
900
'cc_country': do.ups_cc_address_id.country_id and do.ups_cc_address_id.country_id.code or '',
901
'cc_postal': do.ups_cc_address_id.zip_id and do.ups_cc_address_id.zip_id.zipcode or '',
903
if do.bill_shipping == 'thirdparty':
904
xml_ship_confirm_request += """
908
<BillThirdPartyShipper>
909
<AccountNumber>%(thirdparty_account_number)s</AccountNumber>
912
<PostalCode>%(thirdparty_account_postal)s</PostalCode>
913
<CountryCode>%(thirdparty_country)s</CountryCode>
916
</BillThirdPartyShipper>
920
</PaymentInformation>
922
'thirdparty_account_number': do.ups_third_party_account or '',
923
'thirdparty_postal': do.ups_third_party_address_id and do.ups_third_party_address_id.zip_id and \
924
do.ups_third_party_address_id.zip_id.zipcode or '' ,
925
'thirdparty_country': do.ups_third_party_address_id and do.ups_third_party_address_id.country_id and \
926
do.ups_third_party_address_id.country_id.code or '' ,
927
'thirdparty_consignee_billed': do.ups_third_party_type=='consignee' and '<ConsigneeBilled/>' or '',
929
if do.bill_shipping == 'receiver':
930
xml_ship_confirm_request += """
934
<AccountNumber>%(bill_receiver_account_number)s</AccountNumber>
936
<PostalCode>%(bill_receiver_postal)s</PostalCode>
939
</PaymentInformation>
941
'bill_receiver_account_number': do.ups_bill_receiver_account or '',
942
'bill_receiver_postal': do.ups_bill_receiver_address_id.zip_id and do.ups_bill_receiver_address_id.zip_id.zipcode or '',
944
for package in do.packages_ids:
945
xml_ship_confirm_request += """
947
<Description>%(package_description)s</Description>
949
<Code>%(packaging_type_code)s</Code>
950
<Description>%(packaging_type_description)s</Description>
955
<Description>Inches</Description>
957
<Length>%(package_dimension_length)s</Length>
958
<Width>%(package_dimension_width)s</Width>
959
<Height>%(package_dimension_height)s</Height>
964
<Description>Pounds</Description>
966
<Weight>%(package_dimension_weight)s</Weight>
969
<Code>%(package_reference_code)s</Code>
970
<Value>%(package_reference_value)s</Value>
972
<PackageServiceOptions>
974
<CurrencyCode>USD</CurrencyCode>
975
<MonetaryValue>%(package_insured_value)s</MonetaryValue>
977
</PackageServiceOptions>
980
'package_description': package.description or '',
981
'packaging_type_code': package.package_type.code or '',
982
'packaging_type_description': package.package_type.name or '',
983
'package_dimension_length': str(package.length) or '',
984
'package_dimension_width': str(package.width) or '',
985
'package_dimension_height': str(package.height) or '',
986
'package_dimension_weight': str(package.weight) or '',
987
'package_reference_code': str(package.packge_no) or '',
988
'package_reference_value': package.ref1 or '',
989
'package_insured_value': str(package.decl_val) or '',
991
xml_ship_confirm_request += """
996
<Description>GIF</Description>
998
<HTTPUserAgent></HTTPUserAgent>
1008
<Description>GIF</Description>
1010
</LabelSpecification>
1011
</ShipmentConfirmRequest>
1013
return xml_ship_confirm_request
1015
def process_ship(self, cr, uid, ids, context=None):
1016
deliv_order = self.browse(cr, uid, type(ids) == type([]) and ids[0] or ids, context=context)
1017
if deliv_order.ship_company_code != 'ups':
1018
return super(stock_picking, self).process_ship(cr, uid, ids, context=context)
1021
do_transaction = True
1023
if not (deliv_order.logis_company or deliv_order.shipper or deliv_order.ups_service):
1024
raise osv.except_osv("Warning", "Please select Logistics Company, Shipper and Shipping Service")
1025
if not deliv_order.packages_ids:
1026
raise osv.except_osv("Warning", "Please add shipping packages before doing Process Shipping.")
1027
if deliv_order.sale_id and deliv_order.sale_id.order_policy == 'credit_card' and not deliv_order.sale_id.invoiced:
1028
if not deliv_order.sale_id.cc_pre_auth:
1029
raise osv.except_osv("Warning", "The sales order is not paid")
1031
do_transaction = False
1032
rel_voucher_id = deliv_order.sale_id.rel_account_voucher_id
1033
if rel_voucher_id and rel_voucher_id.state != 'posted' and deliv_order.sale_id.cc_pre_auth:
1034
self.pool.get('account.voucher').write(cr, uid, [rel_voucher_id.id], {'cc_p_authorize': False, 'cc_charge': True}, context=context)
1035
do_transaction = self.pool.get('account.voucher').authorize(cr, uid, [rel_voucher_id.id], context=context)
1036
if not do_transaction:
1037
self.write(cr, uid, ids, {'ship_state': 'hold', 'ship_message': 'Unable to process creditcard payment.'}, context=context)
1039
raise osv.except_osv(_('Final credit card charge cannot be completed!'), _("Please hold shipment and contact customer service..") )
1040
warning_error = False
1042
ship_confirm_request_xml = self.create_ship_confirm_request_new(cr, uid, deliv_order)
1043
ship_confirm_web = ''
1044
ship_confirm_port = ''
1045
if deliv_order.logis_company:
1046
if deliv_order.logis_company.test_mode:
1047
ship_confirm_web = deliv_order.logis_company.ship_req_test_web
1048
ship_confirm_port = deliv_order.logis_company.ship_req_test_port
1050
ship_confirm_web = deliv_order.logis_company.ship_req_web
1051
ship_confirm_port = deliv_order.logis_company.ship_req_port
1052
if ship_confirm_web:
1053
parse_url = urlparse(ship_confirm_web)
1054
serv = parse_url.netloc
1055
serv_path = parse_url.path
1057
raise osv.except_osv(_('Unable to find Shipping URL!'), _("Please configure the shipping company with websites."))
1059
conn = httplib.HTTPSConnection(serv,ship_confirm_port)
1060
res = conn.request("POST",serv_path,ship_confirm_request_xml)
1061
"""1.make and call function to send request/ 2.make function to process the response and write it """
1063
res = conn.getresponse()
1065
response_dic=xml2dic.main(result)
1067
status_description = ''
1070
for elm in response_dic['ShipmentConfirmResponse']:
1071
if elm.get('Response'):
1072
for rep in elm['Response']:
1073
if rep.get('ResponseStatusDescription'):
1074
status_description = rep['ResponseStatusDescription']
1075
if rep.get('ResponseStatusCode'):
1076
if rep['ResponseStatusCode'] == '1':
1078
if rep.get('Error'):
1079
for err in rep['Error']:
1080
if err.get('ErrorDescription'):
1081
status_description += ': ' + err.get('ErrorDescription')
1083
deliv_order.write({'ship_message' : status_description })
1085
shipment_identification_number = ''
1086
shipment_digest = ''
1087
for elm in response_dic['ShipmentConfirmResponse']:
1088
if elm.get('ShipmentIdentificationNumber'):
1089
shipment_identification_number = elm['ShipmentIdentificationNumber']
1091
for elm in response_dic['ShipmentConfirmResponse']:
1092
if elm.get('ShipmentDigest'):
1093
shipment_digest = elm['ShipmentDigest']
1095
deliv_order.write({'shipment_digest': shipment_digest, 'shipment_identific_no': shipment_identification_number}, context=context)
1096
do = self.browse(cr, uid, deliv_order.id, context=context)
1097
status = self.process_ship_accept(cr, uid, do, context=context)
1100
self.send_conf_mail(cr, uid, do.id, context=context)
1101
except Exception, e:
1104
'type': 'ir.actions.report.xml',
1105
'report_name': 'multiple.label.print',
1107
'model': 'stock.picking',
1108
'id': ids and ids[0] or False,
1109
'ids': ids and ids or [],
1110
'report_type': 'pdf'
1117
def _get_journal_id(self, cr, uid, ids, context=None):
1118
journal_obj = self.pool.get('account.journal')
1120
for pick in self.browse(cr, uid, ids, context=context):
1121
src_usage = pick.move_lines[0].location_id.usage
1122
dest_usage = pick.move_lines[0].location_dest_id.usage
1124
if type == 'out' and dest_usage == 'supplier':
1125
journal_type = 'purchase_refund'
1126
elif type == 'out' and dest_usage == 'customer':
1127
journal_type = 'sale'
1128
elif type == 'in' and src_usage == 'supplier':
1129
journal_type = 'purchase'
1130
elif type == 'in' and src_usage == 'customer':
1131
journal_type = 'sale_refund'
1133
journal_type = 'sale'
1134
value = journal_obj.search(cr, uid, [('type', '=', journal_type )], context=context)
1135
for jr_type in journal_obj.browse(cr, uid, value, context=context):
1136
t1 = jr_type.id, jr_type.name
1141
def do_partial(self, cr, uid, ids, partial_datas, context=None):
1142
res = self._get_journal_id(cr, uid, ids, context=context)
1143
result_partial = super(stock_picking, self).do_partial(cr, uid, ids, partial_datas, context=context)
1145
journal_id = res[0][0]
1146
result = result_partial
1147
for picking_obj in self.browse(cr, uid, ids, context=context):
1148
sale = picking_obj.sale_id
1149
if sale and sale.order_policy == 'picking':
1150
pick_id = result_partial[picking_obj.id]['delivered_picking']
1151
result = self.action_invoice_create(cr, uid, [pick_id], journal_id, type=None, context=context)
1152
inv_obj = self.pool.get('account.invoice')
1153
if len(sale.invoice_ids) <= 1 and result:
1154
inv_obj.write(cr, uid, result.values(),{
1155
'ship_method': sale.ship_method,
1156
'shipcharge': sale.shipcharge,
1157
'sale_account_id': sale.ship_method_id and sale.ship_method_id.account_id and \
1158
sale.ship_method_id.account_id.id or False,
1159
'ship_method_id': sale.ship_method_id and sale.ship_method_id.id})
1160
inv_obj.button_reset_taxes(cr, uid, result.values(), context=context)
1161
return result_partial
1164
class shipping_move(osv.osv):
1165
_inherit = "shipping.move"
1167
'shipper': fields.many2one('ups.account.shipping', 'Shipper', help='The specific user ID and shipper. Setup in the company configuration.'),
1171
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: