from openerp import api, fields, models import logging from openerp.exceptions import Warning import pycountry from inema import Internetmarke _logger = logging.getLogger(__name__) TRACKING_URL = 'https://www.deutschepost.de/sendung/simpleQuery.html?locale=en_GB' # convert from ISO3166 2-digit to 3-digit def get_alpha3_country_from_alpha2(twodigit): c = pycountry.countries.get(alpha2=twodigit) return c.alpha3 # split the last word of a string containing stree name + house number def split_street_house(streethouse): # first try to split at last space r = streethouse.rsplit(' ', 1) # if that fails, try to split at last dot if len(r) < 2: r = streethouse.rsplit('.', 1) # if that also fails, return empty house number if len(r) < 2: return (streethouse, '') return (r[0], r[1]) def split_first_lastname(name): # try to split at last space r = name.rsplit(' ', 1) # if this fails, simply claim everything is the last name if len(r) < 2: return ("", name) return (r[0], r[1]) class DPDeliveryCarrier(models.Model): _inherit="delivery.carrier" def conn_auth_im(self): config = self._get_config() partner_id = config['dp_partner_id'] key = config['dp_key'] key_phase = config['dp_key_phase'] pk_user = config['dp_portokasse_user'] pk_passwd = config['dp_portokasse_passwd'] im = Internetmarke(partner_id, key, key_phase) im.authenticate(pk_user, pk_passwd) return im # Convert an Odoo Partner object into Internetmarke Address def build_im_addr(self, im, partner): (street, house) = split_street_house(partner.street) country = get_alpha3_country_from_alpha2(partner.country_id.code) street2 = None if partner.street2: street2 = partner.street2 addr = im.build_addr(street = street, house = house, additional = street2, zipcode = partner.zip, city = partner.city, country = country) if partner.is_company: return im.build_comp_addr(company = partner.name, address = addr) else: if partner.parent_id.name: person = None if partner.name: (first, last) = split_first_lastname(partner.name) person = im.build_pers_name(first=first, last=last, title=partner.title) return im.build_comp_addr(company = partner.parent_id.name, address = addr, person = person) else: (first, last) = split_first_lastname(partner.name) return im.build_pers_addr(first = first, last = last, address = addr) def get_services_by_country(self, service_class, country_code): if country_code == 'DE': return service_class.services_natl else: return service_class.services_intl # determine lowest-matching-max-weight service within same class def get_service_by_class(self, recipient, weight, service_class): services = self.get_services_by_country(service_class, recipient.country_id.code) lowest_max_weight = 100000 lowest_service = None for s in services: if s.weight >= weight and s.weight < lowest_max_weight: lowest_max_weight = s.weight lowest_service = s return lowest_service # determine the maximum weight (in kg) of any service in this class def get_class_max_weight(self, service_class): services = self.get_services_by_country(service_class, recipient.country_id.code) highest_weight = 0 for s in services: if highest_weight > hightest_weight: highest_weight = s.weight return highest_weight @api.one def dp_send_shipping(self, pickings): config = self._get_config() order = self.env['sale.order'].search([('name','=',pickings.origin)]) recipient = pickings.partner_id warehouse = pickings.picking_type_id.warehouse_id.partner_id weight = self._get_weight(order, pickings) service = self.get_service_by_class(recipient, weight, self.sudo().dp_service_class) if not service: raise Warning("Service not available for weight!") im = self.conn_auth_im() im_recipient = self.build_im_addr(im, recipient) im_sender = self.build_im_addr(im, warehouse) im.clear_positions() position = im.build_position(service.code, im_sender, im_recipient) im.add_position(position) r = im.checkoutPNG() voucher = r.shoppingCart.voucherList.voucher[0] filename = 'DP'+voucher.voucherId+'.png' tracking_nr = ' ' if voucher.trackId: tracking_nr += voucher.trackId result = { 'exact_price': im.compute_total()/100, 'weight': service.weight, 'date_delivery': None, 'tracking_number': tracking_nr, 'voucher_id' : voucher.voucherId, 'order_id' : r.shoppingCart.shopOrderId, 'wallet_balance': r.walletBallance, 'attachments': [(filename, voucher.png_bin)]} return result def dp_get_shipping_price_from_so(self, order): price = 0 config = self._get_config() recipient = order.partner_shipping_id if order.partner_shipping_id else order.partner_id warehouse = order.warehouse_id.partner_id service_class = self.sudo().dp_service_class # single-package implementation weight = self._get_weight(order) service = self.get_service_by_class(recipient, weight, service_class) if not service: raise Warning("Service not available for weight!") return service.cost_price # compute the maximum weight of any service within class #class_max_weight = self.get_class_max_weight(service_class) # compute number of packages and each weight #weight, weight_limit, last_package, limits = self.get_package_count(class_max_weight, order) # iterate over list of packages #for line in range(1, limits+1): # if last_package and line == limits: # weight_limit = last_package # service = self.get_service_by_class(recipient, weight, service_class) # price += service.cost_price #return price @api.one def dp_get_tracking_link(self, pickings): return TRACKING_URL @api.one def dp_cancel_shipment(self, pickings): raise Warning('Cancelling DP Shipments not supported!')