This commit is contained in:
2026-05-24 18:47:19 +02:00
parent 01c23c1ec2
commit 390207a371
12 changed files with 190 additions and 19 deletions

View File

@@ -72,6 +72,8 @@ def register():
ctrm_reporting.CTRMPnlExplainContext,
ctrm_reporting.CTRMPnlDimension,
ctrm_reporting.CTRMPnlDimensionContext,
ctrm_reporting.CTRMCreditRisk,
ctrm_reporting.CTRMCreditRiskContext,
configuration.Configuration,
pricing.ImportPricesStart,
pricing.ImportPricesResult,

View File

@@ -777,3 +777,122 @@ class CTRMPnlDimension(ModelSQL, ModelView):
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))

View File

@@ -140,6 +140,26 @@
<field name="view" ref="ctrm_pnl_dimension_view_list"/>
<field name="act_window" ref="act_ctrm_pnl_dimension"/>
</record>
<record model="ir.ui.view" id="ctrm_credit_risk_context_view_form">
<field name="model">ctrm.reporting.risk.credit.context</field>
<field name="type">form</field>
<field name="name">ctrm_credit_risk_context_form</field>
</record>
<record model="ir.ui.view" id="ctrm_credit_risk_view_list">
<field name="model">ctrm.reporting.risk.credit</field>
<field name="type">tree</field>
<field name="name">ctrm_credit_risk_list</field>
</record>
<record model="ir.action.act_window" id="act_ctrm_credit_risk">
<field name="name">Credit Risk</field>
<field name="res_model">ctrm.reporting.risk.credit</field>
<field name="context_model">ctrm.reporting.risk.credit.context</field>
</record>
<record model="ir.action.act_window.view" id="act_ctrm_credit_risk_view">
<field name="sequence" eval="10"/>
<field name="view" ref="ctrm_credit_risk_view_list"/>
<field name="act_window" ref="act_ctrm_credit_risk"/>
</record>
<menuitem
name="Positions"
@@ -209,6 +229,7 @@
name="VaR"
parent="menu_ctrm_risk"
sequence="10"
action="risk.act_pos_report_form"
id="menu_ctrm_risk_var"/>
<menuitem
name="Stress Tests"
@@ -226,9 +247,10 @@
sequence="40"
id="menu_ctrm_risk_limits"/>
<menuitem
name="Credit Exposure"
name="Credit Risk"
parent="menu_ctrm_risk"
sequence="50"
action="act_ctrm_credit_risk"
id="menu_ctrm_risk_credit"/>
<menuitem

View File

@@ -73,9 +73,9 @@ this repository contains the full copyright notices and license terms. -->
<menuitem
name="Fee Report"
parent="purchase_trade.menu_global_reporting"
parent="purchase_trade.menu_ctrm_other"
action="act_fee_report_form"
sequence="20"
id="menu_fee_report_form"/>
</data>
</tryton>
</tryton>

View File

@@ -172,7 +172,7 @@
id="menu_forex_bi"/>
<menuitem
name="Forex Report"
parent="purchase_trade.menu_global_reporting"
parent="purchase_trade.menu_ctrm_other"
action="act_forex_bi"
sequence="25"
id="menu_gr_forex_bi"/>

View File

@@ -32,11 +32,16 @@
sequence="0"
id="menu_global_configuration"
icon="tryton-settings"/>
<menuitem
parent="menu_global_configuration"
action="act_gr_configuration_form"
sequence="10"
id="menu_gr_configuration"
icon="tryton-list"/>
</data>
</tryton>
<menuitem
parent="menu_global_configuration"
action="act_gr_configuration_form"
sequence="10"
id="menu_gr_configuration"
icon="tryton-list"/>
<menuitem
name="Other"
parent="menu_global_reporting"
sequence="60"
id="menu_ctrm_other"/>
</data>
</tryton>

View File

@@ -58,7 +58,7 @@
<field name="act_window" ref="act_invoice_padding_report_form"/>
</record>
<menuitem
parent="purchase_trade.menu_global_reporting"
parent="purchase_trade.menu_ctrm_other"
sequence="101"
action="act_invoice_padding_report_form"
id="menu_invoice_padding_report_form"/>

View File

@@ -22,9 +22,9 @@
</record>
<menuitem
parent="purchase_trade.menu_global_reporting"
parent="purchase_trade.menu_ctrm_other"
sequence="110"
action="act_open_position_form"
id="menu_open_position_form"/>
</data>
</tryton>
</tryton>

View File

@@ -229,22 +229,22 @@ this repository contains the full copyright notices and license terms. -->
<menuitem
name="Pnl Report"
parent="purchase_trade.menu_global_reporting"
parent="purchase_trade.menu_ctrm_other"
action="act_pnl_bi"
sequence="110"
id="menu_pnl_bi"/>
<menuitem
name="Position Report"
parent="purchase_trade.menu_global_reporting"
parent="purchase_trade.menu_ctrm_other"
action="act_position_bi"
sequence="120"
id="menu_position_bi"/>
<menuitem
parent="purchase_trade.menu_global_reporting"
parent="purchase_trade.menu_ctrm_other"
sequence="100"
action="act_pur_inv_report_form"
id="menu_pur_inv_report_form"/>
</data>
</tryton>
</tryton>

View File

@@ -12,6 +12,7 @@ depends:
document_incoming
incoterm
bank
risk
xml:
purchase.xml
sale.xml

View File

@@ -0,0 +1,10 @@
<form>
<label name="party"/>
<field name="party"/>
<label name="currency"/>
<field name="currency"/>
<label name="risk_level"/>
<field name="risk_level"/>
<label name="over_limit_only"/>
<field name="over_limit_only"/>
</form>

View File

@@ -0,0 +1,12 @@
<tree>
<field name="party" width="160"/>
<field name="risk_level"/>
<field name="status"/>
<field name="credit_limit" sum="1"/>
<field name="credit_currency" width="60"/>
<field name="open_exposure" sum="1"/>
<field name="available_credit" sum="1"/>
<field name="utilization"/>
<field name="internal_limit" sum="1"/>
<field name="insurance_limit" sum="1"/>
</tree>