Hi Guys,
I wrote some code that does the following :
A Tile company buys tiles in a box.
Each tile has Square Metre Per Box, with number of tiles in it.
If Square Metre Per box is 1.44 for example, and a customer requires 50 sqm :
50 / 1.44 = 34.72. They do not sell fraction of boxes so round up to next whole number, therefore 35 boxes
Sales order is then 35 x 1.44 = 50.4m2
On the Sales Order 50.4m2 * 899 (list price) = 45309,60 ie
50 is what salesperson types in 'qty' and 45309.60 is what comes out in total amount column.
I used the following code. I created a new type of UoM called m2 for the area (Sq Metre) :
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
from odoo.addons import decimal_precision as dp
import math
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
sq_m_per_box = fields.Float(default=0.0, digits=dp.get_precision('Product Unit of Measure'))
product_uom = fields.Many2one('uom.uom', 'Unit of Measure', required=True, readonly=True)
area_based = fields.Boolean(readonly=True, compute='_compute_measure')
area = fields.Float(compute='_compute_area')
@api.onchange('product_id')
def _compute_measure(self):
for line in self:
if line.product_id.uom_id.id is self.env.ref('area_based_price.product_uom_m2').id:
line.area_based = True
else:
line.area_based = False
@api.onchange('sq_m_per_box')
def _onchange_sq_m_per_box(self):
if self.sq_m_per_box < 0:
self.sq_m_per_box = 0
raise ValidationError(_("You cant have negative sq_m_per_box"))
def _compute_m2_price(self):
if self.product_id.uom_id.id is self.env.ref('area_based_price.product_uom_m2').id:
m2 = self.sq_m_per_box
if m2 > 0:
return math.ceil( self.product_id.list_price * (self.product_uom_qty / m2) * m2 )
@api.onchange('product_id', 'sq_m_per_box', 'product_uom_qty')
def product_id_change(self):
if not self.product_id:
return {'domain': {'product_uom': []}}
vals = {}
domain = {'product_uom': [('category_id', '=', self.product_id.uom_id.category_id.id)]}
if not self.product_uom or (self.product_id.uom_id.id != self.product_uom.id):
vals['product_uom'] = self.product_id.uom_id
vals['product_uom_qty'] = 1.0
product = self.product_id.with_context(
lang=self.order_id.partner_id.lang,
partner=self.order_id.partner_id.id,
quantity=vals.get('product_uom_qty') or self.product_uom_qty,
date=self.order_id.date_order,
pricelist=self.order_id.pricelist_id.id,
uom=self.product_uom.id
)
product.list_price = self._compute_m2_price() or product.list_price
result = {'domain': domain}
warning = {}
if product.sale_line_warn != 'no-message':
title = _("Warning for %s") % product.name
message = product.sale_line_warn_msg
warning['title'] = title
warning['message'] = message
result = {'warning': warning}
if product.sale_line_warn == 'block':
self.product_id = False
return result
name = product.name_get()[0][1]
if product.description_sale:
name += '\n' + product.description_sale
vals['name'] = name
self._compute_tax_id()
if self.order_id.pricelist_id and self.order_id.partner_id:
vals['price_unit'] = self.env['account.tax']._fix_tax_included_price_company(
self._get_display_price(product), product.taxes_id, self.tax_id, self.company_id)
self.update(vals)
return result
Error when opening Sales Order :
Odoo Server Error
Traceback (most recent call last): File "/odoo/odoo-server/odoo/tools/cache.py", line 85, in lookup r = d[key] File "/odoo/odoo-server/odoo/tools/func.py", line 69, in wrapper return func(self, *args, **kwargs) File "/odoo/odoo-server/odoo/tools/lru.py", line 44, in __getitem__ a = self.d[obj].me KeyError: ('ir.model.data', <function IrModelData.xmlid_lookup at 0x7fd07ab18158>, 'area_based_price.product_uom_m2') During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/odoo/odoo-server/odoo/http.py", line 624, in _handle_exception return super(JsonRequest, self)._handle_exception(exception) File "/odoo/odoo-server/odoo/http.py", line 310, in _handle_exception raise pycompat.reraise(type(exception), exception, sys.exc_info()[2]) File "/odoo/odoo-server/odoo/tools/pycompat.py", line 14, in reraise raise value File "/odoo/odoo-server/odoo/http.py", line 669, in dispatch result = self._call_function(**self.params) File "/odoo/odoo-server/odoo/http.py", line 350, in _call_function return checked_call(self.db, *args, **kwargs) File "/odoo/odoo-server/odoo/service/model.py", line 94, in wrapper return f(dbname, *args, **kwargs) File "/odoo/odoo-server/odoo/http.py", line 339, in checked_call result = self.endpoint(*a, **kw) File "/odoo/odoo-server/odoo/http.py", line 915, in __call__ return self.method(*args, **kw) File "/odoo/odoo-server/odoo/http.py", line 515, in response_wrap response = f(*args, **kw) File "/odoo/odoo-server/addons/web/controllers/main.py", line 1322, in call_kw return self._call_kw(model, method, args, kwargs) File "/odoo/odoo-server/addons/web/controllers/main.py", line 1314, in _call_kw return call_kw(request.env[model], method, args, kwargs) File "/odoo/odoo-server/odoo/api.py", line 387, in call_kw result = _call_kw_multi(method, model, args, kwargs) File "/odoo/odoo-server/odoo/api.py", line 374, in _call_kw_multi result = method(recs, *args, **kwargs) File "/odoo/odoo-server/odoo/models.py", line 6085, in onchange record._onchange_eval(name, field_onchange[name], result) File "/odoo/odoo-server/odoo/models.py", line 5886, in _onchange_eval method_res = method(self) File "/odoo/odoo-server/addons/area_based_price_13/models/sale.py", line 18, in _compute_measure if line.product_id.uom_id.id is self.env.ref('area_based_price.product_uom_m2').id: File "/odoo/odoo-server/odoo/api.py", line 501, in ref return self['ir.model.data'].xmlid_to_object(xml_id, raise_if_not_found=raise_if_not_found) File "/odoo/odoo-server/odoo/addons/base/models/ir_model.py", line 1697, in xmlid_to_object t = self.xmlid_to_res_model_res_id(xmlid, raise_if_not_found) File "/odoo/odoo-server/odoo/addons/base/models/ir_model.py", line 1681, in xmlid_to_res_model_res_id return self.xmlid_lookup(xmlid)[1:3] File "<decorator-gen-25>", line 2, in xmlid_lookup File "/odoo/odoo-server/odoo/tools/cache.py", line 90, in lookup value = d[key] = self.method(*args, **kwargs) File "/odoo/odoo-server/odoo/addons/base/models/ir_model.py", line 1670, in xmlid_lookup raise ValueError('External ID not found in the system: %s' % xmlid) ValueError: External ID not found in the system: area_based_price.product_uom_m2
I can send you the entire solution if you require - but basically this is what the error is.