348 lines
15 KiB
Python
348 lines
15 KiB
Python
import json
|
|
from contextlib import contextmanager
|
|
from unittest.mock import patch
|
|
import requests
|
|
|
|
from odoo.tests.common import tagged
|
|
from odoo import Command
|
|
from odoo.addons.delivery_ups_rest.tests.common import DeliveryUPSCommon
|
|
from odoo.tools import mute_logger
|
|
from odoo.tools.float_utils import float_repr
|
|
|
|
|
|
@contextmanager
|
|
def _mock_request_call(specific_ups_check=None):
|
|
def _mock_request(*args, **kwargs):
|
|
url = kwargs.get('url')
|
|
if 'shipments' in url:
|
|
url = url.split('/shipments')[1]
|
|
responses = {
|
|
'token': {'access_token': 'mock_token'},
|
|
'rating': {'RateResponse': {
|
|
'Response': {
|
|
"Alert": {"Code": "string", "Description": "string"},
|
|
},
|
|
'RatedShipment': {'TotalCharges': {'MonetaryValue': '5.5', 'CurrencyCode': 'USD'}}}},
|
|
'ship': {'ShipmentResponse': {'ShipmentResults': {
|
|
'ShipmentCharges': {'TotalCharges': {'MonetaryValue': '5.5', 'CurrencyCode': 'USD'}},
|
|
'ShipmentIdentificationNumber': '123',
|
|
'PackageResults': {'TrackingNumber': '123', 'ShippingLabel': {'GraphicImage': 'some_imag'}}
|
|
}}},
|
|
'cancel': {'VoidShipmentResponse': {'SummaryResult': {'Status': {}}}},
|
|
}
|
|
|
|
for endpoint, content in responses.items():
|
|
if endpoint in url:
|
|
if specific_ups_check:
|
|
specific_ups_check(endpoint, kwargs['json'])
|
|
response = requests.Response()
|
|
response._content = json.dumps(content).encode()
|
|
response.status_code = 200
|
|
return response
|
|
|
|
raise Exception('unhandled request url %s' % url)
|
|
|
|
with patch.object(requests.Session, 'request', _mock_request):
|
|
yield
|
|
|
|
|
|
@tagged('post_install', '-at_install')
|
|
class TestDeliveryUPS(DeliveryUPSCommon):
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
|
|
self.env.company.partner_id.write({
|
|
'country_id': self.env.ref('base.us').id,
|
|
'state_id': self.env.ref('base.state_us_5').id,
|
|
'city': 'Los Angelos',
|
|
'street': 'My street',
|
|
'phone': '1234567890',
|
|
'zip': '1234',
|
|
})
|
|
|
|
self.product = self.env['product.product'].create({
|
|
'name': 'fancy box',
|
|
'type': 'consu',
|
|
'weight': 10.0,
|
|
})
|
|
|
|
self.partner = self.env['res.partner'].create({
|
|
'name': 'Cool Customer',
|
|
'country_id': self.env.ref('base.us').id,
|
|
'state_id': self.env.ref('base.state_us_5').id,
|
|
'street': 'My street',
|
|
'city': 'Los Angelos',
|
|
'phone': '1234567890',
|
|
'zip': '1234',
|
|
})
|
|
|
|
self.hong_kong_partner = self.env['res.partner'].create({
|
|
'name': 'Hong Kong Customer',
|
|
'country_id': self.env.ref('base.hk').id,
|
|
'state_id': self.env.ref('base.state_hk_hk').id,
|
|
'street': "1 H-K Road",
|
|
'city': "Hong Kong",
|
|
'phone': '1234567890',
|
|
'zip': '999077',
|
|
})
|
|
|
|
self.philippino_partner = self.env['res.partner'].create({
|
|
'name': 'PH Customer',
|
|
'country_id': self.env.ref('base.ph').id,
|
|
'state_id': self.env.ref('base.state_ph_26').id,
|
|
'street': "1 Manille Road",
|
|
'city': "Manille",
|
|
'phone': '1234567890',
|
|
'zip': '4607',
|
|
})
|
|
|
|
def test_ups_basic_flow(self):
|
|
def delivery_confirmation_data_check(endpoint, payload):
|
|
if endpoint == 'rating':
|
|
shipment = payload['RateRequest']['Shipment']
|
|
self.assertFalse(shipment['ShipmentServiceOptions'])
|
|
self.assertEqual(shipment['PackageServiceOptions']['DeliveryConfirmation']['DCISType'], '2')
|
|
|
|
self.ups_delivery.ups_require_signature = True
|
|
sale_order = self.env['sale.order'].create({
|
|
'partner_id': self.partner.id,
|
|
'order_line': [(0, 0, {
|
|
'product_id': self.product.id,
|
|
'name': "Fancy box",
|
|
'product_uom_qty': 1.0,
|
|
'price_unit': 20,
|
|
})]
|
|
})
|
|
wiz_action = sale_order.action_open_delivery_wizard()
|
|
choose_delivery_carrier = self.env[wiz_action['res_model']].with_context(wiz_action['context']).create({
|
|
'carrier_id': self.ups_delivery.id,
|
|
'order_id': sale_order.id
|
|
})
|
|
with _mock_request_call(delivery_confirmation_data_check):
|
|
choose_delivery_carrier.update_price()
|
|
choose_delivery_carrier.update_price()
|
|
choose_delivery_carrier.button_confirm()
|
|
self.assertEqual(choose_delivery_carrier.display_price, 5.5)
|
|
sale_order.action_confirm()
|
|
self.assertGreater(len(sale_order.picking_ids), 0, "The Sales Order did not generate pickings for shipment.")
|
|
|
|
picking = sale_order.picking_ids[0]
|
|
self.assertEqual(picking.carrier_id.id, sale_order.carrier_id.id, "Carrier is not the same on Picking and on SO.")
|
|
picking.action_assign()
|
|
picking.move_line_ids[0].quantity = 1.0
|
|
self.assertGreater(picking.weight, 0.0, "Picking weight should be positive.")
|
|
picking._action_done()
|
|
self.assertEqual(picking.carrier_tracking_ref, '123', 'Tracking ref should be set from mock response')
|
|
self.assertEqual(picking.carrier_price, 5.5, 'Price should be set from mock response')
|
|
picking.cancel_shipment()
|
|
self.assertEqual(picking.carrier_tracking_ref, False, 'Shipment cancel failed')
|
|
|
|
def test_ups_rest_sends_correct_delivery_type_for_amazon(self):
|
|
amazon_expected_delivery_type = self.ups_delivery._get_delivery_type()
|
|
self.assertEqual(amazon_expected_delivery_type, 'ups')
|
|
|
|
def test_ups_invoice_uses_correct_currency(self):
|
|
usd = self.env.ref('base.USD')
|
|
eur = self.env.ref('base.EUR')
|
|
pricelists = self.env['product.pricelist'].create([
|
|
{
|
|
'name': 'USD Pricelist',
|
|
'currency_id': usd.id,
|
|
},
|
|
{
|
|
'name': 'EUR Pricelist',
|
|
'currency_id': eur.id,
|
|
},
|
|
])
|
|
for pricelist in pricelists:
|
|
sale_order = self.env['sale.order'].create({
|
|
'partner_id': self.partner.id,
|
|
'pricelist_id': pricelist.id,
|
|
'order_line': [Command.create({
|
|
'product_id': self.product.id,
|
|
'name': "Fancy box",
|
|
'product_uom_qty': 1.0,
|
|
'price_unit': 20,
|
|
})]
|
|
})
|
|
wiz_action = sale_order.action_open_delivery_wizard()
|
|
choose_delivery_carrier = self.env[wiz_action['res_model']].with_context(wiz_action['context']).create({
|
|
'carrier_id': self.ups_delivery.id,
|
|
'order_id': sale_order.id
|
|
})
|
|
with _mock_request_call():
|
|
choose_delivery_carrier.update_price()
|
|
choose_delivery_carrier.button_confirm()
|
|
sale_order.action_confirm()
|
|
picking = sale_order.picking_ids[0]
|
|
picking.action_assign()
|
|
picking._action_done()
|
|
_, shipment_info, _, _, _ = self.ups_delivery._prepare_shipping_data(picking)
|
|
self.assertEqual(shipment_info['itl_currency_code'], pricelist.currency_id.name)
|
|
|
|
def test_ups_commercial_invoice_freight_charge(self):
|
|
'''
|
|
Ensure freight charge is correctly transmitted for internatonal UPS deliveries.
|
|
'''
|
|
def freight_charge_check(endpoint, payload):
|
|
if endpoint == 'ship':
|
|
payload_freight_charge = payload['ShipmentRequest']['Shipment']['ShipmentServiceOptions']['InternationalForms']['FreightCharges']['MonetaryValue']
|
|
self.assertEqual(payload_freight_charge, freight_charge)
|
|
|
|
sale_order = self.env['sale.order'].create({
|
|
'partner_id': self.hong_kong_partner.id,
|
|
'order_line': [(0, 0, {
|
|
'product_id': self.product.id,
|
|
'name': "Fancy box",
|
|
'product_uom_qty': 1.0,
|
|
'price_unit': 20,
|
|
})]
|
|
})
|
|
wiz_action = sale_order.action_open_delivery_wizard()
|
|
choose_delivery_carrier = self.env[wiz_action['res_model']].with_context(wiz_action['context']).create({
|
|
'carrier_id': self.ups_delivery.id,
|
|
'order_id': sale_order.id
|
|
})
|
|
with _mock_request_call(freight_charge_check):
|
|
choose_delivery_carrier.update_price()
|
|
choose_delivery_carrier.button_confirm()
|
|
sale_order.action_confirm()
|
|
freight_charge = float_repr(sale_order.order_line.filtered(lambda sol: sol.is_delivery).price_total, sale_order.currency_id.decimal_places)
|
|
picking = sale_order.picking_ids[0]
|
|
picking._action_done()
|
|
|
|
def test_ups_partner_with_long_province_code(self):
|
|
'''
|
|
Ensure long province codes are correctly sanitised when being sent to UPS.
|
|
'''
|
|
def province_code_length_check(endpoint, payload):
|
|
if endpoint == 'ship':
|
|
province_code = payload['ShipmentRequest']['Shipment']['ShipTo']['Address']['StateProvinceCode']
|
|
self.assertEqual(province_code, '')
|
|
|
|
sale_order = self.env['sale.order'].create({
|
|
'partner_id': self.philippino_partner.id,
|
|
'order_line': [(0, 0, {
|
|
'product_id': self.product.id,
|
|
'name': "Fancy box",
|
|
'product_uom_qty': 1.0,
|
|
'price_unit': 20,
|
|
})]
|
|
})
|
|
wiz_action = sale_order.action_open_delivery_wizard()
|
|
choose_delivery_carrier = self.env[wiz_action['res_model']].with_context(wiz_action['context']).create({
|
|
'carrier_id': self.ups_delivery.id,
|
|
'order_id': sale_order.id
|
|
})
|
|
with _mock_request_call(province_code_length_check):
|
|
choose_delivery_carrier.update_price()
|
|
choose_delivery_carrier.button_confirm()
|
|
sale_order.action_confirm()
|
|
self.assertGreater(len(sale_order.picking_ids), 0)
|
|
|
|
picking = sale_order.picking_ids[0]
|
|
picking.action_assign()
|
|
picking.move_line_ids[0].quantity = 1.0
|
|
picking._action_done()
|
|
|
|
@mute_logger('odoo.tools.translate')
|
|
def test_ups_commercial_invoice_with_different_delivery_and_invoice_address(self):
|
|
'''
|
|
Ensure the commercial invoice uses the partner's delivery address and invoicing address when
|
|
specified. If the 2 address' country are different, ensure 'SoldTo' defaults to the delivery
|
|
address (because UPS does not accept for them to be in different countries).
|
|
'''
|
|
def same_country_commercial_invoice_address_check(endpoint, payload):
|
|
if endpoint == 'ship':
|
|
ship_to = payload['ShipmentRequest']['Shipment']['ShipTo']
|
|
sold_to = payload['ShipmentRequest']['Shipment']['ShipmentServiceOptions']['InternationalForms']['Contacts']['SoldTo']
|
|
self.assertEqual(ship_to['Address']['AddressLine'][0], delivery_address.street)
|
|
self.assertEqual(sold_to['Address']['AddressLine'][0], invoicing_address.street)
|
|
|
|
def different_country_commercial_invoice_address_check(endpoint, payload):
|
|
if endpoint == 'ship':
|
|
ship_to = payload['ShipmentRequest']['Shipment']['ShipTo']
|
|
sold_to = payload['ShipmentRequest']['Shipment']['ShipmentServiceOptions']['InternationalForms']['Contacts']['SoldTo']
|
|
self.assertEqual(ship_to['Address']['AddressLine'][0], sold_to['Address']['AddressLine'][0])
|
|
self.assertEqual(sold_to['Address']['AddressLine'][0], delivery_address.street)
|
|
|
|
delivery_address, invoicing_address = self.env['res.partner'].create([
|
|
{
|
|
'name': 'Hong Kong Delivery Address',
|
|
'type': 'delivery',
|
|
'country_id': self.env.ref('base.hk').id,
|
|
'street': 'Delivery Street 1',
|
|
'state_id': self.env.ref('base.state_hk_hk').id,
|
|
'city': "Hong Kong",
|
|
'phone': '1234567890',
|
|
'zip': '999077',
|
|
'parent_id': self.hong_kong_partner.id,
|
|
},
|
|
{
|
|
'name': 'Hong Kong Invoicing Address',
|
|
'type': 'invoice',
|
|
'country_id': self.env.ref('base.hk').id,
|
|
'street': 'Invoicing Street 1',
|
|
'state_id': self.env.ref('base.state_hk_hk').id,
|
|
'city': "Hong Kong",
|
|
'phone': '1234567890',
|
|
'zip': '999077',
|
|
'parent_id': self.hong_kong_partner.id,
|
|
},
|
|
])
|
|
|
|
sale_order_1, sale_order_2 = self.env['sale.order'].create([
|
|
{
|
|
'partner_id': self.hong_kong_partner.id,
|
|
'order_line': [Command.create({
|
|
'product_id': self.product.id,
|
|
'name': "Fancy box",
|
|
'product_uom_qty': 1.0,
|
|
'price_unit': 20,
|
|
})]
|
|
},
|
|
{
|
|
'partner_id': self.hong_kong_partner.id,
|
|
'order_line': [Command.create({
|
|
'product_id': self.product.id,
|
|
'name': "Fancy box",
|
|
'product_uom_qty': 3.0,
|
|
'price_unit': 30,
|
|
})]
|
|
},
|
|
])
|
|
|
|
wiz_action = sale_order_1.action_open_delivery_wizard()
|
|
choose_delivery_carrier = self.env[wiz_action['res_model']].with_context(wiz_action['context']).create({
|
|
'carrier_id': self.ups_delivery.id,
|
|
'order_id': sale_order_1.id
|
|
})
|
|
with _mock_request_call(same_country_commercial_invoice_address_check):
|
|
choose_delivery_carrier.update_price()
|
|
choose_delivery_carrier.button_confirm()
|
|
sale_order_1.action_confirm()
|
|
self.assertGreater(len(sale_order_1.picking_ids), 0)
|
|
|
|
picking = sale_order_1.picking_ids[0]
|
|
picking.action_assign()
|
|
picking.move_line_ids[0].quantity = 1.0
|
|
picking._action_done()
|
|
|
|
delivery_address.country_id = self.env.ref('base.uk')
|
|
wiz_action = sale_order_2.action_open_delivery_wizard()
|
|
choose_delivery_carrier = self.env[wiz_action['res_model']].with_context(wiz_action['context']).create({
|
|
'carrier_id': self.ups_delivery.id,
|
|
'order_id': sale_order_2.id
|
|
})
|
|
with _mock_request_call(different_country_commercial_invoice_address_check):
|
|
choose_delivery_carrier.update_price()
|
|
choose_delivery_carrier.button_confirm()
|
|
sale_order_2.action_confirm()
|
|
self.assertGreater(len(sale_order_2.picking_ids), 0)
|
|
|
|
picking = sale_order_2.picking_ids[0]
|
|
picking.action_assign()
|
|
picking.move_line_ids[0].quantity = 1.0
|
|
picking._action_done()
|