GR
This commit is contained in:
@@ -64,6 +64,10 @@ def register():
|
||||
ctrm_reporting.CTRMFinancialPositionContext,
|
||||
ctrm_reporting.CTRMNetPosition,
|
||||
ctrm_reporting.CTRMNetPositionContext,
|
||||
ctrm_reporting.CTRMRealizedPnl,
|
||||
ctrm_reporting.CTRMRealizedPnlContext,
|
||||
ctrm_reporting.CTRMMtmPnl,
|
||||
ctrm_reporting.CTRMMtmPnlContext,
|
||||
configuration.Configuration,
|
||||
pricing.ImportPricesStart,
|
||||
pricing.ImportPricesResult,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from sql import Literal
|
||||
from sql import Literal, Null
|
||||
from sql.aggregate import Max, Min, Sum
|
||||
from sql.conditionals import Case, Coalesce
|
||||
from sql.functions import CurrentTimestamp
|
||||
@@ -21,6 +21,7 @@ PHYSICAL_VALUATION_TYPES = [
|
||||
'market',
|
||||
]
|
||||
DERIVATIVE_VALUATION_TYPES = ['derivative']
|
||||
ALL_VALUATION_TYPES = PHYSICAL_VALUATION_TYPES + DERIVATIVE_VALUATION_TYPES
|
||||
|
||||
|
||||
class CTRMValuationContextMixin:
|
||||
@@ -308,3 +309,249 @@ class CTRMNetPosition(ModelSQL, ModelView):
|
||||
Sum(Coalesce(val.mtm, 0)).as_('mtm'),
|
||||
where=where,
|
||||
group_by=group_by)
|
||||
|
||||
|
||||
class CTRMPnlContextMixin:
|
||||
date = fields.Date("Valuation Date")
|
||||
product = fields.Many2One('product.product', "Product")
|
||||
counterparty = fields.Many2One('party.party', "Counterparty")
|
||||
currency = fields.Many2One('currency.currency', "Currency")
|
||||
purchase = fields.Many2One('purchase.purchase', "Purchase")
|
||||
sale = fields.Many2One('sale.sale', "Sale")
|
||||
strategy = fields.Many2One('mtm.strategy', "Strategy")
|
||||
state = fields.Char("State")
|
||||
|
||||
@classmethod
|
||||
def default_date(cls):
|
||||
Date = Pool().get('ir.date')
|
||||
return Date.today()
|
||||
|
||||
|
||||
class CTRMRealizedPnlContext(CTRMPnlContextMixin, ModelView):
|
||||
"CTRM Realized P&L Context"
|
||||
__name__ = 'ctrm.reporting.pnl.realized.context'
|
||||
|
||||
realization = fields.Selection([
|
||||
('purchase_and_sale_invoiced', 'Purchase and Sale Invoiced'),
|
||||
('sale_invoiced', 'Sale Invoiced'),
|
||||
('purchase_invoiced', 'Purchase Invoiced'),
|
||||
('all_valued', 'All Valued Lines'),
|
||||
], "Realization")
|
||||
|
||||
@classmethod
|
||||
def default_realization(cls):
|
||||
return 'purchase_and_sale_invoiced'
|
||||
|
||||
|
||||
class CTRMRealizedPnl(ModelSQL, ModelView):
|
||||
"CTRM Realized P&L"
|
||||
__name__ = 'ctrm.reporting.pnl.realized'
|
||||
|
||||
valuation_date = fields.Date("Valuation Date")
|
||||
lot = fields.Many2One('lot.lot', "Lot")
|
||||
purchase = fields.Many2One('purchase.purchase', "Purchase")
|
||||
purchase_line = fields.Many2One('purchase.line', "Purchase Line")
|
||||
purchase_invoice = fields.Many2One('account.invoice', "Purchase Invoice")
|
||||
sale = fields.Many2One('sale.sale', "Sale")
|
||||
sale_line = fields.Many2One('sale.line', "Sale Line")
|
||||
sale_invoice = fields.Many2One('account.invoice', "Sale Invoice")
|
||||
type = fields.Selection([
|
||||
('priced', 'Price'),
|
||||
('pur. priced', 'Pur. price'),
|
||||
('pur. efp', 'Pur. efp'),
|
||||
('sale priced', 'Sale price'),
|
||||
('sale efp', 'Sale efp'),
|
||||
('line fee', 'Line fee'),
|
||||
('pur. fee', 'Pur. fee'),
|
||||
('sale fee', 'Sale fee'),
|
||||
('shipment fee', 'Shipment fee'),
|
||||
('market', 'Market'),
|
||||
('derivative', 'Derivative'),
|
||||
], "Type")
|
||||
reference = fields.Char("Reference")
|
||||
counterparty = fields.Many2One('party.party', "Counterparty")
|
||||
product = fields.Many2One('product.product', "Product")
|
||||
state = fields.Char("State")
|
||||
quantity = fields.Numeric("Quantity", digits=(16, 5))
|
||||
unit = fields.Many2One('product.uom', "Unit")
|
||||
currency = fields.Many2One('currency.currency', "Currency")
|
||||
amount = fields.Numeric("Amount", digits=(16, 2))
|
||||
base_amount = fields.Numeric("Base Amount", digits=(16, 2))
|
||||
strategy = fields.Many2One('mtm.strategy', "Strategy")
|
||||
|
||||
@classmethod
|
||||
def table_query(cls):
|
||||
ValuationLine = Pool().get('valuation.valuation.line')
|
||||
Lot = Pool().get('lot.lot')
|
||||
InvoiceLine = Pool().get('account.invoice.line')
|
||||
Invoice = Pool().get('account.invoice')
|
||||
|
||||
val = ValuationLine.__table__()
|
||||
lot = Lot.__table__()
|
||||
purchase_invoice_line = InvoiceLine.__table__()
|
||||
purchase_invoice = Invoice.__table__()
|
||||
sale_invoice_line = InvoiceLine.__table__()
|
||||
sale_invoice = Invoice.__table__()
|
||||
|
||||
context = Transaction().context
|
||||
realization = context.get(
|
||||
'realization', 'purchase_and_sale_invoiced')
|
||||
where = val.type.in_(ALL_VALUATION_TYPES)
|
||||
if context.get('date'):
|
||||
where &= val.date == context['date']
|
||||
if context.get('product'):
|
||||
where &= val.product == context['product']
|
||||
if context.get('counterparty'):
|
||||
where &= val.counterparty == context['counterparty']
|
||||
if context.get('currency'):
|
||||
where &= val.currency == context['currency']
|
||||
if context.get('purchase'):
|
||||
where &= val.purchase == context['purchase']
|
||||
if context.get('sale'):
|
||||
where &= val.sale == context['sale']
|
||||
if context.get('strategy'):
|
||||
where &= val.strategy == context['strategy']
|
||||
if context.get('state'):
|
||||
where &= val.state == context['state']
|
||||
|
||||
if realization == 'purchase_and_sale_invoiced':
|
||||
where &= lot.invoice_line != Null
|
||||
where &= lot.sale_invoice_line != Null
|
||||
elif realization == 'sale_invoiced':
|
||||
where &= lot.sale_invoice_line != Null
|
||||
elif realization == 'purchase_invoiced':
|
||||
where &= lot.invoice_line != Null
|
||||
|
||||
return (
|
||||
val
|
||||
.join(lot, 'LEFT', condition=lot.id == val.lot)
|
||||
.join(purchase_invoice_line, 'LEFT',
|
||||
condition=purchase_invoice_line.id == lot.invoice_line)
|
||||
.join(purchase_invoice, 'LEFT',
|
||||
condition=purchase_invoice.id == purchase_invoice_line.invoice)
|
||||
.join(sale_invoice_line, 'LEFT',
|
||||
condition=sale_invoice_line.id == lot.sale_invoice_line)
|
||||
.join(sale_invoice, 'LEFT',
|
||||
condition=sale_invoice.id == sale_invoice_line.invoice)
|
||||
.select(
|
||||
Literal(0).as_('create_uid'),
|
||||
CurrentTimestamp().as_('create_date'),
|
||||
Literal(None).as_('write_uid'),
|
||||
Literal(None).as_('write_date'),
|
||||
val.id.as_('id'),
|
||||
val.date.as_('valuation_date'),
|
||||
val.lot.as_('lot'),
|
||||
val.purchase.as_('purchase'),
|
||||
val.line.as_('purchase_line'),
|
||||
purchase_invoice.id.as_('purchase_invoice'),
|
||||
val.sale.as_('sale'),
|
||||
val.sale_line.as_('sale_line'),
|
||||
sale_invoice.id.as_('sale_invoice'),
|
||||
val.type.as_('type'),
|
||||
val.reference.as_('reference'),
|
||||
val.counterparty.as_('counterparty'),
|
||||
val.product.as_('product'),
|
||||
val.state.as_('state'),
|
||||
val.quantity.as_('quantity'),
|
||||
val.unit.as_('unit'),
|
||||
val.currency.as_('currency'),
|
||||
val.amount.as_('amount'),
|
||||
val.base_amount.as_('base_amount'),
|
||||
val.strategy.as_('strategy'),
|
||||
where=where))
|
||||
|
||||
|
||||
class CTRMMtmPnlContext(CTRMPnlContextMixin, ModelView):
|
||||
"CTRM Mark-to-Market Context"
|
||||
__name__ = 'ctrm.reporting.pnl.mtm.context'
|
||||
|
||||
|
||||
class CTRMMtmPnl(ModelSQL, ModelView):
|
||||
"CTRM Mark-to-Market"
|
||||
__name__ = 'ctrm.reporting.pnl.mtm'
|
||||
|
||||
valuation_date = fields.Date("Valuation Date")
|
||||
lot = fields.Many2One('lot.lot', "Lot")
|
||||
purchase = fields.Many2One('purchase.purchase', "Purchase")
|
||||
purchase_line = fields.Many2One('purchase.line', "Purchase Line")
|
||||
sale = fields.Many2One('sale.sale', "Sale")
|
||||
sale_line = fields.Many2One('sale.line', "Sale Line")
|
||||
type = fields.Selection([
|
||||
('priced', 'Price'),
|
||||
('pur. priced', 'Pur. price'),
|
||||
('pur. efp', 'Pur. efp'),
|
||||
('sale priced', 'Sale price'),
|
||||
('sale efp', 'Sale efp'),
|
||||
('line fee', 'Line fee'),
|
||||
('pur. fee', 'Pur. fee'),
|
||||
('sale fee', 'Sale fee'),
|
||||
('shipment fee', 'Shipment fee'),
|
||||
('market', 'Market'),
|
||||
('derivative', 'Derivative'),
|
||||
], "Type")
|
||||
reference = fields.Char("Reference")
|
||||
counterparty = fields.Many2One('party.party', "Counterparty")
|
||||
product = fields.Many2One('product.product', "Product")
|
||||
state = fields.Char("State")
|
||||
quantity = fields.Numeric("Quantity", digits=(16, 5))
|
||||
unit = fields.Many2One('product.uom', "Unit")
|
||||
price = fields.Numeric("Price", digits=(16, 4))
|
||||
mtm_price = fields.Numeric("MTM Price", digits=(16, 4))
|
||||
currency = fields.Many2One('currency.currency', "Currency")
|
||||
amount = fields.Numeric("Amount", digits=(16, 2))
|
||||
mtm = fields.Numeric("MTM", digits=(16, 2))
|
||||
mtm_delta = fields.Numeric("MTM Delta", digits=(16, 2))
|
||||
strategy = fields.Many2One('mtm.strategy', "Strategy")
|
||||
|
||||
@classmethod
|
||||
def table_query(cls):
|
||||
ValuationLine = Pool().get('valuation.valuation.line')
|
||||
val = ValuationLine.__table__()
|
||||
|
||||
context = Transaction().context
|
||||
where = val.type.in_(ALL_VALUATION_TYPES)
|
||||
if context.get('date'):
|
||||
where &= val.date == context['date']
|
||||
if context.get('product'):
|
||||
where &= val.product == context['product']
|
||||
if context.get('counterparty'):
|
||||
where &= val.counterparty == context['counterparty']
|
||||
if context.get('currency'):
|
||||
where &= val.currency == context['currency']
|
||||
if context.get('purchase'):
|
||||
where &= val.purchase == context['purchase']
|
||||
if context.get('sale'):
|
||||
where &= val.sale == context['sale']
|
||||
if context.get('strategy'):
|
||||
where &= val.strategy == context['strategy']
|
||||
if context.get('state'):
|
||||
where &= val.state == context['state']
|
||||
|
||||
return val.select(
|
||||
Literal(0).as_('create_uid'),
|
||||
CurrentTimestamp().as_('create_date'),
|
||||
Literal(None).as_('write_uid'),
|
||||
Literal(None).as_('write_date'),
|
||||
val.id.as_('id'),
|
||||
val.date.as_('valuation_date'),
|
||||
val.lot.as_('lot'),
|
||||
val.purchase.as_('purchase'),
|
||||
val.line.as_('purchase_line'),
|
||||
val.sale.as_('sale'),
|
||||
val.sale_line.as_('sale_line'),
|
||||
val.type.as_('type'),
|
||||
val.reference.as_('reference'),
|
||||
val.counterparty.as_('counterparty'),
|
||||
val.product.as_('product'),
|
||||
val.state.as_('state'),
|
||||
val.quantity.as_('quantity'),
|
||||
val.unit.as_('unit'),
|
||||
val.price.as_('price'),
|
||||
val.mtm_price.as_('mtm_price'),
|
||||
val.currency.as_('currency'),
|
||||
val.amount.as_('amount'),
|
||||
val.mtm.as_('mtm'),
|
||||
(Coalesce(val.mtm, 0) - Coalesce(val.amount, 0)).as_(
|
||||
'mtm_delta'),
|
||||
val.strategy.as_('strategy'),
|
||||
where=where)
|
||||
|
||||
@@ -60,6 +60,46 @@
|
||||
<field name="view" ref="ctrm_position_net_view_list"/>
|
||||
<field name="act_window" ref="act_ctrm_position_net"/>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="ctrm_pnl_realized_context_view_form">
|
||||
<field name="model">ctrm.reporting.pnl.realized.context</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">ctrm_pnl_realized_context_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="ctrm_pnl_realized_view_list">
|
||||
<field name="model">ctrm.reporting.pnl.realized</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">ctrm_pnl_realized_list</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window" id="act_ctrm_pnl_realized">
|
||||
<field name="name">Realized P&L</field>
|
||||
<field name="res_model">ctrm.reporting.pnl.realized</field>
|
||||
<field name="context_model">ctrm.reporting.pnl.realized.context</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_ctrm_pnl_realized_view">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="ctrm_pnl_realized_view_list"/>
|
||||
<field name="act_window" ref="act_ctrm_pnl_realized"/>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="ctrm_pnl_mtm_context_view_form">
|
||||
<field name="model">ctrm.reporting.pnl.mtm.context</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">ctrm_pnl_mtm_context_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="ctrm_pnl_mtm_view_list">
|
||||
<field name="model">ctrm.reporting.pnl.mtm</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">ctrm_pnl_mtm_list</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window" id="act_ctrm_pnl_mtm">
|
||||
<field name="name">Mark-to-Market</field>
|
||||
<field name="res_model">ctrm.reporting.pnl.mtm</field>
|
||||
<field name="context_model">ctrm.reporting.pnl.mtm.context</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_ctrm_pnl_mtm_view">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="ctrm_pnl_mtm_view_list"/>
|
||||
<field name="act_window" ref="act_ctrm_pnl_mtm"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
name="Positions"
|
||||
@@ -99,11 +139,13 @@
|
||||
name="Realized P&L"
|
||||
parent="menu_ctrm_pnl"
|
||||
sequence="10"
|
||||
action="act_ctrm_pnl_realized"
|
||||
id="menu_ctrm_pnl_realized"/>
|
||||
<menuitem
|
||||
name="Mark-to-Market"
|
||||
parent="menu_ctrm_pnl"
|
||||
sequence="20"
|
||||
action="act_ctrm_pnl_mtm"
|
||||
id="menu_ctrm_pnl_mtm"/>
|
||||
<menuitem
|
||||
name="P&L Explain"
|
||||
|
||||
18
modules/purchase_trade/view/ctrm_pnl_mtm_context_form.xml
Normal file
18
modules/purchase_trade/view/ctrm_pnl_mtm_context_form.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<form>
|
||||
<label name="date"/>
|
||||
<field name="date"/>
|
||||
<label name="product"/>
|
||||
<field name="product"/>
|
||||
<label name="counterparty"/>
|
||||
<field name="counterparty"/>
|
||||
<label name="currency"/>
|
||||
<field name="currency"/>
|
||||
<label name="purchase"/>
|
||||
<field name="purchase"/>
|
||||
<label name="sale"/>
|
||||
<field name="sale"/>
|
||||
<label name="strategy"/>
|
||||
<field name="strategy"/>
|
||||
<label name="state"/>
|
||||
<field name="state"/>
|
||||
</form>
|
||||
21
modules/purchase_trade/view/ctrm_pnl_mtm_list.xml
Normal file
21
modules/purchase_trade/view/ctrm_pnl_mtm_list.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<tree>
|
||||
<field name="valuation_date"/>
|
||||
<field name="lot" width="120"/>
|
||||
<field name="purchase" width="100"/>
|
||||
<field name="purchase_line" width="120"/>
|
||||
<field name="sale" width="100"/>
|
||||
<field name="sale_line" width="120"/>
|
||||
<field name="type"/>
|
||||
<field name="reference" width="120"/>
|
||||
<field name="counterparty" width="120"/>
|
||||
<field name="product" width="140"/>
|
||||
<field name="state"/>
|
||||
<field name="quantity" symbol="unit" sum="1"/>
|
||||
<field name="price"/>
|
||||
<field name="mtm_price"/>
|
||||
<field name="currency" width="60"/>
|
||||
<field name="amount" sum="1"/>
|
||||
<field name="mtm" sum="1"/>
|
||||
<field name="mtm_delta" sum="1"/>
|
||||
<field name="strategy"/>
|
||||
</tree>
|
||||
@@ -0,0 +1,20 @@
|
||||
<form>
|
||||
<label name="date"/>
|
||||
<field name="date"/>
|
||||
<label name="realization"/>
|
||||
<field name="realization"/>
|
||||
<label name="product"/>
|
||||
<field name="product"/>
|
||||
<label name="counterparty"/>
|
||||
<field name="counterparty"/>
|
||||
<label name="currency"/>
|
||||
<field name="currency"/>
|
||||
<label name="purchase"/>
|
||||
<field name="purchase"/>
|
||||
<label name="sale"/>
|
||||
<field name="sale"/>
|
||||
<label name="strategy"/>
|
||||
<field name="strategy"/>
|
||||
<label name="state"/>
|
||||
<field name="state"/>
|
||||
</form>
|
||||
20
modules/purchase_trade/view/ctrm_pnl_realized_list.xml
Normal file
20
modules/purchase_trade/view/ctrm_pnl_realized_list.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<tree>
|
||||
<field name="valuation_date"/>
|
||||
<field name="lot" width="120"/>
|
||||
<field name="purchase" width="100"/>
|
||||
<field name="purchase_line" width="120"/>
|
||||
<field name="purchase_invoice" width="120"/>
|
||||
<field name="sale" width="100"/>
|
||||
<field name="sale_line" width="120"/>
|
||||
<field name="sale_invoice" width="120"/>
|
||||
<field name="type"/>
|
||||
<field name="reference" width="120"/>
|
||||
<field name="counterparty" width="120"/>
|
||||
<field name="product" width="140"/>
|
||||
<field name="state"/>
|
||||
<field name="quantity" symbol="unit" sum="1"/>
|
||||
<field name="currency" width="60"/>
|
||||
<field name="amount" sum="1"/>
|
||||
<field name="base_amount" sum="1"/>
|
||||
<field name="strategy"/>
|
||||
</tree>
|
||||
@@ -22,3 +22,15 @@ Date: 2026-05-24
|
||||
- `Risk`
|
||||
- `Operations & Logistics`
|
||||
- `Finance & Accounting`
|
||||
|
||||
## P&L
|
||||
|
||||
- `Realized P&L` lit aussi `valuation.valuation.line`.
|
||||
- Le critere de realisation est parametre dans le contexte du report.
|
||||
- Defaut retenu: achat et vente factures (`Purchase and Sale Invoiced`).
|
||||
- Autres vues utiles:
|
||||
- vente facturee seule;
|
||||
- achat facture seul;
|
||||
- toutes les lignes valorisees.
|
||||
- `Mark-to-Market` lit la derniere valuation et compare `mtm` a `amount`
|
||||
via une colonne `MTM Delta`.
|
||||
|
||||
Reference in New Issue
Block a user