Advance Payment Entry adjustment against Invoice

This commit is contained in:
Nabin Hait 2016-06-27 17:41:39 +05:30
parent e3a10170f7
commit 28a0528ae4
21 changed files with 509 additions and 278 deletions

View File

@ -234,11 +234,12 @@ frappe.ui.form.on('Payment Entry', {
frm.set_value(field, null);
})
} else {
frm.set_value("party_type", frm.doc.payment_type=="Receive" ? "Customer" : "Supplier");
frm.events.party(frm);
}
},
"mode_of_payment": function(frm) {
mode_of_payment: function(frm) {
return frappe.call({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.get_bank_cash_account",
args: {
@ -357,7 +358,8 @@ frappe.ui.form.on('Payment Entry', {
paid_amount: function(frm) {
frm.set_value("base_paid_amount", flt(frm.doc.paid_amount) * flt(frm.doc.source_exchange_rate));
if(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) {
if(!frm.set_paid_amount_based_on_received_amount &&
(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency)) {
frm.set_value("received_amount", frm.doc.paid_amount);
frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate);
frm.set_value("base_received_amount", frm.doc.base_paid_amount);
@ -366,9 +368,19 @@ frappe.ui.form.on('Payment Entry', {
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.paid_amount);
else
frm.events.set_difference_amount(frm);
frm.set_paid_amount_based_on_received_amount = false;
},
received_amount: function(frm) {
frm.set_paid_amount_based_on_received_amount = true;
if(!frm.doc.paid_amount && frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) {
frm.set_value("paid_amount", frm.doc.received_amount);
frm.set_value("source_exchange_rate", frm.doc.target_exchange_rate);
frm.set_value("base_paid_amount", frm.doc.base_received_amount);
}
frm.set_value("base_received_amount",
flt(frm.doc.received_amount) * flt(frm.doc.target_exchange_rate));
@ -397,12 +409,15 @@ frappe.ui.form.on('Payment Entry', {
},
callback: function(r, rt) {
if(r.message) {
var total_invoice_outstanding_amount = 0;
$.each(r.message, function(i, d) {
var c = frm.add_child("references");
c.reference_doctype = d.voucher_type;
c.reference_name = d.voucher_no;
c.total_amount = d.invoice_amount;
c.outstanding_amount = d.outstanding_amount;
if(!in_list(["Sales Order", "Purchase Order"], d.voucher_type))
total_outstanding_amount += flt(d.outstanding_amount);
var party_account_currency = frm.doc.payment_type=="Receive" ?
frm.doc.paid_from_account_currency : frm.doc.paid_to_account_currency;
@ -416,6 +431,9 @@ frappe.ui.form.on('Payment Entry', {
c.due_date = d.due_date
}
});
var party_amt_field = frm.doc.payment_type=="Receive" ? "paid_amount" : "received_amount";
frm.set_value(party_amt_field, total_outstanding_amount);
}
frm.events.allocate_party_amount_against_ref_docs(frm,
@ -426,12 +444,14 @@ frappe.ui.form.on('Payment Entry', {
allocate_party_amount_against_ref_docs: function(frm, amount) {
$.each(frm.doc.references || [], function(i, row) {
if (!amount) return false;
row.allocated_amount = 0
if(amount) {
if(row.outstanding_amount >= amount) row.allocated_amount = amount;
else row.allocated_amount = row.outstanding_amount;
amount -= flt(row.allocated_amount);
}
})
frm.refresh_fields()
frm.events.set_total_allocated_amount(frm);

View File

@ -27,7 +27,7 @@
"options": "PE-",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
@ -53,7 +53,7 @@
"options": "Receive\nPay\nInternal Transfer",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
@ -129,7 +129,7 @@
"options": "Company",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
@ -208,7 +208,7 @@
"options": "Customer\nSupplier",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
@ -285,7 +285,7 @@
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
@ -337,7 +337,7 @@
"options": "Account",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
@ -364,7 +364,7 @@
"options": "Currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
@ -391,7 +391,7 @@
"options": "paid_from_account_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
@ -442,7 +442,7 @@
"options": "Account",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
@ -469,7 +469,7 @@
"options": "paid_to_account_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
@ -496,7 +496,7 @@
"options": "Currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
@ -576,7 +576,7 @@
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
@ -603,7 +603,7 @@
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
@ -654,7 +654,7 @@
"options": "paid_to_account_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
@ -680,7 +680,7 @@
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
@ -707,7 +707,7 @@
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
@ -834,7 +834,7 @@
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
@ -939,7 +939,7 @@
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
@ -966,7 +966,7 @@
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
@ -1067,7 +1067,7 @@
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
@ -1094,7 +1094,7 @@
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
@ -1201,7 +1201,7 @@
"options": "Project",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
@ -1276,7 +1276,7 @@
"options": "Letter Head",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
@ -1302,7 +1302,7 @@
"options": "Print Heading",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
@ -1352,7 +1352,7 @@
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
@ -1372,7 +1372,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-06-26 17:36:58.416685",
"modified": "2016-06-27 11:17:47.484139",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",

View File

@ -16,17 +16,26 @@ from erpnext.controllers.accounts_controller import AccountsController
class PaymentEntry(AccountsController):
def __init__(self, arg1, arg2=None):
super(PaymentEntry, self).__init__(arg1, arg2)
self.party_account_field = None
self.party_account = None
if self.payment_type == "Receive":
self.party_account_field = "paid_from"
self.party_account = self.paid_from
elif self.payment_type == "Pay":
self.party_account_field = "paid_to"
self.party_account = self.paid_to
def validate(self):
self.define_party_account_field()
self.set_missing_values()
self.validate_party_details()
self.validate_bank_accounts()
self.set_exchange_rate()
self.set_amounts_in_company_currency()
self.validate_reference_documents()
self.set_total_allocated_amount()
self.set_unallocated_amount()
self.set_difference_amount()
self.set_amounts()
self.clear_unallocated_reference_document_rows()
self.set_title()
@ -35,17 +44,9 @@ class PaymentEntry(AccountsController):
self.update_advance_paid()
def on_cancel(self):
self.make_gl_entries()
self.make_gl_entries(cancel=1)
self.update_advance_paid()
def define_party_account_field(self):
self.party_account_field = None
if self.payment_type == "Receive":
self.party_account_field = "paid_from"
elif self.payment_type == "Pay":
self.party_account_field = "paid_to"
def set_missing_values(self):
if self.payment_type == "Internal Transfer":
for field in ("party", "party_balance", "total_allocated_amount",
@ -115,16 +116,6 @@ class PaymentEntry(AccountsController):
self.target_exchange_rate = get_exchange_rate(self.paid_to_account_currency,
self.company_currency)
def set_amounts_in_company_currency(self):
self.base_paid_amount, self.base_received_amount, self.difference_amount = 0, 0, 0
if self.paid_amount:
self.base_paid_amount = flt(flt(self.paid_amount) * flt(self.source_exchange_rate),
self.precision("base_paid_amount"))
if self.received_amount:
self.base_received_amount = flt(flt(self.received_amount) * flt(self.target_exchange_rate),
self.precision("base_received_amount"))
def validate_reference_documents(self):
if self.party_type == "Customer":
valid_reference_doctypes = ("Sales Order", "Sales Invoice", "Journal Entry")
@ -151,6 +142,22 @@ class PaymentEntry(AccountsController):
frappe.throw(_("{0} {1} must be submitted")
.format(d.reference_doctype, d.reference_name))
def set_amounts(self):
self.set_amounts_in_company_currency()
self.set_total_allocated_amount()
self.set_unallocated_amount()
self.set_difference_amount()
def set_amounts_in_company_currency(self):
self.base_paid_amount, self.base_received_amount, self.difference_amount = 0, 0, 0
if self.paid_amount:
self.base_paid_amount = flt(flt(self.paid_amount) * flt(self.source_exchange_rate),
self.precision("base_paid_amount"))
if self.received_amount:
self.base_received_amount = flt(flt(self.received_amount) * flt(self.target_exchange_rate),
self.precision("base_received_amount"))
def set_total_allocated_amount(self):
if self.payment_type == "Internal Transfer":
return
@ -203,13 +210,13 @@ class PaymentEntry(AccountsController):
else:
self.title = self.paid_from + " - " + self.paid_to
def make_gl_entries(self):
def make_gl_entries(self, cancel=0, adv_adj=0):
gl_entries = []
self.add_party_gl_entries(gl_entries)
self.add_bank_gl_entries(gl_entries)
self.add_deductions_gl_entries(gl_entries)
make_gl_entries(gl_entries, cancel = (self.docstatus==2))
make_gl_entries(gl_entries, cancel=cancel, adv_adj=adv_adj)
def add_party_gl_entries(self, gl_entries):
if self.party_account:
@ -333,6 +340,12 @@ def get_outstanding_reference_documents(args):
outstanding_invoices = get_outstanding_invoices(args.get("party_type"), args.get("party"),
args.get("party_account"))
for d in outstanding_invoices:
d.exchange_rate = 1
if party_account_currency != company_currency \
and d.voucher_type in ("Sales Invoice", "Purchase Invoice"):
d.exchange_rate = frappe.db.get_value(d.voucher_type, d.voucher_no, "conversion_rate")
# Get all SO / PO which are not fully billed or aginst which full advance not paid
orders_to_be_billed = get_orders_to_be_billed(args.get("party_type"), args.get("party"),
party_account_currency, company_currency)

View File

@ -52,7 +52,7 @@
"options": "Cost Center",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
@ -97,7 +97,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-06-23 12:45:26.516398",
"modified": "2016-06-27 11:18:35.021945",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry Deduction",

View File

@ -126,7 +126,7 @@
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
@ -201,7 +201,7 @@
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
@ -221,7 +221,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-06-26 15:01:17.161402",
"modified": "2016-06-27 11:18:20.442383",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry Reference",

View File

@ -105,8 +105,8 @@ class PaymentReconciliation(Document):
'party': self.party,
'is_advance' : e.is_advance,
'dr_or_cr' : dr_or_cr,
'unadjusted_amt' : flt(e.amount),
'allocated_amt' : flt(e.allocated_amount)
'unadjusted_amount' : flt(e.amount),
'allocated_amount' : flt(e.allocated_amount)
})
if lst:

View File

@ -2055,7 +2055,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "get_advances_paid",
"fieldname": "get_advances",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
@ -2066,7 +2066,7 @@
"length": 0,
"no_copy": 0,
"oldfieldtype": "Button",
"options": "get_advances",
"options": "",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
@ -3031,7 +3031,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2016-06-30 13:40:39.440646",
"modified": "2016-06-30 13:40:39.440648",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",

View File

@ -65,7 +65,7 @@ class PurchaseInvoice(BuyingController):
self.po_required()
self.pr_required()
self.validate_supplier_invoice()
self.validate_advance_jv("Purchase Order")
# validate cash purchase
if (self.is_paid == 1):
@ -109,11 +109,6 @@ class PurchaseInvoice(BuyingController):
super(PurchaseInvoice, self).set_missing_values(for_validate)
def get_advances(self):
if not self.is_return:
super(PurchaseInvoice, self).get_advances(self.credit_to, "Supplier", self.supplier,
"Purchase Invoice Advance", "advances", "debit_in_account_currency", "purchase_order")
def check_conversion_rate(self):
default_currency = get_company_currency(self.company)
if not default_currency:
@ -234,37 +229,6 @@ class PurchaseInvoice(BuyingController):
if not submitted:
frappe.throw(_("Purchase Receipt {0} is not submitted").format(d.purchase_receipt))
def update_against_document_in_jv(self):
"""
Links invoice and advance voucher:
1. cancel advance voucher
2. split into multiple rows if partially adjusted, assign against voucher
3. submit advance voucher
"""
lst = []
for d in self.get('advances'):
if flt(d.allocated_amount) > 0:
args = {
'voucher_no' : d.journal_entry,
'voucher_detail_no' : d.jv_detail_no,
'against_voucher_type' : 'Purchase Invoice',
'against_voucher' : self.name,
'account' : self.credit_to,
'party_type': 'Supplier',
'party': self.supplier,
'is_advance' : 'Yes',
'dr_or_cr' : 'debit_in_account_currency',
'unadjusted_amt' : flt(d.advance_amount),
'allocated_amt' : flt(d.allocated_amount)
}
lst.append(args)
if lst:
from erpnext.accounts.utils import reconcile_against_document
reconcile_against_document(lst)
def update_status_updater_args(self):
if cint(self.update_stock):
self.status_updater.extend([{

View File

@ -196,8 +196,9 @@ class TestPurchaseInvoice(unittest.TestCase):
pi = frappe.copy_doc(test_records[0])
pi.append("advances", {
"journal_entry": jv.name,
"jv_detail_no": jv.get("accounts")[0].name,
"reference_type": "Journal Entry",
"reference_name": jv.name,
"reference_row": jv.get("accounts")[0].name,
"advance_amount": 400,
"allocated_amount": 300,
"remarks": jv.remark

View File

@ -2,29 +2,33 @@
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2013-03-08 15:36:46",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Document",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "journal_entry",
"fieldname": "reference_type",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Journal Entry",
"in_list_view": 0,
"label": "Reference Type",
"length": 0,
"no_copy": 1,
"oldfieldname": "journal_voucher",
"oldfieldtype": "Link",
"options": "Journal Entry",
"options": "DocType",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "180px",
"read_only": 1,
"report_hide": 0,
@ -38,19 +42,75 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "jv_detail_no",
"fieldname": "reference_name",
"fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Reference Name",
"length": 0,
"no_copy": 1,
"options": "reference_type",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "remarks",
"fieldtype": "Read Only",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Remarks",
"length": 0,
"no_copy": 1,
"oldfieldname": "remarks",
"oldfieldtype": "Small Text",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "150px"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "reference_row",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Journal Entry Detail No",
"label": "Reference Row",
"length": 0,
"no_copy": 1,
"oldfieldname": "jv_detail_no",
"oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"print_width": "80px",
"read_only": 1,
"report_hide": 0,
@ -60,32 +120,6 @@
"unique": 0,
"width": "80px"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "remarks",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Remarks",
"length": 0,
"no_copy": 1,
"oldfieldname": "remarks",
"oldfieldtype": "Small Text",
"permlevel": 0,
"print_hide": 0,
"print_width": "150px",
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "150px"
},
{
"allow_on_submit": 0,
"bold": 0,
@ -94,12 +128,14 @@
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
@ -115,6 +151,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Advance Amount",
@ -125,6 +162,7 @@
"options": "party_account_currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "100px",
"read_only": 1,
"report_hide": 0,
@ -142,6 +180,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Allocated Amount",
@ -152,6 +191,7 @@
"options": "party_account_currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "100px",
"read_only": 0,
"report_hide": 0,
@ -165,18 +205,23 @@
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2015-11-16 06:29:53.288895",
"menu_index": 0,
"modified": "2016-06-27 12:37:42.845967",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Advance",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0
"read_only_onload": 0,
"track_seen": 0,
"version": 0
}

View File

@ -244,7 +244,7 @@ $.extend(cur_frm.cscript, new erpnext.accounts.SalesInvoiceController({frm: cur_
// Hide Fields
// ------------
cur_frm.cscript.hide_fields = function(doc) {
parent_fields = ['project', 'due_date', 'is_opening', 'source', 'total_advance', 'get_advances_received',
parent_fields = ['project', 'due_date', 'is_opening', 'source', 'total_advance', 'get_advances',
'advances', 'sales_partner', 'commission_rate', 'total_commission', 'advances', 'from_date', 'to_date'];
if(cint(doc.is_pos) == 1) {

View File

@ -2019,7 +2019,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "get_advances_received",
"fieldname": "get_advances",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
@ -2030,7 +2030,7 @@
"length": 0,
"no_copy": 0,
"oldfieldtype": "Button",
"options": "get_advances",
"options": "",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
@ -3676,7 +3676,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2016-07-02 20:10:14.146763",
"modified": "2016-07-02 20:10:14.146963",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@ -77,7 +77,6 @@ class SalesInvoice(SellingController):
self.check_close_sales_order("sales_order")
self.validate_debit_to_acc()
self.clear_unallocated_advances("Sales Invoice Advance", "advances")
self.validate_advance_jv("Sales Order")
self.add_remarks()
self.validate_write_off_account()
self.validate_fixed_asset()
@ -294,44 +293,9 @@ class SalesInvoice(SellingController):
return pos
def get_advances(self):
if not self.is_return:
super(SalesInvoice, self).get_advances(self.debit_to, "Customer", self.customer,
"Sales Invoice Advance", "advances", "credit_in_account_currency", "sales_order")
def get_company_abbr(self):
return frappe.db.sql("select abbr from tabCompany where name=%s", self.company)[0][0]
def update_against_document_in_jv(self):
"""
Links invoice and advance voucher:
1. cancel advance voucher
2. split into multiple rows if partially adjusted, assign against voucher
3. submit advance voucher
"""
lst = []
for d in self.get('advances'):
if flt(d.allocated_amount) > 0:
args = {
'voucher_no' : d.journal_entry,
'voucher_detail_no' : d.jv_detail_no,
'against_voucher_type' : 'Sales Invoice',
'against_voucher' : self.name,
'account' : self.debit_to,
'party_type': 'Customer',
'party': self.customer,
'is_advance' : 'Yes',
'dr_or_cr' : 'credit_in_account_currency',
'unadjusted_amt' : flt(d.advance_amount),
'allocated_amt' : flt(d.allocated_amount)
}
lst.append(args)
if lst:
from erpnext.accounts.utils import reconcile_against_document
reconcile_against_document(lst)
def validate_debit_to_acc(self):
account = frappe.db.get_value("Account", self.debit_to,
["account_type", "report_type", "account_currency"], as_dict=True)

View File

@ -676,8 +676,9 @@ class TestSalesInvoice(unittest.TestCase):
si = frappe.copy_doc(test_records[0])
si.append("advances", {
"doctype": "Sales Invoice Advance",
"journal_entry": jv.name,
"jv_detail_no": jv.get("accounts")[0].name,
"reference_type": "Journal Entry",
"reference_name": jv.name,
"reference_row": jv.get("accounts")[0].name,
"advance_amount": 400,
"allocated_amount": 300,
"remarks": jv.remark

View File

@ -2,29 +2,33 @@
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2013-02-22 01:27:41",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Document",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "journal_entry",
"fieldname": "reference_type",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Journal Entry",
"in_list_view": 0,
"label": "Reference Type",
"length": 0,
"no_copy": 1,
"oldfieldname": "journal_voucher",
"oldfieldtype": "Link",
"options": "Journal Entry",
"options": "DocType",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "250px",
"read_only": 1,
"report_hide": 0,
@ -38,10 +42,37 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "remarks",
"fieldtype": "Small Text",
"fieldname": "reference_name",
"fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Reference Name",
"length": 0,
"no_copy": 1,
"options": "reference_type",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "remarks",
"fieldtype": "Read Only",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Remarks",
@ -51,8 +82,9 @@
"oldfieldtype": "Small Text",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@ -64,19 +96,21 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "jv_detail_no",
"fieldname": "reference_row",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Journal Entry Detail No",
"label": "Reference Row",
"length": 0,
"no_copy": 1,
"oldfieldname": "jv_detail_no",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"print_width": "120px",
"read_only": 1,
"report_hide": 0,
@ -94,12 +128,14 @@
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
@ -115,6 +151,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Advance amount",
@ -125,6 +162,7 @@
"options": "party_account_currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "120px",
"read_only": 1,
"report_hide": 0,
@ -142,6 +180,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Allocated amount",
@ -152,6 +191,7 @@
"options": "party_account_currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "120px",
"read_only": 0,
"report_hide": 0,
@ -165,18 +205,24 @@
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2015-11-16 06:29:56.263776",
"menu_index": 0,
"modified": "2016-06-27 12:38:58.845134",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Advance",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0
"read_only_onload": 0,
"sort_order": "DESC",
"track_seen": 0,
"version": 0
}

View File

@ -172,28 +172,33 @@ def reconcile_against_document(args):
Cancel JV, Update aginst document, split if required and resubmit jv
"""
for d in args:
check_if_jv_modified(d)
check_if_advance_entry_modified(d)
validate_allocated_amount(d)
# cancel JV
jv_obj = frappe.get_doc('Journal Entry', d['voucher_no'])
# cancel advance entry
doc = frappe.get_doc(d.voucher_type, d.voucher_no)
jv_obj.make_gl_entries(cancel=1, adv_adj=1)
doc.make_gl_entries(cancel=1, adv_adj=1)
# update ref in JV Detail
update_against_doc(d, jv_obj)
# update ref in advance entry
if d.voucher_type == "Journal Entry":
update_reference_in_journal_entry(d, doc)
else:
update_reference_in_payment_entry(d, doc)
# re-submit JV
jv_obj = frappe.get_doc('Journal Entry', d['voucher_no'])
jv_obj.make_gl_entries(cancel = 0, adv_adj =1)
# re-submit advance entry
doc = frappe.get_doc(d.voucher_type, d.voucher_no)
doc.make_gl_entries(cancel = 0, adv_adj =1)
def check_if_jv_modified(args):
def check_if_advance_entry_modified(args):
"""
check if there is already a voucher reference
check if amount is same
check if jv is submitted
"""
ret = None
if args.voucher_type == "Journal Entry":
ret = frappe.db.sql("""
select t2.{dr_or_cr} from `tabJournal Entry` t1, `tabJournal Entry Account` t2
where t1.name = t2.parent and t2.account = %(account)s
@ -201,24 +206,43 @@ def check_if_jv_modified(args):
and (t2.reference_type is null or t2.reference_type in ("", "Sales Order", "Purchase Order"))
and t1.name = %(voucher_no)s and t2.name = %(voucher_detail_no)s
and t1.docstatus=1 """.format(dr_or_cr = args.get("dr_or_cr")), args)
else:
party_account_field = "paid_from" if args.party_type == "Customer" else "paid_to"
if args.voucher_detail_no:
ret = frappe.db.sql("""select t1.name
from `tabPayment Entry` t1, `tabPayment Entry Reference` t2
where
t1.name = t2.parent and t1.docstatus = 1
and t1.name = %(voucher_no)s and t2.name = %(voucher_detail_no)s
and t1.party_type = %(party_type)s and t1.party = %(party)s and t1.{0} = %(account)s
and t2.reference_doctype in ("", "Sales Order", "Purchase Order")
and t2.allocated_amount = %(unadjusted_amount)s
""".format(party_account_field), args)
else:
ret = frappe.db.sql("""select name from `tabPayment Entry`
where
name = %(voucher_no)s and docstatus = 1
and party_type = %(party_type)s and party = %(party)s and {0} = %(account)s
and unallocated_amount = %(unadjusted_amount)s
""".format(party_account_field), args)
if not ret:
throw(_("""Payment Entry has been modified after you pulled it. Please pull it again."""))
def validate_allocated_amount(args):
if args.get("allocated_amt") < 0:
if args.get("allocated_amount") < 0:
throw(_("Allocated amount can not be negative"))
elif args.get("allocated_amt") > args.get("unadjusted_amt"):
throw(_("Allocated amount can not greater than unadusted amount"))
elif args.get("allocated_amount") > args.get("unadjusted_amount"):
throw(_("Allocated amount can not greater than unadjusted amount"))
def update_against_doc(d, jv_obj):
def update_reference_in_journal_entry(d, jv_obj):
"""
Updates against document, if partial amount splits into rows
"""
jv_detail = jv_obj.get("accounts", {"name": d["voucher_detail_no"]})[0]
jv_detail.set(d["dr_or_cr"], d["allocated_amt"])
jv_detail.set(d["dr_or_cr"], d["allocated_amount"])
jv_detail.set('debit' if d['dr_or_cr']=='debit_in_account_currency' else 'credit',
d["allocated_amt"]*flt(jv_detail.exchange_rate))
d["allocated_amount"]*flt(jv_detail.exchange_rate))
original_reference_type = jv_detail.reference_type
original_reference_name = jv_detail.reference_name
@ -226,14 +250,14 @@ def update_against_doc(d, jv_obj):
jv_detail.set("reference_type", d["against_voucher_type"])
jv_detail.set("reference_name", d["against_voucher"])
if d['allocated_amt'] < d['unadjusted_amt']:
if d['allocated_amount'] < d['unadjusted_amount']:
jvd = frappe.db.sql("""
select cost_center, balance, against_account, is_advance,
account_type, exchange_rate, account_currency
from `tabJournal Entry Account` where name = %s
""", d['voucher_detail_no'], as_dict=True)
amount_in_account_currency = flt(d['unadjusted_amt']) - flt(d['allocated_amt'])
amount_in_account_currency = flt(d['unadjusted_amount']) - flt(d['allocated_amount'])
amount_in_company_currency = amount_in_account_currency * flt(jvd[0]['exchange_rate'])
# new entry with balance amount
@ -264,6 +288,37 @@ def update_against_doc(d, jv_obj):
jv_obj.flags.ignore_validate_update_after_submit = True
jv_obj.save(ignore_permissions=True)
def update_reference_in_payment_entry(d, payment_entry):
reference_details = {
"reference_doctype": d.against_voucher_type,
"reference_name": d.against_voucher,
"total_amount": d.grand_total,
"outstanding_amount": d.outstanding_amount,
"allocated_amount": d.allocated_amount,
"exchange_rate": d.exchange_rate
}
if d.voucher_detail_no:
existing_row = payment_entry.get("references", {"name": d["voucher_detail_no"]})[0]
original_row = existing_row.as_dict().copy()
existing_row.update(reference_details)
if d.allocated_amount < original_row.allocated_amount:
new_row = payment_entry.append("references")
new_row.docstatus = 1
for field in reference_details.keys():
new_row.set(field, original_row[field])
new_row.allocated_amount = original_row.allocated_amount - d.allocated_amount
else:
new_row = payment_entry.append("references")
new_row.docstatus = 1
new_row.update(reference_details)
payment_entry.flags.ignore_validate_update_after_submit = True
payment_entry.set_amounts()
payment_entry.save(ignore_permissions=True)
def remove_against_link_from_jv(ref_type, ref_no):
linked_jv = frappe.db.sql_list("""select parent from `tabJournal Entry Account`
where reference_type=%s and reference_name=%s and docstatus < 2""", (ref_type, ref_no))
@ -425,10 +480,9 @@ def get_outstanding_invoices(party_type, party, account, condition=None):
'payment_amount': flt(d.payment_amount),
'outstanding_amount': flt(d.invoice_amount - d.payment_amount, precision),
'due_date': frappe.db.get_value(d.voucher_type, d.voucher_no, "due_date"),
'exchange_rate': frappe.db.get_value(d.voucher_type, d.voucher_no, "conversion_rate")
})
outstanding_invoices = sorted(outstanding_invoices, key=lambda k: k['due_date'])
outstanding_invoices = sorted(outstanding_invoices, key=lambda k: k['due_date'] or getdate(nowdate()))
return outstanding_invoices

View File

@ -308,7 +308,7 @@ def make_purchase_invoice(source_name, target_doc=None):
def postprocess(source, target):
set_missing_values(source, target)
#Get the advance paid Journal Entries in Purchase Invoice Advance
target.get_advances()
target.set_advances()
def update_item(obj, target, source_parent):
target.amount = flt(obj.amount) - flt(obj.billed_amt)

View File

@ -42,6 +42,7 @@ class AccountsController(TransactionBase):
if self.doctype in ("Sales Invoice", "Purchase Invoice") and not self.is_return:
self.validate_due_date()
self.validate_advance_entries()
if self.meta.get_field("taxes_and_charges"):
self.validate_enabled_taxes_and_charges()
@ -276,22 +277,69 @@ class AccountsController(TransactionBase):
frappe.db.sql("""delete from `tab%s` where parentfield=%s and parent = %s
and allocated_amount = 0""" % (childtype, '%s', '%s'), (parentfield, self.name))
def get_advances(self, account_head, party_type, party, child_doctype, parentfield, dr_or_cr, against_order_field):
def set_advances(self):
"""Returns list of advances against Account, Party, Reference"""
order_list = list(set([d.get(against_order_field) for d in self.get("items") if d.get(against_order_field)]))
# conver sales_order to "Sales Order"
reference_type = against_order_field.replace("_", " ").title()
res = self.get_advance_entries()
self.set("advances", [])
for d in res:
self.append("advances", {
"doctype": self.doctype + " Advance",
"reference_type": d.reference_type,
"reference_name": d.reference_name,
"reference_row": d.reference_row,
"remarks": d.remarks,
"advance_amount": flt(d.amount),
"allocated_amount": flt(d.amount) if d.against_order else 0
})
def get_advance_entries(self, include_unallocated=True):
if self.doctype == "Sales Invoice":
party_account = self.debit_to
party_type = "Customer"
party = self.customer
amount_field = "credit_in_account_currency"
order_field = "sales_order"
order_doctype = "Sales Order"
else:
party_account = self.credit_to
party_type = "Supplier"
party = self.supplier
amount_field = "debit_in_account_currency"
order_field = "purchase_order"
order_doctype = "Purchase Order"
order_list = list(set([d.get(order_field)
for d in self.get("items") if d.get(order_field)]))
journal_entries = self.get_advance_journal_entries(party_type, party, party_account,
amount_field, order_doctype, order_list, include_unallocated)
payment_entries = self.get_advance_payment_entries(party_type, party, party_account,
order_doctype, order_list, include_unallocated)
res = journal_entries + payment_entries
return res
def get_advance_journal_entries(self, party_type, party, party_account, amount_field,
order_doctype, order_list, include_unallocated=True):
conditions = []
if include_unallocated:
conditions.append("ifnull(t2.reference_name, '')=''")
condition = ""
if order_list:
in_placeholder = ', '.join(['%s'] * len(order_list))
condition = "or (t2.reference_type = '{0}' and ifnull(t2.reference_name, '') in ({1}))"\
.format(reference_type, in_placeholder)
order_condition = ', '.join(['%s'] * len(order_list))
conditions.append(" (t2.reference_type = '{0}' and ifnull(t2.reference_name, '') in ({1}))"\
.format(order_doctype, order_condition))
res = frappe.db.sql("""
reference_condition = " and (" + " or ".join(conditions) + ")" if conditions else ""
journal_entries = frappe.db.sql("""
select
t1.name as jv_no, t1.remark, t2.{0} as amount, t2.name as jv_detail_no,
"Journal Entry" as reference_type, t1.name as reference_name,
t1.remark as remarks, t2.{0} as amount, t2.name as reference_row,
t2.reference_name as against_order
from
`tabJournal Entry` t1, `tabJournal Entry Account` t2
@ -299,48 +347,98 @@ class AccountsController(TransactionBase):
t1.name = t2.parent and t2.account = %s
and t2.party_type = %s and t2.party = %s
and t2.is_advance = 'Yes' and t1.docstatus = 1
and (ifnull(t2.reference_type, '')='' {1})
order by t1.posting_date""".format(dr_or_cr, condition),
[account_head, party_type, party] + order_list, as_dict=1)
and (ifnull(t2.reference_name, '')='' {1})
order by t1.posting_date""".format(amount_field, reference_condition),
[party_account, party_type, party] + order_list, as_dict=1)
self.set(parentfield, [])
for d in res:
self.append(parentfield, {
"doctype": child_doctype,
"journal_entry": d.jv_no,
"jv_detail_no": d.jv_detail_no,
"remarks": d.remark,
"advance_amount": flt(d.amount),
"allocated_amount": flt(d.amount) if d.against_order else 0
})
return list(journal_entries)
def get_advance_payment_entries(self, party_type, party, party_account,
order_doctype, order_list, include_unallocated=True):
party_account_field = "paid_from" if party_type == "Customer" else "paid_to"
payment_type = "Receive" if party_type == "Customer" else "Pay"
payment_entries_against_order, unallocated_payment_entries = [], []
def validate_advance_jv(self, reference_type):
against_order_field = frappe.scrub(reference_type)
order_list = list(set([d.get(against_order_field) for d in self.get("items") if d.get(against_order_field)]))
if order_list:
account = self.get("debit_to" if self.doctype=="Sales Invoice" else "credit_to")
payment_entries_against_order = frappe.db.sql("""
select
"Payment Entry" as reference_type, t1.name as reference_name,
t1.remarks, t2.allocated_amount as amount, t2.name as reference_row,
t2.reference_name as against_order
from `tabPayment Entry` t1, `tabPayment Entry Reference` t2
where
t1.name = t2.parent and t1.{0} = %s and t1.payment_type = %s
and t1.party_type = %s and t1.party = %s and t1.docstatus = 1
and t2.reference_doctype = %s and t2.reference_name in ({1})
""".format(party_account_field, ', '.join(['%s'] * len(order_list))),
[party_account, payment_type, party_type, party, order_doctype] + order_list, as_dict=1)
jv_against_order = frappe.db.sql("""select parent, reference_name as against_order
from `tabJournal Entry Account`
where docstatus=1 and account=%s and ifnull(is_advance, 'No') = 'Yes'
and reference_type=%s
and ifnull(reference_name, '') in ({0})
group by parent, reference_name""".format(', '.join(['%s']*len(order_list))),
tuple([account, reference_type] + order_list), as_dict=1)
if include_unallocated:
unallocated_payment_entries = frappe.db.sql("""
select "Payment Entry" as reference_type, name as reference_name,
remarks, unallocated_amount as amount
from `tabPayment Entry`
where
{0} = %s and party_type = %s and party = %s and payment_type = %s
and docstatus = 1 and unallocated_amount > 0
""".format(party_account_field), (party_account, party_type, party, payment_type), 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)
return list(payment_entries_against_order) + list(unallocated_payment_entries)
advance_jv_against_si = [d.journal_entry for d in self.get("advances")]
def validate_advance_entries(self):
advance_entries = self.get_advance_entries(include_unallocated=False)
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.msgprint(_("Journal Entry {0} is linked against Order {1}, check if it should be pulled as advance in this invoice.")
.format(jv, order))
if advance_entries:
advance_entries_against_si = [d.reference_name for d in self.get("advances")]
for d in advance_entries:
if not advance_entries_against_si or d.reference_name not in advance_entries_against_si:
frappe.msgprint(_("Payment Entry {0} is linked against Order {1}, check if it should be pulled as advance in this invoice.")
.format(d.reference_name, d.against_order))
def update_against_document_in_jv(self):
"""
Links invoice and advance voucher:
1. cancel advance voucher
2. split into multiple rows if partially adjusted, assign against voucher
3. submit advance voucher
"""
if self.doctype == "Sales Invoice":
party = self.customer
party_account = self.debit_to
dr_or_cr = "credit_in_account_currency"
else:
party = self.supplier
party_account = self.credit_to
dr_or_cr = "debit_in_account_currency"
lst = []
for d in self.get('advances'):
if flt(d.allocated_amount) > 0:
args = frappe._dict({
'voucher_type': d.reference_type,
'voucher_no' : d.reference_name,
'voucher_detail_no' : d.reference_row,
'against_voucher_type' : self.doctype,
'against_voucher' : self.name,
'account' : party_account,
'party_type': 'Customer',
'party': party,
'is_advance' : 'Yes',
'dr_or_cr' : dr_or_cr,
'unadjusted_amount' : flt(d.advance_amount),
'allocated_amount' : flt(d.allocated_amount),
'exchange_rate': (self.conversion_rate
if self.party_account_currency != self.company_currency else 1),
'grand_total': (self.base_grand_total
if self.party_account_currency==self.company_currency else self.grand_total),
'outstanding_amount': self.outstanding_amount
})
lst.append(args)
if lst:
from erpnext.accounts.utils import reconcile_against_document
reconcile_against_document(lst)
def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield):
from erpnext.controllers.status_updater import get_tolerance_for

View File

@ -5,6 +5,9 @@ from __future__ import unicode_literals
import frappe
def execute():
frappe.reload_doctype("Sales Invoice Advance")
frappe.reload_doctype("Purchase Invoice Advance")
je_rows = frappe.db.sql("""
select name, parent, reference_type, reference_name, debit, credit
from `tabJournal Entry Account`
@ -23,7 +26,7 @@ def execute():
is_advance_entry=None
if d.reference_type in ("Sales Invoice", "Purchase Invoice") and d.reference_name:
is_advance_entry = frappe.db.sql("""select name from `tab{0}`
where journal_entry=%s and jv_detail_no=%s
where reference_name=%s and reference_row=%s
and ifnull(allocated_amount, 0) > 0 and docstatus=1"""
.format(d.reference_type + " Advance"), (d.parent, d.name))

View File

@ -4,6 +4,16 @@
erpnext.TransactionController = erpnext.taxes_and_totals.extend({
setup: function() {
this._super();
if(in_list(["Sales Invoice", "Purchase Invoice"], this.frm.doc.doctype)) {
this.frm.get_field('advances').grid.editable_fields = [
{fieldname: 'reference_name', columns: 2},
{fieldname: 'remarks', columns: 3},
{fieldname: 'advance_amount', columns: 3},
{fieldname: 'allocated_amount', columns: 3}
];
}
frappe.ui.form.on(this.frm.doctype + " Item", "rate", function(frm, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
frappe.model.round_floats_in(item, ["rate", "price_list_rate"]);
@ -978,5 +988,17 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
if(!this.item_selector) {
this.item_selector = new erpnext.ItemSelector({frm: this.frm});
}
},
get_advances: function() {
if(!this.frm.is_return) {
return this.frm.call({
method: "set_advances",
doc: this.frm.doc,
callback: function(r, rt) {
refresh_field("advances");
}
})
}
}
});

View File

@ -441,7 +441,7 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False):
def postprocess(source, target):
set_missing_values(source, target)
#Get the advance paid Journal Entries in Sales Invoice Advance
target.get_advances()
target.set_advances()
def set_missing_values(source, target):
target.is_pos = 0