forked from Mapan/odoo17e
158 lines
7.0 KiB
Python
158 lines
7.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import fields, models
|
|
|
|
class RentalSchedule(models.Model):
|
|
_inherit = "sale.rental.schedule"
|
|
|
|
is_available = fields.Boolean(compute='_compute_is_available', readonly=True, compute_sudo=True)
|
|
|
|
lot_id = fields.Many2one('stock.lot', 'Serial Number', readonly=True)
|
|
warehouse_id = fields.Many2one('stock.warehouse', 'Warehouse', readonly=True)
|
|
# TODO color depending on report_line_status
|
|
|
|
def _compute_is_available(self):
|
|
quoted_rentals_with_product = self.filtered(
|
|
lambda r: r.rental_status not in ['return', 'returned', 'cancel']
|
|
and r.return_date > fields.Datetime.now()
|
|
and r.product_id.type == 'product')
|
|
for rental in quoted_rentals_with_product:
|
|
sol = rental.order_line_id
|
|
rental.is_available = sol.virtual_available_at_date - sol.product_uom_qty >= 0
|
|
(self - quoted_rentals_with_product).is_available = True
|
|
|
|
def _get_product_name(self):
|
|
lang = self.env.lang or 'en_US'
|
|
return f"""COALESCE(lot_info.name, NULLIF(t.name->>'{lang}', ''), t.name->>'en_US') as product_name"""
|
|
|
|
def _id(self):
|
|
return """ROW_NUMBER() OVER () AS id"""
|
|
|
|
def _quantity(self):
|
|
return """
|
|
CASE WHEN lot_info.lot_id IS NULL then sum(sol.product_uom_qty / u.factor * u2.factor) ELSE 1.0 END as product_uom_qty,
|
|
CASE WHEN lot_info.lot_id IS NULL then sum(sol.qty_delivered / u.factor * u2.factor)
|
|
WHEN lot_info.report_line_status = 'reserved' then 0.0
|
|
ELSE 1.0 END as qty_delivered,
|
|
CASE WHEN lot_info.lot_id IS NULL then sum(sol.qty_returned / u.factor * u2.factor)
|
|
WHEN lot_info.report_line_status = 'returned' then 1.0
|
|
ELSE 0.0 END as qty_returned
|
|
"""
|
|
|
|
def _late(self):
|
|
return """
|
|
CASE when lot_info.lot_id is NULL then
|
|
CASE WHEN s.rental_start_date < NOW() AT TIME ZONE 'UTC' AND sol.qty_delivered < sol.product_uom_qty THEN TRUE
|
|
WHEN s.rental_return_date < NOW() AT TIME ZONE 'UTC' AND sol.qty_returned < sol.qty_delivered THEN TRUE
|
|
ELSE FALSE
|
|
END
|
|
ELSE
|
|
CASE WHEN lot_info.report_line_status = 'returned' THEN FALSE
|
|
WHEN lot_info.report_line_status = 'pickedup' THEN
|
|
CASE WHEN s.rental_return_date < NOW() AT TIME ZONE 'UTC' THEN TRUE
|
|
ELSE FALSE
|
|
END
|
|
ELSE
|
|
CASE WHEN s.rental_start_date < NOW() AT TIME ZONE 'UTC' THEN TRUE
|
|
ELSE FALSe
|
|
END
|
|
END
|
|
END as late
|
|
"""
|
|
|
|
def _report_line_status(self):
|
|
return """
|
|
CASE when lot_info.lot_id is NULL then
|
|
CASE when sol.qty_returned = sol.qty_delivered AND sol.qty_delivered = sol.product_uom_qty then 'returned'
|
|
when sol.qty_delivered = sol.product_uom_qty then 'pickedup'
|
|
else 'reserved'
|
|
END
|
|
ELSE lot_info.report_line_status
|
|
END as report_line_status
|
|
"""
|
|
|
|
def _color(self):
|
|
"""2 = orange, 4 = blue, 6 = red, 7 = green"""
|
|
return """
|
|
CASE when lot_info.lot_id is NULL then
|
|
CASE WHEN s.rental_start_date < NOW() AT TIME ZONE 'UTC' AND sol.qty_delivered < sol.product_uom_qty THEN 4
|
|
WHEN s.rental_return_date < NOW() AT TIME ZONE 'UTC' AND sol.qty_returned < sol.qty_delivered THEN 6
|
|
when sol.qty_returned = sol.qty_delivered AND sol.qty_delivered = sol.product_uom_qty THEN 7
|
|
WHEN sol.qty_delivered = sol.product_uom_qty THEN 2
|
|
ELSE 4
|
|
END
|
|
ELSE
|
|
CASE WHEN lot_info.report_line_status = 'returned' THEN 7
|
|
WHEN lot_info.report_line_status = 'pickedup' THEN
|
|
CASE WHEN s.rental_return_date < NOW() AT TIME ZONE 'UTC' THEN 6
|
|
ELSE 2
|
|
END
|
|
ELSE 4
|
|
END
|
|
END as color
|
|
"""
|
|
|
|
def _with(self):
|
|
return """
|
|
WITH ordered_lots (lot_id, name, sol_id, report_line_status) AS
|
|
(SELECT
|
|
lot.id as lot_id,
|
|
lot.name,
|
|
COALESCE(res.sale_order_line_id, pickedup.sale_order_line_id) as sol_id,
|
|
CASE
|
|
WHEN returned.stock_lot_id IS NOT NULL THEN 'returned'
|
|
WHEN pickedup.stock_lot_id IS NOT NULL THEN 'pickedup'
|
|
ELSE 'reserved'
|
|
END AS report_line_status
|
|
FROM
|
|
rental_reserved_lot_rel res
|
|
FULL OUTER JOIN rental_pickedup_lot_rel pickedup
|
|
ON res.sale_order_line_id=pickedup.sale_order_line_id
|
|
AND res.stock_lot_id=pickedup.stock_lot_id
|
|
LEFT OUTER JOIN rental_returned_lot_rel returned
|
|
ON returned.sale_order_line_id=pickedup.sale_order_line_id
|
|
AND returned.stock_lot_id=pickedup.stock_lot_id
|
|
JOIN stock_lot lot
|
|
ON res.stock_lot_id=lot.id
|
|
OR pickedup.stock_lot_id=lot.id
|
|
UNION ALL
|
|
SELECT DISTINCT ON (sml.lot_id)
|
|
sml.lot_id,
|
|
sl.name,
|
|
sol.id AS sol_id,
|
|
CASE
|
|
WHEN so.rental_status='returned' THEN 'returned'
|
|
WHEN so.rental_status='return' THEN 'pickedup'
|
|
WHEN so.rental_status='pickup' THEN 'reserved'
|
|
END AS report_line_status
|
|
FROM sale_order so
|
|
INNER JOIN sale_order_line sol ON so.id=sol.order_id
|
|
INNER JOIN stock_lot sl ON sol.product_id=sl.product_id
|
|
INNER JOIN stock_move_line sml ON sl.id=sml.lot_id
|
|
INNER JOIN stock_picking sp ON sol.order_id=sp.sale_id
|
|
INNER JOIN stock_move sm ON sml.move_id=sm.id
|
|
WHERE sm.sale_line_id=sol.id
|
|
AND so.is_rental_order=true
|
|
)
|
|
"""
|
|
|
|
def _select(self):
|
|
return super(RentalSchedule, self)._select() + """,
|
|
lot_info.lot_id as lot_id,
|
|
s.warehouse_id as warehouse_id
|
|
"""
|
|
|
|
def _from(self):
|
|
return super(RentalSchedule, self)._from() + """
|
|
LEFT OUTER JOIN ordered_lots lot_info ON sol.id=lot_info.sol_id
|
|
"""
|
|
|
|
def _groupby(self):
|
|
# Add ORDER BY to ensure that `ROW_NUMBER() OVER () AS id` targets the same row each time
|
|
return super(RentalSchedule, self)._groupby() + """,
|
|
lot_info.lot_id,
|
|
lot_info.name,
|
|
lot_info.report_line_status
|
|
ORDER BY sol.id, lot_info.lot_id"""
|