diff --git a/grants_management_system/grants_management_system/doctype/grant_application_activity/grant_application_activity.js b/grants_management_system/grants_management_system/doctype/grant_application_activity/grant_application_activity.js index ce058ae..3cf9c50 100644 --- a/grants_management_system/grants_management_system/doctype/grant_application_activity/grant_application_activity.js +++ b/grants_management_system/grants_management_system/doctype/grant_application_activity/grant_application_activity.js @@ -2,7 +2,49 @@ // For license information, please see license.txt frappe.ui.form.on('Grant Application Activity', { - // refresh: function(frm) { - - // } + //Get grant budget_template items + grant_budget_template: function (frm) { + if (frm.doc.grant_budget_template) { + frm.clear_table('grant_application_activity_budget_item'); + frappe.model.with_doc('Grant Budget Template', frm.doc.grant_budget_template, function () { + let source_doc = frappe.model.get_doc('Grant Budget Template', frm.doc.grant_budget_template); + $.each(source_doc.budget_items, function (index, source_row) { + const target_row = frm.add_child('grant_application_activity_budget_item'); + target_row.budget_item = source_row.budget_item; + target_row.budget_category = source_row.budget_category; + frm.refresh_field('grant_application_activity_budget_item'); + }); + }); + } + }, + //Calculate total budget + validate: function (frm) { + //Budget + let total_budget_amt = 0; + $.each(frm.doc.grant_application_activity_budget_item, function (j, bitem) { + total_budget_amt += flt(bitem.amount); + }); + frm.doc.activity_budget = total_budget_amt; + } }); + +//Budget Amount Calculation +var amount_calculation = function (frm, cdt, cdn) { + var row = locals[cdt][cdn]; + if ((row.qty) && (row.rate)) { + frappe.model.set_value(cdt, cdn, 'amount', (row.qty * row.rate)); + frm.refresh_field("amount"); + } +} + +//Budget child table amount calculation on qty change +frappe.ui.form.on("Grant Application Activity Budget Item", "qty", function (frm, cdt, cdn) { + //amount on qty change + amount_calculation(frm, cdt, cdn); +}) + +//Budget child table amount calculation on rate change +frappe.ui.form.on("Grant Application Activity Budget Item", "rate", function (frm, cdt, cdn) { + //amount on rate change + amount_calculation(frm, cdt, cdn); +}) diff --git a/grants_management_system/grants_management_system/doctype/grant_application_budget_review/grant_application_budget_review.js b/grants_management_system/grants_management_system/doctype/grant_application_budget_review/grant_application_budget_review.js index 60b3610..76c7992 100644 --- a/grants_management_system/grants_management_system/doctype/grant_application_budget_review/grant_application_budget_review.js +++ b/grants_management_system/grants_management_system/doctype/grant_application_budget_review/grant_application_budget_review.js @@ -2,7 +2,64 @@ // For license information, please see license.txt frappe.ui.form.on('Grant Application Budget Review', { - // refresh: function(frm) { - - // } + grant_application: function (frm) { + if (frm.doc.grant_application) { + frm.clear_table('grant_application_budget_review_item'); + frappe.model.with_doc('Grant Application', frm.doc.grant_application, function () { + let source_doc = frappe.model.get_doc('Grant Application', frm.doc.grant_application); + $.each(source_doc.grant_application_budget_item, function (index, source_row) { + const target_row = frm.add_child('grant_application_budget_review_item'); + target_row.budget_item = source_row.budget_item; + target_row.unit_of_measure = source_row.unit_of_measure; + target_row.qty = source_row.qty; + target_row.rate = source_row.rate; + target_row.amount = source_row.amount; + target_row.item_description = source_row.item_description; + target_row.reviewed_rate = source_row.rate; + target_row.reviewed_amount = source_row.amount; + frm.refresh_field('grant_application_budget_review_item'); + }); + }); + } + }, + //Calculate total score + validate: function (frm) { + // calculate total budget amount for each line budget item + let total_requested_amount = 0; + let total_reviewed_amount = 0; + $.each(frm.doc.grant_application_budget_review_item, function (i, d) { + total_requested_amount += flt(d.amount); + total_reviewed_amount += flt(d.reviewed_amount); + }); + frm.doc.requested_amount = total_requested_amount; + frm.doc.reviewed_amount = total_reviewed_amount; + }, + setup: function (frm) { + frm.set_indicator_formatter('budget_item', + function (doc) { + return (doc.amount != doc.reviewed_amount) ? "green" : "white" + }) + }, + on_submit: function (frm) { + update_grant_app_average_reviewed_budget_amount(frm); + }, + after_cancel: function (frm) { + update_grant_app_average_reviewed_budget_amount(frm); + } }); + +//Update grant application +var update_grant_app_average_reviewed_budget_amount = function (frm) { + + let count_of_reviews = frappe.db.count('Grant Application Budget Review', + {'grant_application': frm.doc.grant_application, 'docstatus': 1}); + + let sum_of_reviews = frappe.db.get_list('Grant Application Budget Review', + filters = {'grant_application': frm.doc.grant_application, 'docstatus': 1}, + fields = ['sum(reviewed_amount) as sum_rev_amt','grant_application'], + group_by = 'grant_application'); + + let average_reviewed_budget_amount = flt(sum_of_reviews / count_of_reviews, 2); + + frappe.db.set_value('Grant Application', frm.doc.grant_application, 'average_reviewed_budget_amount', average_reviewed_budget_amount); +}; diff --git a/grants_management_system/grants_management_system/doctype/grant_application_endorsement/grant_application_endorsement.js b/grants_management_system/grants_management_system/doctype/grant_application_endorsement/grant_application_endorsement.js index 093e5c0..7955288 100644 --- a/grants_management_system/grants_management_system/doctype/grant_application_endorsement/grant_application_endorsement.js +++ b/grants_management_system/grants_management_system/doctype/grant_application_endorsement/grant_application_endorsement.js @@ -2,7 +2,62 @@ // For license information, please see license.txt frappe.ui.form.on('Grant Application Endorsement', { - // refresh: function(frm) { - - // } + email_id: function (frm) { + get_user_details(frm); + }, + validate: function (frm) { + get_user_details(frm); + }, + send_sms: function (frm) { + send_sms(frm); + } }); + +//Begin of Functions +//Get user details +var get_user_details = function (frm) { + if (frm.doc.email_id) { + frappe.model.with_doc('User', frm.doc.email_id, function () { + let user = frappe.model.get_doc('User', frm.doc.email_id); + if (user['name']) { + frm.set_value('user', user['name']); + frm.set_value('mobile_no', user['mobile_no']); + frm.set_value('first_name', user['first_name']); + frm.set_value('middle_name', user['middle_name']); + frm.set_value('last_name', user['last_name']); + } else{ + frm.set_value('user', null); + frm.set_value('mobile_no', null); + frm.set_value('first_name', null); + frm.set_value('middle_name', null); + frm.set_value('last_name', null); + } + + refresh_field('user'); + refresh_field('mobile_no'); + refresh_field('first_name'); + refresh_field('middle_name'); + refresh_field('last_name'); + }); + } +}; + +//Send SMS +var send_sms = function (frm) { + if (frm.doc.first_name && frm.doc.send_sms === 1 && frm.doc.mobile_no) { + var message = 'Dear, ' + frm.doc.first_name + ', Requesting for a Grant Application Endorsement at: ' + frm.doc.company + ', Sincerely: ' + frm.doc.applicant_name; + frappe.call({ + method: "frappe.core.doctype.sms_settings.sms_settings.send_sms", + args: { + receiver_list: [frm.doc.mobile_no], + msg: message, + }, + callback: function (r) { + if (r.exc) { + msgprint(r.exc); + return; + } + } + }); + } +}; diff --git a/grants_management_system/grants_management_system/doctype/grant_application_review/grant_application_review.js b/grants_management_system/grants_management_system/doctype/grant_application_review/grant_application_review.js index 24a58ed..8837812 100644 --- a/grants_management_system/grants_management_system/doctype/grant_application_review/grant_application_review.js +++ b/grants_management_system/grants_management_system/doctype/grant_application_review/grant_application_review.js @@ -2,7 +2,64 @@ // For license information, please see license.txt frappe.ui.form.on('Grant Application Review', { - // refresh: function(frm) { - - // } + grant_application: function (frm) { + if (frm.doc.grant_application) { + frm.clear_table('grant_application_review_item'); + frappe.model.with_doc('Grant Application', frm.doc.grant_application, function () { + let source_doc = frappe.model.get_doc('Grant Application', frm.doc.grant_application); + $.each(source_doc.details, function (index, source_row) { + const target_row = frm.add_child('grant_application_review_item'); + target_row.parameter = source_row.parameter; + target_row.item_description = source_row.item_description; + target_row.response = source_row.response; + target_row.response_description = source_row.response_description; + target_row.maximum_score = source_row.maximum_score; + frm.refresh_field('grant_application_review_item'); + }); + }); + } + }, + //Calculate total score + validate: function (frm) { + // calculate total budget amount for each line budget item + let total_maximum_score = 0; + let total_score = 0; + $.each(frm.doc.grant_application_review_item, function (i, d) { + total_maximum_score += flt(d.maximum_score); + if (d.score >= 0) { + total_score += flt(d.score); + } + }); + frm.doc.maximum_score = total_maximum_score; + frm.doc.score = total_score; + }, + setup: function (frm) { + frm.set_indicator_formatter('parameter', + function (doc) { + if (doc.score >= 0){ + return "green" + } else if(doc.skip){ + return "orange" + }else{ + return "white" + } + } + ) + } }); + +//Score Validation against Maximum Score +var maximum_score_validation = function (frm, cdt, cdn) { + var d = locals[cdt][cdn]; + if (d.score && d.maximum_score) { + if (d.score > d.maximum_score) { + msgprint('Score is greater than Maximum Score for the Parameter, please amend to continue'); + frappe.validated = false; + } + } +} + +frappe.ui.form.on("Grant Application Review Item", "score", function (frm, cdt, cdn) { + //Score Validation against Maximum Score + maximum_score_validation(frm, cdt, cdn); +}) diff --git a/grants_management_system/grants_management_system/doctype/grant_call/grant_call.js b/grants_management_system/grants_management_system/doctype/grant_call/grant_call.js index 5b594e2..b660134 100644 --- a/grants_management_system/grants_management_system/doctype/grant_call/grant_call.js +++ b/grants_management_system/grants_management_system/doctype/grant_call/grant_call.js @@ -2,7 +2,22 @@ // For license information, please see license.txt frappe.ui.form.on('Grant Call', { - // refresh: function(frm) { - - // } -}); + grant_application_template: function (frm) { + frappe.call({ + method: "copy_grant_application_parameters_from_template", + doc: frm.doc, + callback: function (r) { + refresh_field("grant_application_parameters"); + } + }); + }, + grant_reporting_template: function (frm) { + frappe.call({ + method: "copy_grant_application_report_parameters_from_template", + doc: frm.doc, + callback: function (r) { + refresh_field("grant_reporting_parameters"); + } + }); + } +}); \ No newline at end of file diff --git a/grants_management_system/grants_management_system/doctype/grant_call/grant_call.py b/grants_management_system/grants_management_system/doctype/grant_call/grant_call.py index 7c20c13..bf981c2 100644 --- a/grants_management_system/grants_management_system/doctype/grant_call/grant_call.py +++ b/grants_management_system/grants_management_system/doctype/grant_call/grant_call.py @@ -1,8 +1,168 @@ # Copyright (c) 2022, Navari Limited and contributors # For license information, please see license.txt -# import frappe -from frappe.model.document import Document +from __future__ import unicode_literals +import frappe +from frappe import _ +from frappe.website.website_generator import WebsiteGenerator -class GrantCall(Document): - pass +class GrantCall(WebsiteGenerator): + website = frappe._dict( + condition_field="published", + page_title_field = "grant_call_name", + template= "templates/generators/grant_call.html", + no_cache=1 + ) + + def get_context(self, context): + context.parents = [{"name":frappe._("Home"), "route":"/"}] + + return context + + # Copy grant application parameters from template + @frappe.whitelist() + def copy_grant_application_parameters_from_template(self): + + if self.grant_application_template: + # Validations + if not self.programme: + frappe.throw(_("Please select the Grant Programme"), + title=_("Grant Programme Required")) + # End Validations + # pull grant application parameters from the template + template_parameters = get_grant_template_application_parameters(self) + + if template_parameters: + self.add_parameter_in_grant_application_table( + template_parameters) + else: + frappe.msgprint(_("Grant Parameters are not available for the programme template."), title=_( + "Programme Template Parameters Missing")) + + # Add parameter types in the grant template parameters child table + def add_parameter_in_grant_application_table(self, template_parameters): + """ Add parameter in the grant application parameters child table""" + self.set('grant_application_parameters', []) + + for data in template_parameters: + self.append('grant_application_parameters', { + 'parameter': data.parameter, + 'item_description': data.item_description, + 'required': data.required, + 'is_numeric': data.is_numeric + }) + + # Copy grant application report parameters from template + @frappe.whitelist() + def copy_grant_application_report_parameters_from_template(self): + + if self.grant_reporting_template: + # Validations + if not self.programme: + frappe.throw(_("Please select the Grant Programme"), + title=_("Grant Programme Required")) + # End Validations + # pull grant application parameters from the template + template_parameters = get_grant_template_reporting_parameters(self) + + if template_parameters: + self.add_parameter_in_grant_application_report_table( + template_parameters) + else: + frappe.msgprint(_("Grant Parameters are not available for the programme template."), title=_( + "Programme Template Parameters Missing")) + + # Add parameter types in the grant template parameters child table + def add_parameter_in_grant_application_report_table(self, template_parameters): + """ Add parameter in the grant application parameters child table""" + self.set('grant_reporting_parameters', []) + + for data in template_parameters: + self.append('grant_reporting_parameters', { + 'parameter': data.parameter, + 'item_description': data.item_description, + 'required': data.required, + 'is_numeric': data.is_numeric + }) + +#Copy grant parameters from tabGrant Template, +#these are to be used when creating grants of the particular programme +def get_grant_template_application_parameters(self): + + template_parameters = frappe.db.sql(""" + SELECT distinct gct.name, gct.programme, gctp.* + FROM `tabGrant Call Template` gct, + `tabGrant Call Template Parameter` gctp + WHERE gct.name = %(grant_application_template)s + and gct.programme = %(programme)s + and gct.name = gctp.parent + and gct.disabled = 0 + order by gctp.idx + """.format(1), { + "grant_application_template": self.grant_application_template, + "programme": self.programme + }, as_dict=1) + return template_parameters + +#Copy grant parameters from tabGrant Template, +#these are to be used when creating grants of the particular programme +def get_grant_template_reporting_parameters(self): + + template_parameters = frappe.db.sql(""" + SELECT distinct gct.name, gct.programme, gctp.* + FROM `tabGrant Call Template` gct, + `tabGrant Call Template Parameter` gctp + WHERE gct.name = %(grant_reporting_template)s + and gct.programme = %(programme)s + and gct.name = gctp.parent + and gct.disabled = 0 + order by gctp.idx + """.format(1), { + "grant_reporting_template": self.grant_reporting_template, + "programme": self.programme + }, as_dict=1) + + return template_parameters + + +@frappe.whitelist(allow_guest=True) +def open_search_grant(text): + filters = {"docstatus": 1,"published": 1,"closing_date":[">=", frappe.utils.nowdate()]} + + active_grant_list = frappe.get_all("Grant Call", + filters = filters, + or_filters = { + "name": ["like", "%{0}%".format(text)], + "grant_call_name": ["like", "%{0}%".format(text)], + "programme": ["like", "%{0}%".format(text)], + "discipline": ["like", "%{0}%".format(text)], + }, + fields = ["name", "grant_call_name","programme", "discipline","opening_date","closing_date","route"], + start=0) + + active_grant= [] + for grantcall in active_grant_list: + active_grant.append(grantcall) + + return active_grant_list + +@frappe.whitelist(allow_guest=True) +def closed_search_grant(text): + filters = {"docstatus": 1,"published": 1,"closing_date":["<", frappe.utils.nowdate()]} + + closed_grant_list = frappe.get_all("Grant Call", + filters = filters, + or_filters = { + "name": ["like", "%{0}%".format(text)], + "grant_call_name": ["like", "%{0}%".format(text)], + "programme": ["like", "%{0}%".format(text)], + "discipline": ["like", "%{0}%".format(text)], + }, + fields = ["name", "grant_call_name", "programme", "discipline", "opening_date","closing_date","route"], + start=0) + + closed_grant = [] + for grantcall in closed_grant_list: + closed_grant.append(grantcall) + + return closed_grant_list \ No newline at end of file diff --git a/grants_management_system/grants_management_system/doctype/grant_call_template/grant_call_template.js b/grants_management_system/grants_management_system/doctype/grant_call_template/grant_call_template.js index b7d217a..0664520 100644 --- a/grants_management_system/grants_management_system/doctype/grant_call_template/grant_call_template.js +++ b/grants_management_system/grants_management_system/doctype/grant_call_template/grant_call_template.js @@ -2,7 +2,15 @@ // For license information, please see license.txt frappe.ui.form.on('Grant Call Template', { - // refresh: function(frm) { - - // } -}); + refresh: function(frm) { + frm.add_custom_button(__("Create Grant Call Template Parameters"), function() { + frappe.call({ + method: "create_grant_parameters", + doc: frm.doc, + callback: function (r) { + refresh_field("parameters"); + } + }); + }, __("Tools")); + } +}); \ No newline at end of file diff --git a/grants_management_system/grants_management_system/doctype/grant_call_template/grant_call_template.py b/grants_management_system/grants_management_system/doctype/grant_call_template/grant_call_template.py index a4ac0b6..750a8e9 100644 --- a/grants_management_system/grants_management_system/doctype/grant_call_template/grant_call_template.py +++ b/grants_management_system/grants_management_system/doctype/grant_call_template/grant_call_template.py @@ -1,8 +1,61 @@ # Copyright (c) 2022, Navari Limited and contributors # For license information, please see license.txt -# import frappe +from __future__ import unicode_literals +import frappe +from frappe import _ from frappe.model.document import Document + class GrantCallTemplate(Document): - pass + + # Get grant parameter types + @frappe.whitelist() + def create_grant_parameters(self): + # Validations + if not self.programme: + frappe.throw(_("Please select the Grant Programme"), + title=_("Grant Programme Required")) + # End Validations + + """ Pull non disabled grant parameter for the respective programme selected""" + grant_parameters = get_grant_parameters(self) + + if grant_parameters: + self.add_parameter_in_table(grant_parameters) + else: + frappe.msgprint(_("Grant Parameters are not available for the programme, please create them manually."), title=_( + "Grant Parameter Missing")) + + # Add parameter types in the grant template parameters child table + def add_parameter_in_table(self, grant_parameter_types): + """ Add parameter types in the grant template parameters child table""" + self.set('parameters', []) + + for data in grant_parameter_types: + self.append('parameters', { + 'parameter': data.grant_parameter_name, + 'item_description': data.item_description, + 'required': data.required, + 'is_numeric': data.is_numeric + }) + +# Get grant parameters from the list defined in tabGrant Parameter Type, +# these are to be used when creating grant templates +def get_grant_parameters(self): + + grant_parameters = frappe.db.sql(""" + SELECT distinct gp.* + FROM `tabGrant Parameter` gp + WHERE gp.disabled = 0 + and gp.grant_parameter_name in (select parent + from `tabGrant Parameter Programme` gpp + where gpp.programme = %(programme)s) + and gp.grant_parameter_name not in(select parameter from `tabGrant Call Template Parameter` gctp + where gctp.parent = %(parent)s) + order by gp.parameter_sequence, gp.idx + """.format(1), { + "programme": self.programme, + "parent": self.parent + }, as_dict=1) + return grant_parameters diff --git a/grants_management_system/grants_management_system/doctype/grant_disbursement_entry/grant_disbursement_entry.js b/grants_management_system/grants_management_system/doctype/grant_disbursement_entry/grant_disbursement_entry.js index 3243fd4..9c2d488 100644 --- a/grants_management_system/grants_management_system/doctype/grant_disbursement_entry/grant_disbursement_entry.js +++ b/grants_management_system/grants_management_system/doctype/grant_disbursement_entry/grant_disbursement_entry.js @@ -1,8 +1,73 @@ // Copyright (c) 2022, Navari Limited and contributors // For license information, please see license.txt +//selecting and adding grant application in child table frappe.ui.form.on('Grant Disbursement Entry', { - // refresh: function(frm) { + + get_grant_applications: function (frm) { + frappe.call({ + method: "get_submitted_grant_applications", + doc: frm.doc, + callback: function (r) { + refresh_field("grant_applications"); + } + }); + } +}); - // } +// Action Button to create disbursement +frappe.ui.form.on("Grant Disbursement Entry", { + refresh: function(frm){ + if(frm.doc.docstatus == 1) { + frappe.db.get_value("Loan", {"grant_disbursement_entry": frm.doc.name, "docstatus": 1}, "name", (r) => { + if (Object.keys(r).length === 0) { + frm.add_custom_button(__('Create Disbursement'), function() { + frappe.model.open_mapped_doc({ + method : "erpnext.non_profit.doctype.grant_disbursement_entry.grant_disbursement_entry.make_loan", + frm : frm }) + },__('Action')) + frm.page.set_inner_btn_group_as_primary(__('Action')); + } else { + frm.set_df_property('status', 'read_only', 1); + } + }); + } + } }); + +frappe.ui.form.on('Grant Disbursement Entry', { + onload: function (frm) { + cur_frm.set_query("institution", function () { + return { + "filters": { + "membership_type": "Institution", + } + }; + }); + }, + //Calculate total amount + validate: function (frm) { + // calculate total grant applications amount for each line item + var total = 0; + $.each(frm.doc.grant_applications, function (i, d) { + // calculate total amount + total += d.amount; + }); + frm.doc.amount = total; + } +}); + +frappe.ui.form.on("Grant Disbursement Entry Item",{ + //remove value when a row is deleted + grant_applications_remove:function(frm, cdt, cdn) { + + var d = locals[cdt][cdn]; + var total = 0; + frm.doc.grant_applications.forEach(function(d) { + // calculate total amount after row is deleted + total += d.amount; + }); + frm.set_value('amount', total); + frm.refresh_field('amount'); + } +}); \ No newline at end of file diff --git a/grants_management_system/grants_management_system/doctype/grant_disbursement_entry/grant_disbursement_entry.json b/grants_management_system/grants_management_system/doctype/grant_disbursement_entry/grant_disbursement_entry.json index 925ddcd..023f58b 100644 --- a/grants_management_system/grants_management_system/doctype/grant_disbursement_entry/grant_disbursement_entry.json +++ b/grants_management_system/grants_management_system/doctype/grant_disbursement_entry/grant_disbursement_entry.json @@ -192,7 +192,7 @@ "link_fieldname": "grant_disbursement_entry" } ], - "modified": "2022-10-25 22:42:24.409253", + "modified": "2022-10-25 23:46:58.038683", "modified_by": "Administrator", "module": "Grants Management System", "name": "Grant Disbursement Entry", @@ -236,7 +236,6 @@ "write": 1 } ], - "restrict_to_domain": "Non Profit", "sort_field": "modified", "sort_order": "DESC", "states": [], diff --git a/grants_management_system/grants_management_system/doctype/grant_disbursement_entry/grant_disbursement_entry.py b/grants_management_system/grants_management_system/doctype/grant_disbursement_entry/grant_disbursement_entry.py index fa4ca2d..f9aecfe 100644 --- a/grants_management_system/grants_management_system/doctype/grant_disbursement_entry/grant_disbursement_entry.py +++ b/grants_management_system/grants_management_system/doctype/grant_disbursement_entry/grant_disbursement_entry.py @@ -1,8 +1,111 @@ # Copyright (c) 2022, Navari Limited and contributors # For license information, please see license.txt -# import frappe +from __future__ import unicode_literals +import frappe +from frappe import _ from frappe.model.document import Document +from frappe.model.mapper import get_mapped_doc class GrantDisbursementEntry(Document): - pass + + # Get submitted grant Application + def get_submitted_grant_applications(self): + #Validations + if not self.grant_call: + frappe.throw(_("Please select the Grant Call"),title=_("Grant Call Required")) + + if not self.institution: + frappe.throw(_("Please select the Institution"),title=_("Institution Required")) + + if not self.from_date: + frappe.throw(_("Please select the From Date Filter"),title=_("From Date Required")) + + if not self.to_date: + frappe.throw(_("Please select the To Date Filter"),title=_("To Date Required")) + #End Validations + + + """ Pull grant applications which are submitted based on criteria selected""" + submitted_ga = get_grant_applications(self) + + if submitted_ga: + self.add_si_in_table(submitted_ga) + self.get_items() + frappe.msgprint(_("Grant Applications selection completed"),title=_("Grant Application Selection")) + else: + frappe.msgprint(_("Grant Applications are not available for Grant Disbursement Entry")) + + # Add submitted grant applications in table + def add_ga_in_table(self, submitted_ga): + """ Add grant applications in the table""" + self.set('grant_applications', []) + for data in submitted_ga: + self.append('grant_applications', { + 'grant_application': data.name, + 'applicant': data.applicant, + 'applicant_name':data.applicant_name, + 'amount': data.amount + }) + + # Get Items + def get_items(self): + self.get_ga_items() + + # Get list of Grant Application query + def get_ga_items(self): + # Check for empty table or empty rows + if not self.get("grant_applications"): + frappe.throw(_("Please fill the Items Details table"), + title=_("Grant Applications Items Required")) + +# Get submitted grant application query +def get_grant_applications(self): + si_filter = "" + if self.grant_call: + si_filter += " and ga.grant_call = %(grant_call)s" + if self.institution: + si_filter += " and ga.institution = %(institution)s" + if self.from_date: + si_filter += " and ga.date >= %(from_date)s" + if self.to_date: + si_filter += " and ga.date <= %(to_date)s" + + + submitted_ga = frappe.db.sql(""" + select distinct ga.name, ga.applicant, ga.applicant_name, ga.institution, ga.grant_call, ga.amount, ga.date + from `tabGrant Application` ga + where ga.docstatus = 1 + and ga.company = %(company)s {0} + and (ga.name not in (select gdei.grant_application from `tabGrant Disbursement Entry Item` gdei, + `tabGrant Disbursement Entry` gde where gdei.parent = gde.name and gde.docstatus != 2)) + + order by ga.name + """.format(si_filter), { + "grant_call": self.grant_call, + "institution":self.institution, + "from_date": self.from_date, + "to_date": self.to_date, + "company": self.company + }, as_dict=1) + return submitted_ga + + +@frappe.whitelist() +def make_loan(source_name, target_doc=None): + def postprocess(source, doc): + doc.loan_name = source.name + + doc = get_mapped_doc("Grant Disbursement Entry", source_name, { + "Grant Disbursement Entry": { + "doctype": "Loan", + "validation": { + "docstatus": ["=", 1] + }, + "field_map":{ + "name" : "grant_disbursement_entry" + } + }, + }, target_doc, postprocess) + + return doc diff --git a/grants_management_system/grants_management_system/doctype/grant_project/grant_project.py b/grants_management_system/grants_management_system/doctype/grant_project/grant_project.py index d04ddfa..b240d7a 100644 --- a/grants_management_system/grants_management_system/doctype/grant_project/grant_project.py +++ b/grants_management_system/grants_management_system/doctype/grant_project/grant_project.py @@ -1,8 +1,75 @@ # Copyright (c) 2022, Navari Limited and contributors # For license information, please see license.txt -# import frappe +import frappe +from email_reply_parser import EmailReplyParser +from frappe import _ +from frappe.desk.reportview import get_match_cond from frappe.model.document import Document +from frappe.utils import add_days, flt, get_datetime, get_time, get_url, nowtime, today + +from erpnext.controllers.queries import get_filters_cond +from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday class GrantProject(Document): - pass + def validate(self): + if not self.is_new(): + self.copy_from_grant_application() + #self.update_costing() + #self.update_percent_complete() + + def copy_from_grant_application(self): + ''' + Copy grant application tasks from grant application + ''' + if self.grant_application and not frappe.db.get_all('Grant Project Task', dict(grant_project = self.name), limit=1): + + # has a grant application, and no loaded grant application tasks, so lets create + if not self.expected_start_date: + # grant project starts today + self.expected_start_date = today() + + # create grant project tasks from grant application tasks + grant_application_tasks = get_grant_application_tasks(self) + + for grant_application_task in grant_application_tasks: + self.create_grant_project_task_from_grant_application_task(grant_application_task) + + def create_grant_project_task_from_grant_application_task(self, grant_application_task): + return frappe.get_doc(dict( + doctype = 'Grant Project Task', + key_action_steps_activities = grant_application_task.key_action_step_activity, + type = grant_application_task.type, + grant_project = self.name, + owner = self.owner, + applicant_name = self.applicant_name, + grant_application = self.grant_application, + grant_call = self.grant_call, + company = self.company, + status = 'Open', + expected_start_date = grant_application_task.expected_start_date, + expected_completion_date = grant_application_task.expected_completion_date, + expected_time_in_days = grant_application_task.expected_time_in_days, + expected_output = grant_application_task.expected_output, + means_of_verification = grant_application_task.means_of_verification, + grant_budget_template = grant_application_task.grant_budget_template, + person_responsible = grant_application_task.person_responsible, + institution_responsible = grant_application_task.institution_responsible, + task_budget = grant_application_task.task_budget, + comments = grant_application_task.comments + )).insert() + + def after_insert(self): + self.copy_from_grant_application() + +def get_grant_application_tasks(self): + + grant_application_tasks = frappe.db.sql(""" + SELECT gat.* + FROM `tabGrant Application Task` gat + WHERE gat.grant_application = %(grant_application)s + order by gat.name + """.format(1), { + "grant_application": self.grant_application + }, as_dict=1) + return grant_application_tasks \ No newline at end of file diff --git a/grants_management_system/grants_management_system/doctype/grant_review_assignment/grant_review_assignment.json b/grants_management_system/grants_management_system/doctype/grant_review_assignment/grant_review_assignment.json index f63b29a..30335b2 100644 --- a/grants_management_system/grants_management_system/doctype/grant_review_assignment/grant_review_assignment.json +++ b/grants_management_system/grants_management_system/doctype/grant_review_assignment/grant_review_assignment.json @@ -250,7 +250,7 @@ "link_fieldname": "grant_review_assignment" } ], - "modified": "2022-10-25 22:56:18.022384", + "modified": "2022-10-25 23:46:18.713321", "modified_by": "Administrator", "module": "Grants Management System", "name": "Grant Review Assignment", @@ -294,7 +294,6 @@ "write": 1 } ], - "restrict_to_domain": "Non Profit", "sort_field": "modified", "sort_order": "DESC", "states": [],