integration to odoo (as delivery carrier)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
4.2 KiB

from openerp import api, fields, models
import logging
import pytz
from openerp.exceptions import Warning
from shipcloud_delivery_carrier import build_sc_addr
import shipcloud
_logger = logging.getLogger(__name__)
class SCPickup(models.Model):
_name = "delivery.carrier.pickup"
# carrier who should be picking up
carrier = fields.Selection([('ups','UPS'), ('dpd','DPD'), ('hermes','Hermes'), ('gls','GLS')],
string='Carrier', required=True, default='ups')
# pickings (shipments) to be picked up
pickings = fields.Many2many('stock.picking', string='Pickings', required=True)
# address from where to pick up
address = fields.Many2one('res.partner', string='Pick-up address', required=True)
# earliest pick-up time
earliest = fields.Datetime('Earliest', required=True, default=lambda self:,
readonly=True, states={'draft': [('readonly', False)]})
# latest pick-up time
latest = fields.Datetime('Latest', required=True, default=lambda self:,
readonly=True, states={'draft': [('readonly', False)]})
# draft: not yet requested from shipcloud; confirmed: confirmed by shipcloud
state = fields.Selection([('draft', 'Draft'), ('confirmed', 'Confirmed'), ('done','Done')],
string='Status', default='draft', readonly=True, required=True, copy=False)
sc_pickup_id = fields.Char('Shipcloud Pick-up ID', readonly=True, copy=False)
carrier_pickup_number = fields.Char('Carrier Pick-up Number', readonly=True, copy=False)
def _shipcloud_api(self):
config = self.env['delivery.carrier']._get_config()
api_key = config['sc_api_key_prod']
sandbox_api_key = None if config['sc_api_use_prod'] else config['sc_api_key_sandbox']
return shipcloud.api(api_key, sandbox_api_key)
def button_request(self):
def field_to_datetime(self, dtfield):
tz_name = self._context.get('tz') or
tz = pytz.timezone(tz_name)
dt = fields.Datetime.from_string(dtfield)
return fields.Datetime.context_timestamp(self, dt)
# consistency check
for p in self.pickings:
if p.carrier_id.delivery_type != 'sc':
raise Warning("Picking %s doesn't use shipcloud" % (
if not p.label_genrated:
raise Warning("Picking %s doesn't have a label yet" % (
if not p.sc_shipment_id:
raise Warning("Picking %s has not shipcloud label/id" % (
# collect the SC shipment IDs of all the pickings
sc_ship_ids = []
for p in self.pickings:
sc_ship_ids.append({'id': p.sc_shipment_id})
sc_addr = build_sc_addr(self.address)
sc_earliest = field_to_datetime(self, self.earliest).isoformat()
sc_latest = field_to_datetime(self, self.latest).isoformat()"earliest: %s -> %s" % (self.earliest, sc_earliest))"latest: %s -> %s" % (self.latest, sc_latest))
sc_pickup = shipcloud.gen_pickup(sc_addr, sc_earliest, sc_latest, sc_ship_ids, self.carrier)
# actually use the SC API to request the pickup
api = self._shipcloud_api()
result = api.create_pickup(sc_pickup)
except shipcloud.ApiError as err:
raise Warning(str(err))"shipcloud response: %s", result)
self.sc_pickup_id = result['id']
self.carrier_pickup_number = result['carrier_pickup_number']
self.state = 'confirmed'
# somehow this didn't work as a new (v8) style ORM ?!?
def default_get(self, cr, user, fields_list, context=None):
if context is None:
context = {}
res = super(SCPickup, self).default_get(cr, user, fields_list, context=context)
if context.get('active_model') == 'stock.picking' and context.get('active_ids'):
picking_ids = context['active_ids']
res['pickings'] = picking_ids
# intentionally no default pick-up address to avoid the mistakes of
# leaving the default and hence scheduling a pick-up from the wrong address
return res