diff --git a/erpnext/__init__.py b/erpnext/__init__.py index d0fec441e79..fab544fde1b 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import frappe -__version__ = '7.1.13' +__version__ = '7.1.14' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 145ed815642..28028351d2b 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -64,11 +64,20 @@ class JournalEntry(AccountsController): from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries from erpnext.hr.doctype.salary_slip.salary_slip import unlink_ref_doc_from_salary_slip unlink_ref_doc_from_payment_entries(self.doctype, self.name) - unlink_ref_doc_from_salary_slip(self.name) + unlink_ref_doc_from_salary_slip(self.name) self.make_gl_entries(1) self.update_advance_paid() self.update_expense_claim() - + self.unlink_advance_entry_reference() + + def unlink_advance_entry_reference(self): + for d in self.get("accounts"): + if d.is_advance and d.reference_type in ("Sales Invoice", "Purchase Invoice"): + doc = frappe.get_doc(d.reference_type, d.reference_name) + doc.delink_advance_entries(self.name) + d.reference_type = '' + d.reference_name = '' + d.db_update() def validate_party(self): for d in self.get("accounts"): diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 6ecd8fa5ee2..ce0cb50e203 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -406,7 +406,10 @@ frappe.ui.form.on('Payment Entry', { if(!frm.doc.paid_amount && frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) { frm.set_value("paid_amount", frm.doc.received_amount); - frm.set_value("source_exchange_rate", frm.doc.target_exchange_rate); + + if(frm.doc.target_exchange_rate) { + frm.set_value("source_exchange_rate", frm.doc.target_exchange_rate); + } frm.set_value("base_paid_amount", frm.doc.base_received_amount); } @@ -426,7 +429,10 @@ frappe.ui.form.on('Payment Entry', { (frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency)) { frm.set_value("received_amount", frm.doc.paid_amount); - frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate); + + if(frm.doc.source_exchange_rate) { + frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate); + } frm.set_value("base_received_amount", frm.doc.base_paid_amount); } diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 7b9bf16bffb..d4f8edbb6f7 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -60,7 +60,14 @@ class PaymentEntry(AccountsController): self.setup_party_account_field() self.make_gl_entries(cancel=1) self.update_advance_paid() - + self.delink_advance_entry_references() + + def delink_advance_entry_references(self): + for reference in self.references: + if reference.reference_doctype in ("Sales Invoice", "Purchase Invoice"): + doc = frappe.get_doc(reference.reference_doctype, reference.reference_name) + doc.delink_advance_entries(self.name) + def set_missing_values(self): if self.payment_type == "Internal Transfer": for field in ("party", "party_balance", "total_allocated_amount", diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index b4b8444e77e..d8c9b04800a 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -437,6 +437,85 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEquals(frappe.db.get_value("Serial No", pi.get("items")[0].rejected_serial_no, "warehouse"), pi.get("items")[0].rejected_warehouse) + + def test_outstanding_amount_after_advance_jv_cancelation(self): + from erpnext.accounts.doctype.journal_entry.test_journal_entry \ + import test_records as jv_test_records + + jv = frappe.copy_doc(jv_test_records[1]) + jv.insert() + jv.submit() + + pi = frappe.copy_doc(test_records[0]) + pi.append("advances", { + "reference_type": "Journal Entry", + "reference_name": jv.name, + "reference_row": jv.get("accounts")[0].name, + "advance_amount": 400, + "allocated_amount": 300, + "remarks": jv.remark + }) + pi.insert() + pi.submit() + pi.load_from_db() + + #check outstanding after advance allocation + self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total - pi.total_advance)) + + #added to avoid Document has been modified exception + jv = frappe.get_doc("Journal Entry", jv.name) + jv.cancel() + + pi.load_from_db() + #check outstanding after advance cancellation + self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total + pi.total_advance)) + + def test_outstanding_amount_after_advance_payment_entry_cancelation(self): + pe = frappe.get_doc({ + "doctype": "Payment Entry", + "payment_type": "Pay", + "party_type": "Supplier", + "party": "_Test Supplier", + "company": "_Test Company", + "paid_from_account_currency": "INR", + "paid_to_account_currency": "INR", + "source_exchange_rate": 1, + "target_exchange_rate": 1, + "reference_no": "1", + "reference_date": nowdate(), + "received_amount": 300, + "paid_amount": 300, + "paid_from": "_Test Cash - _TC", + "paid_to": "_Test Payable - _TC" + }) + pe.insert() + pe.submit() + + pi = frappe.copy_doc(test_records[0]) + pi.is_pos = 0 + pi.append("advances", { + "doctype": "Purchase Invoice Advance", + "reference_type": "Payment Entry", + "reference_name": pe.name, + "advance_amount": 300, + "allocated_amount": 300, + "remarks": pe.remarks + }) + pi.insert() + pi.submit() + + pi.load_from_db() + + #check outstanding after advance allocation + self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total - pi.total_advance)) + + #added to avoid Document has been modified exception + pe = frappe.get_doc("Payment Entry", pe.name) + pe.cancel() + + pi.load_from_db() + #check outstanding after advance cancellation + self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total + pi.total_advance)) def unlink_payment_on_cancel_of_invoice(enable=1): accounts_settings = frappe.get_doc("Accounts Settings") diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 0011dfe7363..511eeaab9fb 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -980,6 +980,86 @@ class TestSalesInvoice(unittest.TestCase): pe.submit() self.assertEquals(frappe.db.get_value('Customer', customer.name, 'status'), 'Active') + + def test_outstanding_amount_after_advance_jv_cancelation(self): + from erpnext.accounts.doctype.journal_entry.test_journal_entry \ + import test_records as jv_test_records + + jv = frappe.copy_doc(jv_test_records[0]) + jv.insert() + jv.submit() + + si = frappe.copy_doc(test_records[0]) + si.append("advances", { + "doctype": "Sales Invoice Advance", + "reference_type": "Journal Entry", + "reference_name": jv.name, + "reference_row": jv.get("accounts")[0].name, + "advance_amount": 400, + "allocated_amount": 300, + "remarks": jv.remark + }) + si.insert() + si.submit() + si.load_from_db() + + #check outstanding after advance allocation + self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total - si.total_advance, si.precision("outstanding_amount"))) + + #added to avoid Document has been modified exception + jv = frappe.get_doc("Journal Entry", jv.name) + jv.cancel() + + si.load_from_db() + #check outstanding after advance cancellation + self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount"))) + + def test_outstanding_amount_after_advance_payment_entry_cancelation(self): + pe = frappe.get_doc({ + "doctype": "Payment Entry", + "payment_type": "Receive", + "party_type": "Customer", + "party": "_Test Customer", + "company": "_Test Company", + "paid_from_account_currency": "INR", + "paid_to_account_currency": "INR", + "source_exchange_rate": 1, + "target_exchange_rate": 1, + "reference_no": "1", + "reference_date": nowdate(), + "received_amount": 300, + "paid_amount": 300, + "paid_from": "_Test Receivable - _TC", + "paid_to": "_Test Cash - _TC" + }) + pe.insert() + pe.submit() + + si = frappe.copy_doc(test_records[0]) + si.is_pos = 0 + si.append("advances", { + "doctype": "Sales Invoice Advance", + "reference_type": "Payment Entry", + "reference_name": pe.name, + "advance_amount": 300, + "allocated_amount": 300, + "remarks": pe.remarks + }) + si.insert() + si.submit() + + si.load_from_db() + + #check outstanding after advance allocation + self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total - si.total_advance, si.precision("outstanding_amount"))) + + #added to avoid Document has been modified exception + pe = frappe.get_doc("Payment Entry", pe.name) + pe.cancel() + + si.load_from_db() + #check outstanding after advance cancellation + self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount"))) def create_sales_invoice(**args): si = frappe.new_doc("Sales Invoice") diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 6da496ba174..98390ff2d21 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -32,12 +32,13 @@ def get_filters_cond(doctype, filters, conditions): # searches for active employees def employee_query(doctype, txt, searchfield, start, page_len, filters): + conditions = [] return frappe.db.sql("""select name, employee_name from `tabEmployee` where status = 'Active' and docstatus < 2 and ({key} like %(txt)s or employee_name like %(txt)s) - {mcond} + {fcond} {mcond} order by if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999), if(locate(%(_txt)s, employee_name), locate(%(_txt)s, employee_name), 99999), @@ -45,6 +46,7 @@ def employee_query(doctype, txt, searchfield, start, page_len, filters): name, employee_name limit %(start)s, %(page_len)s""".format(**{ 'key': searchfield, + 'fcond': get_filters_cond(doctype, filters, conditions), 'mcond': get_match_cond(doctype) }), { 'txt': "%%%s%%" % txt, diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 68e91550a8a..60cd68c6350 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -164,14 +164,18 @@ class SellingController(StockController): frappe.throw(_("Maxiumm discount for Item {0} is {1}%").format(d.item_code, discount)) def validate_selling_price(self): + def throw_message(item_name, rate, ref_rate_field): + frappe.throw(_("""Selling price for item {0} is lower than its {1}. Selling price should be atleast {2}""") + .format(item_name, ref_rate_field, rate)) + if not frappe.db.get_single_value("Selling Settings", "validate_selling_price"): return for it in self.get("items"): - last_purchase_rate, is_stock_item = frappe.db.get_value("Item", it.name, ["last_purchase_rate", "is_stock_item"]) + last_purchase_rate, is_stock_item = frappe.db.get_value("Item", it.item_code, ["last_purchase_rate", "is_stock_item"]) if flt(it.base_rate) < flt(last_purchase_rate): - throw(it.name, last_purchase_rate, "last purchase rate") + throw_message(it.item_name, last_purchase_rate, "last purchase rate") last_valuation_rate = frappe.db.sql(""" SELECT valuation_rate FROM `tabStock Ledger Entry` WHERE item_code = %s @@ -182,9 +186,6 @@ class SellingController(StockController): if is_stock_item and flt(it.base_rate) < flt(last_valuation_rate): throw_message(it.name, last_valuation_rate, "valuation rate") - def throw_message(item_name, rate, ref_rate_field): - frappe.throw(_("""Selling price for item {0} is lower than its {1}. Selling price should be atleast {2}""") - .format(item_name, ref_rate_field, rate)) def get_item_list(self): il = [] diff --git a/erpnext/hr/doctype/process_payroll/process_payroll.py b/erpnext/hr/doctype/process_payroll/process_payroll.py index 3554669cca2..2077982f136 100644 --- a/erpnext/hr/doctype/process_payroll/process_payroll.py +++ b/erpnext/hr/doctype/process_payroll/process_payroll.py @@ -22,7 +22,7 @@ class ProcessPayroll(Document): sal_struct = frappe.db.sql(""" select name from `tabSalary Structure` - where docstatus != 2 and company = %(company)s and + where docstatus != 2 and is_active = 'Yes' and company = %(company)s and ifnull(salary_slip_based_on_timesheet,0) = %(salary_slip_based_on_timesheet)s""", {"company": self.company, "salary_slip_based_on_timesheet":self.salary_slip_based_on_timesheet}) @@ -51,8 +51,8 @@ class ProcessPayroll(Document): def get_joining_releiving_condition(self): cond = """ - and ifnull(t1.date_of_joining, '0000-00-00') <= '%(from_date)s' - and ifnull(t1.relieving_date, '2199-12-31') >= '%(to_date)s' + and ifnull(t1.date_of_joining, '0000-00-00') <= '%(to_date)s' + and ifnull(t1.relieving_date, '2199-12-31') >= '%(from_date)s' """ % {"from_date": self.from_date, "to_date": self.to_date} return cond diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.js b/erpnext/hr/doctype/salary_structure/salary_structure.js index 334e8a513d9..c5df2e65180 100755 --- a/erpnext/hr/doctype/salary_structure/salary_structure.js +++ b/erpnext/hr/doctype/salary_structure/salary_structure.js @@ -28,7 +28,15 @@ frappe.ui.form.on('Salary Structure', { type: "deduction" } } - }) + }); + frm.set_query("employee", "employees", function(doc) { + return { + query: "erpnext.controllers.queries.employee_query", + filters: { + company: doc.company + } + } + }); }, refresh: function(frm) { @@ -182,11 +190,3 @@ frappe.ui.form.on('Salary Detail', { calculate_totals(frm.doc); } }) - -frappe.ui.form.on('Salary Structure Employee', { - onload: function(frm) { - frm.set_query("employee","employees", function(doc,cdt,cdn) { - return{ query: "erpnext.controllers.queries.employee_query" } - }) - } -}); diff --git a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.json b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.json index 8d844cda7eb..d9f3082d047 100644 --- a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.json +++ b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.json @@ -816,7 +816,7 @@ "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2016-08-17 05:35:34.331954", + "modified": "2016-11-16 05:35:34.331954", "modified_by": "Administrator", "module": "Manufacturing", "name": "Production Planning Tool", diff --git a/erpnext/patches/v7_1/update_missing_salary_component_type.py b/erpnext/patches/v7_1/update_missing_salary_component_type.py index f0e3f6a4adb..25624f56eaf 100644 --- a/erpnext/patches/v7_1/update_missing_salary_component_type.py +++ b/erpnext/patches/v7_1/update_missing_salary_component_type.py @@ -9,6 +9,8 @@ earnings or deductions in existing salary slips ''' def execute(): + frappe.reload_doc("accounts", "doctype", "salary_component_account") + for s in frappe.db.sql('''select name, type, salary_component_abbr from `tabSalary Component` where ifnull(type, "")="" or ifnull(salary_component_abbr, "") = ""''', as_dict=1): @@ -43,4 +45,4 @@ def execute(): component.salary_component_abbr = abbr - component.save() \ No newline at end of file + component.save() diff --git a/erpnext/schools/doctype/student_applicant/student_applicant.json b/erpnext/schools/doctype/student_applicant/student_applicant.json index e60a54ec374..5c6e2769e41 100644 --- a/erpnext/schools/doctype/student_applicant/student_applicant.json +++ b/erpnext/schools/doctype/student_applicant/student_applicant.json @@ -920,7 +920,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2016-10-10 06:19:19.319038", + "modified": "2016-11-17 10:26:13.225135", "modified_by": "Administrator", "module": "Schools", "name": "Student Applicant", @@ -947,27 +947,6 @@ "share": 1, "submit": 1, "write": 1 - }, - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 1, - "export": 0, - "if_owner": 1, - "import": 0, - "is_custom": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 0, - "role": "Guest", - "set_user_permissions": 0, - "share": 0, - "submit": 0, - "write": 0 } ], "quick_entry": 1, diff --git a/erpnext/templates/includes/order/order_macros.html b/erpnext/templates/includes/order/order_macros.html index 70a1fd8b4cd..e77b8b4801c 100644 --- a/erpnext/templates/includes/order/order_macros.html +++ b/erpnext/templates/includes/order/order_macros.html @@ -4,7 +4,7 @@