This repository has been archived by the owner on Mar 28, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/90-compliance-criteria-new' into…
… release/dev
- Loading branch information
Showing
25 changed files
with
887 additions
and
0 deletions.
There are no files selected for viewing
1 change: 1 addition & 0 deletions
1
setup/spp_programs_compliance_criteria/odoo/addons/spp_programs_compliance_criteria
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../../../spp_programs_compliance_criteria |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import setuptools | ||
|
||
setuptools.setup( | ||
setup_requires=['setuptools-odoo'], | ||
odoo_addon=True, | ||
) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from . import models | ||
from . import wizards |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Part of OpenSPP. See LICENSE file for full copyright and licensing details. | ||
{ | ||
"name": "OpenSPP Programs: Compliance Criteria", | ||
"category": "OpenSPP", | ||
"version": "15.0.0.0.0", | ||
"sequence": 1, | ||
"author": "OpenSPP.org", | ||
"website": "https://github.com/openspp/openspp-program", | ||
"license": "LGPL-3", | ||
"development_status": "Alpha", | ||
"maintainers": ["jeremi", "gonzalesedwin1123"], | ||
"depends": [ | ||
"base", | ||
"g2p_registry_base", | ||
"g2p_programs", | ||
"spp_area", | ||
"spp_programs", | ||
"spp_eligibility_sql", | ||
"spp_eligibility_tags", | ||
"web_domain_field", | ||
], | ||
"data": [ | ||
"security/ir.model.access.csv", | ||
"views/g2p_cycle_views.xml", | ||
"views/g2p_program_views.xml", | ||
"views/res_config_settings_views.xml", | ||
"wizards/g2p_program_create_wizard_views.xml", | ||
], | ||
"assets": { | ||
"web.assets_backend": [ | ||
"spp_programs_compliance_criteria/static/src/js/field_domain.js", | ||
], | ||
}, | ||
"application": False, | ||
"installable": True, | ||
"auto_install": False, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from . import managers | ||
from . import g2p_cycle | ||
from . import g2p_program | ||
from . import res_config_settings |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
from odoo import _, api, fields, models | ||
from odoo.exceptions import ValidationError | ||
from odoo.osv.expression import OR | ||
|
||
|
||
class G2pCycle(models.Model): | ||
_inherit = "g2p.cycle" | ||
|
||
allow_filter_compliance_criteria = fields.Boolean( | ||
compute="_compute_allow_filter_compliance_criteria" | ||
) | ||
|
||
@api.depends("program_id", "program_id.compliance_managers") | ||
def _compute_allow_filter_compliance_criteria(self): | ||
for rec in self: | ||
rec.allow_filter_compliance_criteria = bool( | ||
rec.program_id.compliance_managers | ||
) | ||
|
||
def action_filter_beneficiaries_by_compliance_criteria(self): | ||
self.ensure_one() | ||
if not self.program_id.compliance_managers: | ||
raise ValidationError( | ||
_("Cycle is not on correct condition to filter by compliance!") | ||
) | ||
if self.state not in ("draft", "to_approve") or not self.cycle_membership_ids: | ||
return | ||
registrant_satisfied = ( | ||
self.env["res.partner"] | ||
.sudo() | ||
.search(self._get_compliance_criteria_domain()) | ||
) | ||
membership_to_paused = self.cycle_membership_ids.filtered( | ||
lambda cm: cm.partner_id not in registrant_satisfied | ||
) | ||
membership_to_paused.state = "paused" | ||
membership_to_enrolled = self.cycle_membership_ids - membership_to_paused | ||
membership_to_enrolled.state = "enrolled" | ||
|
||
def _get_compliance_criteria_domain(self): | ||
self.ensure_one() | ||
domain = [] | ||
for manager in self.program_id.compliance_managers: | ||
membership = ( | ||
self.cycle_membership_ids if self.cycle_membership_ids else None | ||
) | ||
domain.append(manager.manager_ref_id._prepare_eligible_domain(membership)) | ||
return OR(domain) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from odoo import fields, models | ||
|
||
|
||
class G2pProgram(models.Model): | ||
_inherit = "g2p.program" | ||
|
||
compliance_managers = fields.One2many( | ||
comodel_name="spp.compliance.manager", | ||
inverse_name="program_id", | ||
auto_join=True, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from . import g2p_cycle_manager_default | ||
from . import g2p_program_entitlement_manager_default | ||
from . import spp_compliance_manager |
22 changes: 22 additions & 0 deletions
22
spp_programs_compliance_criteria/models/managers/g2p_cycle_manager_default.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from odoo import models | ||
from odoo.osv.expression import AND | ||
|
||
|
||
class G2pCycleManagerDefault(models.Model): | ||
_inherit = "g2p.cycle.manager.default" | ||
|
||
def _add_beneficiaries(self, cycle, beneficiaries, state="draft", do_count=False): | ||
automated_beneficiaries_filtering_mechanism = ( | ||
self.env["ir.config_parameter"] | ||
.sudo() | ||
.get_param( | ||
"spp_programs_compliance_criteria.beneficiaries_automated_filtering_mechanism", | ||
"0", | ||
) | ||
) | ||
if automated_beneficiaries_filtering_mechanism == "1": | ||
domain = cycle._get_compliance_criteria_domain() | ||
new_domain = AND([domain, [["id", "in", beneficiaries]]]) | ||
beneficiaries = self.env["res.partner"].sudo().search(new_domain).ids | ||
res = super()._add_beneficiaries(cycle, beneficiaries, state, do_count) | ||
return res |
26 changes: 26 additions & 0 deletions
26
spp_programs_compliance_criteria/models/managers/g2p_program_entitlement_manager_default.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
from odoo import models | ||
|
||
|
||
class G2pProgramEntitlementManagerDefault(models.Model): | ||
_inherit = ["g2p.program.entitlement.manager.default"] | ||
|
||
def prepare_entitlements(self, cycle, beneficiaries): | ||
automated_beneficiaries_filtering_mechanism = ( | ||
self.env["ir.config_parameter"] | ||
.sudo() | ||
.get_param( | ||
"spp_programs_compliance_criteria.beneficiaries_automated_filtering_mechanism", | ||
"0", | ||
) | ||
) | ||
if automated_beneficiaries_filtering_mechanism == "2": | ||
satisfied_registrant_ids = ( | ||
self.env["res.partner"] | ||
.sudo() | ||
.search(cycle._get_compliance_criteria_domain()) | ||
.ids | ||
) | ||
beneficiaries = beneficiaries.filtered( | ||
lambda cm: cm.partner_id.id in satisfied_registrant_ids | ||
) | ||
return super().prepare_entitlements(cycle, beneficiaries) |
28 changes: 28 additions & 0 deletions
28
spp_programs_compliance_criteria/models/managers/spp_compliance_manager.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from odoo import api, fields, models | ||
|
||
|
||
class SppComplianceManager(models.Model): | ||
_name = "spp.compliance.manager" | ||
_inherit = ["g2p.manager.mixin"] | ||
_description = "Compliance Criteria Manager" | ||
|
||
program_id = fields.Many2one( | ||
comodel_name="g2p.program", | ||
string="Program", | ||
required=True, | ||
auto_join=True, | ||
ondelete="cascade", | ||
readonly=True, | ||
) | ||
|
||
@api.model | ||
def _selection_manager_ref_id(self): | ||
res = super()._selection_manager_ref_id() | ||
for item in [ | ||
("g2p.program_membership.manager.default", "Default Manager"), | ||
("g2p.program_membership.manager.sql", "SQL-based Manager"), | ||
("g2p.program_membership.manager.tags", "Tag-based Manager"), | ||
]: | ||
if item not in res: | ||
res.append(item) | ||
return res |
20 changes: 20 additions & 0 deletions
20
spp_programs_compliance_criteria/models/res_config_settings.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from odoo import fields, models | ||
|
||
|
||
class ResConfigSettings(models.TransientModel): | ||
_inherit = "res.config.settings" | ||
|
||
beneficiaries_automated_filtering_mechanism = fields.Selection( | ||
selection=[ | ||
("0", "No Automated Filtering Mechanism"), | ||
("1", "On Cycle Memberships Creating Event"), | ||
("2", "On Entitlement Creating Event"), | ||
], | ||
required=True, | ||
default="0", | ||
config_parameter="spp_programs_compliance_criteria.beneficiaries_automated_filtering_mechanism", | ||
help="Automated Filtering Beneficiaries Mechanism:\n" | ||
"0. No Automated Filtering Mechanism\n" | ||
"1. On Cycle Memberships Creating Event\n" | ||
"2. On Entitlement Creating Event\n", | ||
) |
4 changes: 4 additions & 0 deletions
4
spp_programs_compliance_criteria/security/ir.model.access.csv
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink | ||
access_spp_compliance_manager_group_g2p_admin,spp.compliance.manager.group.g2p.admin,model_spp_compliance_manager,g2p_registry_base.group_g2p_admin,1,1,1,1 | ||
access_spp_compliance_manager_g2p_program_manager,spp.compliance.manager.g2p.program.manager,model_spp_compliance_manager,g2p_programs.g2p_program_manager,1,1,1,0 | ||
access_spp_compliance_manager_g2p_program_validator,spp.compliance.manager.g2p.program.validator,model_spp_compliance_manager,g2p_programs.g2p_program_validator,1,0,0,0 |
19 changes: 19 additions & 0 deletions
19
spp_programs_compliance_criteria/static/src/js/field_domain.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
odoo.define("spp_programs_compliance_criteria.field_domain", function (require) { | ||
const {FieldDomain} = require("web.basic_fields"); | ||
|
||
FieldDomain.include({ | ||
init: function () { | ||
this._super.apply(this, arguments); | ||
this.hideResult = this.nodeOptions.hide_result; | ||
}, | ||
|
||
_replaceContent: function () { | ||
this._super.apply(this, arguments); | ||
if (this.hideResult) { | ||
this.$el.find(".fa-arrow-right").remove(); | ||
this.$el.find(".o_domain_show_selection_button").remove(); | ||
this.$el.find(".o_refresh_count").remove(); | ||
} | ||
}, | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from . import test_g2p_cycle | ||
from . import test_g2p_program_create_wizard |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from odoo.tests import TransactionCase | ||
|
||
|
||
class Common(TransactionCase): | ||
def setUp(self): | ||
super().setUp() | ||
self.areas = self.env["spp.area"].create( | ||
[ | ||
{"draft_name": "Area 1 [TEST]"}, | ||
{"draft_name": "Area 2 [TEST]"}, | ||
{"draft_name": "Area 3 [TEST]"}, | ||
] | ||
) | ||
self._tag = self.env["g2p.registrant.tags"].create({"name": "Tag 1 [TEST]"}) | ||
|
||
def program_create_wizard(self, vals): | ||
vals.update( | ||
{ | ||
"name": "Program 1 [TEST]", | ||
"rrule_type": "monthly", | ||
"eligibility_domain": "[]", | ||
"cycle_duration": 1, | ||
"currency_id": self.env.company.currency_id.id, | ||
"admin_area_ids": [(6, 0, self.areas.ids)], | ||
"amount_per_cycle": 1.0, | ||
} | ||
) | ||
return self.env["g2p.program.create.wizard"].create(vals) |
118 changes: 118 additions & 0 deletions
118
spp_programs_compliance_criteria/tests/test_g2p_cycle.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
from odoo.exceptions import ValidationError | ||
|
||
from . import common | ||
|
||
|
||
class TestG2pCycle(common.Common): | ||
def setUp(self): | ||
super().setUp() | ||
self.individual_1 = self._create_individual({"name": "Individual 1"}) | ||
self.individual_2 = self._create_individual({"name": "Individual 2"}) | ||
self.individual_3 = self._create_individual({"name": "Individual 3"}) | ||
self._test = self.program_create_wizard( | ||
{ | ||
"target_type": "individual", | ||
"compliance_criteria": True, | ||
"compliance_kind": "g2p.program_membership.manager.default", | ||
"compliance_domain": f"[['id', '=', {self.individual_3.id}]]", | ||
"import_beneficiaries": "yes", | ||
} | ||
) | ||
action = self._test.create_program() | ||
self.program = self.env["g2p.program"].browse(action["res_id"]) | ||
|
||
def _create_individual(self, vals): | ||
vals.update( | ||
{ | ||
"is_registrant": True, | ||
"is_group": False, | ||
} | ||
) | ||
return self.env["res.partner"].create(vals) | ||
|
||
def _set_filtering_mechanism(self, value): | ||
if value not in ["0", "1", "2"]: | ||
value = "0" | ||
return ( | ||
self.env["ir.config_parameter"] | ||
.sudo() | ||
.set_param( | ||
"spp_programs_compliance_criteria.beneficiaries_automated_filtering_mechanism", | ||
value, | ||
) | ||
) | ||
|
||
def test_01_create_cycle_without_automated_filtering_mechanism(self): | ||
self._set_filtering_mechanism("100") | ||
self.program.create_new_cycle() | ||
cycle = self.program.cycle_ids[0] | ||
self.assertTrue( | ||
len(self.program.program_membership_ids) == len(cycle.cycle_membership_ids), | ||
"Cycle membership should be copied from program!", | ||
) | ||
self.assertListEqual( | ||
self.program.program_membership_ids.mapped("state"), | ||
cycle.cycle_membership_ids.mapped("state"), | ||
"Cycle membership should be copied from program!", | ||
) | ||
cycle.prepare_entitlement() | ||
self.assertTrue( | ||
len(cycle.cycle_membership_ids) == len(cycle.entitlement_ids), | ||
"One entitlement should be generated for each membership!", | ||
) | ||
self.assertTrue( | ||
cycle.allow_filter_compliance_criteria, | ||
"Program having compliance manager should allow its cycles to filter!", | ||
) | ||
cycle.action_filter_beneficiaries_by_compliance_criteria() | ||
self.assertTrue( | ||
len(cycle.cycle_membership_ids) | ||
> len( | ||
cycle.cycle_membership_ids.filtered(lambda cm: cm.state == "enrolled") | ||
), | ||
"Number of enrolled membership should be reduced after filtering!", | ||
) | ||
|
||
def test_02_create_cycle_automated_filtering_on_entitlement_creating(self): | ||
self._set_filtering_mechanism("2") | ||
self.program.create_new_cycle() | ||
cycle = self.program.cycle_ids[0] | ||
self.assertTrue( | ||
len(self.program.program_membership_ids) == len(cycle.cycle_membership_ids), | ||
"Cycle membership should be copied from program!", | ||
) | ||
self.assertListEqual( | ||
self.program.program_membership_ids.mapped("state"), | ||
cycle.cycle_membership_ids.mapped("state"), | ||
"Cycle membership should be copied from program!", | ||
) | ||
cycle.prepare_entitlement() | ||
self.assertTrue( | ||
len(cycle.cycle_membership_ids) > len(cycle.entitlement_ids), | ||
"Entitlement should only be created for member which satisfied the condition of compliance manager!", | ||
) | ||
|
||
def test_03_create_cycle_automated_filtering_on_membership_creating(self): | ||
self._set_filtering_mechanism("1") | ||
self.program.create_new_cycle() | ||
cycle = self.program.cycle_ids[0] | ||
self.assertTrue( | ||
len(self.program.program_membership_ids) > len(cycle.cycle_membership_ids), | ||
"Cycle membership should not be copied from program!", | ||
) | ||
cycle.prepare_entitlement() | ||
self.assertTrue( | ||
len(cycle.cycle_membership_ids) == len(cycle.entitlement_ids), | ||
"One entitlement should be generated for each membership!", | ||
) | ||
|
||
def test_04_other_test(self): | ||
self.program.create_new_cycle() | ||
cycle = self.program.cycle_ids[0] | ||
cycle.state = "approved" | ||
cycle.action_filter_beneficiaries_by_compliance_criteria() | ||
cycle.state = "to_approve" | ||
self.program.write({"compliance_managers": [(5, 0, 0)]}) | ||
err_msg = "^Cycle is not on correct condition to filter by compliance!$" | ||
with self.assertRaisesRegex(ValidationError, err_msg): | ||
cycle.action_filter_beneficiaries_by_compliance_criteria() |
Oops, something went wrong.