# -*- coding: utf-8 -*- """One-off rate-quote sweep across every FedEx service code. Loops the full carrier selection (~38 services) against two routes — CA domestic (matching SO-30045) and CA → US — to figure out which services are valid for the shipping lanes EN Technologies actually uses. Prints a CSV-ish matrix to stdout so the report can be pasted straight into chat. Run with: odoo shell -c /etc/odoo/odoo.conf -d admin --no-http < this_file """ from types import SimpleNamespace from odoo.addons.fusion_shipping.api.fedex_rest.request import ( FedexRequest as FedexRestRequest, ) CARRIER_ID = 17 # FedEx REST carrier on entech WEIGHT_LB = 5.0 DIMS = {'length': 12, 'width': 10, 'height': 6} carrier = env['delivery.carrier'].browse(CARRIER_ID) assert carrier.exists(), 'FedEx carrier id=17 not found on this DB.' service_codes = [code for code, _label in carrier._fields[ 'fedex_rest_service_type' ].selection] # CA Toronto sender (from company address) sender = SimpleNamespace( street='36 Taber Road', street2=False, city='Toronto', zip='M9W3A8', state_id=env['res.country.state'].search( [('code', '=', 'ON'), ('country_id.code', '=', 'CA')], limit=1, ), country_id=env['res.country'].search([('code', '=', 'CA')], limit=1), name='ENTECH', phone='4167492400', email='ship@entech.test', commercial_partner_id=None, parent_id=None, vat=False, is_company=True, ) # Route A — CA domestic (Niagara Falls, ON) ca_recipient = env['res.partner'].search([ ('city', 'ilike', 'Niagara Falls'), ('country_id.code', '=', 'CA'), ], limit=1) assert ca_recipient.exists(), 'No CA partner found for the domestic route.' # Route B — CA → US (a real US partner with a complete address) us_recipient = env['res.partner'].search([ ('country_id.code', '=', 'US'), ('city', '!=', False), ('zip', '!=', False), ('state_id', '!=', False), ], limit=1) if not us_recipient: # Fabricate one in memory (we won't write to DB). us_recipient = env['res.partner'].new({ 'name': 'Test US Customer', 'street': '1 World Trade Center', 'city': 'New York', 'zip': '10007', 'state_id': env['res.country.state'].search( [('code', '=', 'NY'), ('country_id.code', '=', 'US')], limit=1, ).id, 'country_id': env['res.country'].search( [('code', '=', 'US')], limit=1, ).id, 'phone': '2125551212', 'email': 'us@test.com', }) # Sender partner — use the company partner for proper address resolution. sender_partner = env.company.partner_id def quote(service_code, recipient): srm = FedexRestRequest(carrier) srm.service_type = service_code pkg = SimpleNamespace( weight=WEIGHT_LB, dimension=DIMS, packaging_type='YOUR_PACKAGING', total_cost=0, commodities=[], currency_id=env.ref('base.CAD'), ) try: res = srm._get_shipping_price( ship_from=sender_partner, ship_to=recipient, packages=[pkg], currency='CAD', ) return { 'ok': True, 'price': res.get('price'), 'currency': res.get('currency'), 'service_name': res.get('service_name', '').strip(), 'delivery': (res.get('delivery_timestamp') or '')[:16].replace( 'T', ' ', ), 'transit': res.get('transit_time', ''), 'error': '', } except Exception as exc: msg = str(exc).replace('\n', ' ').strip() # Trim Odoo's "Error from FedEx: " prefix if present. return { 'ok': False, 'price': 0, 'currency': '', 'service_name': '', 'delivery': '', 'transit': '', 'error': msg[:140], } def emit_row(route, code, label, result): print('|{route}|{code}|{label}|{ok}|{price}|{cur}|{eta}|{transit}|{err}|'.format( route=route, code=code, label=label[:50], ok='OK' if result['ok'] else 'FAIL', price=('%.2f' % result['price']) if result['ok'] else '', cur=result['currency'], eta=result['delivery'], transit=result['transit'], err=result['error'], )) print('|Route|ServiceCode|Label|Status|Price|Cur|DeliveryETA|Transit|Error|') print('|---|---|---|---|---|---|---|---|---|') label_map = dict(carrier._fields['fedex_rest_service_type'].selection) for code in service_codes: label = label_map.get(code, code) emit_row('CA->CA', code, label, quote(code, ca_recipient)) emit_row('CA->US', code, label, quote(code, us_recipient)) print('DONE')