01.04.26
This commit is contained in:
@@ -92,6 +92,18 @@ class PurchaseTradeTestCase(ModuleTestCase):
|
|||||||
valuation_module.Valuation._get_strategy_mtm_price(strategy, line),
|
valuation_module.Valuation._get_strategy_mtm_price(strategy, line),
|
||||||
Decimal('100.0000'))
|
Decimal('100.0000'))
|
||||||
|
|
||||||
|
def test_sale_line_is_unmatched_checks_lot_links(self):
|
||||||
|
'sale line unmatched helper ignores empty matches and detects linked purchases'
|
||||||
|
sale_line = Mock()
|
||||||
|
sale_line.get_matched_lines.return_value = []
|
||||||
|
self.assertTrue(
|
||||||
|
valuation_module.ValuationProcess._sale_line_is_unmatched(sale_line))
|
||||||
|
|
||||||
|
linked = Mock(lot_p=Mock(line=Mock()))
|
||||||
|
sale_line.get_matched_lines.return_value = [linked]
|
||||||
|
self.assertFalse(
|
||||||
|
valuation_module.ValuationProcess._sale_line_is_unmatched(sale_line))
|
||||||
|
|
||||||
def test_parse_numbers_supports_inline_and_legacy_separators(self):
|
def test_parse_numbers_supports_inline_and_legacy_separators(self):
|
||||||
'parse_numbers keeps supporting inline entry and legacy separators'
|
'parse_numbers keeps supporting inline entry and legacy separators'
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
|||||||
@@ -107,7 +107,31 @@ class ValuationBase(ModelSQL):
|
|||||||
ValuationLine.delete(valuation_lines)
|
ValuationLine.delete(valuation_lines)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _base_pnl(cls, *, line, lot, pnl_type, sale=None):
|
def _delete_existing_sale_line(cls, sale_line, selected_types=None):
|
||||||
|
Date = Pool().get('ir.date')
|
||||||
|
Valuation = Pool().get('valuation.valuation')
|
||||||
|
ValuationLine = Pool().get('valuation.valuation.line')
|
||||||
|
|
||||||
|
valuation_domain = [
|
||||||
|
('sale_line', '=', sale_line.id),
|
||||||
|
('date', '=', Date.today()),
|
||||||
|
]
|
||||||
|
valuation_line_domain = [('sale_line', '=', sale_line.id)]
|
||||||
|
|
||||||
|
if selected_types is not None:
|
||||||
|
valuation_domain.append(('type', 'in', list(selected_types)))
|
||||||
|
valuation_line_domain.append(('type', 'in', list(selected_types)))
|
||||||
|
|
||||||
|
valuations = Valuation.search(valuation_domain)
|
||||||
|
if valuations:
|
||||||
|
Valuation.delete(valuations)
|
||||||
|
|
||||||
|
valuation_lines = ValuationLine.search(valuation_line_domain)
|
||||||
|
if valuation_lines:
|
||||||
|
ValuationLine.delete(valuation_lines)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _base_pnl(cls, *, line, lot, pnl_type, sale=None, sale_line=None):
|
||||||
Date = Pool().get('ir.date')
|
Date = Pool().get('ir.date')
|
||||||
|
|
||||||
values = {
|
values = {
|
||||||
@@ -120,9 +144,22 @@ class ValuationBase(ModelSQL):
|
|||||||
|
|
||||||
if sale:
|
if sale:
|
||||||
values['sale'] = sale.id
|
values['sale'] = sale.id
|
||||||
|
if sale_line:
|
||||||
|
values['sale_line'] = sale_line.id
|
||||||
|
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _base_sale_pnl(cls, *, sale_line, lot, pnl_type):
|
||||||
|
Date = Pool().get('ir.date')
|
||||||
|
return {
|
||||||
|
'sale': sale_line.sale.id,
|
||||||
|
'sale_line': sale_line.id,
|
||||||
|
'type': pnl_type,
|
||||||
|
'date': Date.today(),
|
||||||
|
'lot': lot.id,
|
||||||
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_strategy_mtm_price(cls, strategy, line):
|
def _get_strategy_mtm_price(cls, strategy, line):
|
||||||
total = Decimal(0)
|
total = Decimal(0)
|
||||||
@@ -156,6 +193,7 @@ class ValuationBase(ModelSQL):
|
|||||||
line=line,
|
line=line,
|
||||||
lot=lot,
|
lot=lot,
|
||||||
sale=sale_line.sale if sale_line else None,
|
sale=sale_line.sale if sale_line else None,
|
||||||
|
sale_line=sale_line if sale_line else None,
|
||||||
pnl_type='sale priced' if sale_line else 'pur. priced'
|
pnl_type='sale priced' if sale_line else 'pur. priced'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -217,6 +255,7 @@ class ValuationBase(ModelSQL):
|
|||||||
line=line,
|
line=line,
|
||||||
lot=lot,
|
lot=lot,
|
||||||
sale=sale_line.sale if sale_line else None,
|
sale=sale_line.sale if sale_line else None,
|
||||||
|
sale_line=sale_line if sale_line else None,
|
||||||
pnl_type=pnl_type
|
pnl_type=pnl_type
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -350,6 +389,139 @@ class ValuationBase(ModelSQL):
|
|||||||
|
|
||||||
return price_lines
|
return price_lines
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _build_basis_pnl_from_sale_line(cls, *, sale_line, lot, pc):
|
||||||
|
Currency = Pool().get('currency.currency')
|
||||||
|
Date = Pool().get('ir.date')
|
||||||
|
values = cls._base_sale_pnl(
|
||||||
|
sale_line=sale_line,
|
||||||
|
lot=lot,
|
||||||
|
pnl_type='sale priced'
|
||||||
|
)
|
||||||
|
|
||||||
|
qty = lot.get_current_quantity_converted()
|
||||||
|
price = pc.price
|
||||||
|
|
||||||
|
values.update({
|
||||||
|
'reference': f"{pc.get_name()} / {pc.ratio}%",
|
||||||
|
'price': round(price, 4),
|
||||||
|
'counterparty': sale_line.sale.party.id,
|
||||||
|
'product': sale_line.product.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
if pc.unfixed_qt == 0:
|
||||||
|
values['state'] = 'fixed'
|
||||||
|
elif pc.fixed_qt == 0:
|
||||||
|
values['state'] = 'unfixed'
|
||||||
|
else:
|
||||||
|
base = sale_line.quantity_theorical
|
||||||
|
values['state'] = f"part. fixed {round(pc.fixed_qt / Decimal(base) * 100, 0)}%"
|
||||||
|
|
||||||
|
if price is not None:
|
||||||
|
amount = round(price * qty, 2)
|
||||||
|
base_amount = amount
|
||||||
|
currency = sale_line.sale.currency.id
|
||||||
|
rate = Decimal(1)
|
||||||
|
if sale_line.sale.company.currency != currency:
|
||||||
|
with Transaction().set_context(date=Date.today()):
|
||||||
|
base_amount = Currency.compute(
|
||||||
|
currency, amount, sale_line.sale.company.currency)
|
||||||
|
rate = round(amount / (base_amount if base_amount else 1), 6)
|
||||||
|
values.update({
|
||||||
|
'quantity': round(qty, 5),
|
||||||
|
'amount': amount,
|
||||||
|
'base_amount': base_amount,
|
||||||
|
'rate': rate,
|
||||||
|
'mtm_price': None,
|
||||||
|
'mtm': None,
|
||||||
|
'unit': sale_line.unit.id,
|
||||||
|
'currency': currency,
|
||||||
|
})
|
||||||
|
return values
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _build_simple_pnl_from_sale_line(cls, *, sale_line, lot, price, state, pnl_type):
|
||||||
|
Currency = Pool().get('currency.currency')
|
||||||
|
Date = Pool().get('ir.date')
|
||||||
|
values = cls._base_sale_pnl(
|
||||||
|
sale_line=sale_line,
|
||||||
|
lot=lot,
|
||||||
|
pnl_type=pnl_type
|
||||||
|
)
|
||||||
|
|
||||||
|
qty = lot.get_current_quantity_converted()
|
||||||
|
amount = round(price * qty, 2)
|
||||||
|
base_amount = amount
|
||||||
|
currency = sale_line.sale.currency.id
|
||||||
|
company_currency = sale_line.sale.company.currency
|
||||||
|
rate = Decimal(1)
|
||||||
|
if sale_line.sale.company.currency != currency:
|
||||||
|
with Transaction().set_context(date=Date.today()):
|
||||||
|
base_amount = Currency.compute(currency, amount, company_currency)
|
||||||
|
if base_amount and amount:
|
||||||
|
rate = round(amount / base_amount, 6)
|
||||||
|
|
||||||
|
values.update({
|
||||||
|
'price': round(price, 4),
|
||||||
|
'quantity': round(qty, 5),
|
||||||
|
'amount': amount,
|
||||||
|
'base_amount': base_amount,
|
||||||
|
'rate': rate,
|
||||||
|
'mtm_price': None,
|
||||||
|
'mtm': Decimal(0),
|
||||||
|
'state': state,
|
||||||
|
'unit': sale_line.unit.id,
|
||||||
|
'currency': currency,
|
||||||
|
'counterparty': sale_line.sale.party.id,
|
||||||
|
'product': sale_line.product.id,
|
||||||
|
'reference': 'Sale/Physic' if lot.lot_type == 'physic' else 'Sale/Open',
|
||||||
|
})
|
||||||
|
|
||||||
|
return values
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_pnl_price_from_sale_line(cls, sale_line):
|
||||||
|
price_lines = []
|
||||||
|
|
||||||
|
for lot in sale_line.lots or []:
|
||||||
|
if sale_line.price_type == 'basis':
|
||||||
|
for pc in sale_line.price_summary or []:
|
||||||
|
values = cls._build_basis_pnl_from_sale_line(
|
||||||
|
sale_line=sale_line, lot=lot, pc=pc)
|
||||||
|
if sale_line.mtm:
|
||||||
|
for strat in sale_line.mtm:
|
||||||
|
values['mtm_price'] = cls._get_strategy_mtm_price(strat, sale_line)
|
||||||
|
values['mtm'] = strat.get_mtm(sale_line, values['quantity'])
|
||||||
|
values['strategy'] = strat
|
||||||
|
|
||||||
|
if values:
|
||||||
|
price_lines.append(values)
|
||||||
|
else:
|
||||||
|
if values:
|
||||||
|
price_lines.append(values)
|
||||||
|
|
||||||
|
elif sale_line.price_type in ('priced', 'efp') and lot.lot_price_sale:
|
||||||
|
values = cls._build_simple_pnl_from_sale_line(
|
||||||
|
sale_line=sale_line,
|
||||||
|
lot=lot,
|
||||||
|
price=lot.lot_price_sale,
|
||||||
|
state='fixed' if sale_line.price_type == 'priced' else 'not fixed',
|
||||||
|
pnl_type=f'sale {sale_line.price_type}'
|
||||||
|
)
|
||||||
|
if sale_line.mtm:
|
||||||
|
for strat in sale_line.mtm:
|
||||||
|
values['mtm_price'] = cls._get_strategy_mtm_price(strat, sale_line)
|
||||||
|
values['mtm'] = strat.get_mtm(sale_line, values['quantity'])
|
||||||
|
values['strategy'] = strat
|
||||||
|
|
||||||
|
if values:
|
||||||
|
price_lines.append(values)
|
||||||
|
else:
|
||||||
|
if values:
|
||||||
|
price_lines.append(values)
|
||||||
|
|
||||||
|
return price_lines
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def group_fees_by_type_supplier(cls,line,fees):
|
def group_fees_by_type_supplier(cls,line,fees):
|
||||||
grouped = defaultdict(list)
|
grouped = defaultdict(list)
|
||||||
@@ -454,6 +626,88 @@ class ValuationBase(ModelSQL):
|
|||||||
|
|
||||||
return fee_lines
|
return fee_lines
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_pnl_fee_from_sale_line(cls, sale_line):
|
||||||
|
fee_lines = []
|
||||||
|
Date = Pool().get('ir.date')
|
||||||
|
Currency = Pool().get('currency.currency')
|
||||||
|
FeeLots = Pool().get('fee.lots')
|
||||||
|
|
||||||
|
for lot in sale_line.lots or ():
|
||||||
|
fl = FeeLots.search([('lot', '=', lot.id)])
|
||||||
|
if not fl:
|
||||||
|
continue
|
||||||
|
|
||||||
|
fees = [
|
||||||
|
e.fee for e in fl
|
||||||
|
if e.fee and (not e.fee.sale_line or e.fee.sale_line.id == sale_line.id)
|
||||||
|
]
|
||||||
|
for sf in cls.group_fees_by_type_supplier(sale_line, fees):
|
||||||
|
sign = -1 if sf.p_r == 'pay' else 1
|
||||||
|
qty = round(lot.get_current_quantity_converted(), 5)
|
||||||
|
if sf.mode == 'ppack' or sf.mode == 'rate':
|
||||||
|
price = sf.price
|
||||||
|
amount = sf.amount * sign
|
||||||
|
elif sf.mode == 'lumpsum':
|
||||||
|
price = sf.price
|
||||||
|
amount = sf.price * sign
|
||||||
|
qty = 1
|
||||||
|
else:
|
||||||
|
price = Decimal(sf.get_price_per_qt())
|
||||||
|
amount = round(price * lot.get_current_quantity_converted() * sign, 2)
|
||||||
|
if sf.currency != sale_line.sale.currency:
|
||||||
|
with Transaction().set_context(date=Date.today()):
|
||||||
|
price = Currency.compute(sf.currency, price, sale_line.sale.currency)
|
||||||
|
if sale_line.mtm:
|
||||||
|
for strat in sale_line.mtm:
|
||||||
|
fee_lines.append({
|
||||||
|
'lot': lot.id,
|
||||||
|
'sale': sale_line.sale.id,
|
||||||
|
'sale_line': sale_line.id,
|
||||||
|
'type': (
|
||||||
|
'shipment fee' if sf.shipment_in
|
||||||
|
else 'sale fee'
|
||||||
|
),
|
||||||
|
'date': Date.today(),
|
||||||
|
'price': price,
|
||||||
|
'counterparty': sf.supplier.id,
|
||||||
|
'reference': f"{sf.product.name}/{'Physic' if lot.lot_type == 'physic' else 'Open'}",
|
||||||
|
'product': sf.product.id,
|
||||||
|
'state': sf.type,
|
||||||
|
'quantity': qty,
|
||||||
|
'amount': amount,
|
||||||
|
'mtm_price': cls._get_strategy_mtm_price(strat, sale_line),
|
||||||
|
'mtm': strat.get_mtm(sale_line, qty),
|
||||||
|
'strategy': strat,
|
||||||
|
'unit': sf.unit.id if sf.unit else sale_line.unit.id,
|
||||||
|
'currency': sf.currency.id,
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
fee_lines.append({
|
||||||
|
'lot': lot.id,
|
||||||
|
'sale': sale_line.sale.id,
|
||||||
|
'sale_line': sale_line.id,
|
||||||
|
'type': (
|
||||||
|
'shipment fee' if sf.shipment_in
|
||||||
|
else 'sale fee'
|
||||||
|
),
|
||||||
|
'date': Date.today(),
|
||||||
|
'price': price,
|
||||||
|
'counterparty': sf.supplier.id,
|
||||||
|
'reference': f"{sf.product.name}/{'Physic' if lot.lot_type == 'physic' else 'Open'}",
|
||||||
|
'product': sf.product.id,
|
||||||
|
'state': sf.type,
|
||||||
|
'quantity': qty,
|
||||||
|
'amount': amount,
|
||||||
|
'mtm_price': None,
|
||||||
|
'mtm': Decimal(0),
|
||||||
|
'strategy': None,
|
||||||
|
'unit': sf.unit.id if sf.unit else sale_line.unit.id,
|
||||||
|
'currency': sf.currency.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
return fee_lines
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_pnl_der_from_line(cls, line):
|
def create_pnl_der_from_line(cls, line):
|
||||||
Date = Pool().get('ir.date')
|
Date = Pool().get('ir.date')
|
||||||
@@ -488,6 +742,40 @@ class ValuationBase(ModelSQL):
|
|||||||
|
|
||||||
return der_lines
|
return der_lines
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_pnl_der_from_sale_line(cls, sale_line):
|
||||||
|
Date = Pool().get('ir.date')
|
||||||
|
der_lines = []
|
||||||
|
|
||||||
|
for d in sale_line.derivatives or []:
|
||||||
|
price = Decimal(d.price_index.get_price_per_qt(
|
||||||
|
d.price, sale_line.unit, sale_line.sale.currency
|
||||||
|
))
|
||||||
|
|
||||||
|
mtm_price = Decimal(d.price_index.get_price(
|
||||||
|
Date.today(), sale_line.unit, sale_line.sale.currency, True
|
||||||
|
))
|
||||||
|
|
||||||
|
der_lines.append({
|
||||||
|
'sale': sale_line.sale.id,
|
||||||
|
'sale_line': sale_line.id,
|
||||||
|
'type': 'derivative',
|
||||||
|
'date': Date.today(),
|
||||||
|
'reference': d.price_index.price_index,
|
||||||
|
'price': round(price, 4),
|
||||||
|
'counterparty': d.party.id,
|
||||||
|
'product': d.product.id,
|
||||||
|
'state': 'fixed',
|
||||||
|
'quantity': round(d.quantity, 5),
|
||||||
|
'amount': round(price * d.quantity * Decimal(-1), 2),
|
||||||
|
'mtm_price': round(mtm_price, 4),
|
||||||
|
'mtm': round((price * d.quantity * Decimal(-1)) - (mtm_price * d.quantity * Decimal(-1)), 2),
|
||||||
|
'unit': sale_line.unit.id,
|
||||||
|
'currency': sale_line.sale.currency.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
return der_lines
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate(cls, line, valuation_type='all'):
|
def generate(cls, line, valuation_type='all'):
|
||||||
selected_types = cls._get_generate_types(valuation_type)
|
selected_types = cls._get_generate_types(valuation_type)
|
||||||
@@ -504,6 +792,22 @@ class ValuationBase(ModelSQL):
|
|||||||
Valuation.create(values)
|
Valuation.create(values)
|
||||||
ValuationLine.create(values)
|
ValuationLine.create(values)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def generate_from_sale_line(cls, sale_line, valuation_type='all'):
|
||||||
|
selected_types = cls._get_generate_types(valuation_type)
|
||||||
|
cls._delete_existing_sale_line(sale_line, selected_types=selected_types)
|
||||||
|
values = []
|
||||||
|
values.extend(cls.create_pnl_fee_from_sale_line(sale_line))
|
||||||
|
values.extend(cls.create_pnl_price_from_sale_line(sale_line))
|
||||||
|
values.extend(cls.create_pnl_der_from_sale_line(sale_line))
|
||||||
|
values = cls._filter_values_by_types(values, selected_types)
|
||||||
|
|
||||||
|
if values:
|
||||||
|
Valuation = Pool().get('valuation.valuation')
|
||||||
|
ValuationLine = Pool().get('valuation.valuation.line')
|
||||||
|
Valuation.create(values)
|
||||||
|
ValuationLine.create(values)
|
||||||
|
|
||||||
class Valuation(ValuationBase, ModelView):
|
class Valuation(ValuationBase, ModelView):
|
||||||
"Valuation"
|
"Valuation"
|
||||||
__name__ = 'valuation.valuation'
|
__name__ = 'valuation.valuation'
|
||||||
@@ -855,6 +1159,52 @@ class ValuationProcess(Wizard):
|
|||||||
purchase_line_ids.add(matched_line.lot_p.line.id)
|
purchase_line_ids.add(matched_line.lot_p.line.id)
|
||||||
return purchase_line_ids
|
return purchase_line_ids
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _sale_line_is_unmatched(cls, sale_line):
|
||||||
|
for matched_line in sale_line.get_matched_lines() or []:
|
||||||
|
if matched_line.lot_p and matched_line.lot_p.line:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _sale_line_ids_from_sale_ids(cls, sale_ids, unmatched_only=False):
|
||||||
|
if not sale_ids:
|
||||||
|
return set()
|
||||||
|
SaleLine = Pool().get('sale.line')
|
||||||
|
sale_lines = SaleLine.search([('sale', 'in', list(sale_ids))])
|
||||||
|
if unmatched_only:
|
||||||
|
sale_lines = [
|
||||||
|
sale_line for sale_line in sale_lines
|
||||||
|
if cls._sale_line_is_unmatched(sale_line)
|
||||||
|
]
|
||||||
|
return {sale_line.id for sale_line in sale_lines}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_target_sale_line_ids(cls, start):
|
||||||
|
Sale = Pool().get('sale.sale')
|
||||||
|
dimension_filters = cls._get_dimension_filters(start)
|
||||||
|
has_purchase_filters = bool(
|
||||||
|
start.purchase_from_date
|
||||||
|
or start.purchase_to_date
|
||||||
|
or cls._parse_numbers(start.purchase_numbers)
|
||||||
|
)
|
||||||
|
has_sale_filters = bool(
|
||||||
|
start.sale_from_date
|
||||||
|
or start.sale_to_date
|
||||||
|
or cls._parse_numbers(start.sale_numbers)
|
||||||
|
)
|
||||||
|
|
||||||
|
if has_sale_filters:
|
||||||
|
sale_ids = cls._search_sale_ids(start, dimension_filters)
|
||||||
|
return cls._sale_line_ids_from_sale_ids(sale_ids, unmatched_only=True)
|
||||||
|
if dimension_filters and not has_purchase_filters:
|
||||||
|
sale_ids = cls._search_sale_ids(start, dimension_filters)
|
||||||
|
return cls._sale_line_ids_from_sale_ids(sale_ids, unmatched_only=True)
|
||||||
|
if not has_purchase_filters and not has_sale_filters and not dimension_filters:
|
||||||
|
sale_ids = {sale.id for sale in Sale.search([])}
|
||||||
|
return cls._sale_line_ids_from_sale_ids(sale_ids, unmatched_only=True)
|
||||||
|
return set()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_target_purchase_line_ids(cls, start):
|
def _get_target_purchase_line_ids(cls, start):
|
||||||
PurchaseLine = Pool().get('purchase.line')
|
PurchaseLine = Pool().get('purchase.line')
|
||||||
@@ -899,8 +1249,11 @@ class ValuationProcess(Wizard):
|
|||||||
|
|
||||||
def transition_process(self):
|
def transition_process(self):
|
||||||
PurchaseLine = Pool().get('purchase.line')
|
PurchaseLine = Pool().get('purchase.line')
|
||||||
|
SaleLine = Pool().get('sale.line')
|
||||||
target_ids = self._get_target_purchase_line_ids(self.start)
|
target_ids = self._get_target_purchase_line_ids(self.start)
|
||||||
|
target_sale_line_ids = self._get_target_sale_line_ids(self.start)
|
||||||
lines = PurchaseLine.browse(list(target_ids))
|
lines = PurchaseLine.browse(list(target_ids))
|
||||||
|
sale_lines = SaleLine.browse(list(target_sale_line_ids))
|
||||||
purchase_ids = {line.purchase.id for line in lines if line.purchase}
|
purchase_ids = {line.purchase.id for line in lines if line.purchase}
|
||||||
sale_ids = set()
|
sale_ids = set()
|
||||||
for line in lines:
|
for line in lines:
|
||||||
@@ -910,10 +1263,16 @@ class ValuationProcess(Wizard):
|
|||||||
|
|
||||||
Valuation.generate(line, valuation_type=self.start.valuation_type)
|
Valuation.generate(line, valuation_type=self.start.valuation_type)
|
||||||
|
|
||||||
|
for sale_line in sale_lines:
|
||||||
|
sale_ids.add(sale_line.sale.id)
|
||||||
|
Valuation.generate_from_sale_line(
|
||||||
|
sale_line, valuation_type=self.start.valuation_type)
|
||||||
|
|
||||||
self._result_message = (
|
self._result_message = (
|
||||||
f"Processed {len(lines)} purchase line(s) "
|
f"Processed {len(lines)} purchase line(s) "
|
||||||
|
f"and {len(sale_lines)} unmatched sale line(s) "
|
||||||
f"from {len(purchase_ids)} purchase(s) "
|
f"from {len(purchase_ids)} purchase(s) "
|
||||||
f"and {len(sale_ids)} linked sale(s)."
|
f"and {len(sale_ids)} sale(s)."
|
||||||
)
|
)
|
||||||
return 'result'
|
return 'result'
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user