Reverted gl entry splitting based on payment terms (#12117)
* Reverted gl entry splitting based on payment terms * changed modified date
This commit is contained in:
parent
2f9f4f9c01
commit
a5cc84f8af
@ -74,36 +74,6 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 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,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -748,7 +718,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-08-10 18:06:44.904081",
|
"modified": "2017-12-20 12:40:09.611951",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "GL Entry",
|
"name": "GL Entry",
|
||||||
@ -824,4 +794,4 @@
|
|||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 0,
|
"track_changes": 0,
|
||||||
"track_seen": 0
|
"track_seen": 0
|
||||||
}
|
}
|
||||||
|
@ -61,16 +61,6 @@ frappe.ui.form.on("Journal Entry", {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
|
||||||
|
|
||||||
accounts_on_form_rendered: function(frm) {
|
|
||||||
const options = frm.doc.__onload;
|
|
||||||
|
|
||||||
if (options && frm.cur_grid) {
|
|
||||||
frm.cur_grid.get_field("reference_due_date")
|
|
||||||
.df.options = options[frm.cur_grid.get_field('reference_name').value];
|
|
||||||
frm.cur_grid.refresh_field('reference_due_date');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -204,39 +194,8 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
due_date_options_cache: {},
|
|
||||||
|
|
||||||
reference_name: function(doc, cdt, cdn) {
|
reference_name: function(doc, cdt, cdn) {
|
||||||
var d = frappe.get_doc(cdt, cdn);
|
var d = frappe.get_doc(cdt, cdn);
|
||||||
var me = this;
|
|
||||||
|
|
||||||
const get_invoice_due_dates = invoice_name => {
|
|
||||||
const options = this.due_date_options_cache[invoice_name];
|
|
||||||
const input = $(cur_frm.fields_dict["accounts"].wrapper).find("select[data-fieldname=reference_due_date]");
|
|
||||||
|
|
||||||
if (options) {
|
|
||||||
input.empty();
|
|
||||||
input.add_options(options);
|
|
||||||
frappe.model.set_value(cdt, cdn, "reference_due_date", options[0]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
frappe.call({
|
|
||||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_invoice_due_dates",
|
|
||||||
args: {name: invoice_name},
|
|
||||||
callback: function(r) {
|
|
||||||
const options = [];
|
|
||||||
$.each(r.message, function(key, value) {
|
|
||||||
options.push(value.due_date);
|
|
||||||
});
|
|
||||||
input.empty();
|
|
||||||
input.add_options(options);
|
|
||||||
frappe.model.set_value(cdt, cdn, "reference_due_date", options[0]);
|
|
||||||
me.frm.cur_grid.get_field("reference_due_date").df.options = options.join('\n');
|
|
||||||
me.due_date_options_cache[d.reference_name] = options;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(d.reference_name) {
|
if(d.reference_name) {
|
||||||
if (d.reference_type==="Purchase Invoice" && !flt(d.debit)) {
|
if (d.reference_type==="Purchase Invoice" && !flt(d.debit)) {
|
||||||
@ -246,32 +205,6 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
|||||||
} else if (d.reference_type==="Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
|
} else if (d.reference_type==="Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
|
||||||
this.get_outstanding('Journal Entry', d.reference_name, doc.company, d);
|
this.get_outstanding('Journal Entry', d.reference_name, doc.company, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( in_list(["Sales Invoice", "Purchase Invoice"]), d.reference_type) {
|
|
||||||
get_invoice_due_dates(d.reference_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
reference_due_date: function(doc, cdt, cdn) {
|
|
||||||
const d = frappe.get_doc(cdt, cdn);
|
|
||||||
|
|
||||||
if (d.reference_type && d.reference_name && d.reference_due_date) {
|
|
||||||
if (in_list(["Sales Invoice", "Purchase Invoice"], d.reference_type)) {
|
|
||||||
frappe.model.set_value(cdt, cdn, 'debit_in_account_currency', '');
|
|
||||||
frappe.model.set_value(cdt, cdn, 'credit_in_account_currency', '');
|
|
||||||
}
|
|
||||||
if (d.reference_type==="Purchase Invoice") {
|
|
||||||
this.get_outstanding(
|
|
||||||
'Purchase Invoice', d.reference_name, doc.company, d, d.reference_due_date
|
|
||||||
);
|
|
||||||
} else if (d.reference_type==="Sales Invoice") {
|
|
||||||
this.get_outstanding(
|
|
||||||
'Sales Invoice', d.reference_name, doc.company, d, d.reference_due_date
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
frappe.model.set_value(cdt, cdn, 'reference_due_date', d.reference_due_date);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -286,8 +219,6 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
|||||||
"company": company
|
"company": company
|
||||||
}
|
}
|
||||||
|
|
||||||
if (due_date) args.due_date = due_date;
|
|
||||||
|
|
||||||
return frappe.call({
|
return frappe.call({
|
||||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_outstanding",
|
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_outstanding",
|
||||||
args: { args: args},
|
args: { args: args},
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe, erpnext, json
|
import frappe, erpnext, json
|
||||||
from frappe.utils import cstr, flt, fmt_money, formatdate, getdate, DATE_FORMAT
|
from frappe.utils import cstr, flt, fmt_money, formatdate, getdate
|
||||||
from frappe import msgprint, _, scrub
|
from frappe import msgprint, _, scrub
|
||||||
from erpnext.controllers.accounts_controller import AccountsController
|
from erpnext.controllers.accounts_controller import AccountsController
|
||||||
from erpnext.accounts.utils import get_balance_on, get_account_currency
|
from erpnext.accounts.utils import get_balance_on, get_account_currency
|
||||||
@ -434,8 +434,7 @@ class JournalEntry(AccountsController):
|
|||||||
"against_voucher": d.reference_name,
|
"against_voucher": d.reference_name,
|
||||||
"remarks": self.remark,
|
"remarks": self.remark,
|
||||||
"cost_center": d.cost_center,
|
"cost_center": d.cost_center,
|
||||||
"project": d.project,
|
"project": d.project
|
||||||
"due_date": d.reference_due_date
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -687,54 +686,22 @@ def get_payment_entry(ref_doc, args):
|
|||||||
"remark": args.get("remarks")
|
"remark": args.get("remarks")
|
||||||
})
|
})
|
||||||
|
|
||||||
if not ref_doc.payment_schedule:
|
party_row = je.append("accounts", {
|
||||||
je.append("accounts", {
|
"account": args.get("party_account"),
|
||||||
"account": args.get("party_account"),
|
"party_type": args.get("party_type"),
|
||||||
"party_type": args.get("party_type"),
|
"party": ref_doc.get(args.get("party_type").lower()),
|
||||||
"party": ref_doc.get(args.get("party_type").lower()),
|
"cost_center": cost_center,
|
||||||
"cost_center": cost_center,
|
"account_type": frappe.db.get_value("Account", args.get("party_account"), "account_type"),
|
||||||
"account_type": frappe.db.get_value("Account", args.get("party_account"), "account_type"),
|
"account_currency": args.get("party_account_currency") or \
|
||||||
"account_currency": args.get("party_account_currency") or \
|
get_account_currency(args.get("party_account")),
|
||||||
get_account_currency(args.get("party_account")),
|
"balance": get_balance_on(args.get("party_account")),
|
||||||
"balance": get_balance_on(args.get("party_account")),
|
"party_balance": get_balance_on(party=args.get("party"), party_type=args.get("party_type")),
|
||||||
"party_balance": get_balance_on(party=args.get("party"), party_type=args.get("party_type")),
|
"exchange_rate": exchange_rate,
|
||||||
"exchange_rate": exchange_rate,
|
args.get("amount_field_party"): args.get("amount"),
|
||||||
args.get("amount_field_party"): args.get("amount"),
|
"is_advance": args.get("is_advance"),
|
||||||
"is_advance": args.get("is_advance"),
|
"reference_type": ref_doc.doctype,
|
||||||
"reference_type": ref_doc.doctype,
|
"reference_name": ref_doc.name
|
||||||
"reference_name": ref_doc.name
|
})
|
||||||
})
|
|
||||||
|
|
||||||
else:
|
|
||||||
options_ref_name_list = [
|
|
||||||
d.due_date.strftime(DATE_FORMAT) for d in ref_doc.payment_schedule
|
|
||||||
if d.get('due_date')
|
|
||||||
]
|
|
||||||
|
|
||||||
for payment_term in ref_doc.payment_schedule:
|
|
||||||
je.append("accounts", {
|
|
||||||
"account": args.get("party_account"),
|
|
||||||
"party_type": args.get("party_type"),
|
|
||||||
"party": ref_doc.get(args.get("party_type").lower()),
|
|
||||||
"cost_center": cost_center,
|
|
||||||
"account_type": frappe.db.get_value("Account", args.get("party_account"), "account_type"),
|
|
||||||
"account_currency": args.get("party_account_currency") or \
|
|
||||||
get_account_currency(args.get("party_account")),
|
|
||||||
"balance": get_balance_on(args.get("party_account")),
|
|
||||||
"party_balance": get_balance_on(party=args.get("party"), party_type=args.get("party_type")),
|
|
||||||
"exchange_rate": exchange_rate,
|
|
||||||
args.get("amount_field_party"): payment_term.payment_amount,
|
|
||||||
"is_advance": args.get("is_advance"),
|
|
||||||
"reference_type": ref_doc.doctype,
|
|
||||||
"reference_name": ref_doc.name,
|
|
||||||
"reference_due_date": payment_term.due_date
|
|
||||||
})
|
|
||||||
je.set_onload(ref_doc.name, '\n'.join(options_ref_name_list))
|
|
||||||
|
|
||||||
# First multi currency check
|
|
||||||
for row in je.accounts:
|
|
||||||
if row.account_currency != ref_doc.company_currency:
|
|
||||||
je.multi_currency = 1
|
|
||||||
|
|
||||||
bank_row = je.append("accounts")
|
bank_row = je.append("accounts")
|
||||||
|
|
||||||
@ -758,8 +725,8 @@ def get_payment_entry(ref_doc, args):
|
|||||||
bank_row.set(args.get("amount_field_bank"), amount * exchange_rate)
|
bank_row.set(args.get("amount_field_bank"), amount * exchange_rate)
|
||||||
|
|
||||||
# Multi currency check again
|
# Multi currency check again
|
||||||
if not je.multi_currency:
|
if party_row.account_currency != ref_doc.company_currency \
|
||||||
if bank_row.account_currency and bank_row.account_currency != ref_doc.company_currency:
|
or (bank_row.account_currency and bank_row.account_currency != ref_doc.company_currency):
|
||||||
je.multi_currency = 1
|
je.multi_currency = 1
|
||||||
|
|
||||||
je.set_amounts_in_company_currency()
|
je.set_amounts_in_company_currency()
|
||||||
@ -816,7 +783,8 @@ def get_outstanding(args):
|
|||||||
}
|
}
|
||||||
elif args.get("doctype") in ("Sales Invoice", "Purchase Invoice"):
|
elif args.get("doctype") in ("Sales Invoice", "Purchase Invoice"):
|
||||||
party_type = "Customer" if args.get("doctype") == "Sales Invoice" else "Supplier"
|
party_type = "Customer" if args.get("doctype") == "Sales Invoice" else "Supplier"
|
||||||
invoice = frappe.get_doc(args['doctype'], args['docname']).as_dict()
|
invoice = frappe.db.get_value(args["doctype"], args["docname"],
|
||||||
|
["outstanding_amount", "conversion_rate", scrub(party_type)], as_dict=1)
|
||||||
|
|
||||||
exchange_rate = invoice.conversion_rate if (args.get("account_currency") != company_currency) else 1
|
exchange_rate = invoice.conversion_rate if (args.get("account_currency") != company_currency) else 1
|
||||||
|
|
||||||
@ -827,23 +795,13 @@ def get_outstanding(args):
|
|||||||
amount_field = "debit_in_account_currency" \
|
amount_field = "debit_in_account_currency" \
|
||||||
if flt(invoice.outstanding_amount) > 0 else "credit_in_account_currency"
|
if flt(invoice.outstanding_amount) > 0 else "credit_in_account_currency"
|
||||||
|
|
||||||
if args.get('due_date'):
|
|
||||||
outstanding = ''
|
|
||||||
for d in invoice.payment_schedule:
|
|
||||||
if d.due_date == getdate(args['due_date']):
|
|
||||||
outstanding = abs(flt(d.payment_amount))
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
outstanding = abs(flt(invoice.outstanding_amount))
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
amount_field: outstanding,
|
amount_field: abs(flt(invoice.outstanding_amount)),
|
||||||
"exchange_rate": exchange_rate,
|
"exchange_rate": exchange_rate,
|
||||||
"party_type": party_type,
|
"party_type": party_type,
|
||||||
"party": invoice.get(scrub(party_type))
|
"party": invoice.get(scrub(party_type))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_party_account_and_balance(company, party_type, party):
|
def get_party_account_and_balance(company, party_type, party):
|
||||||
if not frappe.has_permission("Account"):
|
if not frappe.has_permission("Account"):
|
||||||
@ -941,15 +899,4 @@ def get_average_exchange_rate(account):
|
|||||||
bank_balance_in_company_currency = get_balance_on(account, in_account_currency=False)
|
bank_balance_in_company_currency = get_balance_on(account, in_account_currency=False)
|
||||||
exchange_rate = bank_balance_in_company_currency / bank_balance_in_account_currency
|
exchange_rate = bank_balance_in_company_currency / bank_balance_in_account_currency
|
||||||
|
|
||||||
return exchange_rate
|
return exchange_rate
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def get_invoice_due_dates(name):
|
|
||||||
result = frappe.get_list(
|
|
||||||
doctype='GL Entry',
|
|
||||||
filters={'voucher_no': name, "ifnull(due_date, '')": ('!=', '')},
|
|
||||||
fields=['due_date'], distinct=True
|
|
||||||
)
|
|
||||||
|
|
||||||
return result
|
|
@ -661,39 +661,7 @@
|
|||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "eval:doc.reference_type&&!in_list(doc.reference_type, ['Expense Claim', 'Asset', 'Employee Loan', 'Employee Advance'])",
|
|
||||||
"fieldname": "reference_due_date",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"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": "Reference Due Date",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "",
|
|
||||||
"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,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
|
@ -71,9 +71,10 @@ class PaymentEntry(AccountsController):
|
|||||||
def validate_duplicate_entry(self):
|
def validate_duplicate_entry(self):
|
||||||
reference_names = []
|
reference_names = []
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
if (d.reference_doctype, d.reference_name, d.due_date) in reference_names:
|
if (d.reference_doctype, d.reference_name) in reference_names:
|
||||||
frappe.throw(_("Row #{0}: Duplicate entry in References {1} {2}").format(d.idx, d.reference_doctype, d.reference_name))
|
frappe.throw(_("Row #{0}: Duplicate entry in References {1} {2}")
|
||||||
reference_names.append((d.reference_doctype, d.reference_name, d.due_date))
|
.format(d.idx, d.reference_doctype, d.reference_name))
|
||||||
|
reference_names.append((d.reference_doctype, d.reference_name))
|
||||||
|
|
||||||
def validate_allocated_amount(self):
|
def validate_allocated_amount(self):
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
@ -413,8 +414,7 @@ class PaymentEntry(AccountsController):
|
|||||||
gle = party_gl_dict.copy()
|
gle = party_gl_dict.copy()
|
||||||
gle.update({
|
gle.update({
|
||||||
"against_voucher_type": d.reference_doctype,
|
"against_voucher_type": d.reference_doctype,
|
||||||
"against_voucher": d.reference_name,
|
"against_voucher": d.reference_name
|
||||||
"due_date": d.due_date
|
|
||||||
})
|
})
|
||||||
|
|
||||||
allocated_amount_in_company_currency = flt(flt(d.allocated_amount) * flt(d.exchange_rate),
|
allocated_amount_in_company_currency = flt(flt(d.allocated_amount) * flt(d.exchange_rate),
|
||||||
@ -545,10 +545,8 @@ def get_outstanding_reference_documents(args):
|
|||||||
def get_orders_to_be_billed(posting_date, party_type, party, party_account_currency, company_currency):
|
def get_orders_to_be_billed(posting_date, party_type, party, party_account_currency, company_currency):
|
||||||
if party_type == "Customer":
|
if party_type == "Customer":
|
||||||
voucher_type = 'Sales Order'
|
voucher_type = 'Sales Order'
|
||||||
payment_dr_or_cr = "credit_in_account_currency - debit_in_account_currency"
|
|
||||||
elif party_type == "Supplier":
|
elif party_type == "Supplier":
|
||||||
voucher_type = 'Purchase Order'
|
voucher_type = 'Purchase Order'
|
||||||
payment_dr_or_cr = "debit_in_account_currency - credit_in_account_currency"
|
|
||||||
elif party_type == "Employee":
|
elif party_type == "Employee":
|
||||||
voucher_type = None
|
voucher_type = None
|
||||||
|
|
||||||
@ -557,131 +555,36 @@ def get_orders_to_be_billed(posting_date, party_type, party, party_account_curre
|
|||||||
ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"
|
ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"
|
||||||
|
|
||||||
orders = frappe.db.sql("""
|
orders = frappe.db.sql("""
|
||||||
select
|
|
||||||
name as voucher_no,
|
|
||||||
{ref_field} as invoice_amount,
|
|
||||||
({ref_field} - advance_paid) as outstanding_amount,
|
|
||||||
transaction_date as posting_date
|
|
||||||
from
|
|
||||||
`tab{voucher_type}`
|
|
||||||
where
|
|
||||||
{party_type} = %s
|
|
||||||
and docstatus = 1
|
|
||||||
and ifnull(status, "") != "Closed"
|
|
||||||
and {ref_field} > advance_paid
|
|
||||||
and abs(100 - per_billed) > 0.01
|
|
||||||
order by
|
|
||||||
transaction_date, name
|
|
||||||
""".format(**{
|
|
||||||
"ref_field": ref_field,
|
|
||||||
"voucher_type": voucher_type,
|
|
||||||
"party_type": scrub(party_type)
|
|
||||||
}), party, as_dict=True)
|
|
||||||
|
|
||||||
if voucher_type and party_type is not "Employee":
|
|
||||||
ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"
|
|
||||||
|
|
||||||
# find orders without considering if they have Payment Schedule
|
|
||||||
orders_without_schedule = frappe.db.sql("""
|
|
||||||
select
|
|
||||||
name as voucher_no,
|
|
||||||
{ref_field} as invoice_amount,
|
|
||||||
({ref_field} - advance_paid) as outstanding_amount,
|
|
||||||
transaction_date as posting_date
|
|
||||||
from
|
|
||||||
`tab{voucher_type}`
|
|
||||||
where
|
|
||||||
{party_type} = %s
|
|
||||||
and docstatus = 1
|
|
||||||
and ifnull(status, "") != "Closed"
|
|
||||||
and {ref_field} > advance_paid
|
|
||||||
and abs(100 - per_billed) > 0.01
|
|
||||||
order by
|
|
||||||
transaction_date, name
|
|
||||||
""".format(**{
|
|
||||||
"ref_field": ref_field,
|
|
||||||
"voucher_type": voucher_type,
|
|
||||||
"party_type": scrub(party_type)
|
|
||||||
}), party, as_dict=True)
|
|
||||||
|
|
||||||
# find orders considering if they have Payment Schedule
|
|
||||||
if voucher_type and party_type is not "Employee":
|
|
||||||
ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"
|
|
||||||
|
|
||||||
orders_with_schedule = frappe.db.sql("""
|
|
||||||
select
|
select
|
||||||
VT.name as voucher_no,
|
name as voucher_no,
|
||||||
PS.payment_amount as invoice_amount,
|
{ref_field} as invoice_amount,
|
||||||
PS.payment_amount - (select
|
({ref_field} - advance_paid) as outstanding_amount,
|
||||||
ifnull(sum({payment_dr_or_cr}), 0)
|
transaction_date as posting_date
|
||||||
from `tabGL Entry`
|
|
||||||
where
|
|
||||||
against_voucher = VT.name
|
|
||||||
and due_date = PS.due_date
|
|
||||||
) as outstanding_amount,
|
|
||||||
VT.transaction_date as posting_date,
|
|
||||||
PS.due_date
|
|
||||||
from
|
from
|
||||||
`tab{voucher_type}` VT
|
`tab{voucher_type}`
|
||||||
join
|
|
||||||
`tabPayment Schedule` PS on VT.name = PS.parent
|
|
||||||
where
|
where
|
||||||
{party_type} = %s
|
{party_type} = %s
|
||||||
and VT.docstatus = 1
|
and docstatus = 1
|
||||||
and ifnull(status, "") != "Closed"
|
and ifnull(status, "") != "Closed"
|
||||||
and {ref_field} > advance_paid
|
and {ref_field} > advance_paid
|
||||||
and abs(100 - per_billed) > 0.01
|
and abs(100 - per_billed) > 0.01
|
||||||
order by
|
order by
|
||||||
VT.transaction_date, VT.name
|
transaction_date, name
|
||||||
""".format(**{
|
""".format(**{
|
||||||
"ref_field": ref_field,
|
"ref_field": ref_field,
|
||||||
"voucher_type": voucher_type,
|
"voucher_type": voucher_type,
|
||||||
"party_type": scrub(party_type),
|
"party_type": scrub(party_type)
|
||||||
"payment_dr_or_cr": payment_dr_or_cr
|
}), party, as_dict=True)
|
||||||
}), party, as_dict=True)
|
|
||||||
|
|
||||||
# reconcile both results such that we have a list that contains unique entries.
|
|
||||||
# Where both lists contain a record that is common, we select the one with
|
|
||||||
# linked Payment Schedule
|
|
||||||
orders = _merge_query_results(orders_without_schedule, orders_with_schedule, 'voucher_no')
|
|
||||||
|
|
||||||
order_list = []
|
order_list = []
|
||||||
for d in orders:
|
for d in orders:
|
||||||
d["voucher_type"] = voucher_type
|
d["voucher_type"] = voucher_type
|
||||||
# This assumes that the exchange rate required is the one in the SO
|
# This assumes that the exchange rate required is the one in the SO
|
||||||
d["exchange_rate"] = get_exchange_rate(party_account_currency,
|
d["exchange_rate"] = get_exchange_rate(party_account_currency, company_currency, posting_date)
|
||||||
company_currency, posting_date)
|
|
||||||
order_list.append(d)
|
order_list.append(d)
|
||||||
|
|
||||||
return order_list
|
return order_list
|
||||||
|
|
||||||
|
|
||||||
def _merge_query_results(result1, result2, dict_key):
|
|
||||||
"""
|
|
||||||
Merges two list of query results that are dictionaries.
|
|
||||||
For every item in result1 that is found in result2, the item is removed from
|
|
||||||
result1. At the end of processing result1, result1 and result2 are concatenated
|
|
||||||
and returned.
|
|
||||||
|
|
||||||
:param result1: List of dict
|
|
||||||
:param result2: List of dict
|
|
||||||
:return: List of dict
|
|
||||||
"""
|
|
||||||
for item in result1[:]:
|
|
||||||
found = False
|
|
||||||
for item2 in result2:
|
|
||||||
if item[dict_key] == item2[dict_key]:
|
|
||||||
found = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if found:
|
|
||||||
result1.remove(item)
|
|
||||||
|
|
||||||
final_result = result1 + result2
|
|
||||||
|
|
||||||
return final_result
|
|
||||||
|
|
||||||
|
|
||||||
def get_negative_outstanding_invoices(party_type, party, party_account, party_account_currency, company_currency):
|
def get_negative_outstanding_invoices(party_type, party, party_account, party_account_currency, company_currency):
|
||||||
voucher_type = "Sales Invoice" if party_type == "Customer" else "Purchase Invoice"
|
voucher_type = "Sales Invoice" if party_type == "Customer" else "Purchase Invoice"
|
||||||
if party_account_currency == company_currency:
|
if party_account_currency == company_currency:
|
||||||
@ -900,40 +803,15 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
|||||||
pe.allocate_payment_amount = 1
|
pe.allocate_payment_amount = 1
|
||||||
pe.letter_head = doc.get("letter_head")
|
pe.letter_head = doc.get("letter_head")
|
||||||
|
|
||||||
if dt == "Employee Advance":
|
pe.append("references", {
|
||||||
pe.append("references", {
|
'reference_doctype': dt,
|
||||||
'reference_doctype': dt,
|
'reference_name': dn,
|
||||||
'reference_name': dn,
|
"bill_no": doc.get("bill_no"),
|
||||||
'total_amount': grand_total,
|
"due_date": doc.get("due_date"),
|
||||||
'outstanding_amount': outstanding_amount,
|
'total_amount': grand_total,
|
||||||
'allocated_amount': outstanding_amount
|
'outstanding_amount': outstanding_amount,
|
||||||
})
|
'allocated_amount': outstanding_amount
|
||||||
else:
|
})
|
||||||
args = {
|
|
||||||
'party_account': party_account,
|
|
||||||
'company': pe.company,
|
|
||||||
'party_type': pe.party_type,
|
|
||||||
'party': pe.party,
|
|
||||||
'posting_date': pe.posting_date,
|
|
||||||
'voucher_type': dt,
|
|
||||||
'voucher_no': dn
|
|
||||||
}
|
|
||||||
references = get_outstanding_reference_documents(args=args)
|
|
||||||
|
|
||||||
for reference in references:
|
|
||||||
if reference.voucher_no == dn:
|
|
||||||
allocated_amount = min(paid_amount, reference.outstanding_amount)
|
|
||||||
pe.append("references", {
|
|
||||||
'reference_doctype': reference.voucher_type,
|
|
||||||
'reference_name': reference.voucher_no,
|
|
||||||
'due_date': reference.due_date,
|
|
||||||
'total_amount': reference.invoice_amount,
|
|
||||||
'outstanding_amount': reference.outstanding_amount,
|
|
||||||
'allocated_amount': allocated_amount,
|
|
||||||
"bill_no": reference.get("bill_no")
|
|
||||||
})
|
|
||||||
if paid_amount:
|
|
||||||
paid_amount -= allocated_amount
|
|
||||||
|
|
||||||
pe.setup_party_account_field()
|
pe.setup_party_account_field()
|
||||||
pe.set_missing_values()
|
pe.set_missing_values()
|
||||||
|
@ -66,18 +66,6 @@ class TestPaymentEntry(unittest.TestCase):
|
|||||||
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
|
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
|
||||||
self.assertEqual(outstanding_amount, 100)
|
self.assertEqual(outstanding_amount, 100)
|
||||||
|
|
||||||
def test_payment_entry_against_si_multi_due_dates(self):
|
|
||||||
si = create_sales_invoice(do_not_save=1)
|
|
||||||
si.payment_terms_template = '_Test Payment Term Template'
|
|
||||||
si.insert()
|
|
||||||
si.submit()
|
|
||||||
|
|
||||||
pe = get_payment_entry(si.doctype, si.name)
|
|
||||||
pe.reference_no = "1"
|
|
||||||
pe.reference_date = "2016-01-01"
|
|
||||||
pe.insert()
|
|
||||||
pe.submit()
|
|
||||||
|
|
||||||
def test_payment_entry_against_pi(self):
|
def test_payment_entry_against_pi(self):
|
||||||
pi = make_purchase_invoice(supplier="_Test Supplier USD", debit_to="_Test Payable USD - _TC",
|
pi = make_purchase_invoice(supplier="_Test Supplier USD", debit_to="_Test Payable USD - _TC",
|
||||||
currency="USD", conversion_rate=50)
|
currency="USD", conversion_rate=50)
|
||||||
|
@ -363,27 +363,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
|
|
||||||
def make_supplier_gl_entry(self, gl_entries):
|
def make_supplier_gl_entry(self, gl_entries):
|
||||||
grand_total = self.rounded_total or self.grand_total
|
grand_total = self.rounded_total or self.grand_total
|
||||||
if self.get("payment_schedule"):
|
if grand_total:
|
||||||
for d in self.get("payment_schedule"):
|
|
||||||
payment_amount_in_company_currency = flt(d.payment_amount * self.conversion_rate,
|
|
||||||
d.precision("payment_amount"))
|
|
||||||
|
|
||||||
gl_entries.append(
|
|
||||||
self.get_gl_dict({
|
|
||||||
"account": self.credit_to,
|
|
||||||
"party_type": "Supplier",
|
|
||||||
"party": self.supplier,
|
|
||||||
"due_date": d.due_date,
|
|
||||||
"against": self.against_expense_account,
|
|
||||||
"credit": payment_amount_in_company_currency,
|
|
||||||
"credit_in_account_currency": payment_amount_in_company_currency \
|
|
||||||
if self.party_account_currency==self.company_currency else d.payment_amount,
|
|
||||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
|
||||||
"against_voucher_type": self.doctype
|
|
||||||
}, self.party_account_currency)
|
|
||||||
)
|
|
||||||
|
|
||||||
elif grand_total:
|
|
||||||
# Didnot use base_grand_total to book rounding loss gle
|
# Didnot use base_grand_total to book rounding loss gle
|
||||||
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
||||||
self.precision("grand_total"))
|
self.precision("grand_total"))
|
||||||
|
@ -6,7 +6,7 @@ from __future__ import unicode_literals
|
|||||||
import unittest
|
import unittest
|
||||||
import frappe, erpnext
|
import frappe, erpnext
|
||||||
import frappe.model
|
import frappe.model
|
||||||
from frappe.utils import cint, flt, today, nowdate, getdate, add_days
|
from frappe.utils import cint, flt, today, nowdate, add_days
|
||||||
import frappe.defaults
|
import frappe.defaults
|
||||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \
|
||||||
test_records as pr_test_records
|
test_records as pr_test_records
|
||||||
@ -647,39 +647,6 @@ class TestPurchaseInvoice(unittest.TestCase):
|
|||||||
self.assertEquals(pi.total_taxes_and_charges, 462.3)
|
self.assertEquals(pi.total_taxes_and_charges, 462.3)
|
||||||
self.assertEquals(pi.grand_total, 1712.3)
|
self.assertEquals(pi.grand_total, 1712.3)
|
||||||
|
|
||||||
def test_gl_entry_based_on_payment_schedule(self):
|
|
||||||
pi = make_purchase_invoice(do_not_save=True, supplier="_Test Supplier P")
|
|
||||||
pi.append("payment_schedule", {
|
|
||||||
"due_date": add_days(nowdate(), 15),
|
|
||||||
"payment_amount": 100,
|
|
||||||
"invoice_portion": 40.00
|
|
||||||
})
|
|
||||||
pi.append("payment_schedule", {
|
|
||||||
"due_date": add_days(nowdate(), 25),
|
|
||||||
"payment_amount": 150,
|
|
||||||
"invoice_portion": 60.00
|
|
||||||
})
|
|
||||||
|
|
||||||
pi.save()
|
|
||||||
pi.submit()
|
|
||||||
|
|
||||||
gl_entries = frappe.db.sql("""select account, debit, credit, due_date
|
|
||||||
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
|
|
||||||
order by account asc, debit asc""", pi.name, as_dict=1)
|
|
||||||
self.assertTrue(gl_entries)
|
|
||||||
|
|
||||||
expected_gl_entries = sorted([
|
|
||||||
[pi.credit_to, 0.0, 100.0, add_days(nowdate(), 15)],
|
|
||||||
[pi.credit_to, 0.0, 150.0, add_days(nowdate(), 25)],
|
|
||||||
["_Test Account Cost for Goods Sold - _TC", 250.0, 0.0, None]
|
|
||||||
])
|
|
||||||
|
|
||||||
for i, gle in enumerate(sorted(gl_entries, key=lambda gle: gle.account)):
|
|
||||||
self.assertEquals(expected_gl_entries[i][0], gle.account)
|
|
||||||
self.assertEquals(expected_gl_entries[i][1], gle.debit)
|
|
||||||
self.assertEquals(expected_gl_entries[i][2], gle.credit)
|
|
||||||
self.assertEquals(getdate(expected_gl_entries[i][3]), getdate(gle.due_date))
|
|
||||||
|
|
||||||
def test_make_pi_without_terms(self):
|
def test_make_pi_without_terms(self):
|
||||||
pi = make_purchase_invoice(do_not_save=1)
|
pi = make_purchase_invoice(do_not_save=1)
|
||||||
|
|
||||||
|
@ -637,27 +637,7 @@ class SalesInvoice(SellingController):
|
|||||||
|
|
||||||
def make_customer_gl_entry(self, gl_entries):
|
def make_customer_gl_entry(self, gl_entries):
|
||||||
grand_total = self.rounded_total or self.grand_total
|
grand_total = self.rounded_total or self.grand_total
|
||||||
if self.get("payment_schedule"):
|
if grand_total:
|
||||||
for d in self.get("payment_schedule"):
|
|
||||||
payment_amount_in_company_currency = flt(d.payment_amount * self.conversion_rate,
|
|
||||||
d.precision("payment_amount"))
|
|
||||||
|
|
||||||
gl_entries.append(
|
|
||||||
self.get_gl_dict({
|
|
||||||
"account": self.debit_to,
|
|
||||||
"party_type": "Customer",
|
|
||||||
"party": self.customer,
|
|
||||||
"due_date": d.due_date,
|
|
||||||
"against": self.against_income_account,
|
|
||||||
"debit": payment_amount_in_company_currency,
|
|
||||||
"debit_in_account_currency": payment_amount_in_company_currency \
|
|
||||||
if self.party_account_currency==self.company_currency else d.payment_amount,
|
|
||||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
|
||||||
"against_voucher_type": self.doctype
|
|
||||||
}, self.party_account_currency)
|
|
||||||
)
|
|
||||||
|
|
||||||
elif grand_total:
|
|
||||||
# Didnot use base_grand_total to book rounding loss gle
|
# Didnot use base_grand_total to book rounding loss gle
|
||||||
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
||||||
self.precision("grand_total"))
|
self.precision("grand_total"))
|
||||||
|
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
import unittest, copy, time
|
import unittest, copy, time
|
||||||
from frappe.utils import nowdate, add_days, flt, getdate, cint
|
from frappe.utils import nowdate, flt, getdate, cint
|
||||||
from frappe.model.dynamic_links import get_dynamic_link_map
|
from frappe.model.dynamic_links import get_dynamic_link_map
|
||||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
|
||||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
|
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
|
||||||
@ -1321,40 +1321,6 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
})
|
})
|
||||||
si.insert()
|
si.insert()
|
||||||
return si
|
return si
|
||||||
|
|
||||||
def test_gl_entry_based_on_payment_schedule(self):
|
|
||||||
si = create_sales_invoice(do_not_save=True, customer="_Test Customer P")
|
|
||||||
si.append("payment_schedule", {
|
|
||||||
"due_date": add_days(nowdate(), 15),
|
|
||||||
"payment_amount": 20,
|
|
||||||
"invoice_portion": 20.00
|
|
||||||
})
|
|
||||||
si.append("payment_schedule", {
|
|
||||||
"due_date": add_days(nowdate(), 45),
|
|
||||||
"payment_amount": 80,
|
|
||||||
"invoice_portion": 80.00
|
|
||||||
})
|
|
||||||
|
|
||||||
si.save()
|
|
||||||
si.submit()
|
|
||||||
|
|
||||||
gl_entries = frappe.db.sql("""select account, debit, credit, due_date
|
|
||||||
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
|
|
||||||
order by account asc, debit asc""", si.name, as_dict=1)
|
|
||||||
self.assertTrue(gl_entries)
|
|
||||||
|
|
||||||
expected_gl_entries = sorted([
|
|
||||||
[si.debit_to, 20.0, 0.0, add_days(nowdate(), 15)],
|
|
||||||
[si.debit_to, 80.0, 0.0, add_days(nowdate(), 45)],
|
|
||||||
["Sales - _TC", 0.0, 100.0, None]
|
|
||||||
])
|
|
||||||
|
|
||||||
for i, gle in enumerate(sorted(gl_entries, key=lambda gle: gle.account)):
|
|
||||||
self.assertEquals(expected_gl_entries[i][0], gle.account)
|
|
||||||
self.assertEquals(expected_gl_entries[i][1], gle.debit)
|
|
||||||
self.assertEquals(expected_gl_entries[i][2], gle.credit)
|
|
||||||
self.assertEquals(getdate(expected_gl_entries[i][3]), getdate(gle.due_date))
|
|
||||||
|
|
||||||
|
|
||||||
def test_company_monthly_sales(self):
|
def test_company_monthly_sales(self):
|
||||||
existing_current_month_sales = frappe.db.get_value("Company", "_Test Company", "total_monthly_sales")
|
existing_current_month_sales = frappe.db.get_value("Company", "_Test Company", "total_monthly_sales")
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe, erpnext
|
import frappe, erpnext
|
||||||
from frappe.utils import flt, cstr, cint, getdate
|
from frappe.utils import flt, cstr, cint
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.model.meta import get_field_precision
|
from frappe.model.meta import get_field_precision
|
||||||
from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget
|
from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget
|
||||||
@ -75,8 +75,7 @@ def check_if_in_list(gle, gl_map):
|
|||||||
and cstr(e.get('against_voucher'))==cstr(gle.get('against_voucher')) \
|
and cstr(e.get('against_voucher'))==cstr(gle.get('against_voucher')) \
|
||||||
and cstr(e.get('against_voucher_type')) == cstr(gle.get('against_voucher_type')) \
|
and cstr(e.get('against_voucher_type')) == cstr(gle.get('against_voucher_type')) \
|
||||||
and cstr(e.get('cost_center')) == cstr(gle.get('cost_center')) \
|
and cstr(e.get('cost_center')) == cstr(gle.get('cost_center')) \
|
||||||
and cstr(e.get('project')) == cstr(gle.get('project')) \
|
and cstr(e.get('project')) == cstr(gle.get('project')):
|
||||||
and getdate(e.get('due_date')) == getdate(gle.get('due_date')):
|
|
||||||
return e
|
return e
|
||||||
|
|
||||||
def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False):
|
def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False):
|
||||||
|
@ -113,7 +113,7 @@ class ReceivablePayableReport(object):
|
|||||||
row += [self.get_party_name(gle.party_type, gle.party)]
|
row += [self.get_party_name(gle.party_type, gle.party)]
|
||||||
|
|
||||||
# get due date
|
# get due date
|
||||||
due_date = gle.due_date or voucher_details.get(gle.voucher_no, {}).get("due_date", "")
|
due_date = voucher_details.get(gle.voucher_no, {}).get("due_date", "")
|
||||||
|
|
||||||
row += [gle.voucher_type, gle.voucher_no, due_date]
|
row += [gle.voucher_type, gle.voucher_no, due_date]
|
||||||
|
|
||||||
@ -188,8 +188,7 @@ class ReceivablePayableReport(object):
|
|||||||
reverse_dr_or_cr = "credit" if dr_or_cr=="debit" else "debit"
|
reverse_dr_or_cr = "credit" if dr_or_cr=="debit" else "debit"
|
||||||
|
|
||||||
for e in self.get_gl_entries_for(gle.party, gle.party_type, gle.voucher_type, gle.voucher_no):
|
for e in self.get_gl_entries_for(gle.party, gle.party_type, gle.voucher_type, gle.voucher_no):
|
||||||
if getdate(e.posting_date) <= report_date and e.name!=gle.name \
|
if getdate(e.posting_date) <= report_date and e.name!=gle.name:
|
||||||
and (not gle.due_date or getdate(e.due_date) == getdate(gle.due_date)):
|
|
||||||
amount = flt(e.get(reverse_dr_or_cr)) - flt(e.get(dr_or_cr))
|
amount = flt(e.get(reverse_dr_or_cr)) - flt(e.get(dr_or_cr))
|
||||||
if e.voucher_no not in return_entries:
|
if e.voucher_no not in return_entries:
|
||||||
payment_amount += amount
|
payment_amount += amount
|
||||||
@ -251,11 +250,11 @@ class ReceivablePayableReport(object):
|
|||||||
select_fields = "sum(debit) as debit, sum(credit) as credit"
|
select_fields = "sum(debit) as debit, sum(credit) as credit"
|
||||||
|
|
||||||
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party,
|
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party,
|
||||||
voucher_type, voucher_no, against_voucher_type, against_voucher, due_date,
|
voucher_type, voucher_no, against_voucher_type, against_voucher,
|
||||||
account_currency, remarks, {0}
|
account_currency, remarks, {0}
|
||||||
from `tabGL Entry`
|
from `tabGL Entry`
|
||||||
where docstatus < 2 and party_type=%s and (party is not null and party != '') {1}
|
where docstatus < 2 and party_type=%s and (party is not null and party != '') {1}
|
||||||
group by voucher_type, voucher_no, against_voucher_type, against_voucher, party, due_date
|
group by voucher_type, voucher_no, against_voucher_type, against_voucher, party
|
||||||
order by posting_date, party"""
|
order by posting_date, party"""
|
||||||
.format(select_fields, conditions), values, as_dict=True)
|
.format(select_fields, conditions), values, as_dict=True)
|
||||||
|
|
||||||
|
@ -583,9 +583,10 @@ def get_outstanding_invoices(party_type, party, account, condition=None):
|
|||||||
dr_or_cr = "credit_in_account_currency - debit_in_account_currency"
|
dr_or_cr = "credit_in_account_currency - debit_in_account_currency"
|
||||||
payment_dr_or_cr = "payment_gl_entry.debit_in_account_currency - payment_gl_entry.credit_in_account_currency"
|
payment_dr_or_cr = "payment_gl_entry.debit_in_account_currency - payment_gl_entry.credit_in_account_currency"
|
||||||
|
|
||||||
|
invoice = 'Sales Invoice' if party_type == 'Customer' else 'Purchase Invoice'
|
||||||
invoice_list = frappe.db.sql("""
|
invoice_list = frappe.db.sql("""
|
||||||
select
|
select
|
||||||
voucher_no, voucher_type, posting_date, ifnull(sum({dr_or_cr}), 0) as invoice_amount, due_date,
|
voucher_no, voucher_type, posting_date, ifnull(sum({dr_or_cr}), 0) as invoice_amount,
|
||||||
(
|
(
|
||||||
select ifnull(sum({payment_dr_or_cr}), 0)
|
select ifnull(sum({payment_dr_or_cr}), 0)
|
||||||
from `tabGL Entry` payment_gl_entry
|
from `tabGL Entry` payment_gl_entry
|
||||||
@ -596,7 +597,6 @@ def get_outstanding_invoices(party_type, party, account, condition=None):
|
|||||||
and payment_gl_entry.party_type = invoice_gl_entry.party_type
|
and payment_gl_entry.party_type = invoice_gl_entry.party_type
|
||||||
and payment_gl_entry.party = invoice_gl_entry.party
|
and payment_gl_entry.party = invoice_gl_entry.party
|
||||||
and payment_gl_entry.account = invoice_gl_entry.account
|
and payment_gl_entry.account = invoice_gl_entry.account
|
||||||
and payment_gl_entry.due_date = invoice_gl_entry.due_date
|
|
||||||
and {payment_dr_or_cr} > 0
|
and {payment_dr_or_cr} > 0
|
||||||
) as payment_amount
|
) as payment_amount
|
||||||
from
|
from
|
||||||
@ -608,10 +608,11 @@ def get_outstanding_invoices(party_type, party, account, condition=None):
|
|||||||
and ((voucher_type = 'Journal Entry'
|
and ((voucher_type = 'Journal Entry'
|
||||||
and (against_voucher = '' or against_voucher is null))
|
and (against_voucher = '' or against_voucher is null))
|
||||||
or (voucher_type not in ('Journal Entry', 'Payment Entry')))
|
or (voucher_type not in ('Journal Entry', 'Payment Entry')))
|
||||||
group by voucher_type, voucher_no, due_date
|
group by voucher_type, voucher_no
|
||||||
having (invoice_amount - payment_amount) > 0.005
|
having (invoice_amount - payment_amount) > 0.005
|
||||||
order by posting_date, name, due_date""".format(
|
order by posting_date, name, due_date""".format(
|
||||||
dr_or_cr=dr_or_cr,
|
dr_or_cr=dr_or_cr,
|
||||||
|
invoice = invoice,
|
||||||
payment_dr_or_cr=payment_dr_or_cr,
|
payment_dr_or_cr=payment_dr_or_cr,
|
||||||
condition=condition or ""
|
condition=condition or ""
|
||||||
), {
|
), {
|
||||||
@ -621,12 +622,8 @@ def get_outstanding_invoices(party_type, party, account, condition=None):
|
|||||||
}, as_dict=True)
|
}, as_dict=True)
|
||||||
|
|
||||||
for d in invoice_list:
|
for d in invoice_list:
|
||||||
due_date = d.due_date or (
|
due_date = frappe.db.get_value(d.voucher_type, d.voucher_no,
|
||||||
frappe.db.get_value(
|
"posting_date" if party_type == "Employee" else "due_date")
|
||||||
d.voucher_type, d.voucher_no,
|
|
||||||
"posting_date" if party_type == "Employee" else "due_date"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
outstanding_invoices.append(
|
outstanding_invoices.append(
|
||||||
frappe._dict({
|
frappe._dict({
|
||||||
|
@ -485,4 +485,3 @@ erpnext.patches.v10_0.enabled_regional_print_format_based_on_country
|
|||||||
erpnext.patches.v10_0.update_asset_calculate_depreciation
|
erpnext.patches.v10_0.update_asset_calculate_depreciation
|
||||||
erpnext.patches.v10_0.enabled_regional_print_format_based_on_country
|
erpnext.patches.v10_0.enabled_regional_print_format_based_on_country
|
||||||
erpnext.patches.v10_0.update_asset_calculate_depreciation
|
erpnext.patches.v10_0.update_asset_calculate_depreciation
|
||||||
erpnext.patches.v10_0.update_due_date_in_gle_and_payment_entries
|
|
||||||
|
@ -1,100 +0,0 @@
|
|||||||
from __future__ import unicode_literals
|
|
||||||
import frappe
|
|
||||||
from frappe.utils import update_progress_bar
|
|
||||||
|
|
||||||
def execute():
|
|
||||||
frappe.reload_doc("accounts", "doctype", "gl_entry")
|
|
||||||
frappe.reload_doc("accounts", "doctype", "payment_entry_reference")
|
|
||||||
frappe.reload_doc("accounts", "doctype", "journal_entry_account")
|
|
||||||
|
|
||||||
print "Updating Due Date in GL Entry, Journal Entry and Payment Entry"
|
|
||||||
for doctype in ("Sales Invoice", "Purchase Invoice"):
|
|
||||||
invoice_due_dates = frappe.db.sql("""select name, due_date from `tab{0}`
|
|
||||||
where docstatus=1 order by name""".format(doctype))
|
|
||||||
|
|
||||||
# update gle
|
|
||||||
count = 0
|
|
||||||
total_count = len(invoice_due_dates)
|
|
||||||
batch_size = 1000
|
|
||||||
|
|
||||||
while(count < total_count):
|
|
||||||
update_progress_bar("Based on {0}".format(doctype), count, total_count)
|
|
||||||
sub_set = invoice_due_dates[count:count+batch_size]
|
|
||||||
invoices = [d[0] for d in sub_set]
|
|
||||||
|
|
||||||
update_gl_entries(doctype, invoices, sub_set)
|
|
||||||
update_payment_entries(doctype, invoices, sub_set)
|
|
||||||
|
|
||||||
count += batch_size
|
|
||||||
|
|
||||||
def update_gl_entries(doctype, invoices, invoice_due_dates):
|
|
||||||
when_then = get_when_then_for_gle(doctype, invoice_due_dates)
|
|
||||||
|
|
||||||
frappe.db.sql("""
|
|
||||||
UPDATE `tabGL Entry`
|
|
||||||
SET due_date = CASE
|
|
||||||
%s
|
|
||||||
ELSE `due_date` END
|
|
||||||
WHERE
|
|
||||||
(
|
|
||||||
(voucher_type = %s and voucher_no in (%s))
|
|
||||||
or (voucher_type in ('Journal Entry', 'Payment Entry')
|
|
||||||
and against_voucher in (%s))
|
|
||||||
)
|
|
||||||
and ifnull(party, '') != ''
|
|
||||||
and ifnull(due_date, '') = ''
|
|
||||||
""" % (when_then, '%s', ', '.join(['%s']*len(invoices)), ', '.join(['%s']*len(invoices))),
|
|
||||||
tuple([doctype] + invoices + invoices))
|
|
||||||
|
|
||||||
def get_when_then_for_gle(doctype, data):
|
|
||||||
cond = ""
|
|
||||||
for d in data:
|
|
||||||
cond += """
|
|
||||||
WHEN (
|
|
||||||
(voucher_type = '{voucher_type}' and voucher_no = '{voucher_no}')
|
|
||||||
or (voucher_type in ('Journal Entry', 'Payment Entry')
|
|
||||||
and against_voucher = '{voucher_no}')
|
|
||||||
) THEN '{date}'
|
|
||||||
""".format(voucher_type=doctype, voucher_no=frappe.db.escape(d[0]), date=d[1])
|
|
||||||
|
|
||||||
return cond
|
|
||||||
|
|
||||||
def update_payment_entries(ref_doctype, invoices, invoice_due_dates):
|
|
||||||
for d in (
|
|
||||||
("Payment Entry Reference", "reference_doctype", "due_date"),
|
|
||||||
("Journal Entry Account", "reference_type", "reference_due_date")):
|
|
||||||
|
|
||||||
when_then = get_when_then_for_payment_entries(ref_doctype, d[1], invoice_due_dates)
|
|
||||||
|
|
||||||
frappe.db.sql("""
|
|
||||||
UPDATE `tab{doctype}`
|
|
||||||
SET {due_date_field} = CASE
|
|
||||||
{when_then}
|
|
||||||
ELSE `{due_date_field}` END
|
|
||||||
WHERE
|
|
||||||
{ref_doctype_fieldname} = '{ref_doctype}'
|
|
||||||
and reference_name in ({reference_names})
|
|
||||||
and ifnull({due_date_field}, '') = ''
|
|
||||||
""".format(
|
|
||||||
doctype = d[0],
|
|
||||||
due_date_field = d[2],
|
|
||||||
when_then = when_then,
|
|
||||||
ref_doctype_fieldname = d[1],
|
|
||||||
ref_doctype = ref_doctype,
|
|
||||||
reference_names = ', '.join(['%s']*len(invoices))
|
|
||||||
), tuple(invoices))
|
|
||||||
|
|
||||||
def get_when_then_for_payment_entries(ref_doctype, ref_doctype_fieldname, data):
|
|
||||||
cond = ""
|
|
||||||
for d in data:
|
|
||||||
cond += """
|
|
||||||
WHEN {ref_doctype_fieldname} = '{ref_doctype}'
|
|
||||||
and reference_name = '{voucher_no}'
|
|
||||||
THEN '{date}'
|
|
||||||
""".format(
|
|
||||||
ref_doctype_fieldname=ref_doctype_fieldname,
|
|
||||||
ref_doctype=ref_doctype,
|
|
||||||
voucher_no=frappe.db.escape(d[0]),
|
|
||||||
date=d[1])
|
|
||||||
|
|
||||||
return cond
|
|
Loading…
Reference in New Issue
Block a user