diff --git a/addons/delivery/models/delivery_carrier.py b/addons/delivery/models/delivery_carrier.py index ad0d4f3cb30..8171fb9ab08 100644 --- a/addons/delivery/models/delivery_carrier.py +++ b/addons/delivery/models/delivery_carrier.py @@ -45,6 +45,12 @@ class DeliveryCarrier(models.Model): company_id = fields.Many2one('res.company', string='Company', related='product_id.company_id', store=True, readonly=False) product_id = fields.Many2one('product.product', string='Delivery Product', required=True, ondelete='restrict') + invoice_policy = fields.Selection([ + ('estimated', 'Estimated cost'), + ('real', 'Real cost') + ], string='Invoicing Policy', default='estimated', required=True, + help="Estimated Cost: the customer will be invoiced the estimated cost of the shipping.\nReal Cost: the customer will be invoiced the real cost of the shipping, the cost of the shipping will be updated on the SO after the delivery.") + country_ids = fields.Many2many('res.country', 'delivery_carrier_country_rel', 'carrier_id', 'country_id', 'Countries') state_ids = fields.Many2many('res.country.state', 'delivery_carrier_state_rel', 'carrier_id', 'state_id', 'States') zip_from = fields.Char('Zip From') diff --git a/addons/delivery/models/sale_order.py b/addons/delivery/models/sale_order.py index 414b46fe561..1c082138d2f 100644 --- a/addons/delivery/models/sale_order.py +++ b/addons/delivery/models/sale_order.py @@ -86,7 +86,7 @@ class SaleOrder(models.Model): order._create_delivery_line(order.carrier_id, price_unit) return True - def _create_delivery_line(self, carrier, price_unit): + def _create_delivery_line(self, carrier, price_unit, price_unit_in_description=False): SaleOrderLine = self.env['sale.order.line'] if self.partner_id: # set delivery detail in the customer language @@ -105,15 +105,28 @@ class SaleOrder(models.Model): 'product_uom_qty': 1, 'product_uom': carrier.product_id.uom_id.id, 'product_id': carrier.product_id.id, - 'price_unit': price_unit, 'tax_id': [(6, 0, taxes_ids)], 'is_delivery': True, } + if price_unit_in_description: + values['price_unit'] = 0 + values['name'] += _(' (Estimated Cost: %s )') % self._format_currency_amount(price_unit) + else: + values['price_unit'] = price_unit + if self.order_line: values['sequence'] = self.order_line[-1].sequence + 1 sol = SaleOrderLine.sudo().create(values) return sol + def _format_currency_amount(self, amount): + pre = post = u'' + if self.currency_id.position == 'before': + pre = u'{symbol}\N{NO-BREAK SPACE}'.format(symbol=self.currency_id.symbol or '') + else: + post = u'\N{NO-BREAK SPACE}{symbol}'.format(symbol=self.currency_id.symbol or '') + return u' {pre}{0}{post}'.format(amount, pre=pre, post=post) + @api.depends('state', 'order_line.invoice_status', 'order_line.invoice_lines', 'order_line.is_delivery', 'order_line.is_downpayment', 'order_line.product_id.invoice_policy') def _get_invoiced(self): diff --git a/addons/delivery/models/stock_picking.py b/addons/delivery/models/stock_picking.py index accc102c2b7..0b77cb4ca5b 100644 --- a/addons/delivery/models/stock_picking.py +++ b/addons/delivery/models/stock_picking.py @@ -186,12 +186,33 @@ class StockPicking(models.Model): msg = _("Shipment sent to carrier %s for shipping with tracking number %s
Cost: %.2f %s") % (self.carrier_id.name, self.carrier_tracking_ref, self.carrier_price, order_currency.name) self.message_post(body=msg) + def _get_new_delivery_price(self): + if self.carrier_id.integration_level != 'rate_and_ship': + res = self.carrier_id.rate_shipment(self.sale_id) + if res['success']: + self.carrier_price = res['price'] + else: + raise UserError(_("Unable to update the delivery price because of: ") + res['error_message']) + @api.multi def _add_delivery_cost_to_so(self): self.ensure_one() sale_order = self.sale_id + # if there isn't a delivery line on the SO yet if sale_order.invoice_shipping_on_delivery: - sale_order._create_delivery_line(self.carrier_id, self.carrier_price) + self._get_new_delivery_price() # fill `self.carrier_price` if needed + sale_order._create_delivery_line(self.carrier_id, self.carrier_price, price_unit_in_description=False) + else: + # we only want to update the price of the delivery line if the invoice + # policy is 'Real' but we chose not to if the user updated it in the meantime + delivery_line = sale_order.order_line.filtered(lambda line: line.is_delivery) + if self.carrier_id.invoice_policy == 'real' and delivery_line.currency_id.is_zero(delivery_line.price_unit): + self._get_new_delivery_price() + delivery_line.write({ + 'price_unit': self.carrier_price, + # remove the estimated price from the description + 'name': sale_order.carrier_id.with_context(lang=self.partner_id.lang).name, + }) @api.multi def open_website_url(self): diff --git a/addons/delivery/views/delivery_view.xml b/addons/delivery/views/delivery_view.xml index 660cc53a41c..c852ebde898 100644 --- a/addons/delivery/views/delivery_view.xml +++ b/addons/delivery/views/delivery_view.xml @@ -84,6 +84,7 @@ +