23.03.26
This commit is contained in:
@@ -812,26 +812,41 @@ class PenaltyRuleTier(ModelSQL, ModelView):
|
||||
threshold_unit = fields.Many2One('assay.unit', "Unit")
|
||||
deduction_per_unit = fields.Numeric("Deduction / unit")
|
||||
penalty_value = fields.Numeric("Penalty Value (USD/DMT)")
|
||||
mode = fields.Selection([
|
||||
('excess', 'Excess above threshold'),
|
||||
('full', 'Full grade in tier'),
|
||||
('min_or_both', 'Min(grade, cap) — full tier amount'),
|
||||
], "Mode")
|
||||
|
||||
@classmethod
|
||||
def default_mode(cls):
|
||||
return 'excess'
|
||||
|
||||
def compute_tier_penalty(self, grade):
|
||||
"""
|
||||
Retourne la pénalité USD pour ce palier uniquement.
|
||||
grade : Decimal – teneur brute de l'élément
|
||||
dry_weight_dmt: Decimal – poids sec en DMT
|
||||
"""
|
||||
grade = Decimal(str(grade))
|
||||
|
||||
# Grade en dessous du seuil bas → ce palier ne s'applique pas
|
||||
|
||||
if grade <= self.threshold_from:
|
||||
return Decimal(0)
|
||||
|
||||
# Excès au-dessus du seuil bas, plafonné au seuil haut si existant
|
||||
excess_top = grade if self.threshold_to is None else min(grade, self.threshold_to)
|
||||
excess = excess_top - self.threshold_from
|
||||
if self.mode == 'excess':
|
||||
# Ton comportement actuel : on paye seulement l'excès au-dessus du seuil bas
|
||||
# Ex Codelco : As=0,7% → palier 0,2-0,5% donne 0,3% d'excès
|
||||
excess_top = grade if self.threshold_to is None else min(grade, self.threshold_to)
|
||||
taxable = excess_top - self.threshold_from
|
||||
|
||||
# USD/DMT × DMT
|
||||
return (excess * self.penalty_value).quantize(Decimal('0.01'))
|
||||
elif self.mode == 'full':
|
||||
# Pénalité sur toute la teneur dans ce palier dès déclenchement
|
||||
# Ex : As=0,7% → palier 0,5-1,0% donne 0,7% entier (pas 0,2%)
|
||||
taxable = grade if self.threshold_to is None else min(grade, self.threshold_to)
|
||||
|
||||
elif self.mode == 'min_or_both':
|
||||
# Pénalité sur min(grade, plafond) — utile quand le contrat dit
|
||||
# "si As dépasse X%, pénalité sur la tranche entière jusqu'à Y%"
|
||||
# Ex vente fichier : palier 0,3-0,9%, As=0,6% → taxable = min(0,6%, 0,9%) = 0,6%
|
||||
cap = self.threshold_to if self.threshold_to is not None else grade
|
||||
taxable = min(grade, cap)
|
||||
|
||||
return (taxable * self.penalty_value).quantize(Decimal('0.01'))
|
||||
|
||||
class PenaltyRule(ModelSQL, ModelView):
|
||||
"Penalty Rule"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<tree editable="1">
|
||||
<field name="mode"/>
|
||||
<field name="threshold_from"/>
|
||||
<field name="threshold_to"/>
|
||||
<field name="threshold_unit"/>
|
||||
|
||||
Reference in New Issue
Block a user