Files
tradon/modules/purchase_trade/ctrm_reporting.py
2026-05-24 17:53:33 +02:00

278 lines
9.7 KiB
Python

from sql import Literal, Null
from sql.aggregate import Max, Min, Sum
from sql.conditionals import Case, Coalesce
from sql.functions import CurrentTimestamp
from trytond.model import ModelSQL, ModelView, fields
from trytond.pool import Pool
from trytond.transaction import Transaction
class CTRMPhysicalPositionContext(ModelView):
"CTRM Physical Position Context"
__name__ = 'ctrm.reporting.position.physical.context'
as_of = fields.Date("As of")
product = fields.Many2One('product.product', "Product")
supplier = fields.Many2One('party.party', "Supplier")
client = fields.Many2One('party.party', "Client")
currency = fields.Many2One('currency.currency', "Currency")
position_type = fields.Selection([
(None, ""),
('open', 'Open'),
('physic', 'Physic'),
('shipped', 'Shipped'),
], "Position Type")
@classmethod
def default_as_of(cls):
Date = Pool().get('ir.date')
return Date.today()
class CTRMPhysicalPosition(ModelSQL, ModelView):
"CTRM Physical Position"
__name__ = 'ctrm.reporting.position.physical'
product = fields.Many2One('product.product', "Product")
supplier = fields.Many2One('party.party', "Supplier")
client = fields.Many2One('party.party', "Client")
currency = fields.Many2One('currency.currency', "Currency")
uom = fields.Many2One('product.uom', "Unit")
position_type = fields.Selection([
('open', 'Open'),
('physic', 'Physic'),
('shipped', 'Shipped'),
], "Position Type")
physical_qty = fields.Numeric("Physical Quantity", digits=(16, 5))
hedged_qty = fields.Numeric("Hedged Quantity", digits=(16, 5))
net_exposure = fields.Numeric("Net Exposure", digits=(16, 5))
amount = fields.Numeric("Amount", digits=(16, 2))
mtm = fields.Numeric("MTM", digits=(16, 2))
pnl = fields.Numeric("P&L", digits=(16, 2))
period_start = fields.Date("Period Start")
period_end = fields.Date("Period End")
@classmethod
def table_query(cls):
LotReport = Pool().get('lot.report')
PurchaseLine = Pool().get('purchase.line')
Purchase = Pool().get('purchase.purchase')
SaleLine = Pool().get('sale.line')
Sale = Pool().get('sale.sale')
context = Transaction().context
as_of = context.get('as_of')
product = context.get('product')
supplier = context.get('supplier')
client = context.get('client')
currency = context.get('currency')
position_type = context.get('position_type')
lot_context = {
'purchase': None,
'sale': None,
'shipment': None,
'type': 'all',
'state': 'all',
'wh': 'all',
'group': 'by_physic',
'origin': 'all',
'ps': 'all',
'shipping_status': 'all',
}
if as_of:
lot_context['todate'] = as_of
if product:
lot_context['product'] = product
if supplier:
lot_context['supplier'] = supplier
if client:
lot_context['client'] = client
lr = LotReport.table_query(lot_context)
pl = PurchaseLine.__table__()
pu = Purchase.__table__()
sl = SaleLine.__table__()
sa = Sale.__table__()
position_type_expr = Case(
(lr.r_lot_type == 'virtual', 'open'),
(lr.r_shipping_status.in_(['scheduled', 'shipped', 'received']),
'shipped'),
else_='physic')
currency_expr = Coalesce(sa.currency, pu.currency)
price_expr = Coalesce(sl.unit_price, pl.unit_price, 0)
where = Literal(True)
if currency:
where &= currency_expr == currency
if position_type:
where &= position_type_expr == position_type
group_by = [
lr.r_lot_product,
lr.r_supplier,
lr.r_client,
currency_expr,
lr.r_lot_unit,
position_type_expr,
]
return (
lr
.join(pl, 'LEFT', condition=pl.id == lr.r_line)
.join(pu, 'LEFT', condition=pu.id == lr.r_purchase)
.join(sl, 'LEFT', condition=sl.id == lr.r_sale_line)
.join(sa, 'LEFT', condition=sa.id == lr.r_sale)
.select(
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
Literal(None).as_('write_uid'),
Literal(None).as_('write_date'),
Min(lr.id).as_('id'),
lr.r_lot_product.as_('product'),
lr.r_supplier.as_('supplier'),
lr.r_client.as_('client'),
currency_expr.as_('currency'),
lr.r_lot_unit.as_('uom'),
position_type_expr.as_('position_type'),
Sum(lr.r_lot_quantity).as_('physical_qty'),
Literal(0).as_('hedged_qty'),
Sum(lr.r_lot_quantity).as_('net_exposure'),
Sum(lr.r_lot_quantity * price_expr).as_('amount'),
Literal(None).as_('mtm'),
Literal(None).as_('pnl'),
Literal(None).as_('period_start'),
Literal(None).as_('period_end'),
where=where,
group_by=group_by))
class CTRMFinancialPositionContext(ModelView):
"CTRM Financial Position Context"
__name__ = 'ctrm.reporting.position.financial.context'
trade_from = fields.Date("Trade Date From")
trade_to = fields.Date("Trade Date To")
maturity_from = fields.Date("Maturity From")
maturity_to = fields.Date("Maturity To")
product = fields.Many2One('product.product', "Product")
party = fields.Many2One('party.party', "Counterparty")
purchase = fields.Many2One('purchase.purchase', "Purchase")
sale = fields.Many2One('sale.sale', "Sale")
direction = fields.Selection([
(None, ''),
('long', 'Long'),
('short', 'Short'),
], 'Direction')
state = fields.Selection([
(None, ''),
('open', 'Open'),
('closed', 'Closed'),
], 'State')
open_only = fields.Boolean("Open Positions Only")
@classmethod
def default_trade_to(cls):
Date = Pool().get('ir.date')
return Date.today()
@classmethod
def default_open_only(cls):
return True
class CTRMFinancialPosition(ModelSQL, ModelView):
"CTRM Financial Position"
__name__ = 'ctrm.reporting.position.financial'
derivative = fields.Many2One('derivative.derivative', "Derivative")
trade_date = fields.Date("Trade Date")
maturity_date = fields.Date("Maturity")
product = fields.Many2One('product.product', "Product")
party = fields.Many2One('party.party', "Counterparty")
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")
price_index = fields.Many2One('price.price', "Curve")
direction = fields.Selection([
('long', 'Long'),
('short', 'Short'),
], 'Direction')
state = fields.Selection([
('open', 'Open'),
('closed', 'Closed'),
], 'State')
contract_count = fields.Integer("Nb ct")
open_qty = fields.Numeric("Open Quantity", digits='unit')
entry_price = fields.Numeric("Entry Price", digits='currency')
exit_price = fields.Numeric("Exit Price", digits='currency')
@classmethod
def table_query(cls):
Derivative = Pool().get('derivative.derivative')
d = Derivative.__table__()
context = Transaction().context
trade_from = context.get('trade_from')
trade_to = context.get('trade_to')
maturity_from = context.get('maturity_from')
maturity_to = context.get('maturity_to')
product = context.get('product')
party = context.get('party')
purchase = context.get('purchase')
sale = context.get('sale')
direction = context.get('direction')
state = context.get('state')
open_only = context.get('open_only')
where = Literal(True)
if trade_from:
where &= d.trade_date >= trade_from
if trade_to:
where &= d.trade_date <= trade_to
if maturity_from:
where &= d.maturity_date >= maturity_from
if maturity_to:
where &= d.maturity_date <= maturity_to
if product:
where &= d.product == product
if party:
where &= d.party == party
if purchase:
where &= d.purchase == purchase
if sale:
where &= d.sale == sale
if direction:
where &= d.direction == direction
if state:
where &= d.state == state
if open_only:
where &= d.open_qty > 0
return d.select(
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
Literal(None).as_('write_uid'),
Literal(None).as_('write_date'),
d.id.as_('id'),
d.id.as_('derivative'),
d.trade_date.as_('trade_date'),
d.maturity_date.as_('maturity_date'),
d.product.as_('product'),
d.party.as_('party'),
d.purchase.as_('purchase'),
d.line.as_('purchase_line'),
d.sale.as_('sale'),
d.sale_line.as_('sale_line'),
d.price_index.as_('price_index'),
d.direction.as_('direction'),
d.state.as_('state'),
d.nb_ct.as_('contract_count'),
d.open_qty.as_('open_qty'),
d.price.as_('entry_price'),
d.exit_price.as_('exit_price'),
where=where)