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)