Merge pull request #18239 from netchampfaris/breadcrumbs-module-map-2
fix: Add module map for breadcrumbs
diff --git a/erpnext/config/stock.py b/erpnext/config/stock.py
index 84aa847..f5e48b3 100644
--- a/erpnext/config/stock.py
+++ b/erpnext/config/stock.py
@@ -281,9 +281,9 @@
},
{
"type": "report",
+ "is_query_report": True,
"name": "Item Shortage Report",
- "route": "#Report/Bin/Item Shortage Report",
- "doctype": "Purchase Receipt"
+ "doctype": "Bin"
},
{
"type": "report",
diff --git a/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.py b/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.py
index 29a1a2b..96a533e 100644
--- a/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.py
+++ b/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.py
@@ -7,7 +7,9 @@
from frappe import _
from frappe.model.document import Document
from requests_oauthlib import OAuth2Session
-import json, requests
+import json
+import requests
+import traceback
from erpnext import encode_company_abbr
# QuickBooks requires a redirect URL, User will be redirect to this URL
@@ -32,7 +34,6 @@
class QuickBooksMigrator(Document):
def __init__(self, *args, **kwargs):
super(QuickBooksMigrator, self).__init__(*args, **kwargs)
- from pprint import pprint
self.oauth = OAuth2Session(
client_id=self.client_id,
redirect_uri=self.redirect_url,
@@ -46,7 +47,9 @@
if self.company:
# We need a Cost Center corresponding to the selected erpnext Company
self.default_cost_center = frappe.db.get_value('Company', self.company, 'cost_center')
- self.default_warehouse = frappe.get_all('Warehouse', filters={"company": self.company, "is_group": 0})[0]["name"]
+ company_warehouses = frappe.get_all('Warehouse', filters={"company": self.company, "is_group": 0})
+ if company_warehouses:
+ self.default_warehouse = company_warehouses[0].name
if self.authorization_endpoint:
self.authorization_url = self.oauth.authorization_url(self.authorization_endpoint)[0]
@@ -218,7 +221,7 @@
def _fetch_general_ledger(self):
try:
- query_uri = "{}/company/{}/reports/GeneralLedger".format(self.api_endpoint ,self.quickbooks_company_id)
+ query_uri = "{}/company/{}/reports/GeneralLedger".format(self.api_endpoint, self.quickbooks_company_id)
response = self._get(query_uri,
params={
"columns": ",".join(["tx_date", "txn_type", "credit_amt", "debt_amt"]),
@@ -493,17 +496,17 @@
"account_currency": customer["CurrencyRef"]["value"],
"company": self.company,
})[0]["name"]
- except Exception as e:
+ except Exception:
receivable_account = None
erpcustomer = frappe.get_doc({
"doctype": "Customer",
"quickbooks_id": customer["Id"],
- "customer_name" : encode_company_abbr(customer["DisplayName"], self.company),
- "customer_type" : "Individual",
- "customer_group" : "Commercial",
+ "customer_name": encode_company_abbr(customer["DisplayName"], self.company),
+ "customer_type": "Individual",
+ "customer_group": "Commercial",
"default_currency": customer["CurrencyRef"]["value"],
"accounts": [{"company": self.company, "account": receivable_account}],
- "territory" : "All Territories",
+ "territory": "All Territories",
"company": self.company,
}).insert()
if "BillAddr" in customer:
@@ -521,7 +524,7 @@
item_dict = {
"doctype": "Item",
"quickbooks_id": item["Id"],
- "item_code" : encode_company_abbr(item["Name"], self.company),
+ "item_code": encode_company_abbr(item["Name"], self.company),
"stock_uom": "Unit",
"is_stock_item": 0,
"item_group": "All Item Groups",
@@ -549,14 +552,14 @@
erpsupplier = frappe.get_doc({
"doctype": "Supplier",
"quickbooks_id": vendor["Id"],
- "supplier_name" : encode_company_abbr(vendor["DisplayName"], self.company),
- "supplier_group" : "All Supplier Groups",
+ "supplier_name": encode_company_abbr(vendor["DisplayName"], self.company),
+ "supplier_group": "All Supplier Groups",
"company": self.company,
}).insert()
if "BillAddr" in vendor:
self._create_address(erpsupplier, "Supplier", vendor["BillAddr"], "Billing")
if "ShipAddr" in vendor:
- self._create_address(erpsupplier, "Supplier",vendor["ShipAddr"], "Shipping")
+ self._create_address(erpsupplier, "Supplier", vendor["ShipAddr"], "Shipping")
except Exception as e:
self._log_error(e)
@@ -829,7 +832,7 @@
"currency": invoice["CurrencyRef"]["value"],
"conversion_rate": invoice.get("ExchangeRate", 1),
"posting_date": invoice["TxnDate"],
- "due_date": invoice.get("DueDate", invoice["TxnDate"]),
+ "due_date": invoice.get("DueDate", invoice["TxnDate"]),
"credit_to": credit_to_account,
"supplier": frappe.get_all("Supplier",
filters={
@@ -1200,7 +1203,7 @@
def _create_address(self, entity, doctype, address, address_type):
- try :
+ try:
if not frappe.db.exists({"doctype": "Address", "quickbooks_id": address["Id"]}):
frappe.get_doc({
"doctype": "Address",
@@ -1252,8 +1255,6 @@
def _log_error(self, execption, data=""):
- import json, traceback
- traceback.print_exc()
frappe.log_error(title="QuickBooks Migration Error",
message="\n".join([
"Data",
diff --git a/erpnext/hr/doctype/employee_loan_application/employee_loan_application.py b/erpnext/hr/doctype/employee_loan_application/employee_loan_application.py
deleted file mode 100644
index b6c6502..0000000
--- a/erpnext/hr/doctype/employee_loan_application/employee_loan_application.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-import frappe, math
-from frappe import _
-from frappe.utils import flt, rounded
-from frappe.model.mapper import get_mapped_doc
-from frappe.model.document import Document
-
-from erpnext.hr.doctype.employee_loan.employee_loan import get_monthly_repayment_amount, check_repayment_method
-
-class EmployeeLoanApplication(Document):
- def validate(self):
- check_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount, self.repayment_periods)
- self.validate_loan_amount()
- self.get_repayment_details()
-
- def validate_loan_amount(self):
- maximum_loan_limit = frappe.db.get_value('Loan Type', self.loan_type, 'maximum_loan_amount')
- if maximum_loan_limit and self.loan_amount > maximum_loan_limit:
- frappe.throw(_("Loan Amount cannot exceed Maximum Loan Amount of {0}").format(maximum_loan_limit))
-
- def get_repayment_details(self):
- if self.repayment_method == "Repay Over Number of Periods":
- self.repayment_amount = get_monthly_repayment_amount(self.repayment_method, self.loan_amount, self.rate_of_interest, self.repayment_periods)
-
- if self.repayment_method == "Repay Fixed Amount per Period":
- monthly_interest_rate = flt(self.rate_of_interest) / (12 *100)
- if monthly_interest_rate:
- monthly_interest_amount = self.loan_amount * monthly_interest_rate
- if monthly_interest_amount >= self.repayment_amount:
- frappe.throw(_("Repayment amount {} should be greater than monthly interest amount {}").
- format(self.repayment_amount, monthly_interest_amount))
-
- self.repayment_periods = math.ceil((math.log(self.repayment_amount) -
- math.log(self.repayment_amount - (monthly_interest_amount))) /
- (math.log(1 + monthly_interest_rate)))
- else:
- self.repayment_periods = self.loan_amount / self.repayment_amount
-
- self.calculate_payable_amount()
-
- def calculate_payable_amount(self):
- balance_amount = self.loan_amount
- self.total_payable_amount = 0
- self.total_payable_interest = 0
-
- while(balance_amount > 0):
- interest_amount = rounded(balance_amount * flt(self.rate_of_interest) / (12*100))
- balance_amount = rounded(balance_amount + interest_amount - self.repayment_amount)
-
- self.total_payable_interest += interest_amount
-
- self.total_payable_amount = self.loan_amount + self.total_payable_interest
-
-@frappe.whitelist()
-def make_employee_loan(source_name, target_doc = None):
- doclist = get_mapped_doc("Employee Loan Application", source_name, {
- "Employee Loan Application": {
- "doctype": "Employee Loan",
- "validation": {
- "docstatus": ["=", 1]
- }
- }
- }, target_doc)
-
- return doclist
\ No newline at end of file
diff --git a/erpnext/hr/doctype/loan/loan.js b/erpnext/hr/doctype/loan/loan.js
index e1b4178..3f5c30c 100644
--- a/erpnext/hr/doctype/loan/loan.js
+++ b/erpnext/hr/doctype/loan/loan.js
@@ -39,31 +39,19 @@
},
refresh: function (frm) {
- if (frm.doc.docstatus == 1 && frm.doc.status == "Sanctioned") {
- frm.add_custom_button(__('Create Disbursement Entry'), function() {
- frm.trigger("make_jv");
- })
- }
- if (frm.doc.repayment_schedule) {
- let total_amount_paid = 0;
- $.each(frm.doc.repayment_schedule || [], function(i, row) {
- if (row.paid) {
- total_amount_paid += row.total_payment;
- }
- });
- frm.set_value("total_amount_paid", total_amount_paid);
-; }
- if (frm.doc.docstatus == 1 && frm.doc.repayment_start_date && (frm.doc.applicant_type == 'Member' || frm.doc.repay_from_salary == 0)) {
- frm.add_custom_button(__('Create Repayment Entry'), function() {
- frm.trigger("make_repayment_entry");
- })
+ if (frm.doc.docstatus == 1) {
+ if (frm.doc.status == "Sanctioned") {
+ frm.add_custom_button(__('Create Disbursement Entry'), function() {
+ frm.trigger("make_jv");
+ }).addClass("btn-primary");
+ } else if (frm.doc.status == "Disbursed" && frm.doc.repayment_start_date && (frm.doc.applicant_type == 'Member' || frm.doc.repay_from_salary == 0)) {
+ frm.add_custom_button(__('Create Repayment Entry'), function() {
+ frm.trigger("make_repayment_entry");
+ }).addClass("btn-primary");
+ }
}
frm.trigger("toggle_fields");
},
- status: function (frm) {
- frm.toggle_reqd("disbursement_date", frm.doc.status == 'Disbursed')
- frm.toggle_reqd("repayment_start_date", frm.doc.status == 'Disbursed')
- },
make_jv: function (frm) {
frappe.call({
diff --git a/erpnext/hr/doctype/loan/loan.json b/erpnext/hr/doctype/loan/loan.json
index 587b301..505b601 100644
--- a/erpnext/hr/doctype/loan/loan.json
+++ b/erpnext/hr/doctype/loan/loan.json
@@ -1,5 +1,6 @@
{
"allow_copy": 0,
+ "allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 0,
@@ -20,6 +21,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "applicant_type",
"fieldtype": "Select",
"hidden": 0,
@@ -53,6 +55,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "applicant",
"fieldtype": "Dynamic Link",
"hidden": 0,
@@ -86,6 +89,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "applicant_name",
"fieldtype": "Data",
"hidden": 0,
@@ -118,6 +122,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "loan_application",
"fieldtype": "Link",
"hidden": 0,
@@ -151,6 +156,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "loan_type",
"fieldtype": "Link",
"hidden": 0,
@@ -184,6 +190,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
@@ -215,7 +222,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "default": "",
+ "default": "Today",
+ "fetch_if_empty": 0,
"fieldname": "posting_date",
"fieldtype": "Date",
"hidden": 0,
@@ -248,6 +256,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -282,6 +291,7 @@
"collapsible": 0,
"columns": 0,
"default": "Sanctioned",
+ "fetch_if_empty": 0,
"fieldname": "status",
"fieldtype": "Select",
"hidden": 0,
@@ -299,7 +309,7 @@
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
- "read_only": 0,
+ "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
@@ -316,6 +326,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.applicant_type==\"Employee\"",
+ "fetch_if_empty": 0,
"fieldname": "repay_from_salary",
"fieldtype": "Check",
"hidden": 0,
@@ -348,6 +359,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "section_break_8",
"fieldtype": "Section Break",
"hidden": 0,
@@ -380,6 +392,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "loan_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -415,6 +428,7 @@
"columns": 0,
"default": "",
"fetch_from": "loan_type.rate_of_interest",
+ "fetch_if_empty": 0,
"fieldname": "rate_of_interest",
"fieldtype": "Percent",
"hidden": 0,
@@ -448,6 +462,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "depends_on": "eval:doc.status==\"Disbursed\"",
+ "fetch_if_empty": 0,
"fieldname": "disbursement_date",
"fieldtype": "Date",
"hidden": 0,
@@ -480,6 +496,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "repayment_start_date",
"fieldtype": "Date",
"hidden": 0,
@@ -499,7 +516,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 0,
+ "reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
@@ -512,6 +529,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "column_break_11",
"fieldtype": "Column Break",
"hidden": 0,
@@ -544,6 +562,7 @@
"collapsible": 0,
"columns": 0,
"default": "Repay Over Number of Periods",
+ "fetch_if_empty": 0,
"fieldname": "repayment_method",
"fieldtype": "Select",
"hidden": 0,
@@ -579,6 +598,7 @@
"columns": 0,
"default": "",
"depends_on": "",
+ "fetch_if_empty": 0,
"fieldname": "repayment_periods",
"fieldtype": "Int",
"hidden": 0,
@@ -613,6 +633,7 @@
"columns": 0,
"default": "",
"depends_on": "",
+ "fetch_if_empty": 0,
"fieldname": "monthly_repayment_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -646,6 +667,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "account_info",
"fieldtype": "Section Break",
"hidden": 0,
@@ -678,6 +700,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "mode_of_payment",
"fieldtype": "Link",
"hidden": 0,
@@ -711,6 +734,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "payment_account",
"fieldtype": "Link",
"hidden": 0,
@@ -744,6 +768,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "column_break_9",
"fieldtype": "Column Break",
"hidden": 0,
@@ -775,6 +800,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "loan_account",
"fieldtype": "Link",
"hidden": 0,
@@ -808,6 +834,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "interest_income_account",
"fieldtype": "Link",
"hidden": 0,
@@ -841,6 +868,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "section_break_15",
"fieldtype": "Section Break",
"hidden": 0,
@@ -873,6 +901,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "repayment_schedule",
"fieldtype": "Table",
"hidden": 0,
@@ -906,6 +935,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "section_break_17",
"fieldtype": "Section Break",
"hidden": 0,
@@ -939,6 +969,7 @@
"collapsible": 0,
"columns": 0,
"default": "0",
+ "fetch_if_empty": 0,
"fieldname": "total_payment",
"fieldtype": "Currency",
"hidden": 0,
@@ -972,6 +1003,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "column_break_19",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1004,6 +1036,7 @@
"collapsible": 0,
"columns": 0,
"default": "0",
+ "fetch_if_empty": 0,
"fieldname": "total_interest_payable",
"fieldtype": "Currency",
"hidden": 0,
@@ -1037,6 +1070,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "total_amount_paid",
"fieldtype": "Currency",
"hidden": 0,
@@ -1070,6 +1104,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
@@ -1106,7 +1141,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-08-21 16:15:53.267145",
+ "modified": "2019-07-10 13:04:20.953694",
"modified_by": "Administrator",
"module": "HR",
"name": "Loan",
@@ -1149,7 +1184,6 @@
"set_user_permissions": 0,
"share": 0,
"submit": 0,
- "user_permission_doctypes": "[\"Employee\"]",
"write": 0
}
],
diff --git a/erpnext/hr/doctype/loan/loan.py b/erpnext/hr/doctype/loan/loan.py
index 58c9b8f..a803863 100644
--- a/erpnext/hr/doctype/loan/loan.py
+++ b/erpnext/hr/doctype/loan/loan.py
@@ -6,29 +6,33 @@
import frappe, math, json
import erpnext
from frappe import _
-from frappe.utils import flt, rounded, add_months, nowdate
+from frappe.utils import flt, rounded, add_months, nowdate, getdate
from erpnext.controllers.accounts_controller import AccountsController
class Loan(AccountsController):
def validate(self):
- check_repayment_method(self.repayment_method, self.loan_amount, self.monthly_repayment_amount, self.repayment_periods)
+ validate_repayment_method(self.repayment_method, self.loan_amount, self.monthly_repayment_amount, self.repayment_periods)
+ self.set_missing_fields()
+ self.make_repayment_schedule()
+ self.set_repayment_period()
+ self.calculate_totals()
+
+ def set_missing_fields(self):
if not self.company:
self.company = erpnext.get_default_company()
+
if not self.posting_date:
self.posting_date = nowdate()
+
if self.loan_type and not self.rate_of_interest:
self.rate_of_interest = frappe.db.get_value("Loan Type", self.loan_type, "rate_of_interest")
+
if self.repayment_method == "Repay Over Number of Periods":
self.monthly_repayment_amount = get_monthly_repayment_amount(self.repayment_method, self.loan_amount, self.rate_of_interest, self.repayment_periods)
+
if self.status == "Repaid/Closed":
self.total_amount_paid = self.total_payment
- if self.status == 'Disbursed' and self.repayment_start_date < self.disbursement_date:
- frappe.throw(_("Repayment Start Date cannot be before Disbursement Date."))
- if self.status == "Disbursed":
- self.make_repayment_schedule()
- self.set_repayment_period()
- self.calculate_totals()
def make_jv_entry(self):
self.check_permission('write')
@@ -105,20 +109,31 @@
frappe.db.set_value("Loan", doc.name, "total_amount_paid", total_amount_paid)
def update_disbursement_status(doc):
- disbursement = frappe.db.sql("""select posting_date, ifnull(sum(credit_in_account_currency), 0) as disbursed_amount
- from `tabGL Entry` where account = %s and against_voucher_type = 'Loan' and against_voucher = %s""",
- (doc.payment_account, doc.name), as_dict=1)[0]
- if disbursement.disbursed_amount == doc.loan_amount:
- frappe.db.set_value("Loan", doc.name , "status", "Disbursed")
- if disbursement.disbursed_amount == 0:
- frappe.db.set_value("Loan", doc.name , "status", "Sanctioned")
- if disbursement.disbursed_amount > doc.loan_amount:
- frappe.throw(_("Disbursed Amount cannot be greater than Loan Amount {0}").format(doc.loan_amount))
- if disbursement.disbursed_amount > 0:
- frappe.db.set_value("Loan", doc.name , "disbursement_date", disbursement.posting_date)
- frappe.db.set_value("Loan", doc.name , "repayment_start_date", disbursement.posting_date)
+ disbursement = frappe.db.sql("""
+ select posting_date, ifnull(sum(credit_in_account_currency), 0) as disbursed_amount
+ from `tabGL Entry`
+ where account = %s and against_voucher_type = 'Loan' and against_voucher = %s
+ """, (doc.payment_account, doc.name), as_dict=1)[0]
-def check_repayment_method(repayment_method, loan_amount, monthly_repayment_amount, repayment_periods):
+ disbursement_date = None
+ if not disbursement or disbursement.disbursed_amount == 0:
+ status = "Sanctioned"
+ elif disbursement.disbursed_amount == doc.loan_amount:
+ disbursement_date = disbursement.posting_date
+ status = "Disbursed"
+ elif disbursement.disbursed_amount > doc.loan_amount:
+ frappe.throw(_("Disbursed Amount cannot be greater than Loan Amount {0}").format(doc.loan_amount))
+
+ if status == 'Disbursed' and getdate(disbursement_date) > getdate(frappe.db.get_value("Loan", doc.name, "repayment_start_date")):
+ frappe.throw(_("Disbursement Date cannot be after Loan Repayment Start Date"))
+
+ frappe.db.sql("""
+ update `tabLoan`
+ set status = %s, disbursement_date = %s
+ where name = %s
+ """, (status, disbursement_date, doc.name))
+
+def validate_repayment_method(repayment_method, loan_amount, monthly_repayment_amount, repayment_periods):
if repayment_method == "Repay Over Number of Periods" and not repayment_periods:
frappe.throw(_("Please enter Repayment Periods"))
@@ -222,4 +237,4 @@
"reference_name": loan,
})
journal_entry.set("accounts", account_amt_list)
- return journal_entry.as_dict()
\ No newline at end of file
+ return journal_entry.as_dict()
diff --git a/erpnext/hr/doctype/loan_application/loan_application.js b/erpnext/hr/doctype/loan_application/loan_application.js
index febcbd8..a73b62a 100644
--- a/erpnext/hr/doctype/loan_application/loan_application.js
+++ b/erpnext/hr/doctype/loan_application/loan_application.js
@@ -23,9 +23,8 @@
},
add_toolbar_buttons: function(frm) {
if (frm.doc.status == "Approved") {
- frm.add_custom_button(__('Loan'), function() {
+ frm.add_custom_button(__('Create Loan'), function() {
frappe.call({
- type: "GET",
method: "erpnext.hr.doctype.loan_application.loan_application.make_loan",
args: {
"source_name": frm.doc.name
@@ -37,7 +36,7 @@
}
}
});
- })
+ }).addClass("btn-primary");
}
}
});
diff --git a/erpnext/hr/doctype/loan_application/loan_application.py b/erpnext/hr/doctype/loan_application/loan_application.py
index 706c964..5dbcf15 100644
--- a/erpnext/hr/doctype/loan_application/loan_application.py
+++ b/erpnext/hr/doctype/loan_application/loan_application.py
@@ -9,11 +9,11 @@
from frappe.model.mapper import get_mapped_doc
from frappe.model.document import Document
-from erpnext.hr.doctype.loan.loan import get_monthly_repayment_amount, check_repayment_method
+from erpnext.hr.doctype.loan.loan import get_monthly_repayment_amount, validate_repayment_method
class LoanApplication(Document):
def validate(self):
- check_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount, self.repayment_periods)
+ validate_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount, self.repayment_periods)
self.validate_loan_amount()
self.get_repayment_details()
@@ -29,14 +29,14 @@
if self.repayment_method == "Repay Fixed Amount per Period":
monthly_interest_rate = flt(self.rate_of_interest) / (12 *100)
if monthly_interest_rate:
- self.repayment_periods = math.ceil((math.log(self.repayment_amount) -
+ self.repayment_periods = math.ceil((math.log(self.repayment_amount) -
math.log(self.repayment_amount - (self.loan_amount*monthly_interest_rate))) /
(math.log(1 + monthly_interest_rate)))
else:
self.repayment_periods = self.loan_amount / self.repayment_amount
self.calculate_payable_amount()
-
+
def calculate_payable_amount(self):
balance_amount = self.loan_amount
self.total_payable_amount = 0
@@ -47,9 +47,9 @@
balance_amount = rounded(balance_amount + interest_amount - self.repayment_amount)
self.total_payable_interest += interest_amount
-
+
self.total_payable_amount = self.loan_amount + self.total_payable_interest
-
+
@frappe.whitelist()
def make_loan(source_name, target_doc = None):
doclist = get_mapped_doc("Loan Application", source_name, {
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 75eb794..766f675 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -594,6 +594,7 @@
sum(bom_item.{qty_field}/ifnull(bom.quantity, 1)) * %(qty)s as qty,
item.description,
item.image,
+ bom.project,
item.stock_uom,
item.allow_alternative_item,
item_default.default_warehouse,
diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py
index cc29039..5096ed4 100644
--- a/erpnext/patches/v12_0/set_priority_for_support.py
+++ b/erpnext/patches/v12_0/set_priority_for_support.py
@@ -33,19 +33,23 @@
service_level_priorities = frappe.get_list("Service Level", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"])
frappe.reload_doc("support", "doctype", "service_level")
+ frappe.reload_doc("support", "doctype", "support_settings")
+ frappe.db.set_value('Support Settings', None, 'track_service_level_agreement', 1)
for service_level in service_level_priorities:
if service_level:
doc = frappe.get_doc("Service Level", service_level.name)
- doc.append("priorities", {
- "priority": service_level.priority,
- "default_priority": 1,
- "response_time": service_level.response_time,
- "response_time_period": service_level.response_time_period,
- "resolution_time": service_level.resolution_time,
- "resolution_time_period": service_level.resolution_time_period
- })
- doc.save(ignore_permissions=True)
+ if not doc.priorities:
+ doc.append("priorities", {
+ "priority": service_level.priority,
+ "default_priority": 1,
+ "response_time": service_level.response_time,
+ "response_time_period": service_level.response_time_period,
+ "resolution_time": service_level.resolution_time,
+ "resolution_time_period": service_level.resolution_time_period
+ })
+ doc.flags.ignore_validate = True
+ doc.save(ignore_permissions=True)
except frappe.db.TableMissingError:
frappe.reload_doc("support", "doctype", "service_level")
@@ -73,6 +77,7 @@
"resolution_time": service_level_agreement.resolution_time,
"resolution_time_period": service_level_agreement.resolution_time_period
})
+ doc.flags.ignore_validate = True
doc.save(ignore_permissions=True)
except frappe.db.TableMissingError:
frappe.reload_doc("support", "doctype", "service_level_agreement")
\ No newline at end of file
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index 5351f32..96e31ff 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -211,6 +211,7 @@
d.stock_uom = item.stock_uom;
d.conversion_factor = 1;
d.qty = item.qty;
+ d.project = item.project;
});
}
d.hide();