Merge branch 'develop' into asset-delete-fix
This commit is contained in:
commit
819879dd12
File diff suppressed because it is too large
Load Diff
@ -58,7 +58,7 @@
|
||||
"type": "Report"
|
||||
},
|
||||
{
|
||||
"label": "Assets Dashboard",
|
||||
"label": "Dashboard",
|
||||
"link_to": "Asset",
|
||||
"type": "Dashboard"
|
||||
}
|
||||
|
@ -33,7 +33,7 @@
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Other Reports",
|
||||
"links": "[\n {\n \"is_query_report\": true,\n \"label\": \"Items To Be Requested\",\n \"name\": \"Items To Be Requested\",\n \"onboard\": 1,\n \"reference_doctype\": \"Item\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Item-wise Purchase History\",\n \"name\": \"Item-wise Purchase History\",\n \"onboard\": 1,\n \"reference_doctype\": \"Item\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Subcontracted Raw Materials To Be Transferred\",\n \"name\": \"Subcontracted Raw Materials To Be Transferred\",\n \"reference_doctype\": \"Purchase Order\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Subcontracted Item To Be Received\",\n \"name\": \"Subcontracted Item To Be Received\",\n \"reference_doctype\": \"Purchase Order\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Quoted Item Comparison\",\n \"name\": \"Quoted Item Comparison\",\n \"onboard\": 1,\n \"reference_doctype\": \"Supplier Quotation\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Material Requests for which Supplier Quotations are not created\",\n \"name\": \"Material Requests for which Supplier Quotations are not created\",\n \"reference_doctype\": \"Material Request\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Supplier Addresses And Contacts\",\n \"name\": \"Address And Contacts\",\n \"reference_doctype\": \"Address\",\n \"route_options\": {\n \"party_type\": \"Supplier\"\n },\n \"type\": \"report\"\n }\n]"
|
||||
"links": "[\n {\n \"is_query_report\": true,\n \"label\": \"Items To Be Requested\",\n \"name\": \"Items To Be Requested\",\n \"onboard\": 1,\n \"reference_doctype\": \"Item\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Item-wise Purchase History\",\n \"name\": \"Item-wise Purchase History\",\n \"onboard\": 1,\n \"reference_doctype\": \"Item\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Purchase Receipt Trends\",\n \"name\": \"Purchase Receipt Trends\",\n \"reference_doctype\": \"Purchase Receipt\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Purchase Invoice Trends\",\n \"name\": \"Purchase Invoice Trends\",\n \"reference_doctype\": \"Purchase Invoice\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Subcontracted Raw Materials To Be Transferred\",\n \"name\": \"Subcontracted Raw Materials To Be Transferred\",\n \"reference_doctype\": \"Purchase Order\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Subcontracted Item To Be Received\",\n \"name\": \"Subcontracted Item To Be Received\",\n \"reference_doctype\": \"Purchase Order\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Quoted Item Comparison\",\n \"name\": \"Quoted Item Comparison\",\n \"onboard\": 1,\n \"reference_doctype\": \"Supplier Quotation\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Material Requests for which Supplier Quotations are not created\",\n \"name\": \"Material Requests for which Supplier Quotations are not created\",\n \"reference_doctype\": \"Material Request\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Supplier Addresses And Contacts\",\n \"name\": \"Address And Contacts\",\n \"reference_doctype\": \"Address\",\n \"route_options\": {\n \"party_type\": \"Supplier\"\n },\n \"type\": \"report\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
@ -60,7 +60,7 @@
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"label": "Buying",
|
||||
"modified": "2020-05-28 13:32:49.960574",
|
||||
"modified": "2020-06-29 19:30:24.983050",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Buying",
|
||||
|
@ -166,7 +166,8 @@ frappe.ui.form.on("Request for Quotation",{
|
||||
{ "fieldtype": "Select", "label": __("Supplier"),
|
||||
"fieldname": "supplier",
|
||||
"options": doc.suppliers.map(d => d.supplier),
|
||||
"reqd": 1 },
|
||||
"reqd": 1,
|
||||
"default": doc.suppliers.length === 1 ? doc.suppliers[0].supplier_name : "" },
|
||||
{ "fieldtype": "Button", "label": __('Create Supplier Quotation'),
|
||||
"fieldname": "make_supplier_quotation", "cssClass": "btn-primary" },
|
||||
]
|
||||
|
@ -13,7 +13,7 @@ source_link = "https://github.com/frappe/erpnext"
|
||||
app_logo_url = '/assets/erpnext/images/erp-icon.svg'
|
||||
|
||||
|
||||
develop_version = '12.x.x-develop'
|
||||
develop_version = '13.x.x-develop'
|
||||
|
||||
app_include_js = "assets/js/erpnext.min.js"
|
||||
app_include_css = "assets/css/erpnext.css"
|
||||
|
@ -300,6 +300,11 @@ frappe.ui.form.on("Expense Claim", {
|
||||
cost_center: function(frm) {
|
||||
frm.events.set_child_cost_center(frm);
|
||||
},
|
||||
|
||||
validate: function(frm) {
|
||||
frm.events.set_child_cost_center(frm);
|
||||
},
|
||||
|
||||
set_child_cost_center: function(frm){
|
||||
(frm.doc.expenses || []).forEach(function(d) {
|
||||
if (!d.cost_center){
|
||||
@ -349,9 +354,6 @@ frappe.ui.form.on("Expense Claim", {
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Expense Claim Detail", {
|
||||
expenses_add: function(frm, cdt, cdn) {
|
||||
frm.events.set_child_cost_center(frm);
|
||||
},
|
||||
amount: function(frm, cdt, cdn) {
|
||||
var child = locals[cdt][cdn];
|
||||
frappe.model.set_value(cdt, cdn, 'sanctioned_amount', child.amount);
|
||||
|
@ -129,7 +129,7 @@ class ExpenseClaim(AccountsController):
|
||||
"debit": data.sanctioned_amount,
|
||||
"debit_in_account_currency": data.sanctioned_amount,
|
||||
"against": self.employee,
|
||||
"cost_center": data.cost_center
|
||||
"cost_center": data.cost_center or self.cost_center
|
||||
}, item=data)
|
||||
)
|
||||
|
||||
|
@ -32,7 +32,8 @@ class JobOffer(Document):
|
||||
return frappe.get_all("Job Offer", filters={
|
||||
"offer_date": ['between', (from_date, to_date)],
|
||||
"designation": self.designation,
|
||||
"company": self.company
|
||||
"company": self.company,
|
||||
"docstatus": 1
|
||||
}, fields=['name'])
|
||||
|
||||
def update_job_applicant(status, job_applicant):
|
||||
|
@ -1,4 +1,5 @@
|
||||
from __future__ import unicode_literals
|
||||
from frappe import _
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
@ -8,13 +9,17 @@ def get_data():
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'items': ['Employee']
|
||||
},
|
||||
{
|
||||
'items': ['Employee Grade']
|
||||
'label': _('Employees'),
|
||||
'items': ['Employee', 'Employee Grade']
|
||||
},
|
||||
{
|
||||
'label': _('Leaves'),
|
||||
'items': ['Leave Allocation']
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -45,15 +45,6 @@ frappe.ui.form.on('Loan', {
|
||||
});
|
||||
})
|
||||
|
||||
frm.set_query('loan_security_pledge', function(doc, cdt, cdn) {
|
||||
return {
|
||||
filters: {
|
||||
applicant: frm.doc.applicant,
|
||||
docstatus: 1,
|
||||
loan_application: frm.doc.loan_application || ''
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function (frm) {
|
||||
@ -86,9 +77,6 @@ frappe.ui.form.on('Loan', {
|
||||
frm.toggle_display("repayment_periods", s1 - frm.doc.is_term_loan);
|
||||
},
|
||||
|
||||
is_secured_loan: function(frm) {
|
||||
frm.toggle_reqd("loan_security_pledge", frm.doc.is_secured_loan);
|
||||
},
|
||||
|
||||
make_loan_disbursement: function (frm) {
|
||||
frappe.call({
|
||||
|
@ -25,15 +25,12 @@
|
||||
"disbursement_date",
|
||||
"disbursed_amount",
|
||||
"column_break_11",
|
||||
"maximum_loan_amount",
|
||||
"is_term_loan",
|
||||
"repayment_method",
|
||||
"repayment_periods",
|
||||
"monthly_repayment_amount",
|
||||
"repayment_start_date",
|
||||
"loan_security_details_section",
|
||||
"loan_security_pledge",
|
||||
"column_break_25",
|
||||
"maximum_loan_value",
|
||||
"account_info",
|
||||
"mode_of_payment",
|
||||
"payment_account",
|
||||
@ -292,13 +289,8 @@
|
||||
"default": "0",
|
||||
"fieldname": "is_secured_loan",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Secured Loan"
|
||||
},
|
||||
{
|
||||
"depends_on": "is_secured_loan",
|
||||
"fieldname": "loan_security_details_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Loan Security Details"
|
||||
"label": "Is Secured Loan",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
@ -324,12 +316,6 @@
|
||||
"options": "Company:company:default_currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "loan_security_pledge",
|
||||
"fieldtype": "Link",
|
||||
"label": "Loan Security Pledge",
|
||||
"options": "Loan Security Pledge"
|
||||
},
|
||||
{
|
||||
"fieldname": "disbursed_amount",
|
||||
"fieldtype": "Currency",
|
||||
@ -338,21 +324,17 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "loan_security_pledge.maximum_loan_value",
|
||||
"fieldname": "maximum_loan_value",
|
||||
"fetch_from": "loan_application.maximum_loan_amount",
|
||||
"fieldname": "maximum_loan_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Maximum Loan Value",
|
||||
"label": "Maximum Loan Amount",
|
||||
"options": "Company:company:default_currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_25",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-04-13 13:16:10.192624",
|
||||
"modified": "2020-07-02 20:46:40.128142",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Loan Management",
|
||||
"name": "Loan",
|
||||
|
@ -13,11 +13,9 @@ from erpnext.controllers.accounts_controller import AccountsController
|
||||
class Loan(AccountsController):
|
||||
def validate(self):
|
||||
self.set_loan_amount()
|
||||
|
||||
self.validate_loan_amount()
|
||||
self.set_missing_fields()
|
||||
self.validate_accounts()
|
||||
self.validate_loan_security_pledge()
|
||||
self.validate_loan_amount()
|
||||
self.check_sanctioned_amount_limit()
|
||||
self.validate_repay_from_salary()
|
||||
|
||||
@ -56,21 +54,6 @@ class Loan(AccountsController):
|
||||
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)
|
||||
|
||||
def validate_loan_security_pledge(self):
|
||||
|
||||
if self.is_secured_loan and not self.loan_security_pledge:
|
||||
frappe.throw(_("Loan Security Pledge is mandatory for secured loan"))
|
||||
|
||||
if self.loan_security_pledge:
|
||||
loan_security_details = frappe.db.get_value("Loan Security Pledge", self.loan_security_pledge,
|
||||
['loan', 'company'], as_dict=1)
|
||||
|
||||
if loan_security_details.loan:
|
||||
frappe.throw(_("Loan Security Pledge already pledged against loan {0}").format(loan_security_details.loan))
|
||||
|
||||
if loan_security_details.company != self.company:
|
||||
frappe.throw(_("Loan Security Pledge Company and Loan Company must be same"))
|
||||
|
||||
def check_sanctioned_amount_limit(self):
|
||||
total_loan_amount = get_total_loan_amount(self.applicant_type, self.applicant, self.company)
|
||||
sanctioned_amount_limit = get_sanctioned_amount_limit(self.applicant_type, self.applicant, self.company)
|
||||
@ -129,22 +112,29 @@ class Loan(AccountsController):
|
||||
self.total_payment = self.loan_amount
|
||||
|
||||
def set_loan_amount(self):
|
||||
if self.loan_application and not self.loan_amount:
|
||||
self.loan_amount = frappe.db.get_value('Loan Application', self.loan_application, 'loan_amount')
|
||||
|
||||
if not self.loan_amount and self.is_secured_loan and self.loan_security_pledge:
|
||||
self.loan_amount = self.maximum_loan_value
|
||||
|
||||
def validate_loan_amount(self):
|
||||
if self.is_secured_loan and self.loan_amount > self.maximum_loan_value:
|
||||
msg = _("Loan amount cannot be greater than {0}").format(self.maximum_loan_value)
|
||||
if self.maximum_loan_amount and self.loan_amount > self.maximum_loan_amount:
|
||||
msg = _("Loan amount cannot be greater than {0}").format(self.maximum_loan_amount)
|
||||
frappe.throw(msg)
|
||||
|
||||
if not self.loan_amount:
|
||||
frappe.throw(_("Loan amount is mandatory"))
|
||||
|
||||
def link_loan_security_pledge(self):
|
||||
frappe.db.sql("""UPDATE `tabLoan Security Pledge` SET
|
||||
loan = %s, status = 'Pledged', pledge_time = %s
|
||||
where name = %s """, (self.name, now_datetime(), self.loan_security_pledge))
|
||||
if self.is_secured_loan:
|
||||
loan_security_pledge = frappe.db.get_value('Loan Security Pledge', {'loan_application': self.loan_application},
|
||||
'name')
|
||||
|
||||
if loan_security_pledge:
|
||||
frappe.db.set_value('Loan Security Pledge', loan_security_pledge, {
|
||||
'loan': self.name,
|
||||
'status': 'Pledged',
|
||||
'pledge_time': now_datetime()
|
||||
})
|
||||
|
||||
def unlink_loan_security_pledge(self):
|
||||
frappe.db.sql("""UPDATE `tabLoan Security Pledge` SET
|
||||
|
@ -16,6 +16,7 @@ from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual
|
||||
from erpnext.loan_management.doctype.process_loan_security_shortfall.process_loan_security_shortfall import create_process_loan_security_shortfall
|
||||
from erpnext.loan_management.doctype.loan.loan import create_loan_security_unpledge
|
||||
from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import get_pledged_security_qty
|
||||
from erpnext.loan_management.doctype.loan_application.loan_application import create_pledge
|
||||
|
||||
class TestLoan(unittest.TestCase):
|
||||
def setUp(self):
|
||||
@ -72,31 +73,31 @@ class TestLoan(unittest.TestCase):
|
||||
self.assertEquals(loan.total_payment, 302712)
|
||||
|
||||
def test_loan_with_security(self):
|
||||
pledges = []
|
||||
pledges.append({
|
||||
|
||||
pledge = [{
|
||||
"loan_security": "Test Security 1",
|
||||
"qty": 4000.00,
|
||||
"haircut": 50,
|
||||
"loan_security_price": 500.00
|
||||
})
|
||||
}]
|
||||
|
||||
loan_security_pledge = create_loan_security_pledge(self.applicant2, pledges)
|
||||
|
||||
loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_security_pledge.name)
|
||||
loan_application = create_loan_application('_Test Company', self.applicant2,
|
||||
'Stock Loan', pledge, "Repay Over Number of Periods", 12)
|
||||
create_pledge(loan_application)
|
||||
|
||||
loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods",
|
||||
12, loan_application)
|
||||
self.assertEquals(loan.loan_amount, 1000000)
|
||||
|
||||
def test_loan_disbursement(self):
|
||||
pledges = []
|
||||
pledges.append({
|
||||
pledge = [{
|
||||
"loan_security": "Test Security 1",
|
||||
"qty": 4000.00,
|
||||
"haircut": 50
|
||||
})
|
||||
"qty": 4000.00
|
||||
}]
|
||||
|
||||
loan_security_pledge = create_loan_security_pledge(self.applicant2, pledges)
|
||||
loan_application = create_loan_application('_Test Company', self.applicant2, 'Stock Loan', pledge, "Repay Over Number of Periods", 12)
|
||||
|
||||
loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_security_pledge.name)
|
||||
create_pledge(loan_application)
|
||||
|
||||
loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_application)
|
||||
self.assertEquals(loan.loan_amount, 1000000)
|
||||
|
||||
loan.submit()
|
||||
@ -121,18 +122,15 @@ class TestLoan(unittest.TestCase):
|
||||
self.assertTrue(gl_entries2)
|
||||
|
||||
def test_regular_loan_repayment(self):
|
||||
pledges = []
|
||||
pledges.append({
|
||||
pledge = [{
|
||||
"loan_security": "Test Security 1",
|
||||
"qty": 4000.00,
|
||||
"haircut": 50
|
||||
})
|
||||
"qty": 4000.00
|
||||
}]
|
||||
|
||||
loan_security_pledge = create_loan_security_pledge(self.applicant2, pledges)
|
||||
|
||||
loan = create_demand_loan(self.applicant2, "Demand Loan", loan_security_pledge.name,
|
||||
posting_date=get_first_day(nowdate()))
|
||||
loan_application = create_loan_application('_Test Company', self.applicant2, 'Demand Loan', pledge)
|
||||
create_pledge(loan_application)
|
||||
|
||||
loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date=get_first_day(nowdate()))
|
||||
loan.submit()
|
||||
|
||||
self.assertEquals(loan.loan_amount, 1000000)
|
||||
@ -166,16 +164,15 @@ class TestLoan(unittest.TestCase):
|
||||
penalty_amount - amounts[0], 2))
|
||||
|
||||
def test_loan_closure_repayment(self):
|
||||
pledges = []
|
||||
pledges.append({
|
||||
pledge = [{
|
||||
"loan_security": "Test Security 1",
|
||||
"qty": 4000.00,
|
||||
"haircut": 50
|
||||
})
|
||||
"qty": 4000.00
|
||||
}]
|
||||
|
||||
loan_security_pledge = create_loan_security_pledge(self.applicant2, pledges)
|
||||
loan = create_demand_loan(self.applicant2, "Demand Loan", loan_security_pledge.name,
|
||||
posting_date=get_first_day(nowdate()))
|
||||
loan_application = create_loan_application('_Test Company', self.applicant2, 'Demand Loan', pledge)
|
||||
create_pledge(loan_application)
|
||||
|
||||
loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date=get_first_day(nowdate()))
|
||||
loan.submit()
|
||||
|
||||
self.assertEquals(loan.loan_amount, 1000000)
|
||||
@ -214,23 +211,21 @@ class TestLoan(unittest.TestCase):
|
||||
self.assertEquals(loan.status, "Loan Closure Requested")
|
||||
|
||||
def test_loan_repayment_for_term_loan(self):
|
||||
pledges = []
|
||||
pledges.append({
|
||||
pledges = [{
|
||||
"loan_security": "Test Security 2",
|
||||
"qty": 4000.00,
|
||||
"haircut": 50
|
||||
})
|
||||
|
||||
pledges.append({
|
||||
"qty": 4000.00
|
||||
},
|
||||
{
|
||||
"loan_security": "Test Security 1",
|
||||
"qty": 2000.00,
|
||||
"haircut": 50
|
||||
})
|
||||
"qty": 2000.00
|
||||
}]
|
||||
|
||||
loan_security_pledge = create_loan_security_pledge(self.applicant2, pledges)
|
||||
loan_application = create_loan_application('_Test Company', self.applicant2, 'Stock Loan', pledges,
|
||||
"Repay Over Number of Periods", 12)
|
||||
create_pledge(loan_application)
|
||||
|
||||
loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12,
|
||||
loan_security_pledge.name, posting_date=add_months(nowdate(), -1))
|
||||
loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_application,
|
||||
posting_date=add_months(nowdate(), -1))
|
||||
|
||||
loan.submit()
|
||||
|
||||
@ -250,16 +245,18 @@ class TestLoan(unittest.TestCase):
|
||||
self.assertEquals(amounts[1], 78303.00)
|
||||
|
||||
def test_security_shortfall(self):
|
||||
pledges = []
|
||||
pledges.append({
|
||||
pledges = [{
|
||||
"loan_security": "Test Security 2",
|
||||
"qty": 8000.00,
|
||||
"haircut": 50,
|
||||
})
|
||||
}]
|
||||
|
||||
loan_security_pledge = create_loan_security_pledge(self.applicant2, pledges)
|
||||
loan_application = create_loan_application('_Test Company', self.applicant2,
|
||||
'Stock Loan', pledges, "Repay Over Number of Periods", 12)
|
||||
|
||||
loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_security_pledge.name)
|
||||
create_pledge(loan_application)
|
||||
|
||||
loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_application)
|
||||
loan.submit()
|
||||
|
||||
make_loan_disbursement_entry(loan.name, loan.loan_amount)
|
||||
@ -279,16 +276,15 @@ class TestLoan(unittest.TestCase):
|
||||
where loan_security='Test Security 2'""")
|
||||
|
||||
def test_loan_security_unpledge(self):
|
||||
pledges = []
|
||||
pledges.append({
|
||||
pledge = [{
|
||||
"loan_security": "Test Security 1",
|
||||
"qty": 4000.00,
|
||||
"haircut": 50
|
||||
})
|
||||
"qty": 4000.00
|
||||
}]
|
||||
|
||||
loan_security_pledge = create_loan_security_pledge(self.applicant2, pledges)
|
||||
loan = create_demand_loan(self.applicant2, "Demand Loan", loan_security_pledge.name,
|
||||
posting_date=get_first_day(nowdate()))
|
||||
loan_application = create_loan_application('_Test Company', self.applicant2, 'Demand Loan', pledge)
|
||||
create_pledge(loan_application)
|
||||
|
||||
loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date=get_first_day(nowdate()))
|
||||
loan.submit()
|
||||
|
||||
self.assertEquals(loan.loan_amount, 1000000)
|
||||
@ -446,12 +442,13 @@ def create_loan_security():
|
||||
"haircut": 50.00,
|
||||
}).insert(ignore_permissions=True)
|
||||
|
||||
def create_loan_security_pledge(applicant, pledges):
|
||||
def create_loan_security_pledge(applicant, pledges, loan_application):
|
||||
|
||||
lsp = frappe.new_doc("Loan Security Pledge")
|
||||
lsp.applicant_type = 'Customer'
|
||||
lsp.applicant = applicant
|
||||
lsp.company = "_Test Company"
|
||||
lsp.loan_application = loan_application
|
||||
|
||||
for pledge in pledges:
|
||||
lsp.append('securities', {
|
||||
@ -510,6 +507,31 @@ def create_repayment_entry(loan, applicant, posting_date, payment_type, paid_amo
|
||||
|
||||
return lr
|
||||
|
||||
def create_loan_application(company, applicant, loan_type, proposed_pledges, repayment_method=None,
|
||||
repayment_periods=None, posting_date=None):
|
||||
loan_application = frappe.new_doc('Loan Application')
|
||||
loan_application.applicant_type = 'Customer'
|
||||
loan_application.company = company
|
||||
loan_application.applicant = applicant
|
||||
loan_application.loan_type = loan_type
|
||||
loan_application.posting_date = posting_date or nowdate()
|
||||
loan_application.is_secured_loan = 1
|
||||
|
||||
if repayment_method:
|
||||
loan_application.repayment_method = repayment_method
|
||||
loan_application.repayment_periods = repayment_periods
|
||||
|
||||
for pledge in proposed_pledges:
|
||||
loan_application.append('proposed_pledges', pledge)
|
||||
|
||||
loan_application.save()
|
||||
loan_application.submit()
|
||||
|
||||
loan_application.status = 'Approved'
|
||||
loan_application.save()
|
||||
|
||||
return loan_application.name
|
||||
|
||||
|
||||
def create_loan(applicant, loan_type, loan_amount, repayment_method, repayment_periods,
|
||||
repayment_start_date=None, posting_date=None):
|
||||
@ -531,14 +553,13 @@ def create_loan(applicant, loan_type, loan_amount, repayment_method, repayment_p
|
||||
loan.save()
|
||||
return loan
|
||||
|
||||
def create_loan_with_security(applicant, loan_type, repayment_method, repayment_periods, loan_security_pledge,
|
||||
posting_date=None, repayment_start_date=None):
|
||||
|
||||
def create_loan_with_security(applicant, loan_type, repayment_method, repayment_periods, loan_application, posting_date=None, repayment_start_date=None):
|
||||
loan = frappe.get_doc({
|
||||
"doctype": "Loan",
|
||||
"company": "_Test Company",
|
||||
"applicant_type": "Customer",
|
||||
"posting_date": posting_date or nowdate(),
|
||||
"loan_application": loan_application,
|
||||
"applicant": applicant,
|
||||
"loan_type": loan_type,
|
||||
"is_term_loan": 1,
|
||||
@ -547,7 +568,6 @@ def create_loan_with_security(applicant, loan_type, repayment_method, repayment_
|
||||
"repayment_periods": repayment_periods,
|
||||
"repayment_start_date": repayment_start_date or nowdate(),
|
||||
"mode_of_payment": frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name'),
|
||||
"loan_security_pledge": loan_security_pledge,
|
||||
"payment_account": 'Payment Account - _TC',
|
||||
"loan_account": 'Loan Account - _TC',
|
||||
"interest_income_account": 'Interest Income Account - _TC',
|
||||
@ -558,19 +578,19 @@ def create_loan_with_security(applicant, loan_type, repayment_method, repayment_
|
||||
|
||||
return loan
|
||||
|
||||
def create_demand_loan(applicant, loan_type, loan_security_pledge, posting_date=None):
|
||||
def create_demand_loan(applicant, loan_type, loan_application, posting_date=None):
|
||||
|
||||
loan = frappe.get_doc({
|
||||
"doctype": "Loan",
|
||||
"company": "_Test Company",
|
||||
"applicant_type": "Customer",
|
||||
"posting_date": posting_date or nowdate(),
|
||||
'loan_application': loan_application,
|
||||
"applicant": applicant,
|
||||
"loan_type": loan_type,
|
||||
"is_term_loan": 0,
|
||||
"is_secured_loan": 1,
|
||||
"mode_of_payment": frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name'),
|
||||
"loan_security_pledge": loan_security_pledge,
|
||||
"payment_account": 'Payment Account - _TC',
|
||||
"loan_account": 'Loan Account - _TC',
|
||||
"interest_income_account": 'Interest Income Account - _TC',
|
||||
|
@ -103,10 +103,13 @@ class LoanApplication(Document):
|
||||
if self.is_secured_loan and not self.proposed_pledges:
|
||||
frappe.throw(_("Proposed Pledges are mandatory for secured Loans"))
|
||||
|
||||
if not self.loan_amount and self.is_secured_loan and self.proposed_pledges:
|
||||
self.loan_amount = 0
|
||||
if self.is_secured_loan and self.proposed_pledges:
|
||||
self.maximum_loan_amount = 0
|
||||
for security in self.proposed_pledges:
|
||||
self.loan_amount += security.post_haircut_amount
|
||||
self.maximum_loan_amount += security.post_haircut_amount
|
||||
|
||||
if not self.loan_amount and self.is_secured_loan and self.proposed_pledges:
|
||||
self.loan_amount = self.maximum_loan_amount
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_loan(source_name, target_doc=None, submit=0):
|
||||
@ -116,7 +119,6 @@ def create_loan(source_name, target_doc=None, submit=0):
|
||||
filters = {'name': source_doc.loan_type}
|
||||
)[0]
|
||||
|
||||
loan_security_pledge = frappe.db.get_value("Loan Security Pledge", {"loan_application": source_name}, 'name')
|
||||
|
||||
target_doc.mode_of_payment = account_details.mode_of_payment
|
||||
target_doc.payment_account = account_details.payment_account
|
||||
@ -124,9 +126,6 @@ def create_loan(source_name, target_doc=None, submit=0):
|
||||
target_doc.interest_income_account = account_details.interest_income_account
|
||||
target_doc.penalty_income_account = account_details.penalty_income_account
|
||||
|
||||
if loan_security_pledge:
|
||||
target_doc.is_secured_loan = 1
|
||||
target_doc.loan_security_pledge = loan_security_pledge
|
||||
|
||||
doclist = get_mapped_doc("Loan Application", source_name, {
|
||||
"Loan Application": {
|
||||
|
@ -5,11 +5,12 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
import unittest
|
||||
from frappe.utils import (nowdate, add_days, get_datetime, get_first_day, get_last_day, date_diff, flt, add_to_date)
|
||||
from erpnext.loan_management.doctype.loan.test_loan import (create_loan_type, create_loan_security_pledge, create_repayment_entry,
|
||||
from erpnext.loan_management.doctype.loan.test_loan import (create_loan_type, create_loan_security_pledge, create_repayment_entry, create_loan_application,
|
||||
make_loan_disbursement_entry, create_loan_accounts, create_loan_security_type, create_loan_security, create_demand_loan, create_loan_security_price)
|
||||
from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_demand_loans
|
||||
from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year
|
||||
from erpnext.selling.doctype.customer.test_customer import get_customer_dict
|
||||
from erpnext.loan_management.doctype.loan_application.loan_application import create_pledge
|
||||
|
||||
class TestLoanDisbursement(unittest.TestCase):
|
||||
|
||||
@ -31,18 +32,15 @@ class TestLoanDisbursement(unittest.TestCase):
|
||||
self.applicant = frappe.db.get_value("Customer", {'name': '_Test Loan Customer'}, 'name')
|
||||
|
||||
def test_loan_topup(self):
|
||||
pledges = []
|
||||
pledges.append({
|
||||
pledge = [{
|
||||
"loan_security": "Test Security 1",
|
||||
"qty": 4000.00,
|
||||
"haircut": 50,
|
||||
"loan_security_price": 500.00
|
||||
})
|
||||
"qty": 4000.00
|
||||
}]
|
||||
|
||||
loan_security_pledge = create_loan_security_pledge(self.applicant, pledges)
|
||||
loan_application = create_loan_application('_Test Company', self.applicant, 'Demand Loan', pledge)
|
||||
create_pledge(loan_application)
|
||||
|
||||
loan = create_demand_loan(self.applicant, "Demand Loan", loan_security_pledge.name,
|
||||
posting_date=get_first_day(nowdate()))
|
||||
loan = create_demand_loan(self.applicant, "Demand Loan", loan_application, posting_date=get_first_day(nowdate()))
|
||||
|
||||
loan.submit()
|
||||
|
||||
|
@ -6,10 +6,11 @@ import frappe
|
||||
import unittest
|
||||
from frappe.utils import (nowdate, add_days, get_datetime, get_first_day, get_last_day, date_diff, flt, add_to_date)
|
||||
from erpnext.loan_management.doctype.loan.test_loan import (create_loan_type, create_loan_security_pledge, create_loan_security_price,
|
||||
make_loan_disbursement_entry, create_loan_accounts, create_loan_security_type, create_loan_security, create_demand_loan)
|
||||
make_loan_disbursement_entry, create_loan_accounts, create_loan_security_type, create_loan_security, create_demand_loan, create_loan_application)
|
||||
from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_demand_loans
|
||||
from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year
|
||||
from erpnext.selling.doctype.customer.test_customer import get_customer_dict
|
||||
from erpnext.loan_management.doctype.loan_application.loan_application import create_pledge
|
||||
|
||||
class TestLoanInterestAccrual(unittest.TestCase):
|
||||
def setUp(self):
|
||||
@ -29,17 +30,15 @@ class TestLoanInterestAccrual(unittest.TestCase):
|
||||
self.applicant = frappe.db.get_value("Customer", {'name': '_Test Loan Customer'}, 'name')
|
||||
|
||||
def test_loan_interest_accural(self):
|
||||
pledges = []
|
||||
pledges.append({
|
||||
pledge = [{
|
||||
"loan_security": "Test Security 1",
|
||||
"qty": 4000.00,
|
||||
"haircut": 50,
|
||||
"loan_security_price": 500.00
|
||||
})
|
||||
"qty": 4000.00
|
||||
}]
|
||||
|
||||
loan_security_pledge = create_loan_security_pledge(self.applicant, pledges)
|
||||
loan_application = create_loan_application('_Test Company', self.applicant, 'Demand Loan', pledge)
|
||||
create_pledge(loan_application)
|
||||
|
||||
loan = create_demand_loan(self.applicant, "Demand Loan", loan_security_pledge.name,
|
||||
loan = create_demand_loan(self.applicant, "Demand Loan", loan_application,
|
||||
posting_date=get_first_day(nowdate()))
|
||||
|
||||
loan.submit()
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "LS-.{applicant}.-.#####",
|
||||
"creation": "2019-08-29 18:48:51.371674",
|
||||
"doctype": "DocType",
|
||||
@ -6,10 +7,10 @@
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"loan_details_section",
|
||||
"loan_application",
|
||||
"loan",
|
||||
"applicant_type",
|
||||
"applicant",
|
||||
"loan",
|
||||
"loan_application",
|
||||
"column_break_3",
|
||||
"company",
|
||||
"pledge_time",
|
||||
@ -55,15 +56,13 @@
|
||||
"fieldname": "loan",
|
||||
"fieldtype": "Link",
|
||||
"label": "Loan",
|
||||
"options": "Loan",
|
||||
"read_only": 1
|
||||
"options": "Loan"
|
||||
},
|
||||
{
|
||||
"fieldname": "loan_application",
|
||||
"fieldtype": "Link",
|
||||
"label": "Loan Application",
|
||||
"options": "Loan Application",
|
||||
"read_only": 1
|
||||
"options": "Loan Application"
|
||||
},
|
||||
{
|
||||
"fieldname": "total_security_value",
|
||||
@ -133,7 +132,8 @@
|
||||
}
|
||||
],
|
||||
"is_submittable": 1,
|
||||
"modified": "2019-10-10 13:22:53.297519",
|
||||
"links": [],
|
||||
"modified": "2020-07-02 23:38:24.002382",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Loan Management",
|
||||
"name": "Loan Security Pledge",
|
||||
|
@ -192,7 +192,7 @@ def get_number_cards():
|
||||
]),
|
||||
"function": "Count",
|
||||
"is_public": 1,
|
||||
"label": _("Monthly Total Work Order"),
|
||||
"label": _("Monthly Total Work Orders"),
|
||||
"show_percentage_stats": 1,
|
||||
"stats_time_interval": "Weekly"
|
||||
},
|
||||
@ -207,7 +207,7 @@ def get_number_cards():
|
||||
]),
|
||||
"function": "Count",
|
||||
"is_public": 1,
|
||||
"label": _("Monthly Completed Work Order"),
|
||||
"label": _("Monthly Completed Work Orders"),
|
||||
"show_percentage_stats": 1,
|
||||
"stats_time_interval": "Weekly"
|
||||
},
|
||||
@ -221,7 +221,7 @@ def get_number_cards():
|
||||
]),
|
||||
"function": "Count",
|
||||
"is_public": 1,
|
||||
"label": _("Ongoing Job Card"),
|
||||
"label": _("Ongoing Job Cards"),
|
||||
"show_percentage_stats": 1,
|
||||
"stats_time_interval": "Weekly"
|
||||
},
|
||||
@ -235,7 +235,7 @@ def get_number_cards():
|
||||
]),
|
||||
"function": "Count",
|
||||
"is_public": 1,
|
||||
"label": _("Monthly Quality Inspection"),
|
||||
"label": _("Monthly Quality Inspections"),
|
||||
"show_percentage_stats": 1,
|
||||
"stats_time_interval": "Weekly"
|
||||
}]
|
@ -93,12 +93,6 @@
|
||||
"stats_filter": "{ \n \"status\": [\"not in\", [\"Completed\"]]\n}",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"label": "Dashboard",
|
||||
"link_to": "Manufacturing",
|
||||
"restrict_to_domain": "Manufacturing",
|
||||
"type": "Dashboard"
|
||||
},
|
||||
{
|
||||
"label": "Forecasting",
|
||||
"link_to": "Exponential Smoothing Forecasting",
|
||||
@ -119,6 +113,12 @@
|
||||
"label": "Production Planning Report",
|
||||
"link_to": "Production Planning Report",
|
||||
"type": "Report"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Dashboard",
|
||||
"link_to": "Manufacturing",
|
||||
"restrict_to_domain": "Manufacturing",
|
||||
"type": "Dashboard"
|
||||
}
|
||||
]
|
||||
}
|
@ -19,7 +19,7 @@
|
||||
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/manufacturing",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"modified": "2020-05-19 12:51:42.744570",
|
||||
"modified": "2020-06-29 20:25:36.899106",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Manufacturing",
|
||||
@ -52,6 +52,5 @@
|
||||
],
|
||||
"subtitle": "Products, Raw Materials, BOM, Work Order and more.",
|
||||
"success_message": "Manufacturing module is all setup!",
|
||||
"title": "Let's Setup Manufacturing Module",
|
||||
"user_can_dismiss": 1
|
||||
}
|
||||
"title": "Let's Set Up the Manufacturing Module"
|
||||
}
|
||||
|
@ -53,7 +53,7 @@
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2020-06-22 20:12:32.684189",
|
||||
"modified": "2020-06-29 17:17:12.689089",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Payroll",
|
||||
"name": "Payroll Period",
|
||||
@ -96,6 +96,7 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
|
@ -207,7 +207,7 @@ class SalarySlip(TransactionBase):
|
||||
frappe.throw(_("There are more holidays than working days this month."))
|
||||
|
||||
if not payroll_based_on:
|
||||
frappe.throw(_("Please set Payroll based on in HR settings"))
|
||||
frappe.throw(_("Please set Payroll based on in Payroll settings"))
|
||||
|
||||
if payroll_based_on == "Attendance":
|
||||
actual_lwp, absent = self.calculate_lwp_and_absent_days_based_on_attendance(holidays)
|
||||
@ -244,15 +244,13 @@ class SalarySlip(TransactionBase):
|
||||
for holiday in holidays:
|
||||
if not frappe.db.exists("Attendance", {"employee": self.employee, "attendance_date": holiday, "docstatus": 1 }):
|
||||
self.payment_days += 1
|
||||
|
||||
|
||||
else:
|
||||
self.payment_days = 0
|
||||
|
||||
def get_unmarked_days(self):
|
||||
marked_days = frappe.get_all("Attendance", filters = {
|
||||
"attendance_date": ["between", ['2020-05-1',"2020-05-30"]],
|
||||
"employee": 'HR-EMP-00003',
|
||||
"attendance_date": ["between", [self.start_date, self.end_date]],
|
||||
"employee": self.employee,
|
||||
"docstatus": 1
|
||||
}, fields = ["COUNT(*) as marked_days"])[0].marked_days
|
||||
|
||||
|
@ -105,7 +105,7 @@ class TestSalarySlip(unittest.TestCase):
|
||||
#Gross pay calculation based on attendances
|
||||
gross_pay = 78000 - ((78000 / (days_in_month - no_of_holidays)) * flt(ss.leave_without_pay))
|
||||
|
||||
self.assertEqual(ss.gross_pay, gross_pay)
|
||||
self.assertEqual(flt(ss.gross_pay, 2), flt(gross_pay, 2))
|
||||
|
||||
frappe.db.set_value("Payroll Settings", None, "payroll_based_on", "Leave")
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/human-resources/payroll-entry",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"modified": "2020-06-04 16:35:30.650792",
|
||||
"modified": "2020-06-29 17:00:25.113341",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Payroll",
|
||||
"name": "Payroll",
|
||||
|
@ -8,7 +8,7 @@
|
||||
"is_mandatory": 1,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-06-01 11:53:54.553947",
|
||||
"modified": "2020-06-29 11:53:54.553947",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Create Payroll Period",
|
||||
"owner": "Administrator",
|
||||
|
@ -1,19 +1,19 @@
|
||||
{
|
||||
"action": "Go to Page",
|
||||
"action": "Update Settings",
|
||||
"creation": "2020-06-04 16:34:29.664917",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_mandatory": 0,
|
||||
"is_single": 0,
|
||||
"is_single": 1,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-06-04 16:34:29.664917",
|
||||
"modified": "2020-06-29 16:34:29.664917",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Payroll Settings",
|
||||
"owner": "Administrator",
|
||||
"path": "#Form/Payroll Settings",
|
||||
"reference_document": "Payroll Settings",
|
||||
"show_full_form": 0,
|
||||
"title": "Payroll Settings",
|
||||
"validate_action": 1
|
||||
"validate_action": 0
|
||||
}
|
@ -152,6 +152,9 @@ def set_company_account(payment_accounts, payroll_entries):
|
||||
company_accounts_map[acc.account] = acc
|
||||
|
||||
for entry in payroll_entries:
|
||||
entry["company_account"] = company_accounts_map[entry.payment_account]['bank_account_no']
|
||||
company_account = ''
|
||||
if entry.payment_account in company_accounts_map:
|
||||
company_account = company_accounts_map[entry.payment_account]['bank_account_no']
|
||||
entry["company_account"] = company_account
|
||||
|
||||
return payroll_entries
|
||||
|
@ -100,6 +100,8 @@ def get_data(filters, mode_of_payments):
|
||||
total_row = get_total_based_on_mode_of_payment(data, mode_of_payments)
|
||||
total_deductions = gross_pay - total_row.get("total")
|
||||
|
||||
report_summary = []
|
||||
|
||||
if data:
|
||||
data.append(total_row)
|
||||
data.append({})
|
||||
|
@ -68,7 +68,7 @@
|
||||
"type": "Report"
|
||||
},
|
||||
{
|
||||
"label": "Project Dashboard",
|
||||
"label": "Dashboard",
|
||||
"link_to": "Project",
|
||||
"type": "Dashboard"
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ def prepare_data(entry,component_type_dict):
|
||||
"employee": d.employee,
|
||||
"employee_name": d.employee_name,
|
||||
"pf_account": employee_account_dict.get(d.employee),
|
||||
"component_type": d.amount
|
||||
component_type: d.amount
|
||||
})
|
||||
|
||||
return data_list
|
||||
|
@ -11,14 +11,17 @@ def update_itemised_tax_data(doc):
|
||||
|
||||
for row in doc.items:
|
||||
tax_rate = 0.0
|
||||
item_tax_rate = frappe.parse_json(row.item_tax_rate)
|
||||
item_tax_rate = 0.0
|
||||
|
||||
if row.item_tax_rate:
|
||||
item_tax_rate = frappe.parse_json(row.item_tax_rate)
|
||||
|
||||
# First check if tax rate is present
|
||||
# If not then look up in item_wise_tax_detail
|
||||
if item_tax_rate:
|
||||
for account, rate in iteritems(item_tax_rate):
|
||||
tax_rate += rate
|
||||
elif itemised_tax.get(row.item_code):
|
||||
elif row.item_code and itemised_tax.get(row.item_code):
|
||||
tax_rate = sum([tax.get('tax_rate', 0) for d, tax in itemised_tax.get(row.item_code).items()])
|
||||
|
||||
row.tax_rate = flt(tax_rate, row.precision("tax_rate"))
|
||||
|
@ -23,7 +23,7 @@
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Other Reports",
|
||||
"links": "[\n {\n \"dependencies\": [\n \"Lead\"\n ],\n \"doctype\": \"Lead\",\n \"is_query_report\": true,\n \"label\": \"Lead Details\",\n \"name\": \"Lead Details\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Address\"\n ],\n \"doctype\": \"Address\",\n \"is_query_report\": true,\n \"label\": \"Customer Addresses And Contacts\",\n \"name\": \"Address And Contacts\",\n \"route_options\": {\n \"party_type\": \"Customer\"\n },\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Available Stock for Packing Items\",\n \"name\": \"Available Stock for Packing Items\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Pending SO Items For Purchase Request\",\n \"name\": \"Pending SO Items For Purchase Request\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customer Credit Balance\",\n \"name\": \"Customer Credit Balance\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customers Without Any Sales Transactions\",\n \"name\": \"Customers Without Any Sales Transactions\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Sales Partners Commission\",\n \"name\": \"Sales Partners Commission\",\n \"type\": \"report\"\n }\n]"
|
||||
"links": "[\n {\n \"dependencies\": [\n \"Lead\"\n ],\n \"doctype\": \"Lead\",\n \"is_query_report\": true,\n \"label\": \"Lead Details\",\n \"name\": \"Lead Details\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Address\"\n ],\n \"doctype\": \"Address\",\n \"is_query_report\": true,\n \"label\": \"Customer Addresses And Contacts\",\n \"name\": \"Address And Contacts\",\n \"route_options\": {\n \"party_type\": \"Customer\"\n },\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Available Stock for Packing Items\",\n \"name\": \"Available Stock for Packing Items\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Pending SO Items For Purchase Request\",\n \"name\": \"Pending SO Items For Purchase Request\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Delivery Note\"\n ],\n \"doctype\": \"Delivery Note\",\n \"is_query_report\": true,\n \"label\": \"Delivery Note Trends\",\n \"name\": \"Delivery Note Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Invoice Trends\",\n \"name\": \"Sales Invoice Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customer Credit Balance\",\n \"name\": \"Customer Credit Balance\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customers Without Any Sales Transactions\",\n \"name\": \"Customers Without Any Sales Transactions\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Sales Partners Commission\",\n \"name\": \"Sales Partners Commission\",\n \"type\": \"report\"\n }\n]"
|
||||
}
|
||||
],
|
||||
"category": "Modules",
|
||||
@ -44,7 +44,7 @@
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"label": "Selling",
|
||||
"modified": "2020-06-19 13:23:24.861706",
|
||||
"modified": "2020-06-29 19:26:35.139097",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Selling",
|
||||
|
@ -342,11 +342,10 @@ def get_loyalty_programs(doc):
|
||||
@frappe.whitelist()
|
||||
def get_customer_list(doctype, txt, searchfield, start, page_len, filters=None):
|
||||
from erpnext.controllers.queries import get_fields
|
||||
fields = ["name", "customer_name", "customer_group", "territory"]
|
||||
|
||||
if frappe.db.get_default("cust_master_name") == "Customer Name":
|
||||
fields = ["name", "customer_group", "territory"]
|
||||
else:
|
||||
fields = ["name", "customer_name", "customer_group", "territory"]
|
||||
|
||||
fields = get_fields("Customer", fields)
|
||||
|
||||
@ -552,4 +551,4 @@ def get_customer_primary_contact(doctype, txt, searchfield, start, page_len, fil
|
||||
""", {
|
||||
'customer': customer,
|
||||
'txt': '%%%s%%' % txt
|
||||
})
|
||||
})
|
File diff suppressed because it is too large
Load Diff
@ -6,9 +6,12 @@ import frappe
|
||||
from frappe import _
|
||||
|
||||
|
||||
from frappe.utils.nestedset import NestedSet
|
||||
from frappe.utils.nestedset import NestedSet, get_root_of
|
||||
class CustomerGroup(NestedSet):
|
||||
nsm_parent_field = 'parent_customer_group'
|
||||
def validate(self):
|
||||
if not self.parent_customer_group:
|
||||
self.parent_customer_group = get_root_of("Customer Group")
|
||||
|
||||
def on_update(self):
|
||||
self.validate_name_with_customer()
|
||||
|
@ -5,13 +5,16 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
from frappe.utils.nestedset import NestedSet
|
||||
from frappe.utils.nestedset import NestedSet, get_root_of
|
||||
from erpnext import get_default_currency
|
||||
|
||||
class SalesPerson(NestedSet):
|
||||
nsm_parent_field = 'parent_sales_person'
|
||||
|
||||
def validate(self):
|
||||
if not self.parent_sales_person:
|
||||
self.parent_sales_person = get_root_of("Sales Person")
|
||||
|
||||
for d in self.get('targets') or []:
|
||||
if not flt(d.target_qty) and not flt(d.target_amount):
|
||||
frappe.throw(_("Either target qty or target amount is mandatory."))
|
||||
|
@ -6,12 +6,14 @@ import frappe
|
||||
from frappe.utils import flt
|
||||
from frappe import _
|
||||
|
||||
from frappe.utils.nestedset import NestedSet
|
||||
from frappe.utils.nestedset import NestedSet, get_root_of
|
||||
|
||||
class Territory(NestedSet):
|
||||
nsm_parent_field = 'parent_territory'
|
||||
|
||||
def validate(self):
|
||||
if not self.parent_territory:
|
||||
self.parent_territory = get_root_of("Territory")
|
||||
|
||||
for d in self.get('targets') or []:
|
||||
if not flt(d.target_qty) and not flt(d.target_amount):
|
||||
|
@ -987,6 +987,7 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"depends_on": "eval:(!doc.is_item_from_hub)",
|
||||
"fieldname": "hub_publishing_sb",
|
||||
"fieldtype": "Section Break",
|
||||
@ -1060,7 +1061,7 @@
|
||||
"image_field": "image",
|
||||
"links": [],
|
||||
"max_attachments": 1,
|
||||
"modified": "2020-04-08 15:56:06.195722",
|
||||
"modified": "2020-06-30 12:01:07.534447",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Item",
|
||||
@ -1122,4 +1123,4 @@
|
||||
"sort_order": "DESC",
|
||||
"title_field": "item_name",
|
||||
"track_changes": 1
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@ frappe.tour['Stock Settings'] = [
|
||||
{
|
||||
fieldname: "item_naming_by",
|
||||
title: __("Item Naming By"),
|
||||
description: __("By default, the Item Name is set as per the Item Code entered. If you want Items to be named by a") + "<a href='https://docs.erpnext.com/docs/user/manual/en/setting-up/settings/naming-series' target='_blank'>Naming Series</a>" + __(" choose the 'Naming Series' option."),
|
||||
description: __("By default, the Item Name is set as per the Item Code entered. If you want Items to be named by a ") + "<a href='https://docs.erpnext.com/docs/user/manual/en/setting-up/settings/naming-series' target='_blank'>Naming Series</a>" + __(" choose the 'Naming Series' option."),
|
||||
},
|
||||
{
|
||||
fieldname: "default_warehouse",
|
||||
|
@ -19,7 +19,7 @@
|
||||
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/stock",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"modified": "2020-05-19 19:03:23.602423",
|
||||
"modified": "2020-06-29 16:41:09.440378",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Stock",
|
||||
@ -31,15 +31,15 @@
|
||||
{
|
||||
"step": "Create a Product"
|
||||
},
|
||||
{
|
||||
"step": "Create a Supplier"
|
||||
},
|
||||
{
|
||||
"step": "Introduction to Stock Entry"
|
||||
},
|
||||
{
|
||||
"step": "Create a Stock Entry"
|
||||
},
|
||||
{
|
||||
"step": "Create a Supplier"
|
||||
},
|
||||
{
|
||||
"step": "Create a Purchase Receipt"
|
||||
},
|
||||
@ -49,6 +49,5 @@
|
||||
],
|
||||
"subtitle": "Inventory, Warehouses, Analysis and more.",
|
||||
"success_message": "The Stock Module is all set up!",
|
||||
"title": "Let's Setup the Stock Module.",
|
||||
"user_can_dismiss": 1
|
||||
"title": "Let's Set Up the Stock Module."
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
"is_mandatory": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-05-14 22:09:10.043554",
|
||||
"modified": "2020-06-29 16:36:53.948242",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Create a Supplier",
|
||||
"owner": "Administrator",
|
||||
|
Loading…
Reference in New Issue
Block a user