Merge pull request #18195 from deepeshgarg007/b2cs_json
fix: GSTR-1 B2CS JSON file generation and cess amount fixes
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js
index fcbd10f..dd20632 100644
--- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js
@@ -9,6 +9,26 @@
frappe.set_route("List", frm.doc.document_type);
});
}
+
+ let button = frm.doc.disabled ? "Enable" : "Disable";
+
+ frm.add_custom_button(__(button), function() {
+
+ frm.set_value('disabled', 1 - frm.doc.disabled);
+
+ frappe.call({
+ method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.disable_dimension",
+ args: {
+ doc: frm.doc
+ },
+ freeze: true,
+ callback: function(r) {
+ let message = frm.doc.disabled ? "Dimension Disabled" : "Dimension Enabled";
+ frm.save();
+ frappe.show_alert({message:__(message), indicator:'green'});
+ }
+ });
+ });
},
document_type: function(frm) {
@@ -21,13 +41,4 @@
}
});
},
-
- disabled: function(frm) {
- frappe.call({
- method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.disable_dimension",
- args: {
- doc: frm.doc
- }
- });
- }
});
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json
index 1e2bb92..57543a0 100644
--- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json
@@ -38,7 +38,8 @@
"default": "0",
"fieldname": "disabled",
"fieldtype": "Check",
- "label": "Disable"
+ "label": "Disable",
+ "read_only": 1
},
{
"default": "0",
@@ -53,7 +54,7 @@
"label": "Mandatory For Profit and Loss Account"
}
],
- "modified": "2019-05-27 18:18:17.792726",
+ "modified": "2019-07-07 18:56:19.517450",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting Dimension",
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
index 91d03be..15ace72 100644
--- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
@@ -121,11 +121,11 @@
@frappe.whitelist()
def disable_dimension(doc):
if frappe.flags.in_test:
- frappe.enqueue(start_dimension_disabling, doc=doc)
+ toggle_disabling(doc=doc)
else:
- start_dimension_disabling(doc=doc)
+ frappe.enqueue(toggle_disabling, doc=doc)
-def start_dimension_disabling(doc):
+def toggle_disabling(doc):
doc = json.loads(doc)
if doc.get('disabled'):
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.json b/erpnext/accounts/doctype/gl_entry/gl_entry.json
index 333d39a..a232a95 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.json
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.json
@@ -848,6 +848,39 @@
"set_only_once": 0,
"translatable": 0,
"unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fetch_if_empty": 0,
+ "fieldname": "due_date",
+ "fieldtype": "Date",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Due Date",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
}
],
"has_web_view": 0,
@@ -861,7 +894,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2019-01-07 07:05:00.366399",
+ "modified": "2019-05-01 07:05:00.366399",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GL Entry",
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 3132c93..8fbddb9 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -498,6 +498,7 @@
self.get_gl_dict({
"account": d.account,
"party_type": d.party_type,
+ "due_date": self.due_date,
"party": d.party,
"against": d.against_account,
"debit": flt(d.debit, d.precision("debit")),
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 2c382c5..f17b2cb 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -302,7 +302,7 @@
},
() => frm.set_value("party_balance", r.message.party_balance),
() => frm.set_value("party_name", r.message.party_name),
- () => frm.events.get_outstanding_documents(frm),
+ () => frm.clear_table("references"),
() => frm.events.hide_unhide_fields(frm),
() => frm.events.set_dynamic_labels(frm),
() => {
@@ -323,9 +323,7 @@
frm.events.set_account_currency_and_balance(frm, frm.doc.paid_from,
"paid_from_account_currency", "paid_from_account_balance", function(frm) {
- if (frm.doc.payment_type == "Receive") {
- frm.events.get_outstanding_documents(frm);
- } else if (frm.doc.payment_type == "Pay") {
+ if (frm.doc.payment_type == "Pay") {
frm.events.paid_amount(frm);
}
}
@@ -337,9 +335,7 @@
frm.events.set_account_currency_and_balance(frm, frm.doc.paid_to,
"paid_to_account_currency", "paid_to_account_balance", function(frm) {
- if(frm.doc.payment_type == "Pay") {
- frm.events.get_outstanding_documents(frm);
- } else if (frm.doc.payment_type == "Receive") {
+ if (frm.doc.payment_type == "Receive") {
if(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) {
if(frm.doc.source_exchange_rate) {
frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate);
@@ -533,26 +529,87 @@
frm.events.set_unallocated_amount(frm);
},
- get_outstanding_documents: function(frm) {
+ get_outstanding_invoice: function(frm) {
+ const today = frappe.datetime.get_today();
+ const fields = [
+ {fieldtype:"Section Break", label: __("Posting Date")},
+ {fieldtype:"Date", label: __("From Date"),
+ fieldname:"from_posting_date", default:frappe.datetime.add_days(today, -30)},
+ {fieldtype:"Column Break"},
+ {fieldtype:"Date", label: __("To Date"), fieldname:"to_posting_date", default:today},
+ {fieldtype:"Section Break", label: __("Due Date")},
+ {fieldtype:"Date", label: __("From Date"), fieldname:"from_due_date"},
+ {fieldtype:"Column Break"},
+ {fieldtype:"Date", label: __("To Date"), fieldname:"to_due_date"},
+ {fieldtype:"Section Break", label: __("Outstanding Amount")},
+ {fieldtype:"Float", label: __("Greater Than Amount"),
+ fieldname:"outstanding_amt_greater_than", default: 0},
+ {fieldtype:"Column Break"},
+ {fieldtype:"Float", label: __("Less Than Amount"), fieldname:"outstanding_amt_less_than"},
+ {fieldtype:"Section Break"},
+ {fieldtype:"Check", label: __("Allocate Payment Amount"), fieldname:"allocate_payment_amount", default:1},
+ ];
+
+ frappe.prompt(fields, function(filters){
+ frappe.flags.allocate_payment_amount = true;
+ frm.events.validate_filters_data(frm, filters);
+ frm.events.get_outstanding_documents(frm, filters);
+ }, __("Filters"), __("Get Outstanding Invoices"));
+ },
+
+ validate_filters_data: function(frm, filters) {
+ const fields = {
+ 'Posting Date': ['from_posting_date', 'to_posting_date'],
+ 'Due Date': ['from_posting_date', 'to_posting_date'],
+ 'Advance Amount': ['from_posting_date', 'to_posting_date'],
+ };
+
+ for (let key in fields) {
+ let from_field = fields[key][0];
+ let to_field = fields[key][1];
+
+ if (filters[from_field] && !filters[to_field]) {
+ frappe.throw(__("Error: {0} is mandatory field",
+ [to_field.replace(/_/g, " ")]
+ ));
+ } else if (filters[from_field] && filters[from_field] > filters[to_field]) {
+ frappe.throw(__("{0}: {1} must be less than {2}",
+ [key, from_field.replace(/_/g, " "), to_field.replace(/_/g, " ")]
+ ));
+ }
+ }
+ },
+
+ get_outstanding_documents: function(frm, filters) {
frm.clear_table("references");
- if(!frm.doc.party) return;
+ if(!frm.doc.party) {
+ return;
+ }
frm.events.check_mandatory_to_fetch(frm);
var company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
+ var args = {
+ "posting_date": frm.doc.posting_date,
+ "company": frm.doc.company,
+ "party_type": frm.doc.party_type,
+ "payment_type": frm.doc.payment_type,
+ "party": frm.doc.party,
+ "party_account": frm.doc.payment_type=="Receive" ? frm.doc.paid_from : frm.doc.paid_to,
+ "cost_center": frm.doc.cost_center
+ }
+
+ for (let key in filters) {
+ args[key] = filters[key];
+ }
+
+ frappe.flags.allocate_payment_amount = filters['allocate_payment_amount'];
+
return frappe.call({
method: 'erpnext.accounts.doctype.payment_entry.payment_entry.get_outstanding_reference_documents',
args: {
- args: {
- "posting_date": frm.doc.posting_date,
- "company": frm.doc.company,
- "party_type": frm.doc.party_type,
- "payment_type": frm.doc.payment_type,
- "party": frm.doc.party,
- "party_account": frm.doc.payment_type=="Receive" ? frm.doc.paid_from : frm.doc.paid_to,
- "cost_center": frm.doc.cost_center
- }
+ args:args
},
callback: function(r, rt) {
if(r.message) {
@@ -608,25 +665,11 @@
frm.events.allocate_party_amount_against_ref_docs(frm,
(frm.doc.payment_type=="Receive" ? frm.doc.paid_amount : frm.doc.received_amount));
+
}
});
},
- allocate_payment_amount: function(frm) {
- if(frm.doc.payment_type == 'Internal Transfer'){
- return
- }
-
- if(frm.doc.references.length == 0){
- frm.events.get_outstanding_documents(frm);
- }
- if(frm.doc.payment_type == 'Internal Transfer') {
- frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.paid_amount);
- } else {
- frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount);
- }
- },
-
allocate_party_amount_against_ref_docs: function(frm, paid_amount) {
var total_positive_outstanding_including_order = 0;
var total_negative_outstanding = 0;
@@ -677,7 +720,7 @@
$.each(frm.doc.references || [], function(i, row) {
row.allocated_amount = 0 //If allocate payment amount checkbox is unchecked, set zero to allocate amount
- if(frm.doc.allocate_payment_amount){
+ if(frappe.flags.allocate_payment_amount){
if(row.outstanding_amount > 0 && allocated_positive_outstanding > 0) {
if(row.outstanding_amount >= allocated_positive_outstanding) {
row.allocated_amount = allocated_positive_outstanding;
@@ -958,7 +1001,7 @@
},
() => {
if(frm.doc.payment_type != "Internal") {
- frm.events.get_outstanding_documents(frm);
+ frm.clear_table("references");
}
}
]);
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json
index fcaa570..a85eccd 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.json
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json
@@ -40,7 +40,7 @@
"target_exchange_rate",
"base_received_amount",
"section_break_14",
- "allocate_payment_amount",
+ "get_outstanding_invoice",
"references",
"section_break_34",
"total_allocated_amount",
@@ -325,19 +325,15 @@
"reqd": 1
},
{
- "collapsible": 1,
- "collapsible_depends_on": "references",
"depends_on": "eval:(doc.party && doc.paid_from && doc.paid_to && doc.paid_amount && doc.received_amount)",
"fieldname": "section_break_14",
"fieldtype": "Section Break",
"label": "Reference"
},
{
- "default": "1",
- "depends_on": "eval:in_list(['Pay', 'Receive'], doc.payment_type)",
- "fieldname": "allocate_payment_amount",
- "fieldtype": "Check",
- "label": "Allocate Payment Amount"
+ "fieldname": "get_outstanding_invoice",
+ "fieldtype": "Button",
+ "label": "Get Outstanding Invoice"
},
{
"fieldname": "references",
@@ -570,7 +566,7 @@
}
],
"is_submittable": 1,
- "modified": "2019-05-25 22:02:40.575822",
+ "modified": "2019-05-27 15:53:21.108857",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index ea76126..699f046 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -574,8 +574,8 @@
# Get negative outstanding sales /purchase invoices
negative_outstanding_invoices = []
if args.get("party_type") not in ["Student", "Employee"] and not args.get("voucher_no"):
- negative_outstanding_invoices = get_negative_outstanding_invoices(args.get("party_type"),
- args.get("party"), args.get("party_account"), party_account_currency, company_currency)
+ negative_outstanding_invoices = get_negative_outstanding_invoices(args.get("party_type"), args.get("party"),
+ args.get("party_account"), args.get("company"), party_account_currency, company_currency)
# Get positive outstanding sales /purchase invoices/ Fees
condition = ""
@@ -585,10 +585,23 @@
# Add cost center condition
if args.get("cost_center") and get_allow_cost_center_in_entry_of_bs_account():
- condition += " and cost_center='%s'" % args.get("cost_center")
+ condition += " and cost_center='%s'" % args.get("cost_center")
+
+ date_fields_dict = {
+ 'posting_date': ['from_posting_date', 'to_posting_date'],
+ 'due_date': ['from_due_date', 'to_due_date']
+ }
+
+ for fieldname, date_fields in date_fields_dict.items():
+ if args.get(date_fields[0]) and args.get(date_fields[1]):
+ condition += " and {0} between '{1}' and '{2}'".format(fieldname,
+ args.get(date_fields[0]), args.get(date_fields[1]))
+
+ if args.get("company"):
+ condition += " and company = {0}".format(frappe.db.escape(args.get("company")))
outstanding_invoices = get_outstanding_invoices(args.get("party_type"), args.get("party"),
- args.get("party_account"), condition=condition)
+ args.get("party_account"), filters=args, condition=condition, limit=100)
for d in outstanding_invoices:
d["exchange_rate"] = 1
@@ -606,12 +619,19 @@
orders_to_be_billed = []
if (args.get("party_type") != "Student"):
orders_to_be_billed = get_orders_to_be_billed(args.get("posting_date"),args.get("party_type"),
- args.get("party"), party_account_currency, company_currency)
+ args.get("party"), args.get("company"), party_account_currency, company_currency, filters=args)
- return negative_outstanding_invoices + outstanding_invoices + orders_to_be_billed
+ data = negative_outstanding_invoices + outstanding_invoices + orders_to_be_billed
+
+ if not data:
+ frappe.msgprint(_("No outstanding invoices found for the {0} <b>{1}</b>.")
+ .format(args.get("party_type").lower(), args.get("party")))
+
+ return data
-def get_orders_to_be_billed(posting_date, party_type, party, party_account_currency, company_currency, cost_center=None):
+def get_orders_to_be_billed(posting_date, party_type, party,
+ company, party_account_currency, company_currency, cost_center=None, filters=None):
if party_type == "Customer":
voucher_type = 'Sales Order'
elif party_type == "Supplier":
@@ -641,6 +661,7 @@
where
{party_type} = %s
and docstatus = 1
+ and company = %s
and ifnull(status, "") != "Closed"
and {ref_field} > advance_paid
and abs(100 - per_billed) > 0.01
@@ -652,10 +673,14 @@
"voucher_type": voucher_type,
"party_type": scrub(party_type),
"condition": condition
- }), party, as_dict=True)
+ }), (party, company), as_dict=True)
order_list = []
for d in orders:
+ if not (d.outstanding_amount >= filters.get("outstanding_amt_greater_than")
+ and d.outstanding_amount <= filters.get("outstanding_amt_less_than")):
+ continue
+
d["voucher_type"] = voucher_type
# This assumes that the exchange rate required is the one in the SO
d["exchange_rate"] = get_exchange_rate(party_account_currency, company_currency, posting_date)
@@ -663,7 +688,8 @@
return order_list
-def get_negative_outstanding_invoices(party_type, party, party_account, party_account_currency, company_currency, cost_center=None):
+def get_negative_outstanding_invoices(party_type, party, party_account,
+ company, party_account_currency, company_currency, cost_center=None):
voucher_type = "Sales Invoice" if party_type == "Customer" else "Purchase Invoice"
supplier_condition = ""
if voucher_type == "Purchase Invoice":
@@ -684,7 +710,8 @@
from
`tab{voucher_type}`
where
- {party_type} = %s and {party_account} = %s and docstatus = 1 and outstanding_amount < 0
+ {party_type} = %s and {party_account} = %s and docstatus = 1 and
+ company = %s and outstanding_amount < 0
{supplier_condition}
order by
posting_date, name
@@ -696,7 +723,7 @@
"party_type": scrub(party_type),
"party_account": "debit_to" if party_type == "Customer" else "credit_to",
"cost_center": cost_center
- }), (party, party_account), as_dict=True)
+ }), (party, party_account, company), as_dict=True)
@frappe.whitelist()
@@ -924,7 +951,6 @@
pe.paid_to_account_currency = party_account_currency if payment_type=="Pay" else bank.account_currency
pe.paid_amount = paid_amount
pe.received_amount = received_amount
- pe.allocate_payment_amount = 1
pe.letter_head = doc.get("letter_head")
if pe.party_type in ["Customer", "Supplier"]:
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 1b03896..219d989 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -337,7 +337,8 @@
if not self.is_return:
self.update_against_document_in_jv()
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
- self.update_billing_status_in_pr()
+
+ self.update_billing_status_in_pr()
# Updating stock ledger should always be called after updating prevdoc status,
# because updating ordered qty in bin depends upon updated ordered qty in PO
@@ -416,6 +417,7 @@
"account": self.credit_to,
"party_type": "Supplier",
"party": self.supplier,
+ "due_date": self.due_date,
"against": self.against_expense_account,
"credit": grand_total_in_company_currency,
"credit_in_account_currency": grand_total_in_company_currency \
@@ -773,7 +775,8 @@
if not self.is_return:
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
- self.update_billing_status_in_pr()
+
+ self.update_billing_status_in_pr()
# Updating stock ledger should always be called after updating prevdoc status,
# because updating ordered qty in bin depends upon updated ordered qty in PO
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 71bdc2a..f8bb971 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -734,6 +734,7 @@
"account": self.debit_to,
"party_type": "Customer",
"party": self.customer,
+ "due_date": self.due_date,
"against": self.against_income_account,
"debit": grand_total_in_company_currency,
"debit_in_account_currency": grand_total_in_company_currency \
diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js
index 70f193e..f6a561f 100644
--- a/erpnext/accounts/report/accounts_payable/accounts_payable.js
+++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js
@@ -108,3 +108,14 @@
});
}
}
+
+erpnext.dimension_filters.then((dimensions) => {
+ dimensions.forEach((dimension) => {
+ frappe.query_reports["Accounts Payable"].filters.splice(9, 0 ,{
+ "fieldname": dimension["fieldname"],
+ "label": __(dimension["label"]),
+ "fieldtype": "Link",
+ "options": dimension["document_type"]
+ });
+ });
+});
diff --git a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js
index 06499ad..ec4f0c9 100644
--- a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js
+++ b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js
@@ -92,3 +92,14 @@
});
}
}
+
+erpnext.dimension_filters.then((dimensions) => {
+ dimensions.forEach((dimension) => {
+ frappe.query_reports["Accounts Payable Summary"].filters.splice(9, 0 ,{
+ "fieldname": dimension["fieldname"],
+ "label": __(dimension["label"]),
+ "fieldtype": "Link",
+ "options": dimension["document_type"]
+ });
+ });
+});
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
index 3661afe..2a45454 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
@@ -172,3 +172,14 @@
});
}
}
+
+erpnext.dimension_filters.then((dimensions) => {
+ dimensions.forEach((dimension) => {
+ frappe.query_reports["Accounts Receivable"].filters.splice(9, 0 ,{
+ "fieldname": dimension["fieldname"],
+ "label": __(dimension["label"]),
+ "fieldtype": "Link",
+ "options": dimension["document_type"]
+ });
+ });
+});
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 2973748..0cda2c1 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -5,6 +5,7 @@
import frappe, erpnext
from frappe import _, scrub
from frappe.utils import getdate, nowdate, flt, cint, formatdate, cstr
+from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
class ReceivablePayableReport(object):
def __init__(self, filters=None):
@@ -553,6 +554,14 @@
conditions.append("account in (%s)" % ','.join(['%s'] *len(accounts)))
values += accounts
+ accounting_dimensions = get_accounting_dimensions()
+
+ if accounting_dimensions:
+ for dimension in accounting_dimensions:
+ if self.filters.get(dimension):
+ conditions.append("{0} = %s".format(dimension))
+ values.append(self.filters.get(dimension))
+
return " and ".join(conditions), values
def get_gl_entries_for(self, party, party_type, against_voucher_type, against_voucher):
diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
index f9162ad..a7c0787 100644
--- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
+++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
@@ -116,3 +116,14 @@
});
}
}
+
+erpnext.dimension_filters.then((dimensions) => {
+ dimensions.forEach((dimension) => {
+ frappe.query_reports["Accounts Receivable Summary"].filters.splice(9, 0 ,{
+ "fieldname": dimension["fieldname"],
+ "label": __(dimension["label"]),
+ "fieldtype": "Link",
+ "options": dimension["document_type"]
+ });
+ });
+});
diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js
index b2072f0..f2a33a8 100644
--- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js
+++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js
@@ -63,9 +63,7 @@
]
}
-let dimension_filters = erpnext.get_dimension_filters();
-
-dimension_filters.then((dimensions) => {
+erpnext.dimension_filters.then((dimensions) => {
dimensions.forEach((dimension) => {
frappe.query_reports["Budget Variance Report"].filters[4].options.push(dimension["document_type"]);
});
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js
index 32af644..ea82575 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.js
+++ b/erpnext/accounts/report/general_ledger/general_ledger.js
@@ -159,9 +159,7 @@
]
}
-let dimension_filters = erpnext.get_dimension_filters();
-
-dimension_filters.then((dimensions) => {
+erpnext.dimension_filters.then((dimensions) => {
dimensions.forEach((dimension) => {
frappe.query_reports["General Ledger"].filters.splice(15, 0 ,{
"fieldname": dimension["fieldname"],
diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
index 80b50b9..d6864b5 100644
--- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
+++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
@@ -16,7 +16,7 @@
"fieldname": "based_on",
"label": __("Based On"),
"fieldtype": "Select",
- "options": "Cost Center\nProject",
+ "options": ["Cost Center", "Project"],
"default": "Cost Center",
"reqd": 1
},
@@ -104,5 +104,10 @@
"parent_field": "parent_account",
"initial_depth": 3
}
-});
+ erpnext.dimension_filters.then((dimensions) => {
+ dimensions.forEach((dimension) => {
+ frappe.query_reports["Profitability Analysis"].filters[1].options.push(dimension["document_type"]);
+ });
+ });
+});
diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.py b/erpnext/accounts/report/profitability_analysis/profitability_analysis.py
index a0d8c5f..6e9b31f 100644
--- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.py
+++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.py
@@ -24,8 +24,17 @@
if based_on == 'cost_center':
return frappe.db.sql("""select name, parent_cost_center as parent_account, cost_center_name as account_name, lft, rgt
from `tabCost Center` where company=%s order by name""", company, as_dict=True)
- else:
+ elif based_on == 'project':
return frappe.get_all('Project', fields = ["name"], filters = {'company': company}, order_by = 'name')
+ else:
+ filters = {}
+ doctype = frappe.unscrub(based_on)
+ has_company = frappe.db.has_column(doctype, 'company')
+
+ if has_company:
+ filters.update({'company': company})
+
+ return frappe.get_all(doctype, fields = ["name"], filters = filters, order_by = 'name')
def get_data(accounts, filters, based_on):
if not accounts:
@@ -42,7 +51,7 @@
accumulate_values_into_parents(accounts, accounts_by_name)
data = prepare_data(accounts, filters, total_row, parent_children_map, based_on)
- data = filter_out_zero_value_rows(data, parent_children_map,
+ data = filter_out_zero_value_rows(data, parent_children_map,
show_zero_values=filters.get("show_zero_values"))
return data
@@ -112,14 +121,14 @@
for key in value_fields:
row[key] = flt(d.get(key, 0.0), 3)
-
+
if abs(row[key]) >= 0.005:
# ignore zero values
has_value = True
row["has_value"] = has_value
data.append(row)
-
+
data.extend([{},total_row])
return data
@@ -174,7 +183,7 @@
if from_date:
additional_conditions.append("and posting_date >= %(from_date)s")
- gl_entries = frappe.db.sql("""select posting_date, {based_on} as based_on, debit, credit,
+ gl_entries = frappe.db.sql("""select posting_date, {based_on} as based_on, debit, credit,
is_opening, (select root_type from `tabAccount` where name = account) as type
from `tabGL Entry` where company=%(company)s
{additional_conditions}
diff --git a/erpnext/accounts/report/sales_register/sales_register.js b/erpnext/accounts/report/sales_register/sales_register.js
index 0b48882c..442aa12 100644
--- a/erpnext/accounts/report/sales_register/sales_register.js
+++ b/erpnext/accounts/report/sales_register/sales_register.js
@@ -67,3 +67,14 @@
}
]
}
+
+erpnext.dimension_filters.then((dimensions) => {
+ dimensions.forEach((dimension) => {
+ frappe.query_reports["Sales Register"].filters.splice(7, 0 ,{
+ "fieldname": dimension["fieldname"],
+ "label": __(dimension["label"]),
+ "fieldtype": "Link",
+ "options": dimension["document_type"]
+ });
+ });
+});
diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py
index de60995..d08056f 100644
--- a/erpnext/accounts/report/sales_register/sales_register.py
+++ b/erpnext/accounts/report/sales_register/sales_register.py
@@ -5,6 +5,7 @@
import frappe
from frappe.utils import flt
from frappe import msgprint, _
+from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
def execute(filters=None):
return _execute(filters)
@@ -163,6 +164,16 @@
where parent=`tabSales Invoice`.name
and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s)"""
+ accounting_dimensions = get_accounting_dimensions()
+
+ if accounting_dimensions:
+ for dimension in accounting_dimensions:
+ if filters.get(dimension):
+ conditions += """ and exists(select name from `tabSales Invoice Item`
+ where parent=`tabSales Invoice`.name
+ and ifnull(`tabSales Invoice Item`.{0}, '') = %({0})s)""".format(dimension)
+
+
return conditions
def get_invoices(filters, additional_query_columns):
diff --git a/erpnext/accounts/report/trial_balance/trial_balance.js b/erpnext/accounts/report/trial_balance/trial_balance.js
index 8bc7280..73d2ab3 100644
--- a/erpnext/accounts/report/trial_balance/trial_balance.js
+++ b/erpnext/accounts/report/trial_balance/trial_balance.js
@@ -96,9 +96,7 @@
}
});
-let dimension_filters = erpnext.get_dimension_filters();
-
-dimension_filters.then((dimensions) => {
+erpnext.dimension_filters.then((dimensions) => {
dimensions.forEach((dimension) => {
frappe.query_reports["Trial Balance"].filters.splice(5, 0 ,{
"fieldname": dimension["fieldname"],
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 7a1f6c5..542c7e4 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -628,7 +628,7 @@
return held_invoices
-def get_outstanding_invoices(party_type, party, account, condition=None):
+def get_outstanding_invoices(party_type, party, account, condition=None, filters=None):
outstanding_invoices = []
precision = frappe.get_precision("Sales Invoice", "outstanding_amount") or 2
@@ -644,7 +644,8 @@
invoice_list = frappe.db.sql("""
select
- voucher_no, voucher_type, posting_date, ifnull(sum({dr_or_cr}), 0) as invoice_amount
+ voucher_no, voucher_type, posting_date, due_date,
+ ifnull(sum({dr_or_cr}), 0) as invoice_amount
from
`tabGL Entry`
where
@@ -677,7 +678,7 @@
""".format(payment_dr_or_cr=payment_dr_or_cr), {
"party_type": party_type,
"party": party,
- "account": account,
+ "account": account
}, as_dict=True)
pe_map = frappe._dict()
@@ -688,10 +689,12 @@
payment_amount = pe_map.get((d.voucher_type, d.voucher_no), 0)
outstanding_amount = flt(d.invoice_amount - payment_amount, precision)
if outstanding_amount > 0.5 / (10**precision):
- if not d.voucher_type == "Purchase Invoice" or d.voucher_no not in held_invoices:
- due_date = frappe.db.get_value(
- d.voucher_type, d.voucher_no, "posting_date" if party_type == "Employee" else "due_date")
+ if (filters.get("outstanding_amt_greater_than") and
+ not (outstanding_amount >= filters.get("outstanding_amt_greater_than") and
+ outstanding_amount <= filters.get("outstanding_amt_less_than"))):
+ continue
+ if not d.voucher_type == "Purchase Invoice" or d.voucher_no not in held_invoices:
outstanding_invoices.append(
frappe._dict({
'voucher_no': d.voucher_no,
@@ -700,7 +703,7 @@
'invoice_amount': flt(d.invoice_amount),
'payment_amount': payment_amount,
'outstanding_amount': outstanding_amount,
- 'due_date': due_date
+ 'due_date': d.due_date
})
)
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index f70870b..b193ac2 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -294,7 +294,7 @@
frappe.db.sql("""update `tab%(target_parent_dt)s`
set %(target_parent_field)s = round(
ifnull((select
- ifnull(sum(if(%(target_ref_field)s > %(target_field)s, abs(%(target_field)s), abs(%(target_ref_field)s))), 0)
+ ifnull(sum(if(abs(%(target_ref_field)s) > abs(%(target_field)s), abs(%(target_field)s), abs(%(target_ref_field)s))), 0)
/ sum(abs(%(target_ref_field)s)) * 100
from `tab%(target_dt)s` where parent="%(name)s" having sum(abs(%(target_ref_field)s)) > 0), 0), 6)
%(update_modified)s
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index bd41c7e..0dd88e9 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -615,4 +615,5 @@
erpnext.patches.v12_0.set_quotation_status
erpnext.patches.v12_0.set_priority_for_support
erpnext.patches.v12_0.delete_priority_property_setter
+erpnext.patches.v12_0.update_due_date_in_gle
erpnext.patches.v12_0.add_default_buying_selling_terms_in_company
diff --git a/erpnext/patches/v12_0/update_due_date_in_gle.py b/erpnext/patches/v12_0/update_due_date_in_gle.py
new file mode 100644
index 0000000..4c47a82
--- /dev/null
+++ b/erpnext/patches/v12_0/update_due_date_in_gle.py
@@ -0,0 +1,17 @@
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+ frappe.reload_doc("accounts", "doctype", "gl_entry")
+
+ for doctype in ["Sales Invoice", "Purchase Invoice", "Journal Entry"]:
+ frappe.reload_doc("accounts", "doctype", frappe.scrub(doctype))
+
+ frappe.db.sql(""" UPDATE `tabGL Entry`, `tab{doctype}`
+ SET
+ `tabGL Entry`.due_date = `tab{doctype}`.due_date
+ WHERE
+ `tabGL Entry`.voucher_no = `tab{doctype}`.name and `tabGL Entry`.party is not null
+ and `tabGL Entry`.voucher_type in ('Sales Invoice', 'Purchase Invoice', 'Journal Entry')
+ and account in (select name from `tabAccount` where account_type in ('Receivable', 'Payable') )""" #nosec
+ .format(doctype=doctype))
diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js
index d1113a4..89cb13d 100644
--- a/erpnext/public/js/financial_statements.js
+++ b/erpnext/public/js/financial_statements.js
@@ -129,9 +129,7 @@
}
]
- let dimension_filters = erpnext.get_dimension_filters();
-
- dimension_filters.then((dimensions) => {
+ erpnext.dimension_filters.then((dimensions) => {
dimensions.forEach((dimension) => {
filters.push({
"fieldname": dimension["fieldname"],
diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js
index fef4507..a9122d8 100644
--- a/erpnext/public/js/utils/dimension_tree_filter.js
+++ b/erpnext/public/js/utils/dimension_tree_filter.js
@@ -7,7 +7,7 @@
"Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation",
"Travel Request", "Fees", "POS Profile"];
-let dimension_filters = erpnext.get_dimension_filters();
+erpnext.dimension_filters = erpnext.get_dimension_filters();
erpnext.doctypes_with_dimensions.forEach((doctype) => {
frappe.ui.form.on(doctype, {
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js
index 6bcdc2b..569a03a 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.js
@@ -77,8 +77,34 @@
},
+
print_without_amount: function(frm) {
erpnext.stock.delivery_note.set_print_hide(frm.doc);
+ },
+
+ refresh: function(frm) {
+ if (frm.doc.docstatus === 1 && frm.doc.is_return === 1 && frm.doc.per_billed !== 100) {
+ frm.add_custom_button(__('Credit Note'), function() {
+ frappe.confirm(__("Are you sure you want to make credit note?"),
+ function() {
+ frm.trigger("make_credit_note");
+ }
+ );
+ }, __('Create'));
+
+ frm.page.set_inner_btn_group_as_primary(__('Create'));
+ }
+ },
+
+ make_credit_note: function(frm) {
+ frm.call({
+ method: "make_return_invoice",
+ doc: frm.doc,
+ freeze: true,
+ callback: function() {
+ frm.reload_doc();
+ }
+ });
}
});
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 1e522b8..ec7df2d 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -333,7 +333,10 @@
return_invoice.is_return = True
return_invoice.save()
return_invoice.submit()
- frappe.msgprint(_("Credit Note {0} has been created automatically").format(return_invoice.name))
+
+ credit_note_link = frappe.utils.get_link_to_form('Sales Invoice', return_invoice.name)
+
+ frappe.msgprint(_("Credit Note {0} has been created automatically").format(credit_note_link))
except:
frappe.throw(_("Could not create Credit Note automatically, please uncheck 'Issue Credit Note' and submit again"))
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index e82aa2c..a2d3e75 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -38,6 +38,29 @@
if(frm.doc.company) {
frm.trigger("toggle_display_account_head");
}
+
+ if (frm.doc.docstatus === 1 && frm.doc.is_return === 1 && frm.doc.per_billed !== 100) {
+ frm.add_custom_button(__('Debit Note'), function() {
+ frappe.confirm(__("Are you sure you want to make debit note?"),
+ function() {
+ frm.trigger("make_debit_note");
+ }
+ );
+ }, __('Create'));
+
+ frm.page.set_inner_btn_group_as_primary(__('Create'));
+ }
+ },
+
+ make_debit_note: function(frm) {
+ frm.call({
+ method: "make_return_invoice",
+ doc: frm.doc,
+ freeze: true,
+ callback: function() {
+ frm.reload_doc();
+ }
+ });
},
company: function(frm) {
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 67cd7f8..df28bec 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -387,6 +387,16 @@
self.load_from_db()
+ def make_return_invoice(self):
+ return_invoice = make_purchase_invoice(self.name)
+ return_invoice.is_return = True
+ return_invoice.save()
+ return_invoice.submit()
+
+ debit_note_link = frappe.utils.get_link_to_form('Purchase Invoice', return_invoice.name)
+
+ frappe.msgprint(_("Debit Note {0} has been created automatically").format(debit_note_link))
+
def update_billed_amount_based_on_po(po_detail, update_modified=True):
# Billed against Sales Order directly
billed_against_po = frappe.db.sql("""select sum(amount) from `tabPurchase Invoice Item`