Pricing matrix

This commit is contained in:
2026-05-25 09:04:24 +02:00
parent 1e5611f726
commit ddca542bfc
7 changed files with 315 additions and 57 deletions

View File

@@ -709,25 +709,121 @@ class Component(ModelSQL, ModelView):
triggers = fields.One2Many('pricing.trigger','component',"Period rules")
pricing_date = fields.Date("Pricing date max")
def get_rec_name(self, name=None):
if self.price_index:
return '[' + self.fix_type.name + '] ' + self.price_index.price_index
else:
return '[' + self.fix_type.name + '] '
def get_cur(self,name):
if self.price_index:
PI = Pool().get('price.price')
pi = PI(self.price_index)
return pi.price_currency
def get_nbdays(self, name):
days = 0
if self.triggers:
for t in self.triggers:
l,l2 = t.getApplicationListDates(self.calendar)
days += len(l)
return days
def get_rec_name(self, name=None):
if self.price_index:
return '[' + self.fix_type.name + '] ' + self.price_index.price_index
if self.price_matrix:
return '[' + self.fix_type.name + '] ' + self.price_matrix.name
else:
return '[' + self.fix_type.name + '] '
def get_cur(self,name):
if self.price_index:
PI = Pool().get('price.price')
pi = PI(self.price_index)
return pi.price_currency
if self.price_matrix:
return self.price_matrix.currency
def get_calendar(self):
if self.calendar:
return self.calendar
if self.price_matrix:
return self.price_matrix.calendar
@staticmethod
def _record_id(record):
return getattr(record, 'id', record)
@classmethod
def _matches_optional_field(cls, matrix_line, field_name, target):
value = getattr(matrix_line, field_name, None)
if not value:
return True, 0
if target and cls._record_id(value) == cls._record_id(target):
return True, 1
return False, 0
def _matrix_valid_on(self, price_date):
if not self.price_matrix:
return False
if hasattr(price_date, 'date'):
price_date = price_date.date()
valid_from = getattr(self.price_matrix, 'valid_from', None)
valid_to = getattr(self.price_matrix, 'valid_to', None)
if valid_from and price_date < valid_from:
return False
if valid_to and price_date > valid_to:
return False
return True
def _get_matrix_owner_values(self):
line = getattr(self, 'line', None) or getattr(self, 'sale_line', None)
document = getattr(line, 'purchase', None) or getattr(line, 'sale', None)
return {
'origin': getattr(document, 'from_location', None),
'destination': getattr(document, 'to_location', None),
'product': getattr(line, 'product', None),
'quality': getattr(line, 'quality', None),
}
def _get_matrix_line(self):
MatrixLine = Pool().get('price.matrix.line')
lines = MatrixLine.search([('matrix', '=', self.price_matrix.id)])
owner_values = self._get_matrix_owner_values()
best_line = None
best_score = -1
for line in lines:
score = 0
for field_name, target in owner_values.items():
matches, field_score = self._matches_optional_field(
line, field_name, target)
if not matches:
break
score += field_score
else:
if score > best_score:
best_line = line
best_score = score
return best_line
def _convert_matrix_price(self, price, unit, currency):
price_qt = Decimal(str(price or 0))
matrix_unit = getattr(self.price_matrix, 'unit', None)
matrix_currency = getattr(self.price_matrix, 'currency', None)
if matrix_unit and unit:
Uom = Pool().get('product.uom')
price_qt *= Decimal(str(
Uom.compute_qty(unit, float(1), matrix_unit)))
if matrix_currency and currency and currency != matrix_currency:
Currency = Pool().get('currency.currency')
rates = Currency._get_rate([matrix_currency])
rate = rates.get(matrix_currency.id)
if rate:
price_qt *= Decimal(str(rate))
return round(price_qt, 4)
def get_price(self, price_date, unit, currency, last=False):
if self.price_source_type == 'curve' and self.price_index:
PI = Pool().get('price.price')
pi = PI(self.price_index)
return pi.get_price(price_date, unit, currency, last)
if self.price_source_type == 'matrix' and self.price_matrix:
if not self._matrix_valid_on(price_date):
return Decimal(0)
line = self._get_matrix_line()
if line:
return self._convert_matrix_price(
line.price_value, unit, currency)
return Decimal(0)
def get_nbdays(self, name):
days = 0
if self.triggers:
for t in self.triggers:
l,l2 = t.getApplicationListDates(self.get_calendar())
days += len(l)
return days
@classmethod
def delete(cls, components):
@@ -1171,17 +1267,20 @@ class Trigger(ModelSQL,ModelView):
current_date += datetime.timedelta(days=1)
return l, lprice
def getprice(self,current_date):
PI = Pool().get('price.price')
PC = Pool().get('pricing.component')
pc = PC(self.component)
pi = PI(pc.price_index)
val = {}
val['date'] = current_date
val['price'] = pi.get_price(current_date,pc.line.unit if pc.line else pc.sale_line.unit,pc.line.currency if pc.line else pc.sale_line.currency,self.last)
val['avg'] = val['price']
val['avg_minus_1'] = val['price']
val['isAvg'] = self.average
def getprice(self,current_date):
PC = Pool().get('pricing.component')
pc = PC(self.component)
val = {}
val['date'] = current_date
line = pc.line if pc.line else pc.sale_line
val['price'] = pc.get_price(
current_date,
line.unit,
line.currency,
self.last)
val['avg'] = val['price']
val['avg_minus_1'] = val['price']
val['isAvg'] = self.average
return val
class Period(ModelSQL,ModelView):