# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from markupsafe import Markup
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
class RentalProcessing(models.TransientModel):
_name = 'rental.order.wizard'
_description = "Pick-up/Return products"
order_id = fields.Many2one('sale.order', required=True, ondelete='cascade')
rental_wizard_line_ids = fields.One2many('rental.order.wizard.line', 'rental_order_wizard_id')
status = fields.Selection(
selection=[
('pickup', 'Pickup'),
('return', 'Return'),
],
)
is_late = fields.Boolean(related='order_id.is_late')
@api.onchange('order_id')
def _get_wizard_lines(self):
"""Use Wizard lines to set by default the pickup/return value
to the total pickup/return value expected"""
rental_lines_ids = self.env.context.get('order_line_ids', [])
rental_lines_to_process = self.env['sale.order.line'].browse(rental_lines_ids)
# generate line values
if rental_lines_to_process:
lines_values = []
for line in rental_lines_to_process:
lines_values.append(self.env['rental.order.wizard.line']._default_wizard_line_vals(line, self.status))
self.rental_wizard_line_ids = [(6, 0, [])] + [(0, 0, vals) for vals in lines_values]
def apply(self):
"""Apply the wizard modifications to the SaleOrderLine(s).
And logs the rental infos in the SaleOrder chatter
"""
for wizard in self:
msg = wizard.rental_wizard_line_ids._apply()
if msg:
for key, value in wizard._fields['status']._description_selection(wizard.env):
if key == wizard.status:
translated_status = value
break
msg = Markup("%s:
") % (translated_status, msg)
wizard.order_id.message_post(body=msg)
return # {'type': 'ir.actions.act_window_close'}
class RentalProcessingLine(models.TransientModel):
_name = 'rental.order.wizard.line'
_description = "RentalOrderLine transient representation"
@api.model
def _default_wizard_line_vals(self, line, status):
return {
'order_line_id': line.id,
'product_id': line.product_id.id,
'qty_reserved': line.product_uom_qty,
'qty_delivered': line.qty_delivered if status == 'return' else line.product_uom_qty - line.qty_delivered,
'qty_returned': line.qty_returned if status == 'pickup' else line.qty_delivered - line.qty_returned,
}
rental_order_wizard_id = fields.Many2one('rental.order.wizard', 'Rental Order Wizard', required=True, ondelete='cascade')
status = fields.Selection(related='rental_order_wizard_id.status')
order_line_id = fields.Many2one('sale.order.line', required=True, ondelete='cascade')
product_id = fields.Many2one('product.product', string='Product', required=True, ondelete='cascade')
qty_reserved = fields.Float("Reserved")
qty_delivered = fields.Float("Picked-up")
qty_returned = fields.Float("Returned")
@api.constrains('qty_returned', 'qty_delivered')
def _only_pickedup_can_be_returned(self):
for wizard_line in self:
if wizard_line.status == 'return' and wizard_line.qty_returned > wizard_line.qty_delivered:
raise ValidationError(_("You can't return more than what's been picked-up."))
def _apply(self):
"""Apply the wizard modifications to the SaleOrderLine.
:return: message to log on the Sales Order.
:rtype: str
"""
msg = self._generate_log_message()
for wizard_line in self:
order_line = wizard_line.order_line_id
if wizard_line.status == 'pickup' and wizard_line.qty_delivered > 0:
delivered_qty = order_line.qty_delivered + wizard_line.qty_delivered
vals = {'qty_delivered': delivered_qty}
if delivered_qty > order_line.product_uom_qty:
vals['product_uom_qty'] = delivered_qty
order_line.update(vals)
elif wizard_line.status == 'return' and wizard_line.qty_returned > 0:
if wizard_line.rental_order_wizard_id.is_late:
# Delays facturation
order_line._generate_delay_line(wizard_line.qty_returned)
order_line.update({
'qty_returned': order_line.qty_returned + wizard_line.qty_returned
})
return msg
def _get_diff(self):
"""Return the quantity changes due to the wizard line.
:return: (diff, old_qty, new_qty) floats
:rtype: tuple(float, float, float)
"""
self.ensure_one()
order_line = self.order_line_id
if self.status == 'pickup':
return self.qty_delivered, order_line.qty_delivered, order_line.qty_delivered + self.qty_delivered
else:
return self.qty_returned, order_line.qty_returned, order_line.qty_returned + self.qty_returned
def _generate_log_message(self):
msg = ""
for line in self:
order_line = line.order_line_id
diff, old_qty, new_qty = line._get_diff()
if diff: # i.e. diff>0
msg += Markup(" %s") % (order_line.product_id.display_name)
if old_qty > 0:
msg += Markup(": %s -> %s %s
") % (old_qty, new_qty, order_line.product_uom.name)
elif new_qty != 1 or order_line.product_uom_qty > 1.0:
msg += Markup(": %s %s
") % (new_qty, order_line.product_uom.name)
# If qty = 1, product has been picked up, no need to specify quantity
# But if ordered_qty > 1.0: we need to still specify pickedup/returned qty
return msg