diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 956dacb55f..7c2bac6d2a 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -49,6 +49,7 @@ class PurchaseInvoice(BuyingController): self.check_conversion_rate() self.validate_credit_acc() self.clear_unallocated_advances("Purchase Invoice Advance", "advance_allocation_details") + self.validate_advance_jv("advance_allocation_details", "purchase_order") self.check_for_acc_head_of_supplier() self.check_for_stopped_status() self.validate_with_previous_doc() @@ -80,7 +81,7 @@ class PurchaseInvoice(BuyingController): def get_advances(self): super(PurchaseInvoice, self).get_advances(self.credit_to, - "Purchase Invoice Advance", "advance_allocation_details", "debit") + "Purchase Invoice Advance", "advance_allocation_details", "debit", "purchase_order") def check_active_purchase_items(self): for d in self.get('entries'): diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 20d20d7cfc..5346b91c7e 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -56,6 +56,7 @@ class SalesInvoice(SellingController): self.validate_debit_acc() self.validate_fixed_asset_account() self.clear_unallocated_advances("Sales Invoice Advance", "advance_adjustment_details") + self.validate_advance_jv("advance_adjustment_details", "sales_order") self.add_remarks() if cint(self.is_pos): @@ -222,7 +223,7 @@ class SalesInvoice(SellingController): def get_advances(self): super(SalesInvoice, self).get_advances(self.debit_to, - "Sales Invoice Advance", "advance_adjustment_details", "credit") + "Sales Invoice Advance", "advance_adjustment_details", "credit", "sales_order") def get_company_abbr(self): return frappe.db.sql("select abbr from tabCompany where name=%s", self.company)[0][0] diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 7fa81c9926..34a342e93f 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -4,9 +4,7 @@ from __future__ import unicode_literals import frappe from frappe import _, throw -from frappe.utils import add_days, cint, cstr, today, date_diff, flt, getdate, nowdate, \ - get_first_day, get_last_day -from frappe.model.naming import make_autoname +from frappe.utils import cint, today, flt from erpnext.setup.utils import get_company_currency, get_exchange_rate from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year from erpnext.utilities.transaction_base import TransactionBase @@ -362,38 +360,67 @@ class AccountsController(TransactionBase): frappe.db.sql("""delete from `tab%s` where parentfield=%s and parent = %s and ifnull(allocated_amount, 0) = 0""" % (childtype, '%s', '%s'), (parentfield, self.name)) - def get_advances(self, account_head, child_doctype, parentfield, dr_or_cr): - against_order_list = [] + def get_advances(self, account_head, child_doctype, parentfield, dr_or_cr, against_order_field): + so_list = list(set([d.get(against_order_field) for d in self.get("entries") if d.get(against_order_field)])) + cond = "" + if so_list: + cond = "or (ifnull(t2.%s, '') in (%s))" % ("against_" + against_order_field, ', '.join(['%s']*len(so_list))) + res = frappe.db.sql(""" select - t1.name as jv_no, t1.remark, t2.%s as amount, t2.name as jv_detail_no, t2.%s as order_no + t1.name as jv_no, t1.remark, t2.%s as amount, t2.name as jv_detail_no from `tabJournal Voucher` t1, `tabJournal Voucher Detail` t2 where t1.name = t2.parent and t2.account = %s and t2.is_advance = 'Yes' and t1.docstatus = 1 - and ifnull(t2.against_voucher, '') = '' - and ifnull(t2.against_invoice, '') = '' - and ifnull(t2.against_jv, '') = '' + and (( + ifnull(t2.against_voucher, '') = '' + and ifnull(t2.against_invoice, '') = '' + and ifnull(t2.against_jv, '') = '' + and ifnull(t2.against_sales_order, '') = '' + and ifnull(t2.against_purchase_order, '') = '' + ) %s) order by t1.posting_date""" % - (dr_or_cr, "against_sales_order" if dr_or_cr == "credit" \ - else "against_purchase_order", '%s'), - account_head, as_dict= True) - - if self.get("entries"): - for i in self.get("entries"): - against_order_list.append(i.sales_order if dr_or_cr == "credit" else i.purchase_order) + (dr_or_cr, '%s', cond), + tuple([account_head] + so_list), as_dict= True) self.set(parentfield, []) for d in res: - if not against_order_list or d.order_no in against_order_list: - self.append(parentfield, { - "doctype": child_doctype, - "journal_voucher": d.jv_no, - "jv_detail_no": d.jv_detail_no, - "remarks": d.remark, - "advance_amount": flt(d.amount), - "allocate_amount": 0 - }) + self.append(parentfield, { + "doctype": child_doctype, + "journal_voucher": d.jv_no, + "jv_detail_no": d.jv_detail_no, + "remarks": d.remark, + "advance_amount": flt(d.amount), + "allocate_amount": 0 + }) + + def validate_advance_jv(self, advance_table_fieldname, against_order_field): + order_list = list(set([d.get(against_order_field) for d in self.get("entries") if d.get(against_order_field)])) + if order_list: + account = self.get("debit_to" if self.doctype=="Sales Invoice" else "credit_to") + + jv_against_order = frappe.db.sql("""select parent, %s as against_order + from `tabJournal Voucher Detail` + where docstatus=1 and account=%s and ifnull(is_advance, 'No') = 'Yes' + and ifnull(against_sales_order, '') in (%s) + group by parent, against_sales_order""" % + ("against_" + against_order_field, '%s', ', '.join(['%s']*len(order_list))), + tuple([account] + order_list), as_dict=1) + + if jv_against_order: + order_jv_map = {} + for d in jv_against_order: + order_jv_map.setdefault(d.against_order, []).append(d.parent) + + advance_jv_against_si = [d.journal_voucher for d in self.get(advance_table_fieldname)] + + for order, jv_list in order_jv_map.items(): + for jv in jv_list: + if not advance_jv_against_si or jv not in advance_jv_against_si: + frappe.throw(_("Journal Voucher {0} is linked against Order {1}, hence it must be fetched as advance in Invoice as well.") + .format(jv, order)) + def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield): from erpnext.controllers.status_updater import get_tolerance_for @@ -421,7 +448,6 @@ class AccountsController(TransactionBase): max_allowed_amt = flt(ref_amt * (100 + tolerance) / 100) if total_billed_amt - max_allowed_amt > 0.01: - reduce_by = total_billed_amt - max_allowed_amt frappe.throw(_("Cannot overbill for Item {0} in row {0} more than {1}. To allow overbilling, please set in Stock Settings").format(item.item_code, item.idx, max_allowed_amt)) def get_company_default(self, fieldname): diff --git a/erpnext/projects/doctype/task/task_calendar.js b/erpnext/projects/doctype/task/task_calendar.js index a9d3d6b566..f372184205 100644 --- a/erpnext/projects/doctype/task/task_calendar.js +++ b/erpnext/projects/doctype/task/task_calendar.js @@ -6,17 +6,17 @@ frappe.views.calendar["Task"] = { "start": "exp_start_date", "end": "exp_end_date", "id": "name", - "title": __("subject"), + "title": "subject", "allDay": "allDay" }, gantt: true, filters: [ { - "fieldtype": "Link", - "fieldname": "project", - "options": "Project", + "fieldtype": "Link", + "fieldname": "project", + "options": "Project", "label": __("Project") } ], get_events_method: "erpnext.projects.doctype.task.task.get_events" -} \ No newline at end of file +} diff --git a/erpnext/setup/doctype/authorization_control/authorization_control.py b/erpnext/setup/doctype/authorization_control/authorization_control.py index be97964861..8e7b0cefb0 100644 --- a/erpnext/setup/doctype/authorization_control/authorization_control.py +++ b/erpnext/setup/doctype/authorization_control/authorization_control.py @@ -40,7 +40,7 @@ class AuthorizationControl(TransactionBase): chk = 1 add_cond1,add_cond2 = '','' if based_on == 'Itemwise Discount': - add_cond1 += " and master_name = '"+cstr(item).replace("'", "\'")+"'" + add_cond1 += " and master_name = '"+cstr(item).replace("'", "\\'")+"'" itemwise_exists = frappe.db.sql("""select value from `tabAuthorization Rule` where transaction = %s and value <= %s and based_on = %s and company = %s and docstatus != 2 %s %s""" % @@ -76,7 +76,7 @@ class AuthorizationControl(TransactionBase): add_cond = '' auth_value = av_dis - if val == 1: add_cond += " and system_user = '"+session['user'].replace("'", "\'")+"'" + if val == 1: add_cond += " and system_user = '"+session['user'].replace("'", "\\'")+"'" elif val == 2: add_cond += " and system_role IN %s" % ("('"+"','".join(frappe.user.get_roles())+"')") else: add_cond += " and ifnull(system_user,'') = '' and ifnull(system_role,'') = ''" @@ -85,7 +85,7 @@ class AuthorizationControl(TransactionBase): if doc_obj: if doc_obj.doctype == 'Sales Invoice': customer = doc_obj.customer else: customer = doc_obj.customer_name - add_cond = " and master_name = '"+cstr(customer).replace("'", "\'")+"'" + add_cond = " and master_name = '"+cstr(customer).replace("'", "\\'")+"'" if based_on == 'Itemwise Discount': if doc_obj: for t in doc_obj.get(doc_obj.fname):