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

@@ -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))