1987 lines
79 KiB
Python
1987 lines
79 KiB
Python
from sql import Literal, Null, Union, Window
|
|
from sql.aggregate import Count, Max, Min, Sum
|
|
from sql.conditionals import Case, Coalesce
|
|
from sql.functions import CurrentTimestamp, RowNumber
|
|
|
|
from trytond.model import ModelSQL, ModelView, fields
|
|
from trytond.pool import Pool
|
|
from trytond.transaction import Transaction
|
|
|
|
|
|
PHYSICAL_VALUATION_TYPES = [
|
|
'priced',
|
|
'pur. priced',
|
|
'pur. efp',
|
|
'sale priced',
|
|
'sale efp',
|
|
'line fee',
|
|
'pur. fee',
|
|
'sale fee',
|
|
'shipment fee',
|
|
'market',
|
|
]
|
|
DERIVATIVE_VALUATION_TYPES = ['derivative']
|
|
ALL_VALUATION_TYPES = PHYSICAL_VALUATION_TYPES + DERIVATIVE_VALUATION_TYPES
|
|
|
|
|
|
class CTRMValuationContextMixin:
|
|
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 CTRMPhysicalPositionContext(
|
|
CTRMValuationContextMixin, ModelView):
|
|
"CTRM Physical Position Context"
|
|
__name__ = 'ctrm.reporting.position.physical.context'
|
|
|
|
|
|
class CTRMPhysicalPosition(ModelSQL, ModelView):
|
|
"CTRM Physical Position"
|
|
__name__ = 'ctrm.reporting.position.physical'
|
|
|
|
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'),
|
|
], "Type")
|
|
reference = fields.Char("Reference")
|
|
counterparty = fields.Many2One('party.party', "Counterparty")
|
|
product = fields.Many2One('product.product', "Product")
|
|
state = fields.Char("State")
|
|
price = fields.Numeric("Price", digits=(16, 4))
|
|
currency = fields.Many2One('currency.currency', "Currency")
|
|
quantity = fields.Numeric("Quantity", digits=(16, 5))
|
|
unit = fields.Many2One('product.uom', "Unit")
|
|
amount = fields.Numeric("Amount", digits=(16, 2))
|
|
base_amount = fields.Numeric("Base Amount", digits=(16, 2))
|
|
mtm_price = fields.Numeric("MTM Price", digits=(16, 4))
|
|
mtm = fields.Numeric("MTM", 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_(PHYSICAL_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.price.as_('price'),
|
|
val.currency.as_('currency'),
|
|
val.quantity.as_('quantity'),
|
|
val.unit.as_('unit'),
|
|
val.amount.as_('amount'),
|
|
val.base_amount.as_('base_amount'),
|
|
val.mtm_price.as_('mtm_price'),
|
|
val.mtm.as_('mtm'),
|
|
val.strategy.as_('strategy'),
|
|
where=where)
|
|
|
|
|
|
class CTRMFinancialPositionContext(
|
|
CTRMValuationContextMixin, ModelView):
|
|
"CTRM Financial Position Context"
|
|
__name__ = 'ctrm.reporting.position.financial.context'
|
|
|
|
|
|
class CTRMFinancialPosition(ModelSQL, ModelView):
|
|
"CTRM Financial Position"
|
|
__name__ = 'ctrm.reporting.position.financial'
|
|
|
|
valuation_date = fields.Date("Valuation Date")
|
|
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")
|
|
reference = fields.Char("Reference")
|
|
counterparty = fields.Many2One('party.party', "Counterparty")
|
|
product = fields.Many2One('product.product', "Product")
|
|
state = fields.Char("State")
|
|
price = fields.Numeric("Price", digits=(16, 4))
|
|
currency = fields.Many2One('currency.currency', "Currency")
|
|
quantity = fields.Numeric("Quantity", digits=(16, 5))
|
|
unit = fields.Many2One('product.uom', "Unit")
|
|
amount = fields.Numeric("Amount", digits=(16, 2))
|
|
base_amount = fields.Numeric("Base Amount", digits=(16, 2))
|
|
mtm_price = fields.Numeric("MTM Price", digits=(16, 4))
|
|
mtm = fields.Numeric("MTM", 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_(DERIVATIVE_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.purchase.as_('purchase'),
|
|
val.line.as_('purchase_line'),
|
|
val.sale.as_('sale'),
|
|
val.sale_line.as_('sale_line'),
|
|
val.reference.as_('reference'),
|
|
val.counterparty.as_('counterparty'),
|
|
val.product.as_('product'),
|
|
val.state.as_('state'),
|
|
val.price.as_('price'),
|
|
val.currency.as_('currency'),
|
|
val.quantity.as_('quantity'),
|
|
val.unit.as_('unit'),
|
|
val.amount.as_('amount'),
|
|
val.base_amount.as_('base_amount'),
|
|
val.mtm_price.as_('mtm_price'),
|
|
val.mtm.as_('mtm'),
|
|
val.strategy.as_('strategy'),
|
|
where=where)
|
|
|
|
|
|
class CTRMNetPositionContext(
|
|
CTRMValuationContextMixin, ModelView):
|
|
"CTRM Net Position Context"
|
|
__name__ = 'ctrm.reporting.position.net.context'
|
|
|
|
|
|
class CTRMNetPosition(ModelSQL, ModelView):
|
|
"CTRM Net Position"
|
|
__name__ = 'ctrm.reporting.position.net'
|
|
|
|
valuation_date = fields.Date("Valuation Date")
|
|
product = fields.Many2One('product.product', "Product")
|
|
counterparty = fields.Many2One('party.party', "Counterparty")
|
|
currency = fields.Many2One('currency.currency', "Currency")
|
|
unit = fields.Many2One('product.uom', "Unit")
|
|
state = fields.Char("State")
|
|
strategy = fields.Many2One('mtm.strategy', "Strategy")
|
|
physical_quantity = fields.Numeric(
|
|
"Physical Quantity", digits=(16, 5))
|
|
derivative_quantity = fields.Numeric(
|
|
"Derivative Quantity", digits=(16, 5))
|
|
net_quantity = fields.Numeric("Net Quantity", digits=(16, 5))
|
|
physical_amount = fields.Numeric("Physical Amount", digits=(16, 2))
|
|
derivative_amount = fields.Numeric("Derivative Amount", digits=(16, 2))
|
|
net_amount = fields.Numeric("Net Amount", digits=(16, 2))
|
|
mtm = fields.Numeric("MTM", digits=(16, 2))
|
|
|
|
@classmethod
|
|
def table_query(cls):
|
|
ValuationLine = Pool().get('valuation.valuation.line')
|
|
val = ValuationLine.__table__()
|
|
|
|
context = Transaction().context
|
|
where = val.type.in_(
|
|
PHYSICAL_VALUATION_TYPES + DERIVATIVE_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']
|
|
|
|
is_derivative = val.type.in_(DERIVATIVE_VALUATION_TYPES)
|
|
physical_quantity = Case(
|
|
(is_derivative, 0), else_=Coalesce(val.quantity, 0))
|
|
derivative_quantity = Case(
|
|
(is_derivative, Coalesce(val.quantity, 0)), else_=0)
|
|
physical_amount = Case(
|
|
(is_derivative, 0), else_=Coalesce(val.amount, 0))
|
|
derivative_amount = Case(
|
|
(is_derivative, Coalesce(val.amount, 0)), else_=0)
|
|
|
|
group_by = [
|
|
val.date,
|
|
val.product,
|
|
val.counterparty,
|
|
val.currency,
|
|
val.unit,
|
|
val.state,
|
|
val.strategy,
|
|
]
|
|
|
|
return val.select(
|
|
Literal(0).as_('create_uid'),
|
|
CurrentTimestamp().as_('create_date'),
|
|
Literal(None).as_('write_uid'),
|
|
Literal(None).as_('write_date'),
|
|
Min(val.id).as_('id'),
|
|
val.date.as_('valuation_date'),
|
|
val.product.as_('product'),
|
|
val.counterparty.as_('counterparty'),
|
|
val.currency.as_('currency'),
|
|
val.unit.as_('unit'),
|
|
val.state.as_('state'),
|
|
val.strategy.as_('strategy'),
|
|
Sum(physical_quantity).as_('physical_quantity'),
|
|
Sum(derivative_quantity).as_('derivative_quantity'),
|
|
Sum(Coalesce(val.quantity, 0)).as_('net_quantity'),
|
|
Sum(physical_amount).as_('physical_amount'),
|
|
Sum(derivative_amount).as_('derivative_amount'),
|
|
Sum(Coalesce(val.amount, 0)).as_('net_amount'),
|
|
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)
|
|
|
|
|
|
class CTRMPnlExplainContext(CTRMPnlContextMixin, ModelView):
|
|
"CTRM P&L Explain Context"
|
|
__name__ = 'ctrm.reporting.pnl.explain.context'
|
|
|
|
|
|
class CTRMPnlExplain(ModelSQL, ModelView):
|
|
"CTRM P&L Explain"
|
|
__name__ = 'ctrm.reporting.pnl.explain'
|
|
|
|
valuation_date = fields.Date("Valuation Date")
|
|
product = fields.Many2One('product.product', "Product")
|
|
counterparty = fields.Many2One('party.party', "Counterparty")
|
|
currency = fields.Many2One('currency.currency', "Currency")
|
|
unit = fields.Many2One('product.uom', "Unit")
|
|
state = fields.Char("State")
|
|
strategy = fields.Many2One('mtm.strategy', "Strategy")
|
|
physical_pnl = fields.Numeric("Physical P&L", digits=(16, 2))
|
|
fee_pnl = fields.Numeric("Fee P&L", digits=(16, 2))
|
|
derivative_pnl = fields.Numeric("Derivative P&L", digits=(16, 2))
|
|
mtm_delta = fields.Numeric("MTM Delta", digits=(16, 2))
|
|
total_pnl = fields.Numeric("Total P&L", digits=(16, 2))
|
|
|
|
@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']
|
|
|
|
is_fee = val.type.in_([
|
|
'line fee',
|
|
'pur. fee',
|
|
'sale fee',
|
|
'shipment fee',
|
|
])
|
|
is_derivative = val.type.in_(DERIVATIVE_VALUATION_TYPES)
|
|
physical_pnl = Case(
|
|
(is_fee | is_derivative, 0), else_=Coalesce(val.amount, 0))
|
|
fee_pnl = Case((is_fee, Coalesce(val.amount, 0)), else_=0)
|
|
derivative_pnl = Case(
|
|
(is_derivative, Coalesce(val.amount, 0)), else_=0)
|
|
mtm_delta = Coalesce(val.mtm, 0) - Coalesce(val.amount, 0)
|
|
|
|
group_by = [
|
|
val.date,
|
|
val.product,
|
|
val.counterparty,
|
|
val.currency,
|
|
val.unit,
|
|
val.state,
|
|
val.strategy,
|
|
]
|
|
|
|
return val.select(
|
|
Literal(0).as_('create_uid'),
|
|
CurrentTimestamp().as_('create_date'),
|
|
Literal(None).as_('write_uid'),
|
|
Literal(None).as_('write_date'),
|
|
Min(val.id).as_('id'),
|
|
val.date.as_('valuation_date'),
|
|
val.product.as_('product'),
|
|
val.counterparty.as_('counterparty'),
|
|
val.currency.as_('currency'),
|
|
val.unit.as_('unit'),
|
|
val.state.as_('state'),
|
|
val.strategy.as_('strategy'),
|
|
Sum(physical_pnl).as_('physical_pnl'),
|
|
Sum(fee_pnl).as_('fee_pnl'),
|
|
Sum(derivative_pnl).as_('derivative_pnl'),
|
|
Sum(mtm_delta).as_('mtm_delta'),
|
|
Sum(Coalesce(val.amount, 0)).as_('total_pnl'),
|
|
where=where,
|
|
group_by=group_by)
|
|
|
|
|
|
class CTRMPnlDimensionContext(CTRMPnlContextMixin, ModelView):
|
|
"CTRM P&L by Dimension Context"
|
|
__name__ = 'ctrm.reporting.pnl.dimension.context'
|
|
|
|
dimension = fields.Many2One('analytic.dimension', "Dimension")
|
|
value = fields.Many2One('analytic.dimension.value', "Value")
|
|
|
|
|
|
class CTRMPnlDimension(ModelSQL, ModelView):
|
|
"CTRM P&L by Dimension"
|
|
__name__ = 'ctrm.reporting.pnl.dimension'
|
|
|
|
valuation_date = fields.Date("Valuation Date")
|
|
dimension = fields.Many2One('analytic.dimension', "Dimension")
|
|
value = fields.Many2One('analytic.dimension.value', "Value")
|
|
product = fields.Many2One('product.product', "Product")
|
|
counterparty = fields.Many2One('party.party', "Counterparty")
|
|
currency = fields.Many2One('currency.currency', "Currency")
|
|
unit = fields.Many2One('product.uom', "Unit")
|
|
state = fields.Char("State")
|
|
strategy = fields.Many2One('mtm.strategy', "Strategy")
|
|
quantity = fields.Numeric("Quantity", digits=(16, 5))
|
|
amount = fields.Numeric("Amount", digits=(16, 2))
|
|
mtm = fields.Numeric("MTM", digits=(16, 2))
|
|
mtm_delta = fields.Numeric("MTM Delta", digits=(16, 2))
|
|
|
|
@classmethod
|
|
def table_query(cls):
|
|
ValuationLine = Pool().get('valuation.valuation.line')
|
|
Assignment = Pool().get('analytic.dimension.assignment')
|
|
val = ValuationLine.__table__()
|
|
purchase_assignment = Assignment.__table__()
|
|
sale_assignment = Assignment.__table__()
|
|
|
|
context = Transaction().context
|
|
dimension_expr = Coalesce(
|
|
sale_assignment.dimension, purchase_assignment.dimension)
|
|
value_expr = Coalesce(sale_assignment.value, purchase_assignment.value)
|
|
|
|
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 context.get('dimension'):
|
|
where &= dimension_expr == context['dimension']
|
|
if context.get('value'):
|
|
where &= value_expr == context['value']
|
|
|
|
group_by = [
|
|
val.date,
|
|
dimension_expr,
|
|
value_expr,
|
|
val.product,
|
|
val.counterparty,
|
|
val.currency,
|
|
val.unit,
|
|
val.state,
|
|
val.strategy,
|
|
]
|
|
grouped = (
|
|
val
|
|
.join(purchase_assignment, 'LEFT',
|
|
condition=purchase_assignment.purchase == val.purchase)
|
|
.join(sale_assignment, 'LEFT',
|
|
condition=sale_assignment.sale == val.sale)
|
|
.select(
|
|
val.date.as_('valuation_date'),
|
|
dimension_expr.as_('dimension'),
|
|
value_expr.as_('value'),
|
|
val.product.as_('product'),
|
|
val.counterparty.as_('counterparty'),
|
|
val.currency.as_('currency'),
|
|
val.unit.as_('unit'),
|
|
val.state.as_('state'),
|
|
val.strategy.as_('strategy'),
|
|
Sum(Coalesce(val.quantity, 0)).as_('quantity'),
|
|
Sum(Coalesce(val.amount, 0)).as_('amount'),
|
|
Sum(Coalesce(val.mtm, 0)).as_('mtm'),
|
|
Sum(Coalesce(val.mtm, 0) - Coalesce(val.amount, 0)).as_(
|
|
'mtm_delta'),
|
|
where=where,
|
|
group_by=group_by))
|
|
|
|
row_number = RowNumber(window=Window([],
|
|
order_by=[
|
|
grouped.valuation_date.asc,
|
|
grouped.dimension.asc,
|
|
grouped.value.asc,
|
|
grouped.product.asc,
|
|
grouped.counterparty.asc,
|
|
grouped.currency.asc,
|
|
grouped.unit.asc,
|
|
grouped.state.asc,
|
|
grouped.strategy.asc,
|
|
]))
|
|
|
|
return grouped.select(
|
|
Literal(0).as_('create_uid'),
|
|
CurrentTimestamp().as_('create_date'),
|
|
Literal(None).as_('write_uid'),
|
|
Literal(None).as_('write_date'),
|
|
row_number.as_('id'),
|
|
grouped.valuation_date.as_('valuation_date'),
|
|
grouped.dimension.as_('dimension'),
|
|
grouped.value.as_('value'),
|
|
grouped.product.as_('product'),
|
|
grouped.counterparty.as_('counterparty'),
|
|
grouped.currency.as_('currency'),
|
|
grouped.unit.as_('unit'),
|
|
grouped.state.as_('state'),
|
|
grouped.strategy.as_('strategy'),
|
|
grouped.quantity.as_('quantity'),
|
|
grouped.amount.as_('amount'),
|
|
grouped.mtm.as_('mtm'),
|
|
grouped.mtm_delta.as_('mtm_delta'))
|
|
|
|
|
|
class CTRMCreditRiskContext(ModelView):
|
|
"CTRM Credit Risk Context"
|
|
__name__ = 'ctrm.reporting.risk.credit.context'
|
|
|
|
party = fields.Many2One('party.party', "Party")
|
|
currency = fields.Many2One('currency.currency', "Credit Currency")
|
|
risk_level = fields.Selection([
|
|
(None, ''),
|
|
('low', 'Low'),
|
|
('medium', 'Medium'),
|
|
('high', 'High'),
|
|
], "Risk Level")
|
|
over_limit_only = fields.Boolean("Over Limit Only")
|
|
|
|
|
|
class CTRMCreditRisk(ModelSQL, ModelView):
|
|
"CTRM Credit Risk"
|
|
__name__ = 'ctrm.reporting.risk.credit'
|
|
|
|
party = fields.Many2One('party.party', "Party")
|
|
credit_limit = fields.Numeric("Credit Limit", digits=(16, 2))
|
|
credit_currency = fields.Many2One(
|
|
'currency.currency', "Credit Currency")
|
|
open_exposure = fields.Numeric("Open Exposure", digits=(16, 2))
|
|
internal_limit = fields.Numeric("Internal Limit", digits=(16, 2))
|
|
insurance_limit = fields.Numeric("Insurance Limit", digits=(16, 2))
|
|
available_credit = fields.Numeric("Available Credit", digits=(16, 2))
|
|
utilization = fields.Numeric("Utilization %", digits=(16, 2))
|
|
risk_level = fields.Selection([
|
|
(None, ''),
|
|
('low', 'Low'),
|
|
('medium', 'Medium'),
|
|
('high', 'High'),
|
|
], "Risk Level")
|
|
status = fields.Char("Status")
|
|
|
|
@classmethod
|
|
def table_query(cls):
|
|
Party = Pool().get('party.party')
|
|
MoveLine = Pool().get('account.move.line')
|
|
InternalLimit = Pool().get('party.internal.limit')
|
|
InsuranceLimit = Pool().get('party.insurance.limit')
|
|
|
|
party = Party.__table__()
|
|
move_line = MoveLine.__table__()
|
|
internal_limit = InternalLimit.__table__()
|
|
insurance_limit = InsuranceLimit.__table__()
|
|
|
|
exposure_query = move_line.select(
|
|
move_line.party.as_('party'),
|
|
Sum(Coalesce(move_line.debit, 0)
|
|
- Coalesce(move_line.credit, 0)).as_('open_exposure'),
|
|
where=((move_line.party != Null)
|
|
& (move_line.reconciliation == Null)),
|
|
group_by=[move_line.party])
|
|
internal_query = internal_limit.select(
|
|
internal_limit.party.as_('party'),
|
|
Sum(Coalesce(internal_limit.amount, 0)).as_('internal_limit'),
|
|
group_by=[internal_limit.party])
|
|
insurance_query = insurance_limit.select(
|
|
insurance_limit.party.as_('party'),
|
|
Sum(Coalesce(insurance_limit.amount, 0)).as_('insurance_limit'),
|
|
group_by=[insurance_limit.party])
|
|
|
|
exposure = Coalesce(exposure_query.open_exposure, 0)
|
|
limit = Coalesce(party.credit_limit, 0)
|
|
utilization = Case(
|
|
(limit != 0, (exposure / limit) * 100),
|
|
else_=0)
|
|
available_credit = limit - exposure
|
|
status = Case(
|
|
(exposure > limit, 'Over limit'),
|
|
(exposure > limit * 0.8, 'Warning'),
|
|
else_='OK')
|
|
|
|
context = Transaction().context
|
|
where = (
|
|
(party.credit_limit != Null)
|
|
| (exposure_query.open_exposure != Null)
|
|
| (internal_query.internal_limit != Null)
|
|
| (insurance_query.insurance_limit != Null))
|
|
if context.get('party'):
|
|
where &= party.id == context['party']
|
|
if context.get('currency'):
|
|
where &= party.credit_currency == context['currency']
|
|
if context.get('risk_level'):
|
|
where &= party.risk_level == context['risk_level']
|
|
if context.get('over_limit_only'):
|
|
where &= exposure > limit
|
|
|
|
return (
|
|
party
|
|
.join(exposure_query, 'LEFT',
|
|
condition=exposure_query.party == party.id)
|
|
.join(internal_query, 'LEFT',
|
|
condition=internal_query.party == party.id)
|
|
.join(insurance_query, 'LEFT',
|
|
condition=insurance_query.party == party.id)
|
|
.select(
|
|
Literal(0).as_('create_uid'),
|
|
CurrentTimestamp().as_('create_date'),
|
|
Literal(None).as_('write_uid'),
|
|
Literal(None).as_('write_date'),
|
|
party.id.as_('id'),
|
|
party.id.as_('party'),
|
|
party.credit_limit.as_('credit_limit'),
|
|
party.credit_currency.as_('credit_currency'),
|
|
exposure.as_('open_exposure'),
|
|
Coalesce(internal_query.internal_limit, 0).as_(
|
|
'internal_limit'),
|
|
Coalesce(insurance_query.insurance_limit, 0).as_(
|
|
'insurance_limit'),
|
|
available_credit.as_('available_credit'),
|
|
utilization.as_('utilization'),
|
|
party.risk_level.as_('risk_level'),
|
|
status.as_('status'),
|
|
where=where))
|
|
|
|
|
|
class CTRMShippingLogisticsContext(ModelView):
|
|
"CTRM Shipping Logistics Context"
|
|
__name__ = 'ctrm.reporting.operations.shipping.context'
|
|
|
|
from_date = fields.Date("From Date")
|
|
to_date = fields.Date("To Date")
|
|
supplier = fields.Many2One('party.party', "Supplier")
|
|
warehouse = fields.Many2One('stock.location', "Warehouse")
|
|
transport_type = fields.Selection([
|
|
(None, ''),
|
|
('vessel', 'Vessel'),
|
|
('truck', 'Truck'),
|
|
('other', 'Other'),
|
|
], "Transport Type")
|
|
vessel = fields.Many2One('trade.vessel', "Vessel")
|
|
state = fields.Char("State")
|
|
|
|
|
|
class CTRMShippingLogistics(ModelSQL, ModelView):
|
|
"CTRM Shipping Logistics"
|
|
__name__ = 'ctrm.reporting.operations.shipping'
|
|
|
|
shipment = fields.Many2One('stock.shipment.in', "Shipment")
|
|
reference = fields.Char("Reference")
|
|
supplier = fields.Many2One('party.party', "Supplier")
|
|
warehouse = fields.Many2One('stock.location', "Warehouse")
|
|
from_location = fields.Many2One('stock.location', "From")
|
|
to_location = fields.Many2One('stock.location', "To")
|
|
transport_type = fields.Selection([
|
|
(None, ''),
|
|
('vessel', 'Vessel'),
|
|
('truck', 'Truck'),
|
|
('other', 'Other'),
|
|
], "Transport Type")
|
|
vessel = fields.Many2One('trade.vessel', "Vessel")
|
|
state = fields.Char("State")
|
|
planned_date = fields.Date("Planned Date")
|
|
effective_date = fields.Date("Effective Date")
|
|
estimated_loading = fields.Date("Estimated Loading")
|
|
eta_pol = fields.Date("ETA POL")
|
|
eta = fields.Date("ETA")
|
|
etd = fields.Date("ETD")
|
|
discharged_date = fields.Date("Discharged Date")
|
|
booking = fields.Char("Booking")
|
|
bl_number = fields.Char("BL Number")
|
|
product = fields.Many2One('product.product', "Product")
|
|
quantity = fields.Numeric("Quantity", digits=(16, 5))
|
|
unit = fields.Many2One('product.uom', "Unit")
|
|
lot_count = fields.Integer("Lots")
|
|
|
|
@classmethod
|
|
def table_query(cls):
|
|
ShipmentIn = Pool().get('stock.shipment.in')
|
|
Lot = Pool().get('lot.lot')
|
|
|
|
shipment = ShipmentIn.__table__()
|
|
lot = Lot.__table__()
|
|
|
|
lot_query = lot.select(
|
|
lot.lot_shipment_in.as_('shipment'),
|
|
Count(lot.id).as_('lot_count'),
|
|
Sum(Coalesce(lot.lot_qt, 0)).as_('quantity'),
|
|
Max(lot.lot_product).as_('product'),
|
|
Max(lot.lot_unit_line).as_('unit'),
|
|
where=((lot.lot_shipment_in != Null)
|
|
& (lot.lot_type == 'physic')),
|
|
group_by=[lot.lot_shipment_in])
|
|
|
|
context = Transaction().context
|
|
logistics_date = Coalesce(
|
|
shipment.etad, shipment.eta, shipment.planned_date)
|
|
where = shipment.id != Null
|
|
if context.get('from_date'):
|
|
where &= logistics_date >= context['from_date']
|
|
if context.get('to_date'):
|
|
where &= logistics_date <= context['to_date']
|
|
if context.get('supplier'):
|
|
where &= shipment.supplier == context['supplier']
|
|
if context.get('warehouse'):
|
|
where &= shipment.warehouse == context['warehouse']
|
|
if context.get('transport_type'):
|
|
where &= shipment.transport_type == context['transport_type']
|
|
if context.get('vessel'):
|
|
where &= shipment.vessel == context['vessel']
|
|
if context.get('state'):
|
|
where &= shipment.state == context['state']
|
|
|
|
return (
|
|
shipment
|
|
.join(lot_query, 'LEFT',
|
|
condition=lot_query.shipment == shipment.id)
|
|
.select(
|
|
Literal(0).as_('create_uid'),
|
|
CurrentTimestamp().as_('create_date'),
|
|
Literal(None).as_('write_uid'),
|
|
Literal(None).as_('write_date'),
|
|
shipment.id.as_('id'),
|
|
shipment.id.as_('shipment'),
|
|
shipment.ref.as_('reference'),
|
|
shipment.supplier.as_('supplier'),
|
|
shipment.warehouse.as_('warehouse'),
|
|
shipment.from_location.as_('from_location'),
|
|
shipment.to_location.as_('to_location'),
|
|
shipment.transport_type.as_('transport_type'),
|
|
shipment.vessel.as_('vessel'),
|
|
shipment.state.as_('state'),
|
|
shipment.planned_date.as_('planned_date'),
|
|
shipment.effective_date.as_('effective_date'),
|
|
shipment.etl.as_('estimated_loading'),
|
|
shipment.eta.as_('eta_pol'),
|
|
shipment.etad.as_('eta'),
|
|
shipment.etd.as_('etd'),
|
|
shipment.unloaded.as_('discharged_date'),
|
|
shipment.booking.as_('booking'),
|
|
shipment.bl_number.as_('bl_number'),
|
|
lot_query.product.as_('product'),
|
|
Coalesce(lot_query.quantity, 0).as_('quantity'),
|
|
lot_query.unit.as_('unit'),
|
|
Coalesce(lot_query.lot_count, 0).as_('lot_count'),
|
|
where=where))
|
|
|
|
|
|
class CTRMInventoryContext(ModelView):
|
|
"CTRM Inventory Context"
|
|
__name__ = 'ctrm.reporting.operations.inventory.context'
|
|
|
|
product = fields.Many2One('product.product', "Product")
|
|
supplier = fields.Many2One('party.party', "Supplier")
|
|
client = fields.Many2One('party.party', "Client")
|
|
warehouse = fields.Many2One('stock.location', "Warehouse")
|
|
lot_status = fields.Selection([
|
|
(None, ''),
|
|
('forecast', 'Forecast'),
|
|
('loading', 'Loading'),
|
|
('transit', 'Transit'),
|
|
('destination', 'Destination'),
|
|
('stock', 'Stock'),
|
|
('delivered', 'Delivered'),
|
|
], "Status")
|
|
availability = fields.Selection([
|
|
(None, ''),
|
|
('available', 'Available'),
|
|
('reserved', 'Reserved'),
|
|
('locked', 'Locked'),
|
|
('prov', 'Prov. inv'),
|
|
('invoiced', 'Invoiced'),
|
|
], "Availability")
|
|
|
|
|
|
class CTRMInventory(ModelSQL, ModelView):
|
|
"CTRM Inventory"
|
|
__name__ = 'ctrm.reporting.operations.inventory'
|
|
|
|
lot = fields.Many2One('lot.lot', "Lot")
|
|
product = fields.Many2One('product.product', "Product")
|
|
supplier = fields.Many2One('party.party', "Supplier")
|
|
client = fields.Many2One('party.party', "Client")
|
|
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")
|
|
lot_status = fields.Selection([
|
|
(None, ''),
|
|
('forecast', 'Forecast'),
|
|
('loading', 'Loading'),
|
|
('transit', 'Transit'),
|
|
('destination', 'Destination'),
|
|
('stock', 'Stock'),
|
|
('delivered', 'Delivered'),
|
|
], "Status")
|
|
availability = fields.Selection([
|
|
(None, ''),
|
|
('available', 'Available'),
|
|
('reserved', 'Reserved'),
|
|
('locked', 'Locked'),
|
|
('prov', 'Prov. inv'),
|
|
('invoiced', 'Invoiced'),
|
|
], "Availability")
|
|
warehouse = fields.Many2One('stock.location', "Warehouse")
|
|
from_location = fields.Many2One('stock.location', "From")
|
|
to_location = fields.Many2One('stock.location', "To")
|
|
shipment_in = fields.Many2One('stock.shipment.in', "Shipment In")
|
|
shipment_out = fields.Many2One('stock.shipment.out', "Shipment Out")
|
|
shipment_internal = fields.Many2One(
|
|
'stock.shipment.internal', "Shipment Internal")
|
|
container = fields.Char("Container")
|
|
quantity = fields.Numeric("Quantity", digits=(16, 5))
|
|
unit = fields.Many2One('product.uom', "Unit")
|
|
|
|
@classmethod
|
|
def table_query(cls):
|
|
pool = Pool()
|
|
Lot = pool.get('lot.lot')
|
|
PurchaseLine = pool.get('purchase.line')
|
|
Purchase = pool.get('purchase.purchase')
|
|
SaleLine = pool.get('sale.line')
|
|
Sale = pool.get('sale.sale')
|
|
ShipmentIn = pool.get('stock.shipment.in')
|
|
|
|
lot = Lot.__table__()
|
|
purchase_line = PurchaseLine.__table__()
|
|
purchase = Purchase.__table__()
|
|
sale_line = SaleLine.__table__()
|
|
sale = Sale.__table__()
|
|
shipment_in = ShipmentIn.__table__()
|
|
|
|
context = Transaction().context
|
|
warehouse = shipment_in.warehouse
|
|
from_location = shipment_in.from_location
|
|
to_location = shipment_in.to_location
|
|
where = lot.lot_type == 'physic'
|
|
if context.get('product'):
|
|
where &= lot.lot_product == context['product']
|
|
if context.get('supplier'):
|
|
where &= purchase.party == context['supplier']
|
|
if context.get('client'):
|
|
where &= sale.party == context['client']
|
|
if context.get('warehouse'):
|
|
where &= warehouse == context['warehouse']
|
|
if context.get('lot_status'):
|
|
where &= lot.lot_status == context['lot_status']
|
|
if context.get('availability'):
|
|
where &= lot.lot_av == context['availability']
|
|
|
|
return (
|
|
lot
|
|
.join(purchase_line, 'LEFT',
|
|
condition=lot.line == purchase_line.id)
|
|
.join(purchase, 'LEFT',
|
|
condition=purchase_line.purchase == purchase.id)
|
|
.join(sale_line, 'LEFT',
|
|
condition=lot.sale_line == sale_line.id)
|
|
.join(sale, 'LEFT',
|
|
condition=sale_line.sale == sale.id)
|
|
.join(shipment_in, 'LEFT',
|
|
condition=lot.lot_shipment_in == shipment_in.id)
|
|
.select(
|
|
Literal(0).as_('create_uid'),
|
|
CurrentTimestamp().as_('create_date'),
|
|
Literal(None).as_('write_uid'),
|
|
Literal(None).as_('write_date'),
|
|
lot.id.as_('id'),
|
|
lot.id.as_('lot'),
|
|
lot.lot_product.as_('product'),
|
|
purchase.party.as_('supplier'),
|
|
sale.party.as_('client'),
|
|
purchase.id.as_('purchase'),
|
|
lot.line.as_('purchase_line'),
|
|
sale.id.as_('sale'),
|
|
lot.sale_line.as_('sale_line'),
|
|
lot.lot_status.as_('lot_status'),
|
|
lot.lot_av.as_('availability'),
|
|
warehouse.as_('warehouse'),
|
|
from_location.as_('from_location'),
|
|
to_location.as_('to_location'),
|
|
lot.lot_shipment_in.as_('shipment_in'),
|
|
lot.lot_shipment_out.as_('shipment_out'),
|
|
lot.lot_shipment_internal.as_('shipment_internal'),
|
|
lot.lot_container.as_('container'),
|
|
Coalesce(lot.lot_qt, 0).as_('quantity'),
|
|
lot.lot_unit_line.as_('unit'),
|
|
where=where))
|
|
|
|
|
|
class CTRMContractPerformanceContext(ModelView):
|
|
"CTRM Contract Performance Context"
|
|
__name__ = 'ctrm.reporting.operations.contract.context'
|
|
|
|
side = fields.Selection([
|
|
(None, ''),
|
|
('purchase', 'Purchase'),
|
|
('sale', 'Sale'),
|
|
], "Side")
|
|
product = fields.Many2One('product.product', "Product")
|
|
counterparty = fields.Many2One('party.party', "Counterparty")
|
|
delivery_period = fields.Many2One('product.month', "Delivery Period")
|
|
status = fields.Selection([
|
|
(None, ''),
|
|
('under', 'Under delivery'),
|
|
('in_tolerance', 'In tolerance'),
|
|
('over', 'Over delivery'),
|
|
], "Status")
|
|
open_only = fields.Boolean("Open Only")
|
|
|
|
|
|
class CTRMContractPerformance(ModelSQL, ModelView):
|
|
"CTRM Contract Performance"
|
|
__name__ = 'ctrm.reporting.operations.contract'
|
|
|
|
side = fields.Selection([
|
|
('purchase', 'Purchase'),
|
|
('sale', 'Sale'),
|
|
], "Side")
|
|
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")
|
|
counterparty = fields.Many2One('party.party', "Counterparty")
|
|
product = fields.Many2One('product.product', "Product")
|
|
delivery_period = fields.Many2One('product.month', "Delivery Period")
|
|
from_date = fields.Date("From")
|
|
to_date = fields.Date("To")
|
|
contract_quantity = fields.Numeric("Contract Quantity", digits=(16, 5))
|
|
actual_quantity = fields.Numeric("Actual Quantity", digits=(16, 5))
|
|
variance_quantity = fields.Numeric("Variance", digits=(16, 5))
|
|
tolerance_min = fields.Numeric("Tolerance Min %", digits=(16, 5))
|
|
tolerance_max = fields.Numeric("Tolerance Max %", digits=(16, 5))
|
|
status = fields.Selection([
|
|
('under', 'Under delivery'),
|
|
('in_tolerance', 'In tolerance'),
|
|
('over', 'Over delivery'),
|
|
], "Status")
|
|
finished = fields.Boolean("Finished")
|
|
unit = fields.Many2One('product.uom', "Unit")
|
|
lot_count = fields.Integer("Lots")
|
|
|
|
@classmethod
|
|
def table_query(cls):
|
|
pool = Pool()
|
|
Lot = pool.get('lot.lot')
|
|
PurchaseLine = pool.get('purchase.line')
|
|
Purchase = pool.get('purchase.purchase')
|
|
SaleLine = pool.get('sale.line')
|
|
Sale = pool.get('sale.sale')
|
|
|
|
lot = Lot.__table__()
|
|
purchase_line = PurchaseLine.__table__()
|
|
purchase = Purchase.__table__()
|
|
sale_line = SaleLine.__table__()
|
|
sale = Sale.__table__()
|
|
|
|
purchase_contract_quantity = Coalesce(
|
|
purchase_line.quantity_theorical, purchase_line.quantity, 0)
|
|
purchase_tolerance_min = Coalesce(
|
|
purchase_line.tol_min, purchase.tol_min, 0)
|
|
purchase_tolerance_max = Coalesce(
|
|
purchase_line.tol_max, purchase.tol_max, 0)
|
|
purchase_actual_quantity = Sum(Coalesce(lot.lot_qt, 0))
|
|
purchase_min_quantity = purchase_contract_quantity * (
|
|
Literal(1) - (purchase_tolerance_min / Literal(100)))
|
|
purchase_max_quantity = purchase_contract_quantity * (
|
|
Literal(1) + (purchase_tolerance_max / Literal(100)))
|
|
purchase_status = Case(
|
|
(purchase_actual_quantity < purchase_min_quantity, 'under'),
|
|
(purchase_actual_quantity > purchase_max_quantity, 'over'),
|
|
else_='in_tolerance')
|
|
|
|
sale_contract_quantity = Coalesce(
|
|
sale_line.quantity_theorical, sale_line.quantity, 0)
|
|
sale_tolerance_min = Coalesce(sale_line.tol_min, sale.tol_min, 0)
|
|
sale_tolerance_max = Coalesce(sale_line.tol_max, sale.tol_max, 0)
|
|
sale_actual_quantity = Sum(Coalesce(lot.lot_qt, 0))
|
|
sale_min_quantity = sale_contract_quantity * (
|
|
Literal(1) - (sale_tolerance_min / Literal(100)))
|
|
sale_max_quantity = sale_contract_quantity * (
|
|
Literal(1) + (sale_tolerance_max / Literal(100)))
|
|
sale_status = Case(
|
|
(sale_actual_quantity < sale_min_quantity, 'under'),
|
|
(sale_actual_quantity > sale_max_quantity, 'over'),
|
|
else_='in_tolerance')
|
|
|
|
context = Transaction().context
|
|
purchase_where = (lot.lot_type == 'physic') & (lot.line != Null)
|
|
if context.get('product'):
|
|
purchase_where &= purchase_line.product == context['product']
|
|
if context.get('counterparty'):
|
|
purchase_where &= purchase.party == context['counterparty']
|
|
if context.get('delivery_period'):
|
|
purchase_where &= purchase_line.del_period == (
|
|
context['delivery_period'])
|
|
if context.get('open_only'):
|
|
purchase_where &= purchase_line.finished == False
|
|
purchase_query = (
|
|
lot
|
|
.join(purchase_line, condition=lot.line == purchase_line.id)
|
|
.join(purchase, condition=purchase_line.purchase == purchase.id)
|
|
.select(
|
|
Literal('purchase').as_('side'),
|
|
purchase.id.as_('purchase'),
|
|
lot.line.as_('purchase_line'),
|
|
Literal(None).as_('sale'),
|
|
Literal(None).as_('sale_line'),
|
|
purchase.party.as_('counterparty'),
|
|
purchase_line.product.as_('product'),
|
|
purchase_line.del_period.as_('delivery_period'),
|
|
purchase_line.from_del.as_('from_date'),
|
|
purchase_line.to_del.as_('to_date'),
|
|
purchase_contract_quantity.as_('contract_quantity'),
|
|
purchase_actual_quantity.as_('actual_quantity'),
|
|
(purchase_actual_quantity - purchase_contract_quantity).as_(
|
|
'variance_quantity'),
|
|
purchase_tolerance_min.as_('tolerance_min'),
|
|
purchase_tolerance_max.as_('tolerance_max'),
|
|
purchase_status.as_('status'),
|
|
purchase_line.finished.as_('finished'),
|
|
purchase_line.unit.as_('unit'),
|
|
Count(lot.id).as_('lot_count'),
|
|
where=purchase_where,
|
|
group_by=[
|
|
purchase.id,
|
|
lot.line,
|
|
purchase.party,
|
|
purchase_line.product,
|
|
purchase_line.del_period,
|
|
purchase_line.from_del,
|
|
purchase_line.to_del,
|
|
purchase_contract_quantity,
|
|
purchase_tolerance_min,
|
|
purchase_tolerance_max,
|
|
purchase_line.finished,
|
|
purchase_line.unit,
|
|
]))
|
|
|
|
sale_where = (lot.lot_type == 'physic') & (lot.sale_line != Null)
|
|
if context.get('product'):
|
|
sale_where &= sale_line.product == context['product']
|
|
if context.get('counterparty'):
|
|
sale_where &= sale.party == context['counterparty']
|
|
if context.get('delivery_period'):
|
|
sale_where &= sale_line.del_period == context['delivery_period']
|
|
if context.get('open_only'):
|
|
sale_where &= sale_line.finished == False
|
|
sale_query = (
|
|
lot
|
|
.join(sale_line, condition=lot.sale_line == sale_line.id)
|
|
.join(sale, condition=sale_line.sale == sale.id)
|
|
.select(
|
|
Literal('sale').as_('side'),
|
|
Literal(None).as_('purchase'),
|
|
Literal(None).as_('purchase_line'),
|
|
sale.id.as_('sale'),
|
|
lot.sale_line.as_('sale_line'),
|
|
sale.party.as_('counterparty'),
|
|
sale_line.product.as_('product'),
|
|
sale_line.del_period.as_('delivery_period'),
|
|
sale_line.from_del.as_('from_date'),
|
|
sale_line.to_del.as_('to_date'),
|
|
sale_contract_quantity.as_('contract_quantity'),
|
|
sale_actual_quantity.as_('actual_quantity'),
|
|
(sale_actual_quantity - sale_contract_quantity).as_(
|
|
'variance_quantity'),
|
|
sale_tolerance_min.as_('tolerance_min'),
|
|
sale_tolerance_max.as_('tolerance_max'),
|
|
sale_status.as_('status'),
|
|
sale_line.finished.as_('finished'),
|
|
sale_line.unit.as_('unit'),
|
|
Count(lot.id).as_('lot_count'),
|
|
where=sale_where,
|
|
group_by=[
|
|
sale.id,
|
|
lot.sale_line,
|
|
sale.party,
|
|
sale_line.product,
|
|
sale_line.del_period,
|
|
sale_line.from_del,
|
|
sale_line.to_del,
|
|
sale_contract_quantity,
|
|
sale_tolerance_min,
|
|
sale_tolerance_max,
|
|
sale_line.finished,
|
|
sale_line.unit,
|
|
]))
|
|
|
|
side = context.get('side')
|
|
if side == 'purchase':
|
|
grouped = Union(purchase_query, purchase_query, all_=False)
|
|
elif side == 'sale':
|
|
grouped = Union(sale_query, sale_query, all_=False)
|
|
else:
|
|
grouped = Union(purchase_query, sale_query, all_=True)
|
|
|
|
report_id = RowNumber(window=Window([],
|
|
order_by=[grouped.side, grouped.purchase_line,
|
|
grouped.sale_line]))
|
|
outer_where = grouped.side != Null
|
|
if context.get('status'):
|
|
outer_where &= grouped.status == context['status']
|
|
|
|
return grouped.select(
|
|
Literal(0).as_('create_uid'),
|
|
CurrentTimestamp().as_('create_date'),
|
|
Literal(None).as_('write_uid'),
|
|
Literal(None).as_('write_date'),
|
|
report_id.as_('id'),
|
|
grouped.side.as_('side'),
|
|
grouped.purchase.as_('purchase'),
|
|
grouped.purchase_line.as_('purchase_line'),
|
|
grouped.sale.as_('sale'),
|
|
grouped.sale_line.as_('sale_line'),
|
|
grouped.counterparty.as_('counterparty'),
|
|
grouped.product.as_('product'),
|
|
grouped.delivery_period.as_('delivery_period'),
|
|
grouped.from_date.as_('from_date'),
|
|
grouped.to_date.as_('to_date'),
|
|
grouped.contract_quantity.as_('contract_quantity'),
|
|
grouped.actual_quantity.as_('actual_quantity'),
|
|
grouped.variance_quantity.as_('variance_quantity'),
|
|
grouped.tolerance_min.as_('tolerance_min'),
|
|
grouped.tolerance_max.as_('tolerance_max'),
|
|
grouped.status.as_('status'),
|
|
grouped.finished.as_('finished'),
|
|
grouped.unit.as_('unit'),
|
|
grouped.lot_count.as_('lot_count'),
|
|
where=outer_where)
|
|
|
|
|
|
class CTRMSchedulingContext(ModelView):
|
|
"CTRM Scheduling Context"
|
|
__name__ = 'ctrm.reporting.operations.scheduling.context'
|
|
|
|
from_date = fields.Date("From Date")
|
|
to_date = fields.Date("To Date")
|
|
product = fields.Many2One('product.product', "Product")
|
|
counterparty = fields.Many2One('party.party', "Counterparty")
|
|
warehouse = fields.Many2One('stock.location', "Warehouse")
|
|
shipment_state = fields.Char("Shipment State")
|
|
lot_status = fields.Selection([
|
|
(None, ''),
|
|
('forecast', 'Forecast'),
|
|
('loading', 'Loading'),
|
|
('transit', 'Transit'),
|
|
('destination', 'Destination'),
|
|
('stock', 'Stock'),
|
|
('delivered', 'Delivered'),
|
|
], "Lot Status")
|
|
|
|
|
|
class CTRMScheduling(ModelSQL, ModelView):
|
|
"CTRM Scheduling"
|
|
__name__ = 'ctrm.reporting.operations.scheduling'
|
|
|
|
lot = fields.Many2One('lot.lot', "Lot")
|
|
product = fields.Many2One('product.product', "Product")
|
|
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")
|
|
counterparty = fields.Many2One('party.party', "Counterparty")
|
|
shipment_in = fields.Many2One('stock.shipment.in', "Shipment")
|
|
warehouse = fields.Many2One('stock.location', "Warehouse")
|
|
from_location = fields.Many2One('stock.location', "From")
|
|
to_location = fields.Many2One('stock.location', "To")
|
|
delivery_period = fields.Many2One('product.month', "Delivery Period")
|
|
contract_from = fields.Date("Contract From")
|
|
contract_to = fields.Date("Contract To")
|
|
scheduled_date = fields.Date("Scheduled Date")
|
|
eta = fields.Date("ETA")
|
|
etd = fields.Date("ETD")
|
|
actual_date = fields.Date("Actual Date")
|
|
lot_status = fields.Selection([
|
|
(None, ''),
|
|
('forecast', 'Forecast'),
|
|
('loading', 'Loading'),
|
|
('transit', 'Transit'),
|
|
('destination', 'Destination'),
|
|
('stock', 'Stock'),
|
|
('delivered', 'Delivered'),
|
|
], "Lot Status")
|
|
shipment_state = fields.Char("Shipment State")
|
|
quantity = fields.Numeric("Quantity", digits=(16, 5))
|
|
unit = fields.Many2One('product.uom', "Unit")
|
|
|
|
@classmethod
|
|
def table_query(cls):
|
|
pool = Pool()
|
|
Lot = pool.get('lot.lot')
|
|
PurchaseLine = pool.get('purchase.line')
|
|
Purchase = pool.get('purchase.purchase')
|
|
SaleLine = pool.get('sale.line')
|
|
Sale = pool.get('sale.sale')
|
|
ShipmentIn = pool.get('stock.shipment.in')
|
|
|
|
lot = Lot.__table__()
|
|
purchase_line = PurchaseLine.__table__()
|
|
purchase = Purchase.__table__()
|
|
sale_line = SaleLine.__table__()
|
|
sale = Sale.__table__()
|
|
shipment = ShipmentIn.__table__()
|
|
|
|
counterparty = Case(
|
|
(lot.line != Null, purchase.party), else_=sale.party)
|
|
delivery_period = Coalesce(
|
|
purchase_line.del_period, sale_line.del_period)
|
|
contract_from = Coalesce(purchase_line.from_del, sale_line.from_del)
|
|
contract_to = Coalesce(purchase_line.to_del, sale_line.to_del)
|
|
scheduled_date = Coalesce(
|
|
shipment.etad, shipment.eta, shipment.planned_date,
|
|
contract_from)
|
|
|
|
context = Transaction().context
|
|
where = lot.lot_type == 'physic'
|
|
if context.get('from_date'):
|
|
where &= scheduled_date >= context['from_date']
|
|
if context.get('to_date'):
|
|
where &= scheduled_date <= context['to_date']
|
|
if context.get('product'):
|
|
where &= lot.lot_product == context['product']
|
|
if context.get('counterparty'):
|
|
where &= counterparty == context['counterparty']
|
|
if context.get('warehouse'):
|
|
where &= shipment.warehouse == context['warehouse']
|
|
if context.get('shipment_state'):
|
|
where &= shipment.state == context['shipment_state']
|
|
if context.get('lot_status'):
|
|
where &= lot.lot_status == context['lot_status']
|
|
|
|
return (
|
|
lot
|
|
.join(purchase_line, 'LEFT',
|
|
condition=lot.line == purchase_line.id)
|
|
.join(purchase, 'LEFT',
|
|
condition=purchase_line.purchase == purchase.id)
|
|
.join(sale_line, 'LEFT',
|
|
condition=lot.sale_line == sale_line.id)
|
|
.join(sale, 'LEFT',
|
|
condition=sale_line.sale == sale.id)
|
|
.join(shipment, 'LEFT',
|
|
condition=lot.lot_shipment_in == shipment.id)
|
|
.select(
|
|
Literal(0).as_('create_uid'),
|
|
CurrentTimestamp().as_('create_date'),
|
|
Literal(None).as_('write_uid'),
|
|
Literal(None).as_('write_date'),
|
|
lot.id.as_('id'),
|
|
lot.id.as_('lot'),
|
|
lot.lot_product.as_('product'),
|
|
purchase.id.as_('purchase'),
|
|
lot.line.as_('purchase_line'),
|
|
sale.id.as_('sale'),
|
|
lot.sale_line.as_('sale_line'),
|
|
counterparty.as_('counterparty'),
|
|
lot.lot_shipment_in.as_('shipment_in'),
|
|
shipment.warehouse.as_('warehouse'),
|
|
shipment.from_location.as_('from_location'),
|
|
shipment.to_location.as_('to_location'),
|
|
delivery_period.as_('delivery_period'),
|
|
contract_from.as_('contract_from'),
|
|
contract_to.as_('contract_to'),
|
|
scheduled_date.as_('scheduled_date'),
|
|
shipment.etad.as_('eta'),
|
|
shipment.etd.as_('etd'),
|
|
shipment.effective_date.as_('actual_date'),
|
|
lot.lot_status.as_('lot_status'),
|
|
shipment.state.as_('shipment_state'),
|
|
Coalesce(lot.lot_qt, 0).as_('quantity'),
|
|
lot.lot_unit_line.as_('unit'),
|
|
where=where))
|
|
|
|
|
|
class CTRMFinanceDateContextMixin:
|
|
from_date = fields.Date("From Date")
|
|
to_date = fields.Date("To Date")
|
|
party = fields.Many2One('party.party', "Party")
|
|
currency = fields.Many2One('currency.currency', "Currency")
|
|
|
|
@classmethod
|
|
def default_to_date(cls):
|
|
Date = Pool().get('ir.date')
|
|
return Date.today()
|
|
|
|
|
|
class CTRMAccrualsContext(CTRMFinanceDateContextMixin, ModelView):
|
|
"CTRM Accruals Context"
|
|
__name__ = 'ctrm.reporting.finance.accruals.context'
|
|
|
|
product = fields.Many2One('product.product', "Product")
|
|
purchase = fields.Many2One('purchase.purchase', "Purchase")
|
|
sale = fields.Many2One('sale.sale', "Sale")
|
|
type = fields.Selection([
|
|
(None, ''),
|
|
('physical', 'Physical'),
|
|
('fee', 'Fee'),
|
|
('derivative', 'Derivative'),
|
|
], "Accrual Type")
|
|
|
|
|
|
class CTRMAccruals(ModelSQL, ModelView):
|
|
"CTRM Accruals"
|
|
__name__ = 'ctrm.reporting.finance.accruals'
|
|
|
|
valuation_date = fields.Date("Valuation Date")
|
|
accrual_type = fields.Selection([
|
|
('physical', 'Physical'),
|
|
('fee', 'Fee'),
|
|
('derivative', 'Derivative'),
|
|
], "Accrual Type")
|
|
lot = fields.Many2One('lot.lot', "Lot")
|
|
product = fields.Many2One('product.product', "Product")
|
|
party = fields.Many2One('party.party', "Party")
|
|
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")
|
|
reference = fields.Char("Reference")
|
|
quantity = fields.Numeric("Quantity", digits=(16, 5))
|
|
unit = fields.Many2One('product.uom', "Unit")
|
|
amount = fields.Numeric("Amount", digits=(16, 2))
|
|
currency = fields.Many2One('currency.currency', "Currency")
|
|
state = fields.Char("State")
|
|
|
|
@classmethod
|
|
def table_query(cls):
|
|
pool = Pool()
|
|
ValuationLine = pool.get('valuation.valuation.line')
|
|
Lot = pool.get('lot.lot')
|
|
val = ValuationLine.__table__()
|
|
lot = Lot.__table__()
|
|
|
|
accrual_type = Case(
|
|
(val.type == 'derivative', 'derivative'),
|
|
(val.type.in_(['line fee', 'pur. fee', 'sale fee',
|
|
'shipment fee']), 'fee'),
|
|
else_='physical')
|
|
context = Transaction().context
|
|
where = (
|
|
val.type.in_(ALL_VALUATION_TYPES)
|
|
& ((val.lot == Null)
|
|
| ((lot.invoice_line == Null)
|
|
& (lot.sale_invoice_line == Null))))
|
|
if context.get('from_date'):
|
|
where &= val.date >= context['from_date']
|
|
if context.get('to_date'):
|
|
where &= val.date <= context['to_date']
|
|
if context.get('party'):
|
|
where &= val.counterparty == context['party']
|
|
if context.get('currency'):
|
|
where &= val.currency == context['currency']
|
|
if context.get('product'):
|
|
where &= val.product == context['product']
|
|
if context.get('purchase'):
|
|
where &= val.purchase == context['purchase']
|
|
if context.get('sale'):
|
|
where &= val.sale == context['sale']
|
|
if context.get('type'):
|
|
where &= accrual_type == context['type']
|
|
|
|
return (
|
|
val
|
|
.join(lot, 'LEFT', condition=val.lot == lot.id)
|
|
.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'),
|
|
accrual_type.as_('accrual_type'),
|
|
val.lot.as_('lot'),
|
|
val.product.as_('product'),
|
|
val.counterparty.as_('party'),
|
|
val.purchase.as_('purchase'),
|
|
val.line.as_('purchase_line'),
|
|
val.sale.as_('sale'),
|
|
val.sale_line.as_('sale_line'),
|
|
val.reference.as_('reference'),
|
|
val.quantity.as_('quantity'),
|
|
val.unit.as_('unit'),
|
|
val.amount.as_('amount'),
|
|
val.currency.as_('currency'),
|
|
val.state.as_('state'),
|
|
where=where))
|
|
|
|
|
|
class CTRMSettlementsContext(CTRMFinanceDateContextMixin, ModelView):
|
|
"CTRM Settlements Context"
|
|
__name__ = 'ctrm.reporting.finance.settlements.context'
|
|
|
|
invoice_type = fields.Selection([
|
|
(None, ''),
|
|
('in', 'Supplier'),
|
|
('out', 'Customer'),
|
|
], "Invoice Type")
|
|
state = fields.Selection([
|
|
(None, ''),
|
|
('draft', 'Draft'),
|
|
('validated', 'Validated'),
|
|
('posted', 'Posted'),
|
|
('paid', 'Paid'),
|
|
('cancelled', 'Cancelled'),
|
|
], "State")
|
|
payment_status = fields.Selection([
|
|
(None, ''),
|
|
('not', 'Not Paid'),
|
|
('partial', 'Partially Paid'),
|
|
('paid', 'Paid'),
|
|
], "Payment Status")
|
|
|
|
|
|
class CTRMSettlements(ModelSQL, ModelView):
|
|
"CTRM Settlements and Invoicing"
|
|
__name__ = 'ctrm.reporting.finance.settlements'
|
|
|
|
invoice = fields.Many2One('account.invoice', "Invoice")
|
|
invoice_type = fields.Selection([
|
|
('in', 'Supplier'),
|
|
('out', 'Customer'),
|
|
], "Invoice Type")
|
|
number = fields.Char("Number")
|
|
reference = fields.Char("Reference")
|
|
invoice_date = fields.Date("Invoice Date")
|
|
party = fields.Many2One('party.party', "Party")
|
|
state = fields.Char("State")
|
|
currency = fields.Many2One('currency.currency', "Currency")
|
|
invoice_amount = fields.Numeric("Invoice Amount", digits=(16, 2))
|
|
paid_amount = fields.Numeric("Paid Amount", digits=(16, 2))
|
|
open_amount = fields.Numeric("Open Amount", digits=(16, 2))
|
|
payment_status = fields.Selection([
|
|
('not', 'Not Paid'),
|
|
('partial', 'Partially Paid'),
|
|
('paid', 'Paid'),
|
|
], "Payment Status")
|
|
move = fields.Many2One('account.move', "Move")
|
|
reconciliation = fields.Integer("Reconciliation")
|
|
|
|
@classmethod
|
|
def table_query(cls):
|
|
pool = Pool()
|
|
Invoice = pool.get('account.invoice')
|
|
InvoicePayment = pool.get('account.invoice-account.move.line')
|
|
MoveLine = pool.get('account.move.line')
|
|
|
|
invoice = Invoice.__table__()
|
|
invoice_payment = InvoicePayment.__table__()
|
|
line = MoveLine.__table__()
|
|
|
|
amount = Coalesce(invoice.total_amount_cache, 0)
|
|
paid = Coalesce(Sum(line.amount_second_currency), 0)
|
|
open_amount = amount - paid
|
|
payment_status = Case(
|
|
(open_amount == 0, 'paid'),
|
|
(paid != 0, 'partial'),
|
|
else_='not')
|
|
|
|
context = Transaction().context
|
|
where = invoice.id != Null
|
|
if context.get('from_date'):
|
|
where &= invoice.invoice_date >= context['from_date']
|
|
if context.get('to_date'):
|
|
where &= invoice.invoice_date <= context['to_date']
|
|
if context.get('party'):
|
|
where &= invoice.party == context['party']
|
|
if context.get('currency'):
|
|
where &= invoice.currency == context['currency']
|
|
if context.get('invoice_type'):
|
|
where &= invoice.type == context['invoice_type']
|
|
if context.get('state'):
|
|
where &= invoice.state == context['state']
|
|
|
|
grouped = (
|
|
invoice
|
|
.join(invoice_payment, 'LEFT',
|
|
condition=invoice_payment.invoice == invoice.id)
|
|
.join(line, 'LEFT',
|
|
condition=line.id == invoice_payment.line)
|
|
.select(
|
|
invoice.id.as_('id'),
|
|
invoice.id.as_('invoice'),
|
|
invoice.type.as_('invoice_type'),
|
|
invoice.number.as_('number'),
|
|
invoice.reference.as_('reference'),
|
|
invoice.invoice_date.as_('invoice_date'),
|
|
invoice.party.as_('party'),
|
|
invoice.state.as_('state'),
|
|
invoice.currency.as_('currency'),
|
|
amount.as_('invoice_amount'),
|
|
paid.as_('paid_amount'),
|
|
open_amount.as_('open_amount'),
|
|
payment_status.as_('payment_status'),
|
|
invoice.move.as_('move'),
|
|
Max(line.reconciliation).as_('reconciliation'),
|
|
where=where,
|
|
group_by=[
|
|
invoice.id, invoice.type, invoice.number,
|
|
invoice.reference, invoice.invoice_date, invoice.party,
|
|
invoice.state, invoice.currency,
|
|
invoice.total_amount_cache, invoice.move,
|
|
]))
|
|
outer_where = grouped.id != Null
|
|
if context.get('payment_status'):
|
|
outer_where &= grouped.payment_status == context['payment_status']
|
|
|
|
return grouped.select(
|
|
Literal(0).as_('create_uid'),
|
|
CurrentTimestamp().as_('create_date'),
|
|
Literal(None).as_('write_uid'),
|
|
Literal(None).as_('write_date'),
|
|
grouped.id.as_('id'),
|
|
grouped.invoice.as_('invoice'),
|
|
grouped.invoice_type.as_('invoice_type'),
|
|
grouped.number.as_('number'),
|
|
grouped.reference.as_('reference'),
|
|
grouped.invoice_date.as_('invoice_date'),
|
|
grouped.party.as_('party'),
|
|
grouped.state.as_('state'),
|
|
grouped.currency.as_('currency'),
|
|
grouped.invoice_amount.as_('invoice_amount'),
|
|
grouped.paid_amount.as_('paid_amount'),
|
|
grouped.open_amount.as_('open_amount'),
|
|
grouped.payment_status.as_('payment_status'),
|
|
grouped.move.as_('move'),
|
|
grouped.reconciliation.as_('reconciliation'),
|
|
where=outer_where)
|
|
|
|
|
|
class CTRMCashFlowContext(CTRMFinanceDateContextMixin, ModelView):
|
|
"CTRM Cash Flow Context"
|
|
__name__ = 'ctrm.reporting.finance.cashflow.context'
|
|
|
|
overdue_only = fields.Boolean("Overdue Only")
|
|
|
|
|
|
class CTRMCashFlow(ModelSQL, ModelView):
|
|
"CTRM Cash Flow Forecast"
|
|
__name__ = 'ctrm.reporting.finance.cashflow'
|
|
|
|
move_line = fields.Many2One('account.move.line', "Move Line")
|
|
move = fields.Many2One('account.move', "Move")
|
|
due_date = fields.Date("Due Date")
|
|
posting_date = fields.Date("Posting Date")
|
|
party = fields.Many2One('party.party', "Party")
|
|
account = fields.Many2One('account.account', "Account")
|
|
currency = fields.Many2One('currency.currency', "Currency")
|
|
amount = fields.Numeric("Amount", digits=(16, 2))
|
|
debit = fields.Numeric("Debit", digits=(16, 2))
|
|
credit = fields.Numeric("Credit", digits=(16, 2))
|
|
second_currency = fields.Many2One('currency.currency', "Second Currency")
|
|
amount_second_currency = fields.Numeric(
|
|
"Amount Second Currency", digits=(16, 2))
|
|
description = fields.Char("Description")
|
|
reference = fields.Char("Reference")
|
|
journal = fields.Many2One('account.journal', "Journal")
|
|
|
|
@classmethod
|
|
def table_query(cls):
|
|
pool = Pool()
|
|
MoveLine = pool.get('account.move.line')
|
|
Move = pool.get('account.move')
|
|
Company = pool.get('company.company')
|
|
|
|
line = MoveLine.__table__()
|
|
move = Move.__table__()
|
|
company = Company.__table__()
|
|
currency = Coalesce(line.second_currency, company.currency)
|
|
amount = Coalesce(line.debit, 0) - Coalesce(line.credit, 0)
|
|
|
|
context = Transaction().context
|
|
where = (
|
|
(line.reconciliation == Null)
|
|
& (line.maturity_date != Null))
|
|
if context.get('from_date'):
|
|
where &= line.maturity_date >= context['from_date']
|
|
if context.get('to_date'):
|
|
where &= line.maturity_date <= context['to_date']
|
|
if context.get('party'):
|
|
where &= line.party == context['party']
|
|
if context.get('currency'):
|
|
where &= currency == context['currency']
|
|
if context.get('overdue_only'):
|
|
Date = Pool().get('ir.date')
|
|
where &= line.maturity_date < Date.today()
|
|
|
|
return (
|
|
line
|
|
.join(move, condition=line.move == move.id)
|
|
.join(company, condition=move.company == company.id)
|
|
.select(
|
|
Literal(0).as_('create_uid'),
|
|
CurrentTimestamp().as_('create_date'),
|
|
Literal(None).as_('write_uid'),
|
|
Literal(None).as_('write_date'),
|
|
line.id.as_('id'),
|
|
line.id.as_('move_line'),
|
|
line.move.as_('move'),
|
|
line.maturity_date.as_('due_date'),
|
|
move.date.as_('posting_date'),
|
|
line.party.as_('party'),
|
|
line.account.as_('account'),
|
|
currency.as_('currency'),
|
|
amount.as_('amount'),
|
|
line.debit.as_('debit'),
|
|
line.credit.as_('credit'),
|
|
line.second_currency.as_('second_currency'),
|
|
line.amount_second_currency.as_('amount_second_currency'),
|
|
line.description.as_('description'),
|
|
Coalesce(line.ext_ref, move.ext_ref).as_('reference'),
|
|
move.journal.as_('journal'),
|
|
where=where))
|
|
|
|
|
|
class CTRMGLReconciliationContext(CTRMFinanceDateContextMixin, ModelView):
|
|
"CTRM GL Reconciliation Context"
|
|
__name__ = 'ctrm.reporting.finance.gl.context'
|
|
|
|
account = fields.Many2One('account.account', "Account")
|
|
lot = fields.Many2One('lot.lot', "Lot")
|
|
unreconciled_only = fields.Boolean("Unreconciled Only")
|
|
|
|
|
|
class CTRMGLReconciliation(ModelSQL, ModelView):
|
|
"CTRM GL Reconciliation"
|
|
__name__ = 'ctrm.reporting.finance.gl'
|
|
|
|
move_line = fields.Many2One('account.move.line', "Move Line")
|
|
move = fields.Many2One('account.move', "Move")
|
|
posting_date = fields.Date("Posting Date")
|
|
journal = fields.Many2One('account.journal', "Journal")
|
|
account = fields.Many2One('account.account', "Account")
|
|
party = fields.Many2One('party.party', "Party")
|
|
lot = fields.Many2One('lot.lot', "Lot")
|
|
fee = fields.Many2One('fee.fee', "Fee")
|
|
invoice = fields.Many2One('account.invoice', "Invoice")
|
|
currency = fields.Many2One('currency.currency', "Currency")
|
|
debit = fields.Numeric("Debit", digits=(16, 2))
|
|
credit = fields.Numeric("Credit", digits=(16, 2))
|
|
balance = fields.Numeric("Balance", digits=(16, 2))
|
|
second_currency = fields.Many2One('currency.currency', "Second Currency")
|
|
amount_second_currency = fields.Numeric(
|
|
"Amount Second Currency", digits=(16, 2))
|
|
reconciliation = fields.Integer("Reconciliation")
|
|
move_state = fields.Char("Move State")
|
|
description = fields.Char("Description")
|
|
reference = fields.Char("Reference")
|
|
|
|
@classmethod
|
|
def table_query(cls):
|
|
pool = Pool()
|
|
MoveLine = pool.get('account.move.line')
|
|
Move = pool.get('account.move')
|
|
Invoice = pool.get('account.invoice')
|
|
Company = pool.get('company.company')
|
|
|
|
line = MoveLine.__table__()
|
|
move = Move.__table__()
|
|
invoice = Invoice.__table__()
|
|
company = Company.__table__()
|
|
currency = Coalesce(line.second_currency, company.currency)
|
|
balance = Coalesce(line.debit, 0) - Coalesce(line.credit, 0)
|
|
|
|
context = Transaction().context
|
|
where = (line.lot != Null) | (line.fee != Null) | (invoice.id != Null)
|
|
if context.get('from_date'):
|
|
where &= move.date >= context['from_date']
|
|
if context.get('to_date'):
|
|
where &= move.date <= context['to_date']
|
|
if context.get('party'):
|
|
where &= line.party == context['party']
|
|
if context.get('currency'):
|
|
where &= currency == context['currency']
|
|
if context.get('account'):
|
|
where &= line.account == context['account']
|
|
if context.get('lot'):
|
|
where &= line.lot == context['lot']
|
|
if context.get('unreconciled_only'):
|
|
where &= line.reconciliation == Null
|
|
|
|
return (
|
|
line
|
|
.join(move, condition=line.move == move.id)
|
|
.join(company, condition=move.company == company.id)
|
|
.join(invoice, 'LEFT', condition=invoice.move == move.id)
|
|
.select(
|
|
Literal(0).as_('create_uid'),
|
|
CurrentTimestamp().as_('create_date'),
|
|
Literal(None).as_('write_uid'),
|
|
Literal(None).as_('write_date'),
|
|
line.id.as_('id'),
|
|
line.id.as_('move_line'),
|
|
line.move.as_('move'),
|
|
move.date.as_('posting_date'),
|
|
move.journal.as_('journal'),
|
|
line.account.as_('account'),
|
|
line.party.as_('party'),
|
|
line.lot.as_('lot'),
|
|
line.fee.as_('fee'),
|
|
invoice.id.as_('invoice'),
|
|
currency.as_('currency'),
|
|
line.debit.as_('debit'),
|
|
line.credit.as_('credit'),
|
|
balance.as_('balance'),
|
|
line.second_currency.as_('second_currency'),
|
|
line.amount_second_currency.as_('amount_second_currency'),
|
|
line.reconciliation.as_('reconciliation'),
|
|
move.state.as_('move_state'),
|
|
line.description.as_('description'),
|
|
Coalesce(line.ext_ref, move.ext_ref).as_('reference'),
|
|
where=where))
|