From 7ac04d409e6e47437e0fa522687bdf62e533421c Mon Sep 17 00:00:00 2001 From: Richard Mathot Date: Mon, 28 Sep 2015 16:27:50 +0200 Subject: [PATCH] [FIX] delivery: invoice actual shipping cost Since commit 78cc0b95f4d6e4f615e624378758a6eb7e71a8be, there was no more way to invoice the actual price of a shipping (after the transfer). In order to make that available again, we introduce a new field on the sale order. This field automatically detects whether a sale order contains a "delivery" line or not, at sale order confirmation (action_confirm). When the delivery order is processed, the actual shipping cost is thus repercuted on the sale order if and only if the shipping price was not "forced" at the sale order confirmation. (and a few refactoring to avoid copy-pasting code lines) --- addons/delivery/models/sale_order.py | 65 +++++++++++++++---------- addons/delivery/models/stock_picking.py | 9 ++++ 2 files changed, 47 insertions(+), 27 deletions(-) diff --git a/addons/delivery/models/sale_order.py b/addons/delivery/models/sale_order.py index 28b82029652..389ea670ed0 100644 --- a/addons/delivery/models/sale_order.py +++ b/addons/delivery/models/sale_order.py @@ -10,6 +10,7 @@ class SaleOrder(models.Model): delivery_price = fields.Float(string='Estimated Delivery Price', compute='_compute_delivery_price', store=True) carrier_id = fields.Many2one("delivery.carrier", string="Delivery Method", help="Fill this field if you plan to invoice the shipping based on picking.") + invoice_shipping_on_delivery = fields.Boolean(string="Invoice Shipping on Delivery") @api.depends('carrier_id', 'partner_id', 'order_line') def _compute_delivery_price(self): @@ -28,6 +29,13 @@ class SaleOrder(models.Model): if self.partner_id: self.carrier_id = self.partner_id.property_delivery_carrier_id + @api.multi + def action_confirm(self): + res = super(SaleOrder, self).action_confirm() + for so in self: + self.invoice_shipping_on_delivery = all([not line.is_delivery for line in so.order_line]) + return res + @api.multi def _delivery_unset(self): self.env['sale.order.line'].search([('order_id', 'in', self.ids), ('is_delivery', '=', True)]).unlink() @@ -35,8 +43,6 @@ class SaleOrder(models.Model): @api.multi def delivery_set(self): - SaleOrderLine = self.env['sale.order.line'] - # Remove delivery products from the sale order self._delivery_unset() @@ -58,35 +64,40 @@ class SaleOrder(models.Model): if order.company_id.currency_id.id != order.pricelist_id.currency_id.id: price_unit = order.company_id.currency_id.with_context(date=order.date_order).compute(price_unit, order.pricelist_id.currency_id) - account_id = carrier.product_id.property_account_income_id.id - if not account_id: - account_id = carrier.product_id.categ_id.property_account_income_categ_id.id - - # Apply fiscal position - taxes = carrier.product_id.taxes_id.filtered(lambda t: t.company_id.id == order.company_id.id) - taxes_ids = taxes.ids - if order.partner_id and order.fiscal_position_id: - account_id = order.fiscal_position_id.map_account(account_id) - taxes_ids = order.fiscal_position_id.map_tax(taxes).ids - - # Create the sale order line - values = { - 'order_id': order.id, - 'name': carrier.name, - '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 order.order_line: - values['sequence'] = order.order_line[-1].sequence + 1 - SaleOrderLine.create(values) + order._create_delivery_line(carrier, price_unit) else: raise UserError(_('No carrier set for this order.')) + def _create_delivery_line(self, carrier, price_unit): + SaleOrderLine = self.env['sale.order.line'] + + account_id = carrier.product_id.property_account_income_id.id + if not account_id: + account_id = carrier.product_id.categ_id.property_account_income_categ_id.id + + # Apply fiscal position + taxes = carrier.product_id.taxes_id.filtered(lambda t: t.company_id.id == self.company_id.id) + taxes_ids = taxes.ids + if self.partner_id and self.fiscal_position_id: + account_id = self.fiscal_position_id.map_account(account_id) + taxes_ids = self.fiscal_position_id.map_tax(taxes).ids + + # Create the sale order line + values = { + 'order_id': self.id, + 'name': carrier.name, + '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 self.order_line: + values['sequence'] = self.order_line[-1].sequence + 1 + SaleOrderLine.create(values) + class SaleOrderLine(models.Model): _inherit = 'sale.order.line' diff --git a/addons/delivery/models/stock_picking.py b/addons/delivery/models/stock_picking.py index 72943861ca5..00d94ef996e 100644 --- a/addons/delivery/models/stock_picking.py +++ b/addons/delivery/models/stock_picking.py @@ -75,6 +75,8 @@ class StockPicking(models.Model): if self.carrier_id and self.carrier_id.delivery_type not in ['fixed', 'base_on_rule'] and self.carrier_id.shipping_enabled: self.send_to_shipper() + self._add_delivery_cost_to_so() + return res @api.multi @@ -86,6 +88,13 @@ class StockPicking(models.Model): msg = _("Shipment sent to carrier %s for expedition with tracking number %s") % (self.carrier_id.name, self.carrier_tracking_ref) self.message_post(body=msg) + @api.multi + def _add_delivery_cost_to_so(self): + self.ensure_one() + sale_order = self.sale_id + if sale_order.invoice_shipping_on_delivery: + sale_order._create_delivery_line(self.carrier_id, self.carrier_price) + @api.multi def open_website_url(self): self.ensure_one()