1
0
forked from Mapan/odoo17e
odoo17e-kedaikipas58/addons/sale_renting/models/product_template.py
2024-12-10 09:04:09 +07:00

152 lines
6.3 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import _, api, fields, models
from odoo.tools import format_amount
class ProductTemplate(models.Model):
_inherit = 'product.template'
rent_ok = fields.Boolean(
string="Can be Rented",
help="Allow renting of this product.")
qty_in_rent = fields.Float("Quantity currently in rent", compute='_get_qty_in_rent')
product_pricing_ids = fields.One2many(
comodel_name='product.pricing',
inverse_name='product_template_id',
string="Custom Pricings",
auto_join=True,
copy=False,
domain=['|', ('pricelist_id', '=', False), ('pricelist_id.active', '=', True)],
)
display_price = fields.Char(
string="Rental price",
compute='_compute_display_price',
help="First rental pricing of the product",
)
# Delays pricing
extra_hourly = fields.Float("Extra Hour", help="Fine by hour overdue", company_dependent=True)
extra_daily = fields.Float("Extra Day", help="Fine by day overdue", company_dependent=True)
def _compute_display_price(self):
rental_products = self.filtered('rent_ok')
rental_priced_products = rental_products.filtered('product_pricing_ids')
(self - rental_products).display_price = ""
for product in (rental_products - rental_priced_products):
# No rental pricing defined, fallback on list price
product.display_price = _(
"%(amount)s (fixed)",
amount=format_amount(self.env, product.list_price, product.currency_id),
)
for product in rental_priced_products:
product.display_price = product.product_pricing_ids[0].description
def _get_qty_in_rent(self):
rentable = self.filtered('rent_ok')
not_rentable = self - rentable
not_rentable.update({'qty_in_rent': 0.0})
for template in rentable:
template.qty_in_rent = sum(template.mapped('product_variant_ids.qty_in_rent'))
@api.model
def _get_incompatible_types(self):
return ['rent_ok'] + super()._get_incompatible_types()
def action_view_rentals(self):
"""Access Gantt view of rentals (sale.rental.schedule), filtered on variants of the current template."""
return {
"type": "ir.actions.act_window",
"name": _("Scheduled Rentals"),
"res_model": "sale.rental.schedule",
"views": [[False, "gantt"]],
'domain': [('product_id', 'in', self.mapped('product_variant_ids').ids)],
'context': {
'search_default_Rentals':1,
'group_by_no_leaf':1,
'group_by':[],
'restrict_renting_products': True,
}
}
@api.depends('rent_ok')
@api.depends_context('rental_products')
def _compute_display_name(self):
super()._compute_display_name()
if not self._context.get('rental_products'):
return
for template in self:
if template.rent_ok:
template.display_name = _("%s (Rental)", template.display_name)
def _get_best_pricing_rule(self, product=False, start_date=False, end_date=False, **kwargs):
""" Return the best pricing rule for the given duration.
:param ProductProduct product: a product recordset (containing at most one record)
:param datetime start_date: start date of leasing period
:param datetime end_date: end date of leasing period
:return: least expensive pricing rule for given duration
"""
self.ensure_one()
best_pricing_rule = self.env['product.pricing']
if not self.product_pricing_ids or not (start_date and end_date):
return best_pricing_rule
pricelist = kwargs.get('pricelist', self.env['product.pricelist'])
currency = kwargs.get('currency', self.currency_id)
company = kwargs.get('company', self.env.company)
duration_dict = self.env['product.pricing']._compute_duration_vals(start_date, end_date)
min_price = float("inf") # positive infinity
available_pricings = self.env['product.pricing']._get_suitable_pricings(
product or self, pricelist=pricelist
)
for pricing in available_pricings:
unit = pricing.recurrence_id.unit
price = pricing._compute_price(duration_dict[unit], unit)
if pricing.currency_id != currency:
price = pricing.currency_id._convert(
from_amount=price,
to_currency=currency,
company=company,
date=fields.Date.today(),
)
if price < min_price:
min_price, best_pricing_rule = price, pricing
return best_pricing_rule
def _get_contextual_price(self, product=None):
self.ensure_one()
if not (product or self).rent_ok:
return super()._get_contextual_price(product=product)
pricelist = self._get_contextual_pricelist()
quantity = self.env.context.get('quantity', 1.0)
uom = self.env['uom.uom'].browse(self.env.context.get('uom'))
date = self.env.context.get('date')
start_date = self.env.context.get('start_date')
end_date = self.env.context.get('end_date')
return pricelist._get_product_price(
product or self, quantity, uom=uom, date=date, start_date=start_date, end_date=end_date
)
def copy(self, default=None):
copied_tmpl = super().copy(default)
for pricing in self.product_pricing_ids:
copied_variant_ids = []
for product in pricing.product_variant_ids:
pav_ids = product.product_template_variant_value_ids.product_attribute_value_id.ids
copied_variant_ids.extend(
copied_tmpl.product_variant_ids.filtered(
lambda p: p
.product_template_variant_value_ids
.product_attribute_value_id
.ids == pav_ids
).ids
)
pricing.copy({
'product_template_id': copied_tmpl.id,
'product_variant_ids': copied_variant_ids,
})
return copied_tmpl