Advance Payment Entry adjustment against Invoice
This commit is contained in:
parent
e3a10170f7
commit
28a0528ae4
@ -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(row.outstanding_amount >= amount) row.allocated_amount = amount;
|
||||
else row.allocated_amount = row.outstanding_amount;
|
||||
if(amount) {
|
||||
if(row.outstanding_amount >= amount) row.allocated_amount = amount;
|
||||
else row.allocated_amount = row.outstanding_amount;
|
||||
|
||||
amount -= flt(row.allocated_amount);
|
||||
amount -= flt(row.allocated_amount);
|
||||
}
|
||||
})
|
||||
frm.refresh_fields()
|
||||
frm.events.set_total_allocated_amount(frm);
|
||||
|
@ -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",
|
||||
|
@ -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)
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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:
|
||||
|
@ -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",
|
||||
|
@ -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([{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
@ -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) {
|
||||
|
@ -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",
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
@ -172,53 +172,77 @@ 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 = 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
|
||||
and t2.party_type = %(party_type)s and t2.party = %(party)s
|
||||
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)
|
||||
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
|
||||
and t2.party_type = %(party_type)s and t2.party = %(party)s
|
||||
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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user