forked from Mapan/odoo17e
213 lines
8.6 KiB
Python
213 lines
8.6 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import api, fields, models, tools
|
|
|
|
from odoo.addons.sale.models.sale_order import SALE_ORDER_STATE
|
|
from odoo.addons.sale_renting.models.sale_order import RENTAL_STATUS
|
|
|
|
|
|
class RentalSchedule(models.Model):
|
|
_name = "sale.rental.schedule"
|
|
_description = "Rental Schedule"
|
|
_auto = False
|
|
_order = 'order_date desc'
|
|
_rec_name = 'card_name'
|
|
|
|
@api.model
|
|
def _read_group_report_line_status(self, report_line_status, domain, order):
|
|
return [key for key, val in self._fields['report_line_status'].selection]
|
|
|
|
@api.model
|
|
def _read_group_product_ids(self, products, domain, order):
|
|
if self._context.get('restrict_renting_products'):
|
|
return products
|
|
all_rental_products = products.search([('rent_ok', '=', True)], order=order)
|
|
if len(all_rental_products) > 80:
|
|
return products
|
|
return all_rental_products
|
|
|
|
@api.model
|
|
def get_gantt_data(self, domain, groupby, read_specification, limit=None, offset=0):
|
|
if (
|
|
limit
|
|
and not offset
|
|
and len(groupby) == 1
|
|
and not self.env.context.get('restrict_renting_products')
|
|
and limit >= self.env['product.product'].search_count(
|
|
[('rent_ok', '=', True)],
|
|
limit=limit + 1,
|
|
)
|
|
):
|
|
# If there are less rental products in the database than the given limit, drop the limit
|
|
# so that the read_group is lazy and the `group_expand` is called
|
|
limit = None
|
|
return super().get_gantt_data(domain, groupby, read_specification, limit=limit, offset=offset)
|
|
|
|
name = fields.Char('Order Reference', readonly=True)
|
|
product_name = fields.Char('Product Reference', readonly=True)
|
|
description = fields.Char('Description', readonly=True)
|
|
order_date = fields.Datetime('Order Date', readonly=True)
|
|
pickup_date = fields.Datetime('Pickup Date', readonly=True)
|
|
return_date = fields.Datetime('Return Date', readonly=True)
|
|
product_id = fields.Many2one('product.product', 'Product', readonly=True, group_expand="_read_group_product_ids")
|
|
product_uom = fields.Many2one('uom.uom', 'Unit of Measure', readonly=True)
|
|
product_uom_qty = fields.Float('Qty Ordered', readonly=True)
|
|
qty_delivered = fields.Float('Qty Picked-Up', readonly=True)
|
|
qty_returned = fields.Float('Qty Returned', readonly=True)
|
|
partner_id = fields.Many2one('res.partner', 'Customer', readonly=True)
|
|
card_name = fields.Char(string="Customer Name", readonly=True)
|
|
company_id = fields.Many2one('res.company', 'Company', readonly=True)
|
|
user_id = fields.Many2one('res.users', 'Salesperson', readonly=True)
|
|
product_tmpl_id = fields.Many2one('product.template', 'Product Template', readonly=True)
|
|
categ_id = fields.Many2one('product.category', 'Product Category', readonly=True)
|
|
analytic_account_id = fields.Many2one('account.analytic.account', 'Analytic Account', readonly=True)
|
|
team_id = fields.Many2one('crm.team', 'Sales Team', readonly=True)
|
|
country_id = fields.Many2one('res.country', 'Customer Country', readonly=True)
|
|
commercial_partner_id = fields.Many2one('res.partner', 'Customer Entity', readonly=True)
|
|
rental_status = fields.Selection(selection=RENTAL_STATUS, string="Rental Status", readonly=True)
|
|
state = fields.Selection(selection=SALE_ORDER_STATE, string="Status", readonly=True)
|
|
|
|
order_id = fields.Many2one('sale.order', 'Order #', readonly=True)
|
|
order_line_id = fields.Many2one('sale.order.line', 'Order line #', readonly=True)
|
|
|
|
report_line_status = fields.Selection([
|
|
('reserved', 'Reserved'),
|
|
('pickedup', 'Pickedup'),
|
|
('returned', 'Returned'),
|
|
], string="Rental Status (advanced)", readonly=True, group_expand="_read_group_report_line_status")
|
|
color = fields.Integer(readonly=True)
|
|
late = fields.Boolean("Is Late", readonly=True)
|
|
|
|
def _with(self):
|
|
return """ """
|
|
|
|
def _id(self):
|
|
return """sol.id as id"""
|
|
|
|
def _get_product_name(self):
|
|
return """t.name as product_name"""
|
|
|
|
def _quantity(self):
|
|
return """
|
|
sum(sol.product_uom_qty / u.factor * u2.factor) as product_uom_qty,
|
|
sum(sol.qty_delivered / u.factor * u2.factor) as qty_delivered,
|
|
sum(sol.qty_returned / u.factor * u2.factor) as qty_returned
|
|
"""
|
|
|
|
def _late(self):
|
|
return """
|
|
CASE WHEN sol.state != 'sale' THEN FALSE
|
|
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 as late
|
|
"""
|
|
|
|
def _report_line_status(self):
|
|
return """
|
|
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 as report_line_status
|
|
"""
|
|
|
|
def _color(self):
|
|
"""2 = orange (pickedup), 4 = blue(reserved), 6 = red(late return), 7 = green(returned)"""
|
|
return """
|
|
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 as color
|
|
"""
|
|
|
|
def _select(self):
|
|
return """%s,
|
|
%s,
|
|
sol.product_id as product_id,
|
|
t.uom_id as product_uom,
|
|
sol.name as description,
|
|
s.name as name,
|
|
%s,
|
|
s.date_order as order_date,
|
|
s.rental_start_date as pickup_date,
|
|
s.rental_return_date as return_date,
|
|
s.state as state,
|
|
s.rental_status as rental_status,
|
|
s.partner_id as partner_id,
|
|
s.user_id as user_id,
|
|
s.company_id as company_id,
|
|
extract(epoch from avg(date_trunc('day',s.rental_return_date)-date_trunc('day',s.rental_start_date)))/(24*60*60)::decimal(16,2) as delay,
|
|
t.categ_id as categ_id,
|
|
s.pricelist_id as pricelist_id,
|
|
s.analytic_account_id as analytic_account_id,
|
|
s.team_id as team_id,
|
|
p.product_tmpl_id,
|
|
partner.country_id as country_id,
|
|
partner.commercial_partner_id as commercial_partner_id,
|
|
CONCAT(partner.name, ', ', s.name) as card_name,
|
|
s.id as order_id,
|
|
sol.id as order_line_id,
|
|
%s,
|
|
%s,
|
|
%s
|
|
""" % (self._id(), self._get_product_name(), self._quantity(), self._report_line_status(), self._late(), self._color())
|
|
|
|
def _from(self):
|
|
return """
|
|
sale_order_line sol
|
|
join sale_order s on (sol.order_id=s.id)
|
|
join res_partner partner on s.partner_id = partner.id
|
|
left join product_product p on (sol.product_id=p.id)
|
|
left join product_template t on (p.product_tmpl_id=t.id)
|
|
left join uom_uom u on (u.id=sol.product_uom)
|
|
left join uom_uom u2 on (u2.id=t.uom_id)
|
|
"""
|
|
|
|
def _groupby(self):
|
|
return """
|
|
sol.product_id,
|
|
sol.order_id,
|
|
t.uom_id,
|
|
t.categ_id,
|
|
t.name,
|
|
s.name,
|
|
s.date_order,
|
|
s.rental_start_date,
|
|
s.rental_return_date,
|
|
s.partner_id,
|
|
s.user_id,
|
|
s.rental_status,
|
|
s.company_id,
|
|
s.pricelist_id,
|
|
s.analytic_account_id,
|
|
s.team_id,
|
|
p.product_tmpl_id,
|
|
partner.country_id,
|
|
partner.commercial_partner_id,
|
|
partner.name,
|
|
s.id,
|
|
sol.id
|
|
"""
|
|
|
|
def _query(self):
|
|
return """
|
|
%s (SELECT %s
|
|
FROM %s
|
|
WHERE sol.product_id IS NOT NULL
|
|
AND sol.is_rental
|
|
GROUP BY %s)
|
|
""" % (
|
|
self._with(),
|
|
self._select(),
|
|
self._from(),
|
|
self._groupby()
|
|
)
|
|
|
|
def init(self):
|
|
# self._table = sale_rental_report
|
|
tools.drop_view_if_exists(self.env.cr, self._table)
|
|
self.env.cr.execute("""CREATE or REPLACE VIEW %s as (%s)""" % (self._table, self._query()))
|