11# Part of OpenG2P. See LICENSE file for full copyright and licensing details.
2+ import logging
23
3- from odoo import fields , models
4+ from odoo import _ , api , fields , models
5+ from odoo .exceptions import UserError
6+
7+ _logger = logging .getLogger (__name__ )
48
59
610class G2PCashEntitlementManager (models .Model ):
@@ -18,20 +22,108 @@ def _get_all_beneficiaries(self, all_beneficiaries_ids, condition, evaluate_one_
1822 return beneficiaries_ids
1923 return all_beneficiaries_ids
2024
21- def prepare_entitlements (self , cycle , beneficiaries ):
22- res = super ().prepare_entitlements (cycle , beneficiaries )
25+ def prepare_entitlements (self , cycle , beneficiaries ): # noqa: C901
26+ # NOTE: This method is an enriched implementation of the prepare_entitlements method
27+ # from spp_entitlement_cash (by OpenSPP):
28+ # <https://github.com/OpenSPP/openspp-modules/tree/17.0/spp_entitlement_cash>
29+
30+ # TODO: Refactor this method once a dedicated _compute_entitlement_amount method is introduced.
31+ if not self .entitlement_item_ids :
32+ raise UserError (_ ("There are no items entered for this entitlement manager." ))
2333
2434 all_beneficiaries_ids = beneficiaries .mapped ("partner_id.id" )
2535
26- for ben in all_beneficiaries_ids :
27- entitlement = self .env ["g2p.entitlement" ].search (
28- [("partner_id" , "=" , ben ), ("cycle_id" , "=" , cycle .id )]
36+ new_entitlements_to_create = {}
37+ for rec in self .entitlement_item_ids :
38+ _logger .info (f"Rec Amount: { rec .amount } " )
39+ if rec .condition :
40+ beneficiaries_ids = self ._get_all_beneficiaries (
41+ all_beneficiaries_ids , rec .condition , self .evaluate_one_item
42+ )
43+ else :
44+ beneficiaries_ids = all_beneficiaries_ids
45+ _logger .info (f"Beneficiaries IDs: { beneficiaries_ids } " )
46+
47+ beneficiaries_with_entitlements = (
48+ self .env ["g2p.entitlement" ]
49+ .search (
50+ [
51+ ("cycle_id" , "=" , cycle .id ),
52+ ("partner_id" , "in" , beneficiaries_ids ),
53+ ]
54+ )
55+ .mapped ("partner_id.id" )
2956 )
30- if entitlement :
31- if self .inflation_rate and self .enable_inflation :
32- entitlement .initial_amount = entitlement .initial_amount * self .inflation_rate
57+ entitlements_to_create = [
58+ beneficiaries_id
59+ for beneficiaries_id in beneficiaries_ids
60+ if beneficiaries_id not in beneficiaries_with_entitlements
61+ ]
62+
63+ entitlement_start_validity = cycle .start_date
64+ entitlement_end_validity = cycle .end_date
65+ entitlement_currency = rec .currency_id .id
66+
67+ beneficiaries_with_entitlements_to_create = self .env ["res.partner" ].browse (entitlements_to_create )
68+
69+ for beneficiary_id in beneficiaries_with_entitlements_to_create :
70+ if rec .multiplier_field :
71+ # Get the multiplier value from multiplier_field else return the default multiplier=1
72+ multiplier = beneficiary_id .mapped (rec .multiplier_field .name )
73+ if multiplier :
74+ multiplier = multiplier [0 ] or 0
75+ else :
76+ multiplier = 1
77+ if rec .max_multiplier > 0 and multiplier > rec .max_multiplier :
78+ multiplier = rec .max_multiplier
79+ _logger .info (f"Multiplier: { multiplier } " )
3380
34- return res
81+ amount = 0.0
82+ if rec .amount_type == "dynamic_field" :
83+ if not rec .amount_field :
84+ raise UserError (_ ("Amount Field can't be empty in case of Dynamic Field Amount Type" ))
85+ else :
86+ amount_field = beneficiary_id .mapped (rec .amount_field .name )
87+ if amount_field :
88+ amount_field = amount_field [0 ] or 0
89+ amount = float (amount_field ) * float (multiplier )
90+ else :
91+ amount = rec .amount * float (multiplier )
92+
93+ # Compute the sum of cash entitlements
94+ if beneficiary_id .id in new_entitlements_to_create :
95+ amount = amount + new_entitlements_to_create [beneficiary_id .id ]["initial_amount" ]
96+ # Check if amount > max_amount; ignore if max_amount is set to 0
97+ if self .max_amount > 0.0 and amount > self .max_amount :
98+ amount = self .max_amount
99+
100+ new_entitlements_to_create [beneficiary_id .id ] = {
101+ "cycle_id" : cycle .id ,
102+ "partner_id" : beneficiary_id .id ,
103+ "initial_amount" : amount ,
104+ "currency_id" : entitlement_currency ,
105+ "state" : "draft" ,
106+ "is_cash_entitlement" : True ,
107+ "valid_from" : entitlement_start_validity ,
108+ "valid_until" : entitlement_end_validity ,
109+ }
110+ # Check if there are additional fields to be added in entitlements
111+ addl_fields = self ._get_addl_entitlement_fields (beneficiary_id )
112+ if addl_fields :
113+ new_entitlements_to_create [beneficiary_id .id ].update (addl_fields )
114+
115+ # Create entitlement records
116+ for ent in new_entitlements_to_create :
117+ initial_amount = new_entitlements_to_create [ent ]["initial_amount" ]
118+ new_entitlements_to_create [ent ]["initial_amount" ] = self ._check_subsidy (initial_amount )
119+ if self .inflation_rate and self .enable_inflation :
120+ new_entitlements_to_create [ent ]["initial_amount" ] = (
121+ new_entitlements_to_create [ent ]["initial_amount" ] * self .inflation_rate
122+ )
123+
124+ # Create non-zero entitlements only
125+ if new_entitlements_to_create [ent ]["initial_amount" ] > 0.0 :
126+ self .env ["g2p.entitlement" ].create (new_entitlements_to_create [ent ])
35127
36128 def show_approve_entitlements (self , entitlement ):
37129 # TODO: Enable the multi-stage entitlement approval
@@ -42,3 +134,18 @@ class G2PCashEntitlementItem(models.Model):
42134 _inherit = "g2p.program.entitlement.manager.cash.item"
43135
44136 name = fields .Char ()
137+
138+ amount_type = fields .Selection (
139+ [("constant" , "Constant" ), ("dynamic_field" , "Dynamic Field" )], default = "constant" , required = True
140+ )
141+ amount_field = fields .Many2one (
142+ "ir.model.fields" ,
143+ domain = [("model_id.model" , "=" , "res.partner" ), ("ttype" , "=" , "integer" )],
144+ )
145+
146+ @api .onchange ("amount_type" )
147+ def onchange_amount_type (self ):
148+ if self .amount_type == "dynamic_field" :
149+ self .amount = 0.0
150+ else :
151+ self .amount_field = None
0 commit comments