Long & Short
This commit is contained in:
@@ -68,6 +68,10 @@ def register():
|
||||
ctrm_reporting.CTRMNetPositionContext,
|
||||
ctrm_reporting.CTRMOpenPosition,
|
||||
ctrm_reporting.CTRMOpenPositionContext,
|
||||
ctrm_reporting.CTRMLongShortProductStrategy,
|
||||
ctrm_reporting.CTRMLongShortCommodityDirection,
|
||||
ctrm_reporting.CTRMLongShortPeriodProduct,
|
||||
ctrm_reporting.CTRMLongShortPricingStatus,
|
||||
ctrm_reporting.CTRMRealizedPnl,
|
||||
ctrm_reporting.CTRMRealizedPnlContext,
|
||||
ctrm_reporting.CTRMMtmPnl,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import datetime
|
||||
|
||||
from sql import Literal, Null, Union, Window
|
||||
from sql.aggregate import Count, Max, Min, Sum
|
||||
from sql.conditionals import Case, Coalesce
|
||||
@@ -332,6 +334,34 @@ class CTRMOpenPositionContext(ModelView):
|
||||
('partly', 'Partly fix'),
|
||||
], "Pricing Status")
|
||||
shipment_period = fields.Many2One('product.month', "Shipment Period")
|
||||
purchase_period_mode = fields.Selection([
|
||||
(None, ''),
|
||||
('all', 'All'),
|
||||
('exact', 'Exact'),
|
||||
('current_3_10', 'Current -3/+10'),
|
||||
('around_3m', 'Around 3M'),
|
||||
('around_6m', 'Around 6M'),
|
||||
('range', 'Range'),
|
||||
], "Purchase Period")
|
||||
purchase_period = fields.Many2One('product.month', "Purchase Period")
|
||||
purchase_period_from = fields.Many2One(
|
||||
'product.month', "Purchase Period From")
|
||||
purchase_period_to = fields.Many2One(
|
||||
'product.month', "Purchase Period To")
|
||||
sale_period_mode = fields.Selection([
|
||||
(None, ''),
|
||||
('all', 'All'),
|
||||
('exact', 'Exact'),
|
||||
('current_3_10', 'Current -3/+10'),
|
||||
('around_3m', 'Around 3M'),
|
||||
('around_6m', 'Around 6M'),
|
||||
('range', 'Range'),
|
||||
], "Sale Period")
|
||||
sale_period = fields.Many2One('product.month', "Sale Period")
|
||||
sale_period_from = fields.Many2One(
|
||||
'product.month', "Sale Period From")
|
||||
sale_period_to = fields.Many2One(
|
||||
'product.month', "Sale Period To")
|
||||
strategy = fields.Many2One('mtm.strategy', "Strategy")
|
||||
counterparty = fields.Many2One('party.party', "Counterparty")
|
||||
direction = fields.Selection([
|
||||
@@ -345,11 +375,16 @@ class CTRMOpenPositionContext(ModelView):
|
||||
def default_valuation_date(cls):
|
||||
return Pool().get('ir.date').today()
|
||||
|
||||
@classmethod
|
||||
def default_purchase_period_mode(cls):
|
||||
return 'all'
|
||||
|
||||
class CTRMOpenPosition(ModelSQL, ModelView):
|
||||
"CTRM Open Position"
|
||||
__name__ = 'ctrm.reporting.risk.open_position'
|
||||
@classmethod
|
||||
def default_sale_period_mode(cls):
|
||||
return 'all'
|
||||
|
||||
|
||||
class CTRMLongShortMixin:
|
||||
product = fields.Many2One(
|
||||
'product.product', "Product", readonly=True)
|
||||
commodity = fields.Many2One(
|
||||
@@ -361,6 +396,10 @@ class CTRMOpenPosition(ModelSQL, ModelView):
|
||||
], "Pricing", readonly=True)
|
||||
shipment_period = fields.Many2One(
|
||||
'product.month', "Shipment Pd", readonly=True)
|
||||
purchase_period = fields.Many2One(
|
||||
'product.month', "Purchase Pd", readonly=True)
|
||||
sale_period = fields.Many2One(
|
||||
'product.month', "Sale Pd", readonly=True)
|
||||
strategy = fields.Many2One(
|
||||
'mtm.strategy', "Strategy", readonly=True)
|
||||
bought = fields.Numeric("Bought", digits=(16, 3), readonly=True)
|
||||
@@ -386,7 +425,100 @@ class CTRMOpenPosition(ModelSQL, ModelView):
|
||||
group_by=[getattr(lot, line_field)])
|
||||
|
||||
@classmethod
|
||||
def table_query(cls):
|
||||
def _as_date(cls, value):
|
||||
if isinstance(value, datetime.date):
|
||||
return value
|
||||
if isinstance(value, str):
|
||||
return datetime.date.fromisoformat(value)
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def _add_months(cls, date, months):
|
||||
month = date.month - 1 + months
|
||||
year = date.year + month // 12
|
||||
month = month % 12 + 1
|
||||
day = min(date.day, cls._last_day(year, month))
|
||||
return datetime.date(year, month, day)
|
||||
|
||||
@staticmethod
|
||||
def _last_day(year, month):
|
||||
if month == 12:
|
||||
next_month = datetime.date(year + 1, 1, 1)
|
||||
else:
|
||||
next_month = datetime.date(year, month + 1, 1)
|
||||
return (next_month - datetime.timedelta(days=1)).day
|
||||
|
||||
@classmethod
|
||||
def _period_record(cls, period_id):
|
||||
if not period_id:
|
||||
return None
|
||||
if hasattr(period_id, 'beg_date'):
|
||||
return period_id
|
||||
return Pool().get('product.month')(period_id)
|
||||
|
||||
@classmethod
|
||||
def _period_ids_for_context(cls, prefix):
|
||||
context = Transaction().context
|
||||
mode = context.get('%s_period_mode' % prefix) or 'all'
|
||||
if mode == 'all':
|
||||
return None
|
||||
|
||||
exact = context.get('%s_period' % prefix)
|
||||
if mode == 'exact':
|
||||
return [exact] if exact else None
|
||||
|
||||
Period = Pool().get('product.month')
|
||||
start = end = None
|
||||
if mode in {'around_3m', 'around_6m'}:
|
||||
months = 3 if mode == 'around_3m' else 6
|
||||
anchor_period = cls._period_record(exact)
|
||||
anchor_date = (
|
||||
anchor_period.beg_date if anchor_period else
|
||||
cls._as_date(context.get('valuation_date')))
|
||||
if not anchor_date:
|
||||
anchor_date = Pool().get('ir.date').today()
|
||||
month_start = anchor_date.replace(day=1)
|
||||
start = cls._add_months(month_start, -months)
|
||||
end_start = cls._add_months(month_start, months)
|
||||
end = end_start.replace(
|
||||
day=cls._last_day(end_start.year, end_start.month))
|
||||
elif mode == 'current_3_10':
|
||||
anchor_date = cls._as_date(context.get('valuation_date'))
|
||||
if not anchor_date:
|
||||
anchor_date = Pool().get('ir.date').today()
|
||||
month_start = anchor_date.replace(day=1)
|
||||
start = cls._add_months(month_start, -3)
|
||||
end_start = cls._add_months(month_start, 10)
|
||||
end = end_start.replace(
|
||||
day=cls._last_day(end_start.year, end_start.month))
|
||||
elif mode == 'range':
|
||||
period_from = cls._period_record(
|
||||
context.get('%s_period_from' % prefix))
|
||||
period_to = cls._period_record(
|
||||
context.get('%s_period_to' % prefix))
|
||||
start = period_from.beg_date if period_from else None
|
||||
end = period_to.end_date if period_to else None
|
||||
|
||||
domain = []
|
||||
if start:
|
||||
domain.append(('end_date', '>=', start))
|
||||
if end:
|
||||
domain.append(('beg_date', '<=', end))
|
||||
if not domain:
|
||||
return None
|
||||
return [p.id for p in Period.search(domain)]
|
||||
|
||||
@classmethod
|
||||
def _apply_period_filter(cls, where, field, prefix):
|
||||
period_ids = cls._period_ids_for_context(prefix)
|
||||
if period_ids is None:
|
||||
return where
|
||||
if period_ids:
|
||||
return where & field.in_(period_ids)
|
||||
return where & (field == -1)
|
||||
|
||||
@classmethod
|
||||
def _open_position_lines(cls):
|
||||
pool = Pool()
|
||||
PurchaseLine = pool.get('purchase.line')
|
||||
Purchase = pool.get('purchase.purchase')
|
||||
@@ -434,6 +566,8 @@ class CTRMOpenPosition(ModelSQL, ModelView):
|
||||
if context.get('shipment_period'):
|
||||
purchase_where &= (
|
||||
purchase_line.del_period == context['shipment_period'])
|
||||
purchase_where = cls._apply_period_filter(
|
||||
purchase_where, purchase_line.del_period, 'purchase')
|
||||
if context.get('strategy'):
|
||||
purchase_where &= (
|
||||
purchase_strategy.strategy == context['strategy'])
|
||||
@@ -457,6 +591,8 @@ class CTRMOpenPosition(ModelSQL, ModelView):
|
||||
purchase_line.product.as_('product'),
|
||||
Max(template_category.category).as_('commodity'),
|
||||
purchase_line.del_period.as_('shipment_period'),
|
||||
purchase_line.del_period.as_('purchase_period'),
|
||||
Literal(None).as_('sale_period'),
|
||||
Max(purchase_strategy.strategy).as_('strategy'),
|
||||
purchase.party.as_('counterparty'),
|
||||
purchase_line.unit.as_('unit'),
|
||||
@@ -466,6 +602,8 @@ class CTRMOpenPosition(ModelSQL, ModelView):
|
||||
'fixed_qty'),
|
||||
Case((purchase_fixed, 0), else_=purchase_open_qty).as_(
|
||||
'unfixed_qty'),
|
||||
Case((purchase_fixed, 'fixed'), else_='unfixed').as_(
|
||||
'line_pricing'),
|
||||
where=purchase_where,
|
||||
group_by=[
|
||||
purchase_line.id,
|
||||
@@ -500,6 +638,8 @@ class CTRMOpenPosition(ModelSQL, ModelView):
|
||||
sale_where &= template_category.category == context['commodity']
|
||||
if context.get('shipment_period'):
|
||||
sale_where &= sale_line.del_period == context['shipment_period']
|
||||
sale_where = cls._apply_period_filter(
|
||||
sale_where, sale_line.del_period, 'sale')
|
||||
if context.get('strategy'):
|
||||
sale_where &= sale_strategy.strategy == context['strategy']
|
||||
if context.get('counterparty'):
|
||||
@@ -522,6 +662,8 @@ class CTRMOpenPosition(ModelSQL, ModelView):
|
||||
sale_line.product.as_('product'),
|
||||
Max(template_category.category).as_('commodity'),
|
||||
sale_line.del_period.as_('shipment_period'),
|
||||
Literal(None).as_('purchase_period'),
|
||||
sale_line.del_period.as_('sale_period'),
|
||||
Max(sale_strategy.strategy).as_('strategy'),
|
||||
sale.party.as_('counterparty'),
|
||||
sale_line.unit.as_('unit'),
|
||||
@@ -531,6 +673,8 @@ class CTRMOpenPosition(ModelSQL, ModelView):
|
||||
'fixed_qty'),
|
||||
Case((sale_fixed, 0), else_=sale_open_qty).as_(
|
||||
'unfixed_qty'),
|
||||
Case((sale_fixed, 'fixed'), else_='unfixed').as_(
|
||||
'line_pricing'),
|
||||
where=sale_where,
|
||||
group_by=[
|
||||
sale_line.id,
|
||||
@@ -545,16 +689,25 @@ class CTRMOpenPosition(ModelSQL, ModelView):
|
||||
],
|
||||
having=sale_open_qty > 0))
|
||||
|
||||
lines = Union(purchase_query, sale_query, all_=True)
|
||||
return Union(purchase_query, sale_query, all_=True)
|
||||
|
||||
@classmethod
|
||||
def _long_short_query(cls, group_names, order_names=None,
|
||||
line_pricing=False):
|
||||
context = Transaction().context
|
||||
lines = cls._open_position_lines()
|
||||
bought = Sum(Coalesce(lines.bought, 0))
|
||||
sold = Sum(Coalesce(lines.sold, 0))
|
||||
net = bought - sold
|
||||
fixed_qty = Sum(Coalesce(lines.fixed_qty, 0))
|
||||
unfixed_qty = Sum(Coalesce(lines.unfixed_qty, 0))
|
||||
pricing = Case(
|
||||
((fixed_qty > 0) & (unfixed_qty > 0), 'partly'),
|
||||
(unfixed_qty > 0, 'unfixed'),
|
||||
else_='fixed')
|
||||
if line_pricing:
|
||||
pricing = lines.line_pricing
|
||||
else:
|
||||
pricing = Case(
|
||||
((fixed_qty > 0) & (unfixed_qty > 0), 'partly'),
|
||||
(unfixed_qty > 0, 'unfixed'),
|
||||
else_='fixed')
|
||||
direction = Case(
|
||||
(net > 0, 'long'),
|
||||
(net < 0, 'short'),
|
||||
@@ -570,8 +723,18 @@ class CTRMOpenPosition(ModelSQL, ModelView):
|
||||
elif context.get('direction') == 'flat':
|
||||
having &= net == 0
|
||||
|
||||
group_by = [getattr(lines, name) for name in group_names]
|
||||
if line_pricing and 'line_pricing' not in group_names:
|
||||
group_by.append(lines.line_pricing)
|
||||
if order_names is None:
|
||||
order_names = group_names
|
||||
order_by = [getattr(lines, name) for name in order_names]
|
||||
report_id = RowNumber(window=Window([],
|
||||
order_by=[lines.product, lines.unit]))
|
||||
order_by=order_by))
|
||||
|
||||
def grouped_or_max(name):
|
||||
column = getattr(lines, name)
|
||||
return column if name in group_names else Max(column)
|
||||
|
||||
return lines.select(
|
||||
Literal(0).as_('create_uid'),
|
||||
@@ -579,11 +742,13 @@ class CTRMOpenPosition(ModelSQL, ModelView):
|
||||
Literal(None).as_('write_uid'),
|
||||
Literal(None).as_('write_date'),
|
||||
report_id.as_('id'),
|
||||
lines.product.as_('product'),
|
||||
Max(lines.commodity).as_('commodity'),
|
||||
grouped_or_max('product').as_('product'),
|
||||
grouped_or_max('commodity').as_('commodity'),
|
||||
pricing.as_('pricing'),
|
||||
Max(lines.shipment_period).as_('shipment_period'),
|
||||
Max(lines.strategy).as_('strategy'),
|
||||
grouped_or_max('shipment_period').as_('shipment_period'),
|
||||
grouped_or_max('purchase_period').as_('purchase_period'),
|
||||
grouped_or_max('sale_period').as_('sale_period'),
|
||||
grouped_or_max('strategy').as_('strategy'),
|
||||
bought.as_('bought'),
|
||||
sold.as_('sold'),
|
||||
net.as_('net'),
|
||||
@@ -591,10 +756,67 @@ class CTRMOpenPosition(ModelSQL, ModelView):
|
||||
lines.unit.as_('unit'),
|
||||
Count(lines.line_id).as_('open_contracts'),
|
||||
unfixed_qty.as_('unfixed_qty'),
|
||||
group_by=[lines.product, lines.unit],
|
||||
group_by=group_by,
|
||||
having=having)
|
||||
|
||||
|
||||
class CTRMOpenPosition(CTRMLongShortMixin, ModelSQL, ModelView):
|
||||
"CTRM Open Position"
|
||||
__name__ = 'ctrm.reporting.risk.open_position'
|
||||
|
||||
@classmethod
|
||||
def table_query(cls):
|
||||
return cls._long_short_query(
|
||||
['product', 'unit'], order_names=['product', 'unit'])
|
||||
|
||||
|
||||
class CTRMLongShortProductStrategy(
|
||||
CTRMLongShortMixin, ModelSQL, ModelView):
|
||||
"CTRM Long & Short by Product and Strategy"
|
||||
__name__ = 'ctrm.reporting.position.long_short.product_strategy'
|
||||
|
||||
@classmethod
|
||||
def table_query(cls):
|
||||
return cls._long_short_query(
|
||||
['product', 'strategy', 'unit'],
|
||||
order_names=['product', 'strategy', 'unit'])
|
||||
|
||||
|
||||
class CTRMLongShortCommodityDirection(
|
||||
CTRMLongShortMixin, ModelSQL, ModelView):
|
||||
"CTRM Long & Short by Commodity and Direction"
|
||||
__name__ = 'ctrm.reporting.position.long_short.commodity_direction'
|
||||
|
||||
@classmethod
|
||||
def table_query(cls):
|
||||
return cls._long_short_query(
|
||||
['commodity', 'unit'], order_names=['commodity', 'unit'])
|
||||
|
||||
|
||||
class CTRMLongShortPeriodProduct(
|
||||
CTRMLongShortMixin, ModelSQL, ModelView):
|
||||
"CTRM Long & Short by Period and Product"
|
||||
__name__ = 'ctrm.reporting.position.long_short.period_product'
|
||||
|
||||
@classmethod
|
||||
def table_query(cls):
|
||||
return cls._long_short_query(
|
||||
['shipment_period', 'product', 'unit'],
|
||||
order_names=['shipment_period', 'product', 'unit'])
|
||||
|
||||
|
||||
class CTRMLongShortPricingStatus(
|
||||
CTRMLongShortMixin, ModelSQL, ModelView):
|
||||
"CTRM Long & Short by Pricing Status"
|
||||
__name__ = 'ctrm.reporting.position.long_short.pricing_status'
|
||||
|
||||
@classmethod
|
||||
def table_query(cls):
|
||||
return cls._long_short_query(
|
||||
['product', 'unit'], order_names=['product', 'unit'],
|
||||
line_pricing=True)
|
||||
|
||||
|
||||
class CTRMPnlContextMixin:
|
||||
date = fields.Date("Valuation Date")
|
||||
product = fields.Many2One('product.product', "Product")
|
||||
|
||||
@@ -55,9 +55,29 @@
|
||||
<field name="type">tree</field>
|
||||
<field name="name">ctrm_open_position_list</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="ctrm_long_short_product_strategy_view_list">
|
||||
<field name="model">ctrm.reporting.position.long_short.product_strategy</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">ctrm_long_short_product_strategy_list</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="ctrm_long_short_commodity_direction_view_list">
|
||||
<field name="model">ctrm.reporting.position.long_short.commodity_direction</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">ctrm_long_short_commodity_direction_list</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="ctrm_long_short_period_product_view_list">
|
||||
<field name="model">ctrm.reporting.position.long_short.period_product</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">ctrm_long_short_period_product_list</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="ctrm_long_short_pricing_status_view_list">
|
||||
<field name="model">ctrm.reporting.position.long_short.pricing_status</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">ctrm_long_short_pricing_status_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_ctrm_open_position">
|
||||
<field name="name">Open Position</field>
|
||||
<field name="name">Long & Short</field>
|
||||
<field name="res_model">ctrm.reporting.risk.open_position</field>
|
||||
<field name="context_model">ctrm.reporting.risk.open_position.context</field>
|
||||
</record>
|
||||
@@ -66,6 +86,46 @@
|
||||
<field name="view" ref="ctrm_open_position_view_list"/>
|
||||
<field name="act_window" ref="act_ctrm_open_position"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window" id="act_ctrm_long_short_product_strategy">
|
||||
<field name="name">Long & Short by Product & Strategy</field>
|
||||
<field name="res_model">ctrm.reporting.position.long_short.product_strategy</field>
|
||||
<field name="context_model">ctrm.reporting.risk.open_position.context</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_ctrm_long_short_product_strategy_view">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="ctrm_long_short_product_strategy_view_list"/>
|
||||
<field name="act_window" ref="act_ctrm_long_short_product_strategy"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window" id="act_ctrm_long_short_commodity_direction">
|
||||
<field name="name">Long & Short by Commodity & Direction</field>
|
||||
<field name="res_model">ctrm.reporting.position.long_short.commodity_direction</field>
|
||||
<field name="context_model">ctrm.reporting.risk.open_position.context</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_ctrm_long_short_commodity_direction_view">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="ctrm_long_short_commodity_direction_view_list"/>
|
||||
<field name="act_window" ref="act_ctrm_long_short_commodity_direction"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window" id="act_ctrm_long_short_period_product">
|
||||
<field name="name">Long & Short by Period & Product</field>
|
||||
<field name="res_model">ctrm.reporting.position.long_short.period_product</field>
|
||||
<field name="context_model">ctrm.reporting.risk.open_position.context</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_ctrm_long_short_period_product_view">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="ctrm_long_short_period_product_view_list"/>
|
||||
<field name="act_window" ref="act_ctrm_long_short_period_product"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window" id="act_ctrm_long_short_pricing_status">
|
||||
<field name="name">Long & Short by Pricing Status</field>
|
||||
<field name="res_model">ctrm.reporting.position.long_short.pricing_status</field>
|
||||
<field name="context_model">ctrm.reporting.risk.open_position.context</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_ctrm_long_short_pricing_status_view">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="ctrm_long_short_pricing_status_view_list"/>
|
||||
<field name="act_window" ref="act_ctrm_long_short_pricing_status"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
name="Global Reporting"
|
||||
@@ -84,6 +144,42 @@
|
||||
sequence="10"
|
||||
id="menu_gr_configuration"
|
||||
icon="tryton-list"/>
|
||||
<menuitem
|
||||
name="Positions"
|
||||
parent="menu_global_reporting"
|
||||
sequence="10"
|
||||
id="menu_ctrm_positions"
|
||||
icon="tradon-reporting-positions"/>
|
||||
<menuitem
|
||||
name="Long & Short"
|
||||
parent="menu_ctrm_positions"
|
||||
action="act_ctrm_open_position"
|
||||
sequence="10"
|
||||
id="menu_ctrm_positions_long_short"/>
|
||||
<menuitem
|
||||
name="By Product & Strategy"
|
||||
parent="menu_ctrm_positions"
|
||||
action="act_ctrm_long_short_product_strategy"
|
||||
sequence="20"
|
||||
id="menu_ctrm_positions_long_short_product_strategy"/>
|
||||
<menuitem
|
||||
name="By Commodity & Direction"
|
||||
parent="menu_ctrm_positions"
|
||||
action="act_ctrm_long_short_commodity_direction"
|
||||
sequence="30"
|
||||
id="menu_ctrm_positions_long_short_commodity_direction"/>
|
||||
<menuitem
|
||||
name="By Period & Product"
|
||||
parent="menu_ctrm_positions"
|
||||
action="act_ctrm_long_short_period_product"
|
||||
sequence="40"
|
||||
id="menu_ctrm_positions_long_short_period_product"/>
|
||||
<menuitem
|
||||
name="By Pricing Status"
|
||||
parent="menu_ctrm_positions"
|
||||
action="act_ctrm_long_short_pricing_status"
|
||||
sequence="50"
|
||||
id="menu_ctrm_positions_long_short_pricing_status"/>
|
||||
<menuitem
|
||||
name="Other"
|
||||
parent="menu_global_reporting"
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<tree>
|
||||
<field name="commodity" width="180"/>
|
||||
<field name="direction"
|
||||
widget="badge"
|
||||
badge_colors="long:#16a34a,short:#ef4444,flat:#64748b"/>
|
||||
<field name="bought" symbol="unit" sum="1"/>
|
||||
<field name="sold" symbol="unit" sum="1"/>
|
||||
<field name="net" symbol="unit" sum="1"/>
|
||||
<field name="pricing"
|
||||
widget="badge"
|
||||
badge_colors="fixed:#16a34a,unfixed:#f59e0b,partly:#fbbf24"/>
|
||||
<field name="unit" optional="1"/>
|
||||
<field name="product" optional="1"/>
|
||||
<field name="unfixed_qty" symbol="unit" optional="1" sum="1"/>
|
||||
<field name="open_contracts" optional="1" sum="1"/>
|
||||
</tree>
|
||||
@@ -0,0 +1,17 @@
|
||||
<tree>
|
||||
<field name="shipment_period" width="110"/>
|
||||
<field name="product" width="180"/>
|
||||
<field name="commodity" width="130"/>
|
||||
<field name="bought" symbol="unit" sum="1"/>
|
||||
<field name="sold" symbol="unit" sum="1"/>
|
||||
<field name="net" symbol="unit" sum="1"/>
|
||||
<field name="direction"
|
||||
widget="badge"
|
||||
badge_colors="long:#16a34a,short:#ef4444,flat:#64748b"/>
|
||||
<field name="pricing"
|
||||
widget="badge"
|
||||
badge_colors="fixed:#16a34a,unfixed:#f59e0b,partly:#fbbf24"/>
|
||||
<field name="unit" optional="1"/>
|
||||
<field name="unfixed_qty" symbol="unit" optional="1" sum="1"/>
|
||||
<field name="open_contracts" optional="1" sum="1"/>
|
||||
</tree>
|
||||
@@ -0,0 +1,16 @@
|
||||
<tree>
|
||||
<field name="pricing"
|
||||
widget="badge"
|
||||
badge_colors="fixed:#16a34a,unfixed:#f59e0b,partly:#fbbf24"/>
|
||||
<field name="product" width="180"/>
|
||||
<field name="commodity" width="130"/>
|
||||
<field name="bought" symbol="unit" sum="1"/>
|
||||
<field name="sold" symbol="unit" sum="1"/>
|
||||
<field name="net" symbol="unit" sum="1"/>
|
||||
<field name="direction"
|
||||
widget="badge"
|
||||
badge_colors="long:#16a34a,short:#ef4444,flat:#64748b"/>
|
||||
<field name="unit" optional="1"/>
|
||||
<field name="unfixed_qty" symbol="unit" optional="1" sum="1"/>
|
||||
<field name="open_contracts" optional="1" sum="1"/>
|
||||
</tree>
|
||||
@@ -0,0 +1,17 @@
|
||||
<tree>
|
||||
<field name="product" width="180"/>
|
||||
<field name="commodity" width="130"/>
|
||||
<field name="strategy" width="140"/>
|
||||
<field name="bought" symbol="unit" sum="1"/>
|
||||
<field name="sold" symbol="unit" sum="1"/>
|
||||
<field name="net" symbol="unit" sum="1"/>
|
||||
<field name="direction"
|
||||
widget="badge"
|
||||
badge_colors="long:#16a34a,short:#ef4444,flat:#64748b"/>
|
||||
<field name="pricing"
|
||||
widget="badge"
|
||||
badge_colors="fixed:#16a34a,unfixed:#f59e0b,partly:#fbbf24"/>
|
||||
<field name="unit" optional="1"/>
|
||||
<field name="unfixed_qty" symbol="unit" optional="1" sum="1"/>
|
||||
<field name="open_contracts" optional="1" sum="1"/>
|
||||
</tree>
|
||||
@@ -9,6 +9,22 @@
|
||||
<field name="pricing_status"/>
|
||||
<label name="shipment_period"/>
|
||||
<field name="shipment_period"/>
|
||||
<label name="purchase_period_mode"/>
|
||||
<field name="purchase_period_mode"/>
|
||||
<label name="purchase_period"/>
|
||||
<field name="purchase_period"/>
|
||||
<label name="purchase_period_from"/>
|
||||
<field name="purchase_period_from"/>
|
||||
<label name="purchase_period_to"/>
|
||||
<field name="purchase_period_to"/>
|
||||
<label name="sale_period_mode"/>
|
||||
<field name="sale_period_mode"/>
|
||||
<label name="sale_period"/>
|
||||
<field name="sale_period"/>
|
||||
<label name="sale_period_from"/>
|
||||
<field name="sale_period_from"/>
|
||||
<label name="sale_period_to"/>
|
||||
<field name="sale_period_to"/>
|
||||
<label name="strategy"/>
|
||||
<field name="strategy"/>
|
||||
<label name="counterparty"/>
|
||||
|
||||
Reference in New Issue
Block a user