-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #288 from vin0dkhichar/17.0-1.3
Added Priority List
- Loading branch information
Showing
23 changed files
with
617 additions
and
1 deletion.
There are no files selected for viewing
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
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 @@ | ||
# OpenG2P Programs Priority List | ||
|
||
Refer to https://docs.openg2p.org. |
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 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 @@ | ||
{ | ||
"name": "OpenG2P Programs Priority List", | ||
"category": "G2P/G2P", | ||
"version": "17.0.1.3.0", | ||
"sequence": 1, | ||
"author": "OpenG2P", | ||
"website": "https://openg2p.org", | ||
"license": "LGPL-3", | ||
"depends": ["g2p_programs"], | ||
"data": [ | ||
"security/ir.model.access.csv", | ||
"views/cycle_view.xml", | ||
"views/program_manager_view.xml", | ||
"views/cycle_manager_view.xml", | ||
"views/cycle_membership_view.xml", | ||
"wizard/create_cycle_wizard.xml", | ||
], | ||
"assets": { | ||
"web.assets_backend": [ | ||
"/g2p_programs_priority_list/static/src/css/style.css", | ||
], | ||
}, | ||
"demo": [], | ||
"images": [], | ||
"application": True, | ||
"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,6 @@ | ||
from . import cycle | ||
from . import cycle_manager | ||
from . import programs | ||
from . import program_manager | ||
from . import cycle_membership | ||
from . import sorting_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,20 @@ | ||
from odoo import api, fields, models | ||
|
||
|
||
class G2PCycleInherited(models.Model): | ||
_inherit = "g2p.cycle" | ||
|
||
inclusion_limit = fields.Integer(default=0) | ||
eligibility_domain = fields.Text(string="Domain", default="[]") | ||
is_not_disbursement = fields.Boolean(string="Not Disbursement", default=True) | ||
sorting_criteria_ids = fields.One2many("g2p.sorting.criteria", "cycle_id", string="Sorting Order") | ||
|
||
@api.model | ||
def create(self, vals): | ||
if "program_id" in vals: | ||
program = self.env["g2p.program"].browse(vals["program_id"]) | ||
if program.program_managers.manager_ref_id: | ||
vals[ | ||
"is_not_disbursement" | ||
] = not program.program_managers.manager_ref_id.is_disbursement_through_priority_list | ||
return super().create(vals) |
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,152 @@ | ||
import logging | ||
|
||
from odoo import _, api, fields, models | ||
from odoo.tools.safe_eval import safe_eval | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
class DefaultCycleManagerInherited(models.Model): | ||
_inherit = "g2p.cycle.manager.default" | ||
|
||
eligibility_domain = fields.Text(string="Domain", default="[]") | ||
inclusion_limit = fields.Integer(default=0) | ||
|
||
sorting_criteria_ids = fields.One2many("g2p.sorting.criteria", "manager_id", string="Sorting Order") | ||
|
||
@api.model | ||
def create(self, vals): | ||
if "program_id" in vals: | ||
vals[ | ||
"eligibility_domain" | ||
] = f"[('program_membership_ids.program_id', 'in', [{vals['program_id']}])]" | ||
return super().create(vals) | ||
|
||
def new_cycle(self, name, new_start_date, sequence): | ||
cycle = super().new_cycle(name, new_start_date, sequence) | ||
|
||
for rec in self: | ||
is_disbursement = ( | ||
self.program_id.program_managers.manager_ref_id.is_disbursement_through_priority_list | ||
) | ||
if is_disbursement: | ||
for sorting_criterion in self.sorting_criteria_ids: | ||
self.env["g2p.sorting.criteria"].create( | ||
{ | ||
"cycle_id": cycle.id, | ||
"sequence": sorting_criterion.sequence, | ||
"field_name": sorting_criterion.field_name.id, | ||
"order": sorting_criterion.order, | ||
} | ||
) | ||
|
||
cycle.write( | ||
{"inclusion_limit": rec.inclusion_limit, "eligibility_domain": rec.eligibility_domain} | ||
) | ||
return cycle | ||
|
||
def add_beneficiaries(self, cycle, beneficiaries, state="draft"): | ||
self.ensure_one() | ||
self._ensure_can_edit_cycle(cycle) | ||
_logger.debug("Adding beneficiaries to the cycle %s", cycle.name) | ||
_logger.debug("Beneficiaries: %s", len(beneficiaries)) | ||
|
||
# Only add beneficiaries not added yet | ||
existing_ids = cycle.cycle_membership_ids.mapped("partner_id.id") | ||
_logger.debug("Existing IDs: %s", len(existing_ids)) | ||
beneficiaries = list(set(beneficiaries) - set(existing_ids)) | ||
|
||
is_disbursement = ( | ||
self.program_id.program_managers.manager_ref_id.is_disbursement_through_priority_list | ||
) | ||
if is_disbursement: | ||
# Convert beneficiaries to recordset first | ||
if beneficiaries: | ||
if isinstance(beneficiaries, list): | ||
ids = beneficiaries | ||
else: | ||
ids = beneficiaries.mapped("partner_id.id") | ||
|
||
domain = safe_eval(cycle.eligibility_domain) | ||
|
||
domain += [("id", "in", ids), ("disabled", "=", False)] | ||
if self.program_id.target_type == "group": | ||
domain += [("is_group", "=", True), ("is_registrant", "=", True)] | ||
if self.program_id.target_type == "individual": | ||
domain += [("is_group", "=", False), ("is_registrant", "=", True)] | ||
|
||
remaining_limit = max(0, cycle.inclusion_limit - len(existing_ids)) | ||
|
||
sorted_criteria = cycle.sorting_criteria_ids.sorted("sequence") | ||
|
||
order = [] | ||
for criterion in sorted_criteria: | ||
field_name = criterion.field_name.name | ||
reverse_flag = criterion.order == "desc" | ||
order_direction = "desc" if reverse_flag else "asc" | ||
order.append(f"{field_name} {order_direction}") | ||
|
||
# Join the order list into a comma-separated string | ||
order_str = ",".join(order) | ||
|
||
# Query partners with sorting applied | ||
sorted_beneficiaries = self.env["res.partner"].search(domain, order=order_str) | ||
|
||
if len(sorted_beneficiaries) > remaining_limit: | ||
beneficiaries = sorted_beneficiaries[:remaining_limit].ids | ||
else: | ||
beneficiaries = sorted_beneficiaries.ids | ||
|
||
if len(beneficiaries) == 0: | ||
message = _("No beneficiaries to import.") | ||
kind = "warning" | ||
sticky = False | ||
elif len(beneficiaries) < self.MIN_ROW_JOB_QUEUE: | ||
self._add_beneficiaries(cycle, beneficiaries, state, do_count=True) | ||
message = _("%s beneficiaries imported.", len(beneficiaries)) | ||
kind = "success" | ||
sticky = False | ||
else: | ||
self._add_beneficiaries_async(cycle, beneficiaries, state) | ||
message = _("Import of %s beneficiaries started.", len(beneficiaries)) | ||
kind = "warning" | ||
sticky = True | ||
|
||
return { | ||
"type": "ir.actions.client", | ||
"tag": "display_notification", | ||
"params": { | ||
"title": _("Enrollment"), | ||
"message": message, | ||
"sticky": sticky, | ||
"type": kind, | ||
"next": { | ||
"type": "ir.actions.act_window_close", | ||
}, | ||
}, | ||
} | ||
|
||
def _add_beneficiaries(self, cycle, beneficiaries, state="draft", do_count=False): | ||
"""Add Beneficiaries with Rank | ||
:param cycle: Recordset of cycle | ||
:param beneficiaries: Recordset of beneficiaries | ||
:param state: String state to be set to beneficiary | ||
:return: None | ||
""" | ||
new_beneficiaries = [] | ||
for index, r in enumerate(beneficiaries): | ||
new_beneficiaries.append( | ||
[ | ||
0, | ||
0, | ||
{ | ||
"partner_id": r, | ||
"enrollment_date": fields.Date.today(), | ||
"state": state, | ||
"rank": index + 1, | ||
}, | ||
] | ||
) | ||
cycle.update({"cycle_membership_ids": new_beneficiaries}) | ||
cycle._compute_members_count() |
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,7 @@ | ||
from odoo import fields, models | ||
|
||
|
||
class G2PCycleMembershipInherited(models.Model): | ||
_inherit = "g2p.cycle.membership" | ||
|
||
rank = fields.Integer(index=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,48 @@ | ||
import logging | ||
from datetime import datetime, timedelta | ||
|
||
from odoo import fields, models | ||
|
||
from odoo.addons.g2p_programs.models.programs import G2PProgram | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
class DefaultProgramManagerInherited(models.Model): | ||
_inherit = "g2p.program.manager.default" | ||
|
||
is_disbursement_through_priority_list = fields.Boolean( | ||
string="Disbursement Through Priority List", default=False | ||
) | ||
|
||
def new_cycle(self): | ||
""" | ||
Create the next cycle of the program. | ||
If `is_disbursement_through_priority_list` is False, it copies enrolled beneficiaries. | ||
""" | ||
self.ensure_one() | ||
|
||
for rec in self: | ||
cycles = self.env["g2p.cycle"].search([("program_id", "=", rec.program_id.id)]) | ||
_logger.debug("Cycles found: %s", cycles) | ||
|
||
cm = rec.program_id.get_manager(G2PProgram.MANAGER_CYCLE) | ||
|
||
if not cycles: | ||
_logger.debug("Creating first cycle with cycle manager: %s", cm) | ||
new_cycle = cm.new_cycle("Cycle 1", datetime.now(), 1) | ||
else: | ||
last_cycle = rec.last_cycle() | ||
new_sequence = last_cycle.sequence + 1 | ||
start_date = last_cycle.end_date + timedelta(days=1) | ||
new_cycle = cm.new_cycle(f"Cycle {new_sequence}", start_date, new_sequence) | ||
|
||
# Only copy beneficiaries if disbursement is NOT based on priority list | ||
if not rec.is_disbursement_through_priority_list: | ||
if new_cycle: | ||
program_beneficiaries = rec.program_id.get_beneficiaries("enrolled").mapped( | ||
"partner_id.id" | ||
) | ||
cm.add_beneficiaries(new_cycle, program_beneficiaries, "enrolled") | ||
|
||
return new_cycle |
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,76 @@ | ||
import logging | ||
|
||
from odoo import _, models | ||
from odoo.exceptions import UserError | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
class G2PProgramInherit(models.Model): | ||
_inherit = "g2p.program" | ||
|
||
def create_new_cycle(self): | ||
if self.beneficiaries_count <= 0: | ||
raise UserError( | ||
_("No enrolled registrants. Enroll registrants to program to create a new cycle.") | ||
) | ||
|
||
for rec in self: | ||
message = None | ||
kind = "success" | ||
cycle_manager = rec.get_manager(self.MANAGER_CYCLE) | ||
program_manager = rec.get_manager(self.MANAGER_PROGRAM) | ||
|
||
if not cycle_manager: | ||
raise UserError(_("No Cycle Manager defined.")) | ||
if not program_manager: | ||
raise UserError(_("No Program Manager defined.")) | ||
|
||
_logger.debug("-" * 80) | ||
_logger.debug("pm: %s", program_manager) | ||
|
||
new_cycle = program_manager.new_cycle() | ||
message = _("New cycle %s created.", new_cycle.name) | ||
|
||
if new_cycle.is_not_disbursement: | ||
return { | ||
"type": "ir.actions.client", | ||
"tag": "display_notification", | ||
"params": { | ||
"title": _("Cycle"), | ||
"message": message, | ||
"sticky": False, | ||
"type": kind, | ||
"next": { | ||
"type": "ir.actions.act_window_close", | ||
}, | ||
}, | ||
} | ||
else: | ||
wizard = self.env["cycle.creation.wizard"].create( | ||
{ | ||
"cycle_id": new_cycle.id, | ||
"name": new_cycle.name, | ||
"program_id": new_cycle.program_id.id, | ||
"eligibility_domain": new_cycle.eligibility_domain, | ||
"inclusion_limit": new_cycle.inclusion_limit, | ||
} | ||
) | ||
|
||
for criterion in new_cycle.sorting_criteria_ids: | ||
self.env["cycle.creation.wizard.criteria"].create( | ||
{ | ||
"wizard_id": wizard.id, | ||
"field_name": criterion.field_name.id, | ||
"order": criterion.order, | ||
"sequence": criterion.sequence, | ||
} | ||
) | ||
return { | ||
"name": _("Update Priority Configuration"), | ||
"type": "ir.actions.act_window", | ||
"res_model": "cycle.creation.wizard", | ||
"view_mode": "form", | ||
"res_id": wizard.id, | ||
"target": "new", | ||
} |
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,17 @@ | ||
from odoo import fields, models | ||
|
||
|
||
class SortingCriteria(models.Model): | ||
_name = "g2p.sorting.criteria" | ||
_description = "Sorting Criteria" | ||
|
||
cycle_id = fields.Many2one("g2p.cycle", string="Cycle") | ||
manager_id = fields.Many2one("g2p.cycle.manager.default", string="Cycle Manager") | ||
|
||
sequence = fields.Integer() | ||
field_name = fields.Many2one( | ||
"ir.model.fields", | ||
domain="[('model', '=', 'res.partner')]", | ||
help="Select a field from res.partner for sorting", | ||
) | ||
order = fields.Selection([("asc", "Ascending"), ("desc", "Descending")], required=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 @@ | ||
[build-system] | ||
requires = ["whool"] | ||
build-backend = "whool.buildapi" |
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,12 @@ | ||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink | ||
g2p_cycle_creation_wizard_admin,Cycle Creation Wizard Admin Access,g2p_programs_priority_list.model_cycle_creation_wizard,g2p_registry_base.group_g2p_admin,1,1,1,1 | ||
g2p_cycle_creation_wizard_program_manager,Cycle Creation Wizard Program Manager Access,g2p_programs_priority_list.model_cycle_creation_wizard,g2p_programs.g2p_program_manager,1,1,1,1 | ||
g2p_cycle_creation_wizard_program_validator,Cycle Creation Wizard Program Validator Access,g2p_programs_priority_list.model_cycle_creation_wizard,g2p_programs.g2p_program_validator,1,1,1,0 | ||
|
||
g2p_sorting_criteria_admin,Sorting Criteria Admin Access,model_g2p_sorting_criteria,g2p_registry_base.group_g2p_admin,1,1,1,1 | ||
g2p_sorting_criteria_program_manager,Sorting Criteria Program Manager Access,model_g2p_sorting_criteria,g2p_programs.g2p_program_manager,1,1,1,1 | ||
g2p_sorting_criteria_program_validator,Sorting Criteria Program Validator Access,model_g2p_sorting_criteria,g2p_programs.g2p_program_validator,1,1,1,0 | ||
|
||
g2p_cycle_creation_wizard_criteria_admin,Cycle Creation Wizard Criteria Admin Access,g2p_programs_priority_list.model_cycle_creation_wizard_criteria,g2p_registry_base.group_g2p_admin,1,1,1,1 | ||
g2p_cycle_creation_wizard_criteria_program_manager,Cycle Creation Wizard Criteria Program Manager Access,g2p_programs_priority_list.model_cycle_creation_wizard_criteria,g2p_programs.g2p_program_manager,1,1,1,1 | ||
g2p_cycle_creation_wizard_criteria_program_validator,Cycle Creation Wizard Criteria Program Validator Access,g2p_programs_priority_list.model_cycle_creation_wizard_criteria,g2p_programs.g2p_program_validator,1,1,1,0 |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.