Skip to content
This repository has been archived by the owner on Mar 28, 2024. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'origin/90-compliance-criteria-new' into…
Browse files Browse the repository at this point in the history
… release/dev
  • Loading branch information
gonzalesedwin1123 committed Oct 26, 2023
2 parents d929145 + ee3b3ba commit b702e3a
Show file tree
Hide file tree
Showing 25 changed files with 887 additions and 0 deletions.
6 changes: 6 additions & 0 deletions setup/spp_programs_compliance_criteria/setup.py
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.
2 changes: 2 additions & 0 deletions spp_programs_compliance_criteria/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import wizards
37 changes: 37 additions & 0 deletions spp_programs_compliance_criteria/__manifest__.py
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,
}
4 changes: 4 additions & 0 deletions spp_programs_compliance_criteria/models/__init__.py
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
48 changes: 48 additions & 0 deletions spp_programs_compliance_criteria/models/g2p_cycle.py
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)
11 changes: 11 additions & 0 deletions spp_programs_compliance_criteria/models/g2p_program.py
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,
)
3 changes: 3 additions & 0 deletions spp_programs_compliance_criteria/models/managers/__init__.py
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
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
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)
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 spp_programs_compliance_criteria/models/res_config_settings.py
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 spp_programs_compliance_criteria/security/ir.model.access.csv
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 spp_programs_compliance_criteria/static/src/js/field_domain.js
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();
}
},
});
});
2 changes: 2 additions & 0 deletions spp_programs_compliance_criteria/tests/__init__.py
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
28 changes: 28 additions & 0 deletions spp_programs_compliance_criteria/tests/common.py
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 spp_programs_compliance_criteria/tests/test_g2p_cycle.py
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()
Loading

0 comments on commit b702e3a

Please sign in to comment.