mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-31 10:49:09 +00:00
Merge branch 'develop' of https://github.com/frappe/erpnext into rebrand-ui
This commit is contained in:
@@ -225,7 +225,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-06-22 20:13:26.043092",
|
"modified": "2020-08-03 20:13:26.043092",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Accounts Settings",
|
"name": "Accounts Settings",
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company
|
|||||||
cost_center = frappe.form_dict.get("cost_center")
|
cost_center = frappe.form_dict.get("cost_center")
|
||||||
|
|
||||||
|
|
||||||
cond = []
|
cond = ["is_cancelled=0"]
|
||||||
if date:
|
if date:
|
||||||
cond.append("posting_date <= %s" % frappe.db.escape(cstr(date)))
|
cond.append("posting_date <= %s" % frappe.db.escape(cstr(date)))
|
||||||
else:
|
else:
|
||||||
@@ -206,7 +206,7 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company
|
|||||||
return flt(bal)
|
return flt(bal)
|
||||||
|
|
||||||
def get_count_on(account, fieldname, date):
|
def get_count_on(account, fieldname, date):
|
||||||
cond = []
|
cond = ["is_cancelled=0"]
|
||||||
if date:
|
if date:
|
||||||
cond.append("posting_date <= %s" % frappe.db.escape(cstr(date)))
|
cond.append("posting_date <= %s" % frappe.db.escape(cstr(date)))
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1084,7 +1084,7 @@
|
|||||||
"idx": 105,
|
"idx": 105,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-07-18 05:09:33.800633",
|
"modified": "2020-07-31 14:13:44.610190",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Purchase Order",
|
"name": "Purchase Order",
|
||||||
@@ -1135,5 +1135,5 @@
|
|||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"timeline_field": "supplier",
|
"timeline_field": "supplier",
|
||||||
"title_field": "title"
|
"title_field": "supplier"
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
import pycountry
|
|
||||||
import taxjar
|
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from erpnext import get_default_company
|
from erpnext import get_default_company
|
||||||
from frappe import _
|
from frappe import _
|
||||||
@@ -32,6 +29,7 @@ def get_client():
|
|||||||
|
|
||||||
|
|
||||||
def create_transaction(doc, method):
|
def create_transaction(doc, method):
|
||||||
|
import taxjar
|
||||||
"""Create an order transaction in TaxJar"""
|
"""Create an order transaction in TaxJar"""
|
||||||
|
|
||||||
if not TAXJAR_CREATE_TRANSACTIONS:
|
if not TAXJAR_CREATE_TRANSACTIONS:
|
||||||
@@ -208,6 +206,7 @@ def get_shipping_address_details(doc):
|
|||||||
|
|
||||||
|
|
||||||
def get_iso_3166_2_state_code(address):
|
def get_iso_3166_2_state_code(address):
|
||||||
|
import pycountry
|
||||||
country_code = frappe.db.get_value("Country", address.get("country"), "code")
|
country_code = frappe.db.get_value("Country", address.get("country"), "code")
|
||||||
|
|
||||||
error_message = _("""{0} is not a valid state! Check for typos or enter the ISO code for your state.""").format(address.get("state"))
|
error_message = _("""{0} is not a valid state! Check for typos or enter the ISO code for your state.""").format(address.get("state"))
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
"doctype": "Dashboard Chart",
|
"doctype": "Dashboard Chart",
|
||||||
"document_type": "Job Applicant",
|
"document_type": "Job Applicant",
|
||||||
"dynamic_filters_json": "",
|
"dynamic_filters_json": "",
|
||||||
"filters_json": "[[\"Job Applicant\",\"creation\",\"Previous\",\"1 month\"]]",
|
"filters_json": "[[\"Job Applicant\",\"creation\",\"Timespan\",\"last month\",false]]",
|
||||||
"group_by_based_on": "status",
|
"group_by_based_on": "status",
|
||||||
"group_by_type": "Count",
|
"group_by_type": "Count",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"is_public": 1,
|
"is_public": 1,
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
"last_synced_on": "2020-07-22 14:27:40.118498",
|
"last_synced_on": "2020-07-28 16:19:12.109979",
|
||||||
"modified": "2020-07-22 14:33:00.404144",
|
"modified": "2020-07-28 16:19:45.279490",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Job Application Status",
|
"name": "Job Application Status",
|
||||||
|
|||||||
@@ -35,7 +35,15 @@ frappe.query_reports["Monthly Attendance Sheet"] = {
|
|||||||
"fieldname":"employee",
|
"fieldname":"employee",
|
||||||
"label": __("Employee"),
|
"label": __("Employee"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Employee"
|
"options": "Employee",
|
||||||
|
get_query: () => {
|
||||||
|
var company = frappe.query_report.get_filter_value('company');
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
'company': company
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname":"company",
|
"fieldname":"company",
|
||||||
|
|||||||
@@ -96,33 +96,35 @@ def get_data(filters):
|
|||||||
|
|
||||||
def get_parent_row(sp_jo_map, sp, jo_ja_map, ja_joff_map):
|
def get_parent_row(sp_jo_map, sp, jo_ja_map, ja_joff_map):
|
||||||
data = []
|
data = []
|
||||||
for jo in sp_jo_map[sp]:
|
if sp in sp_jo_map.keys():
|
||||||
row = {
|
for jo in sp_jo_map[sp]:
|
||||||
"staffing_plan" : sp,
|
row = {
|
||||||
"job_opening" : jo["name"],
|
"staffing_plan" : sp,
|
||||||
}
|
"job_opening" : jo["name"],
|
||||||
data.append(row)
|
}
|
||||||
child_row = get_child_row( jo["name"], jo_ja_map, ja_joff_map)
|
data.append(row)
|
||||||
data += child_row
|
child_row = get_child_row( jo["name"], jo_ja_map, ja_joff_map)
|
||||||
|
data += child_row
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def get_child_row(jo, jo_ja_map, ja_joff_map):
|
def get_child_row(jo, jo_ja_map, ja_joff_map):
|
||||||
data = []
|
data = []
|
||||||
for ja in jo_ja_map[jo]:
|
if jo in jo_ja_map.keys():
|
||||||
row = {
|
for ja in jo_ja_map[jo]:
|
||||||
"indent":1,
|
row = {
|
||||||
"job_applicant": ja.name,
|
"indent":1,
|
||||||
"applicant_name": ja.applicant_name,
|
"job_applicant": ja.name,
|
||||||
"application_status": ja.status,
|
"applicant_name": ja.applicant_name,
|
||||||
}
|
"application_status": ja.status,
|
||||||
if ja.name in ja_joff_map.keys():
|
}
|
||||||
jo_detail =ja_joff_map[ja.name][0]
|
if ja.name in ja_joff_map.keys():
|
||||||
row["job_offer"] = jo_detail.name
|
jo_detail =ja_joff_map[ja.name][0]
|
||||||
row["job_offer_status"] = jo_detail.status
|
row["job_offer"] = jo_detail.name
|
||||||
row["offer_date"]= jo_detail.offer_date.strftime("%d-%m-%Y")
|
row["job_offer_status"] = jo_detail.status
|
||||||
row["designation"] = jo_detail.designation
|
row["offer_date"]= jo_detail.offer_date.strftime("%d-%m-%Y")
|
||||||
|
row["designation"] = jo_detail.designation
|
||||||
|
|
||||||
data.append(row)
|
data.append(row)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def get_staffing_plan(filters):
|
def get_staffing_plan(filters):
|
||||||
@@ -177,7 +179,7 @@ def get_job_applicant(jo_list):
|
|||||||
def get_job_offer(ja_list):
|
def get_job_offer(ja_list):
|
||||||
ja_joff_map = {}
|
ja_joff_map = {}
|
||||||
|
|
||||||
offers = frappe.get_all("Job offer", filters = [["job_applicant", "IN", ja_list]], fields =["name", "job_applicant", "status", 'offer_date', 'designation'])
|
offers = frappe.get_all("Job Offer", filters = [["job_applicant", "IN", ja_list]], fields =["name", "job_applicant", "status", 'offer_date', 'designation'])
|
||||||
|
|
||||||
for offer in offers:
|
for offer in offers:
|
||||||
if offer.job_applicant not in ja_joff_map.keys():
|
if offer.job_applicant not in ja_joff_map.keys():
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
"section_break_8",
|
"section_break_8",
|
||||||
"loan_type",
|
"loan_type",
|
||||||
"loan_amount",
|
"loan_amount",
|
||||||
"is_secured_loan",
|
|
||||||
"rate_of_interest",
|
"rate_of_interest",
|
||||||
|
"is_secured_loan",
|
||||||
"disbursement_date",
|
"disbursement_date",
|
||||||
"disbursed_amount",
|
"disbursed_amount",
|
||||||
"column_break_11",
|
"column_break_11",
|
||||||
@@ -334,7 +334,7 @@
|
|||||||
],
|
],
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-07-02 20:46:40.128142",
|
"modified": "2020-08-01 12:36:11.255233",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Loan Management",
|
"module": "Loan Management",
|
||||||
"name": "Loan",
|
"name": "Loan",
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ class TestLoan(unittest.TestCase):
|
|||||||
self.assertTrue(loan_security_shortfall)
|
self.assertTrue(loan_security_shortfall)
|
||||||
|
|
||||||
self.assertEquals(loan_security_shortfall.loan_amount, 1000000.00)
|
self.assertEquals(loan_security_shortfall.loan_amount, 1000000.00)
|
||||||
self.assertEquals(loan_security_shortfall.security_value, 400000.00)
|
self.assertEquals(loan_security_shortfall.security_value, 800000.00)
|
||||||
self.assertEquals(loan_security_shortfall.shortfall_amount, 600000.00)
|
self.assertEquals(loan_security_shortfall.shortfall_amount, 600000.00)
|
||||||
|
|
||||||
frappe.db.sql(""" UPDATE `tabLoan Security Price` SET loan_security_price = 250
|
frappe.db.sql(""" UPDATE `tabLoan Security Price` SET loan_security_price = 250
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ class LoanSecurityPledge(Document):
|
|||||||
def validate(self):
|
def validate(self):
|
||||||
self.set_pledge_amount()
|
self.set_pledge_amount()
|
||||||
self.validate_duplicate_securities()
|
self.validate_duplicate_securities()
|
||||||
|
self.validate_loan_security_type()
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
if self.loan:
|
if self.loan:
|
||||||
@@ -31,6 +32,27 @@ class LoanSecurityPledge(Document):
|
|||||||
frappe.throw(_('Loan Security {0} added multiple times').format(frappe.bold(
|
frappe.throw(_('Loan Security {0} added multiple times').format(frappe.bold(
|
||||||
security.loan_security)))
|
security.loan_security)))
|
||||||
|
|
||||||
|
def validate_loan_security_type(self):
|
||||||
|
existing_pledge = ''
|
||||||
|
|
||||||
|
if self.loan:
|
||||||
|
existing_pledge = frappe.db.get_value('Loan Security Pledge', {'loan': self.loan}, ['name'])
|
||||||
|
|
||||||
|
if existing_pledge:
|
||||||
|
loan_security_type = frappe.db.get_value('Pledge', {'parent': existing_pledge}, ['loan_security_type'])
|
||||||
|
else:
|
||||||
|
loan_security_type = self.securities[0].loan_security_type
|
||||||
|
|
||||||
|
ltv_ratio_map = frappe._dict(frappe.get_all("Loan Security Type",
|
||||||
|
fields=["name", "loan_to_value_ratio"], as_list=1))
|
||||||
|
|
||||||
|
ltv_ratio = ltv_ratio_map.get(loan_security_type)
|
||||||
|
|
||||||
|
for security in self.securities:
|
||||||
|
if ltv_ratio_map.get(security.loan_security_type) != ltv_ratio:
|
||||||
|
frappe.throw(_("Loan Securities with different LTV ratio cannot be pledged against one loan"))
|
||||||
|
|
||||||
|
|
||||||
def set_pledge_amount(self):
|
def set_pledge_amount(self):
|
||||||
total_security_value = 0
|
total_security_value = 0
|
||||||
maximum_loan_value = 0
|
maximum_loan_value = 0
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import frappe
|
|||||||
from frappe.utils import get_datetime
|
from frappe.utils import get_datetime
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from six import iteritems
|
from six import iteritems
|
||||||
|
from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import get_pledged_security_qty
|
||||||
|
|
||||||
class LoanSecurityShortfall(Document):
|
class LoanSecurityShortfall(Document):
|
||||||
pass
|
pass
|
||||||
@@ -50,31 +51,30 @@ def check_for_ltv_shortfall(process_loan_security_shortfall):
|
|||||||
"valid_upto": (">=", update_time)
|
"valid_upto": (">=", update_time)
|
||||||
}, as_list=1))
|
}, as_list=1))
|
||||||
|
|
||||||
ltv_ratio_map = frappe._dict(frappe.get_all("Loan Security Type",
|
loans = frappe.get_all('Loan', fields=['name', 'loan_amount', 'total_principal_paid'],
|
||||||
fields=["name", "loan_to_value_ratio"], as_list=1))
|
filters={'status': 'Disbursed', 'is_secured_loan': 1})
|
||||||
|
|
||||||
loans = frappe.db.sql(""" SELECT l.name, l.loan_amount, l.total_principal_paid, lp.loan_security, lp.haircut, lp.qty, lp.loan_security_type
|
|
||||||
FROM `tabLoan` l, `tabPledge` lp , `tabLoan Security Pledge`p WHERE lp.parent = p.name and p.loan = l.name and l.docstatus = 1
|
|
||||||
and l.is_secured_loan and l.status = 'Disbursed' and p.status = 'Pledged'""", as_dict=1)
|
|
||||||
|
|
||||||
loan_security_map = {}
|
loan_security_map = {}
|
||||||
|
|
||||||
for loan in loans:
|
for loan in loans:
|
||||||
loan_security_map.setdefault(loan.name, {
|
outstanding_amount = loan.loan_amount - loan.total_principal_paid
|
||||||
"loan_amount": loan.loan_amount - loan.total_principal_paid,
|
pledged_securities = get_pledged_security_qty(loan.name)
|
||||||
"security_value": 0.0
|
ltv_ratio = ''
|
||||||
})
|
security_value = 0.0
|
||||||
|
|
||||||
current_loan_security_amount = loan_security_price_map.get(loan.loan_security, 0) * loan.qty
|
for security, qty in pledged_securities.items():
|
||||||
ltv_ratio = ltv_ratio_map.get(loan.loan_security_type)
|
if not ltv_ratio:
|
||||||
|
ltv_ratio = get_ltv_ratio(security)
|
||||||
|
security_value += loan_security_price_map.get(security) * qty
|
||||||
|
|
||||||
loan_security_map[loan.name]['security_value'] += current_loan_security_amount - (current_loan_security_amount * loan.haircut/100)
|
current_ratio = (outstanding_amount/security_value) * 100
|
||||||
|
|
||||||
for loan, value in iteritems(loan_security_map):
|
if current_ratio > ltv_ratio:
|
||||||
if (value["loan_amount"]/value['security_value'] * 100) > ltv_ratio:
|
shortfall_amount = outstanding_amount - ((security_value * ltv_ratio) / 100)
|
||||||
create_loan_security_shortfall(loan, value, process_loan_security_shortfall)
|
create_loan_security_shortfall(loan.name, outstanding_amount, security_value, shortfall_amount,
|
||||||
|
process_loan_security_shortfall)
|
||||||
|
|
||||||
def create_loan_security_shortfall(loan, value, process_loan_security_shortfall):
|
def create_loan_security_shortfall(loan, loan_amount, security_value, shortfall_amount, process_loan_security_shortfall):
|
||||||
|
|
||||||
existing_shortfall = frappe.db.get_value("Loan Security Shortfall", {"loan": loan, "status": "Pending"}, "name")
|
existing_shortfall = frappe.db.get_value("Loan Security Shortfall", {"loan": loan, "status": "Pending"}, "name")
|
||||||
|
|
||||||
@@ -85,9 +85,14 @@ def create_loan_security_shortfall(loan, value, process_loan_security_shortfall)
|
|||||||
ltv_shortfall.loan = loan
|
ltv_shortfall.loan = loan
|
||||||
|
|
||||||
ltv_shortfall.shortfall_time = get_datetime()
|
ltv_shortfall.shortfall_time = get_datetime()
|
||||||
ltv_shortfall.loan_amount = value["loan_amount"]
|
ltv_shortfall.loan_amount = loan_amount
|
||||||
ltv_shortfall.security_value = value["security_value"]
|
ltv_shortfall.security_value = security_value
|
||||||
ltv_shortfall.shortfall_amount = value["loan_amount"] - value["security_value"]
|
ltv_shortfall.shortfall_amount = shortfall_amount
|
||||||
ltv_shortfall.process_loan_security_shortfall = process_loan_security_shortfall
|
ltv_shortfall.process_loan_security_shortfall = process_loan_security_shortfall
|
||||||
ltv_shortfall.save()
|
ltv_shortfall.save()
|
||||||
|
|
||||||
|
def get_ltv_ratio(loan_security):
|
||||||
|
loan_security_type = frappe.db.get_value('Loan Security', loan_security, 'loan_security_type')
|
||||||
|
ltv_ratio = frappe.db.get_value('Loan Security Type', loan_security_type, 'loan_to_value_ratio')
|
||||||
|
return ltv_ratio
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ from frappe.model.document import Document
|
|||||||
class ProductsSettings(Document):
|
class ProductsSettings(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
if self.home_page_is_products:
|
if self.home_page_is_products:
|
||||||
frappe.db.set_value("Website Settings", "home_page", "products")
|
frappe.db.set_value("Website Settings", None, "home_page", "products")
|
||||||
elif frappe.db.get_single_value("Website Settings", "home_page") == 'products':
|
elif frappe.db.get_single_value("Website Settings", "home_page") == 'products':
|
||||||
frappe.db.set_value("Website Settings", "home_page", "home")
|
frappe.db.set_value("Website Settings", None, "home_page", "home")
|
||||||
|
|
||||||
self.validate_field_filters()
|
self.validate_field_filters()
|
||||||
self.validate_attribute_filters()
|
self.validate_attribute_filters()
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"actions": [],
|
"actions": [],
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_workflow": 1,
|
|
||||||
"autoname": "naming_series:",
|
"autoname": "naming_series:",
|
||||||
"creation": "2013-06-18 12:39:59",
|
"creation": "2013-06-18 12:39:59",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
@@ -1461,7 +1460,7 @@
|
|||||||
"idx": 105,
|
"idx": 105,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-07-18 05:13:06.680696",
|
"modified": "2020-07-31 14:13:17.962015",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Sales Order",
|
"name": "Sales Order",
|
||||||
@@ -1535,7 +1534,7 @@
|
|||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"timeline_field": "customer",
|
"timeline_field": "customer",
|
||||||
"title_field": "title",
|
"title_field": "customer",
|
||||||
"track_changes": 1,
|
"track_changes": 1,
|
||||||
"track_seen": 1
|
"track_seen": 1
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user