payment entry improvements and deletion of payment tool

This commit is contained in:
Nabin Hait 2016-07-14 14:39:16 +05:30
parent 4f5f8d7806
commit 6831b9422b
12 changed files with 9 additions and 1424 deletions

View File

@ -9,6 +9,7 @@
"docstatus": 0,
"doctype": "DocType",
"document_type": "Other",
"editable_grid": 1,
"fields": [
{
"allow_on_submit": 0,
@ -111,31 +112,6 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "allow_payment_entry_via_journal_entry",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Allow Payment Entry via Journal Entry",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@ -199,7 +175,7 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2016-06-27 15:18:28.566087",
"modified": "2016-07-14 14:32:06.056888",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",

View File

@ -36,6 +36,7 @@ class PaymentEntry(AccountsController):
def validate(self):
self.setup_party_account_field()
self.set_missing_values()
self.validate_payment_type()
self.validate_party_details()
self.validate_bank_accounts()
self.set_exchange_rate()
@ -108,6 +109,10 @@ class PaymentEntry(AccountsController):
for field, value in ref_details.items():
if not d.get(field):
d.set(field, value)
def validate_payment_type(self):
if self.payment_type not in ("Receive", "Pay", "Internal Transfer"):
frappe.throw(_("Payment Type must be one of Receive, Pay and Internal Transfer"))
def validate_party_details(self):
if self.party:

View File

@ -1,274 +0,0 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// For license information, please see license.txt
frappe.provide("erpnext.payment_tool");
// Help content
frappe.ui.form.on("Payment Tool", "onload", function(frm) {
frm.set_value("make_jv_help",
+ __("Note: If payment is not made against any reference, make Journal Entry manually."));
frm.set_query("party_type", function() {
return {
filters: {"name": ["in", ["Customer", "Supplier"]]}
};
});
frm.set_query("payment_account", function() {
return {
filters: {
"account_type": ["in", ["Bank", "Cash"]],
"is_group": 0,
"company": frm.doc.company
}
}
});
frm.set_query("against_voucher_type", "vouchers", function() {
if (frm.doc.party_type=="Customer") {
var doctypes = ["Sales Order", "Sales Invoice", "Journal Entry"];
} else {
var doctypes = ["Purchase Order", "Purchase Invoice", "Journal Entry"];
}
return {
filters: { "name": ["in", doctypes] }
};
});
});
frappe.ui.form.on("Payment Tool", "refresh", function(frm) {
frm.disable_save();
frappe.ui.form.trigger("Payment Tool", "party_type");
});
frappe.ui.form.on("Payment Tool", "party_type", function(frm) {
frm.set_value("received_or_paid", frm.doc.party_type=="Customer" ? "Received" : "Paid");
});
frappe.ui.form.on("Payment Tool", "party", function(frm) {
if(frm.doc.party_type && frm.doc.party) {
return frappe.call({
method: "erpnext.accounts.party.get_party_account",
args: {
company: frm.doc.company,
party_type: frm.doc.party_type,
party: frm.doc.party
},
callback: function(r) {
if(!r.exc && r.message) {
frm.set_value("party_account", r.message);
erpnext.payment_tool.check_mandatory_to_set_button(frm);
}
}
});
}
})
frappe.ui.form.on("Payment Tool", "party_account", function(frm) {
if(frm.doc.party_account) {
frm.call({
method: "frappe.client.get_value",
args: {
doctype: "Account",
fieldname: "account_currency",
filters: { name: frm.doc.party_account },
},
callback: function(r, rt) {
if(r.message) {
frm.set_value("party_account_currency", r.message.account_currency);
erpnext.payment_tool.check_mandatory_to_set_button(frm);
}
}
});
}
})
frappe.ui.form.on("Payment Tool", "company", function(frm) {
erpnext.payment_tool.check_mandatory_to_set_button(frm);
});
frappe.ui.form.on("Payment Tool", "received_or_paid", function(frm) {
erpnext.payment_tool.check_mandatory_to_set_button(frm);
});
// Fetch bank/cash account based on payment mode
frappe.ui.form.on("Payment Tool", "payment_mode", function(frm) {
return frappe.call({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.get_bank_cash_account",
args: {
"mode_of_payment": frm.doc.payment_mode,
"company": frm.doc.company
},
callback: function(r, rt) {
if(r.message) {
cur_frm.set_value("payment_account", r.message['account']);
}
}
});
});
erpnext.payment_tool.check_mandatory_to_set_button = function(frm) {
if (frm.doc.company && frm.doc.party_type && frm.doc.party && frm.doc.received_or_paid && frm.doc.party_account) {
frm.fields_dict.get_outstanding_vouchers.$input.addClass("btn-primary");
}
}
// Get outstanding vouchers
frappe.ui.form.on("Payment Tool", "get_outstanding_vouchers", function(frm) {
erpnext.payment_tool.check_mandatory_to_fetch(frm.doc);
frm.set_value("vouchers", []);
return frappe.call({
method: 'erpnext.accounts.doctype.payment_tool.payment_tool.get_outstanding_vouchers',
args: {
args: {
"company": frm.doc.company,
"party_type": frm.doc.party_type,
"received_or_paid": frm.doc.received_or_paid,
"party": frm.doc.party,
"party_account": frm.doc.party_account
}
},
callback: function(r, rt) {
if(r.message) {
frm.fields_dict.get_outstanding_vouchers.$input.removeClass("btn-primary");
frm.fields_dict.make_journal_entry.$input.addClass("btn-primary");
frm.clear_table("vouchers");
$.each(r.message, function(i, d) {
var c = frm.add_child("vouchers");
c.against_voucher_type = d.voucher_type;
c.against_voucher_no = d.voucher_no;
c.total_amount = d.invoice_amount;
c.outstanding_amount = d.outstanding_amount;
if (in_list(['Sales Invoice', 'Purchase Invoice'], d.voucher_type)){
c.due_date = d.due_date
}
if (frm.doc.set_payment_amount) {
c.payment_amount = d.outstanding_amount;
}
});
}
refresh_field("vouchers");
frm.layout.refresh_sections();
erpnext.payment_tool.set_total_payment_amount(frm);
}
});
});
// validate against_voucher_type
frappe.ui.form.on("Payment Tool Detail", "against_voucher_type", function(frm, cdt, cdn) {
var row = frappe.model.get_doc(cdt, cdn);
erpnext.payment_tool.validate_against_voucher(frm, row);
});
erpnext.payment_tool.validate_against_voucher = function(frm, row) {
var _validate = function(i, row) {
if (!row.against_voucher_type) {
return;
}
if(frm.doc.party_type=="Customer"
&& !in_list(["Sales Order", "Sales Invoice", "Journal Entry"], row.against_voucher_type)) {
frappe.model.set_value(row.doctype, row.name, "against_voucher_type", "");
frappe.msgprint(__("Against Voucher Type must be one of Sales Order, Sales Invoice or Journal Entry"));
return false;
}
if(frm.doc.party_type=="Supplier"
&& !in_list(["Purchase Order", "Purchase Invoice", "Journal Entry"], row.against_voucher_type)) {
frappe.model.set_value(row.doctype, row.name, "against_voucher_type", "");
frappe.msgprint(__("Against Voucher Type must be one of Purchase Order, Purchase Invoice or Journal Entry"));
return false;
}
}
if (row) {
_validate(0, row);
} else {
$.each(frm.doc.vouchers || [], _validate);
}
}
// validate against_voucher_type
frappe.ui.form.on("Payment Tool Detail", "against_voucher_no", function(frm, cdt, cdn) {
var row = locals[cdt][cdn];
if (!row.against_voucher_no) {
return;
}
frappe.call({
method: 'erpnext.accounts.doctype.payment_tool.payment_tool.get_against_voucher_details',
args: {
"against_voucher_type": row.against_voucher_type,
"against_voucher_no": row.against_voucher_no,
"party_account": frm.doc.party_account,
"company": frm.doc.company
},
callback: function(r) {
if(!r.exc) {
$.each(r.message, function(k, v) {
frappe.model.set_value(cdt, cdn, k, v);
});
frappe.model.set_value(cdt, cdn, "payment_amount", r.message.outstanding_amount);
}
}
});
});
// Set total payment amount
frappe.ui.form.on("Payment Tool Detail", "payment_amount", function(frm) {
erpnext.payment_tool.set_total_payment_amount(frm);
});
frappe.ui.form.on("Payment Tool Detail", "vouchers_remove", function(frm) {
erpnext.payment_tool.set_total_payment_amount(frm);
});
erpnext.payment_tool.set_total_payment_amount = function(frm) {
var total_amount = 0.00;
$.each(frm.doc.vouchers || [], function(i, row) {
if (row.payment_amount && (row.payment_amount <= row.outstanding_amount)) {
total_amount = total_amount + row.payment_amount;
} else {
if(row.payment_amount < 0)
msgprint(__("Row {0}: Payment amount can not be negative", [row.idx]));
else if(row.payment_amount > row.outstanding_amount)
msgprint(__("Row {0}: Payment Amount cannot be greater than Outstanding Amount", [__(row.idx)]));
frappe.model.set_value(row.doctype, row.name, "payment_amount", 0.0);
}
});
frm.set_value("total_payment_amount", total_amount);
}
// Make Journal Entry
frappe.ui.form.on("Payment Tool", "make_journal_entry", function(frm) {
erpnext.payment_tool.check_mandatory_to_fetch(frm.doc);
return frappe.call({
method: 'make_journal_entry',
doc: frm.doc,
callback: function(r) {
frm.fields_dict.make_journal_entry.$input.addClass("btn-primary");
var doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
}
});
});
erpnext.payment_tool.check_mandatory_to_fetch = function(doc) {
$.each(["Company", "Party Type", "Party", "Received or Paid"], function(i, field) {
if(!doc[frappe.model.scrub(field)]) frappe.throw(__("Please select {0} first", [field]));
});
}

View File

@ -1,551 +0,0 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"creation": "2014-07-23 15:12:27.746665",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "sec_break1",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Find Invoices to Match",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Company",
"no_copy": 0,
"options": "Company",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"default": "Customer",
"fieldname": "party_type",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Party Type",
"no_copy": 0,
"options": "DocType",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "received_or_paid",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Received Or Paid",
"no_copy": 0,
"options": "Received\nPaid",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "col_break1",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "",
"fieldname": "party",
"fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Party",
"no_copy": 0,
"options": "party_type",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "party_account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Party Account",
"no_copy": 1,
"options": "Account",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "party_account_currency",
"fieldtype": "Link",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Party Account Currency",
"no_copy": 1,
"options": "Currency",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "set_payment_amount",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Set Payment Amount = Outstanding Amount",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "get_outstanding_vouchers",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Get Outstanding Vouchers",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "eval:(doc.company && doc.party_type && doc.received_or_paid && doc.party_account)",
"fieldname": "sec_break3",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Set Matching Amounts",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "vouchers",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Against Vouchers",
"no_copy": 0,
"options": "Payment Tool Detail",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "eval:(doc.company && doc.party_type && doc.received_or_paid && doc.party_account)",
"fieldname": "section_break_19",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Make Payment Entry",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "payment_mode",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Payment Mode",
"no_copy": 0,
"options": "Mode of Payment",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "payment_account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Payment Account",
"no_copy": 0,
"options": "Account",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "total_payment_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Total Payment Amount",
"no_copy": 0,
"options": "party_account_currency",
"permlevel": 0,
"print_hide": 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": "data_22",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "reference_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Reference Date",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "reference_no",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Reference No",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "make_journal_entry",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Make Journal Entry",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "eval:(doc.company && doc.party_type && doc.received_or_paid && doc.party_account)",
"fieldname": "section_break_21",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "make_jv_help",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 1,
"icon": "icon-magic",
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"modified": "2015-10-01 09:43:24.199025",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Tool",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Accounts User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@ -1,170 +0,0 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _, scrub
from frappe.utils import flt
from frappe.model.document import Document
import json
from erpnext.accounts.utils import get_account_currency
from erpnext.accounts.doctype.journal_entry.journal_entry import get_exchange_rate
class PaymentTool(Document):
def make_journal_entry(self):
from erpnext.accounts.utils import get_balance_on
total_payment_amount = 0.00
jv = frappe.new_doc('Journal Entry')
jv.voucher_type = 'Journal Entry'
jv.company = self.company
jv.cheque_no = self.reference_no
jv.cheque_date = self.reference_date
party_account_currency, party_account_type = frappe.db.get_value("Account", self.party_account,
["account_currency", "account_type"])
bank_account_currency, bank_account_type = None, None
if self.payment_account:
bank_account_currency, bank_account_type = frappe.db.get_value("Account", self.payment_account,
["account_currency", "account_type"])
if not self.total_payment_amount:
frappe.throw(_("Please enter Payment Amount in atleast one row"))
for v in self.get("vouchers"):
if not frappe.db.get_value(v.against_voucher_type, {"name": v.against_voucher_no}):
frappe.throw(_("Row {0}: {1} is not a valid {2}").format(v.idx, v.against_voucher_no,
v.against_voucher_type))
if v.payment_amount:
exchange_rate = get_exchange_rate(self.party_account, party_account_currency,
self.company, v.against_voucher_type, v.against_voucher_no)
d1 = jv.append("accounts")
d1.account = self.party_account
d1.party_type = self.party_type
d1.party = self.party
d1.account_currency = party_account_currency
d1.account_type = party_account_type
d1.balance = get_balance_on(self.party_account)
d1.party_balance = get_balance_on(party=self.party, party_type=self.party_type)
d1.exchange_rate = exchange_rate
d1.set("debit_in_account_currency" if self.received_or_paid=="Paid" \
else "credit_in_account_currency", flt(v.payment_amount))
d1.reference_type = v.against_voucher_type
d1.reference_name = v.against_voucher_no
d1.is_advance = 'Yes' \
if v.against_voucher_type in ['Sales Order', 'Purchase Order'] else 'No'
amount = flt(d1.debit_in_account_currency) - flt(d1.credit_in_account_currency)
if bank_account_currency == party_account_currency:
total_payment_amount += amount
else:
total_payment_amount += amount*exchange_rate
d2 = jv.append("accounts")
if self.payment_account:
bank_account_currency, bank_account_type = frappe.db.get_value("Account", self.payment_account,
["account_currency", "account_type"])
d2.account = self.payment_account
d2.account_currency = bank_account_currency
d2.account_type = bank_account_type
d2.exchange_rate = get_exchange_rate(self.payment_account, bank_account_currency, self.company,
debit=(abs(total_payment_amount) if total_payment_amount < 0 else 0),
credit=(total_payment_amount if total_payment_amount > 0 else 0))
d2.account_balance = get_balance_on(self.payment_account)
amount_field_bank = 'debit_in_account_currency' if total_payment_amount < 0 \
else 'credit_in_account_currency'
d2.set(amount_field_bank, abs(total_payment_amount))
company_currency = frappe.db.get_value("Company", self.company, "default_currency")
if party_account_currency != company_currency or \
(bank_account_currency and bank_account_currency != company_currency):
jv.multi_currency = 1
jv.set_amounts_in_company_currency()
jv.set_total_debit_credit()
return jv.as_dict()
@frappe.whitelist()
def get_outstanding_vouchers(args):
from erpnext.accounts.utils import get_outstanding_invoices
if not frappe.has_permission("Payment Tool"):
frappe.throw(_("No permission to use Payment Tool"), frappe.PermissionError)
args = json.loads(args)
party_account_currency = get_account_currency(args.get("party_account"))
company_currency = frappe.db.get_value("Company", args.get("company"), "default_currency")
if ((args.get("party_type") == "Customer" and args.get("received_or_paid") == "Paid")
or (args.get("party_type") == "Supplier" and args.get("received_or_paid") == "Received")):
frappe.throw(_("Please enter the Against Vouchers manually"))
# Get all outstanding sales /purchase invoices
outstanding_invoices = get_outstanding_invoices(args.get("party_type"), args.get("party"), args.get("party_account"))
# 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)
return outstanding_invoices + orders_to_be_billed
def get_orders_to_be_billed(party_type, party, party_account_currency, company_currency):
voucher_type = 'Sales Order' if party_type == "Customer" else 'Purchase Order'
ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"
orders = frappe.db.sql("""
select
name as voucher_no,
{ref_field} as invoice_amount,
({ref_field} - advance_paid) as outstanding_amount,
transaction_date as posting_date
from
`tab{voucher_type}`
where
{party_type} = %s
and docstatus = 1
and ifnull(status, "") != "Closed"
and {ref_field} > advance_paid
and abs(100 - per_billed) > 0.01
""".format(**{
"ref_field": ref_field,
"voucher_type": voucher_type,
"party_type": scrub(party_type)
}), party, as_dict = True)
order_list = []
for d in orders:
d["voucher_type"] = voucher_type
order_list.append(d)
return order_list
@frappe.whitelist()
def get_against_voucher_details(against_voucher_type, against_voucher_no, party_account, company):
party_account_currency = get_account_currency(party_account)
company_currency = frappe.db.get_value("Company", company, "default_currency")
ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"
if against_voucher_type in ["Sales Order", "Purchase Order"]:
select_cond = "{0} as total_amount, {0} - advance_paid as outstanding_amount"\
.format(ref_field)
elif against_voucher_type in ["Sales Invoice", "Purchase Invoice"]:
select_cond = "{0} as total_amount, outstanding_amount".format(ref_field)
elif against_voucher_type == "Journal Entry":
ref_field = "total_debit" if party_account_currency == company_currency else "total_debit/exchange_rate"
select_cond = "{0} as total_amount".format(ref_field)
details = frappe.db.sql("""select {0} from `tab{1}` where name = %s"""
.format(select_cond, frappe.db.escape(against_voucher_type)), against_voucher_no, as_dict=1)
return details[0] if details else {}

View File

@ -1,175 +0,0 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import unittest, frappe, json
from frappe.utils import flt
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import test_records as si_test_records
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import test_records as pi_test_records
from erpnext.accounts.doctype.journal_entry.test_journal_entry import test_records as jv_test_records
test_dependencies = ["Item"]
class TestPaymentTool(unittest.TestCase):
def test_make_journal_entry(self):
self.clear_table_entries()
frappe.db.set_default("currency", "INR")
base_customer_jv = self.create_against_jv(jv_test_records[2], { "party": "_Test Customer 3"})
base_supplier_jv = self.create_against_jv(jv_test_records[1], { "party": "_Test Supplier 1"})
# Create SO with partial outstanding
so1 = make_sales_order(customer="_Test Customer 3", qty=10, rate=100)
self.create_against_jv(jv_test_records[0], {
"party": "_Test Customer 3",
"reference_type": "Sales Order",
"reference_name": so1.name,
"is_advance": "Yes"
})
#Create SO with no outstanding
so2 = make_sales_order(customer="_Test Customer 3")
self.create_against_jv(jv_test_records[0], {
"party": "_Test Customer 3",
"reference_type": "Sales Order",
"reference_name": so2.name,
"credit_in_account_currency": 1000,
"is_advance": "Yes"
})
# Purchase order
po = create_purchase_order(supplier="_Test Supplier 1")
#Create SI with partial outstanding
si1 = self.create_voucher(si_test_records[0], {
"customer": "_Test Customer 3",
"debit_to": "_Test Receivable - _TC"
})
self.create_against_jv(jv_test_records[0], {
"party": "_Test Customer 3",
"reference_type": si1.doctype,
"reference_name": si1.name
})
#Create SI with no outstanding
si2 = self.create_voucher(si_test_records[0], {
"customer": "_Test Customer 3",
"debit_to": "_Test Receivable - _TC"
})
self.create_against_jv(jv_test_records[0], {
"party": "_Test Customer 3",
"reference_type": si2.doctype,
"reference_name": si2.name,
"credit_in_account_currency": 561.80
})
pi = self.create_voucher(pi_test_records[0], {
"supplier": "_Test Supplier 1",
"credit_to": "_Test Payable - _TC"
})
#Create a dict containing properties and expected values
expected_outstanding = {
"Journal Entry" : [base_customer_jv.name, 400.00],
"Sales Invoice" : [si1.name, 161.80],
"Purchase Invoice" : [pi.name, 1512.30],
"Sales Order" : [so1.name, 600.00],
"Purchase Order" : [po.name, 5000.00]
}
args = {
"company": "_Test Company",
"party_type": "Customer",
"received_or_paid": "Received",
"party": "_Test Customer 3",
"party_account": "_Test Receivable - _TC",
"payment_mode": "Cheque",
"payment_account": "_Test Bank - _TC",
"reference_no": "123456",
"reference_date": "2013-02-14"
}
self.make_voucher_for_party(args, expected_outstanding)
args.update({
"party_type": "Supplier",
"received_or_paid": "Paid",
"party": "_Test Supplier 1",
"party_account": "_Test Payable - _TC"
})
expected_outstanding["Journal Entry"] = [base_supplier_jv.name, 400.00]
self.make_voucher_for_party(args, expected_outstanding)
def create_voucher(self, test_record, args):
doc = frappe.copy_doc(test_record)
doc.update(args)
doc.insert()
doc.submit()
return doc
def create_against_jv(self, test_record, args):
jv = frappe.copy_doc(test_record)
jv.get("accounts")[0].update(args)
if args.get("debit_in_account_currency"):
jv.get("accounts")[1].credit_in_account_currency = args["debit_in_account_currency"]
elif args.get("credit_in_account_currency"):
jv.get("accounts")[1].debit_in_account_currency = args["credit_in_account_currency"]
jv.insert()
jv.submit()
return jv
def make_voucher_for_party(self, args, expected_outstanding):
#Make Journal Entry for Party
payment_tool_doc = frappe.new_doc("Payment Tool")
for k, v in args.items():
payment_tool_doc.set(k, v)
self.check_outstanding_vouchers(payment_tool_doc, args, expected_outstanding)
def check_outstanding_vouchers(self, doc, args, expected_outstanding):
from erpnext.accounts.doctype.payment_tool.payment_tool import get_outstanding_vouchers
outstanding_entries = get_outstanding_vouchers(json.dumps(args))
for d in outstanding_entries:
self.assertEquals(flt(d.get("outstanding_amount"), 2),
expected_outstanding.get(d.get("voucher_type"))[1])
self.check_jv_entries(doc, outstanding_entries, expected_outstanding)
def check_jv_entries(self, paytool, outstanding_entries, expected_outstanding):
for e in outstanding_entries:
d1 = paytool.append("vouchers")
d1.against_voucher_type = e.get("voucher_type")
d1.against_voucher_no = e.get("voucher_no")
d1.total_amount = e.get("invoice_amount")
d1.outstanding_amount = e.get("outstanding_amount")
d1.payment_amount = 100.00
paytool.total_payment_amount = 300
new_jv = paytool.make_journal_entry()
for jv_entry in new_jv.get("accounts"):
if paytool.party_account == jv_entry.get("account") and paytool.party == jv_entry.get("party"):
self.assertEquals(100.00, jv_entry.get("debit_in_account_currency"
if paytool.party_type=="Supplier" else "credit_in_account_currency"))
self.assertEquals(jv_entry.reference_name,
expected_outstanding[jv_entry.reference_type][0])
self.assertEquals(new_jv.get("cheque_no"), paytool.reference_no)
self.assertEquals(new_jv.get("cheque_date"), paytool.reference_date)
def clear_table_entries(self):
frappe.db.sql("""delete from `tabGL Entry` where party in ("_Test Customer 3", "_Test Supplier 1")""")
frappe.db.sql("""delete from `tabSales Order` where customer = "_Test Customer 3" """)
frappe.db.sql("""delete from `tabSales Invoice` where customer = "_Test Customer 3" """)
frappe.db.sql("""delete from `tabPurchase Order` where supplier = "_Test Supplier 1" """)
frappe.db.sql("""delete from `tabPurchase Invoice` where supplier = "_Test Supplier 1" """)

View File

@ -1,213 +0,0 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2014-08-11 14:27:54.463897",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "against_voucher_type",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Against Voucher Type",
"length": 0,
"no_copy": 0,
"options": "DocType",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "",
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": ""
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "against_voucher_no",
"fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Against Voucher No",
"length": 0,
"no_copy": 0,
"options": "against_voucher_type",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "due_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Due Date",
"length": 0,
"no_copy": 0,
"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": "column_break_3",
"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,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "total_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Total Amount",
"length": 0,
"no_copy": 0,
"options": "party_account_currency",
"permlevel": 0,
"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": "outstanding_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Outstanding Amount",
"length": 0,
"no_copy": 0,
"options": "party_account_currency",
"permlevel": 0,
"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": "payment_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Payment Amount",
"length": 0,
"no_copy": 0,
"options": "party_account_currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-07-11 03:28:03.793149",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Tool Detail",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_seen": 0
}

View File

@ -1,9 +0,0 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class PaymentToolDetail(Document):
pass

View File

@ -129,11 +129,6 @@ def get_data():
{
"label": _("Banking and Payments"),
"items": [
{
"type": "doctype",
"name": "Payment Tool",
"description": _("Create Payment Entries against Orders or Invoices.")
},
{
"type": "doctype",
"label": _("Update Bank Transaction Dates"),

View File

@ -294,4 +294,5 @@ execute:frappe.delete_doc_if_exists("Report", "Customers Not Buying Since Long T
erpnext.patches.v7_0.make_is_group_fieldtype_as_check
execute:frappe.reload_doc('projects', 'doctype', 'timesheet', force=True)
execute:frappe.delete_doc_if_exists("Report", "Employee Holiday Attendance")
execute:frappe.delete_doc_if_exists("DocType", "Payment Tool")
execute:frappe.delete_doc_if_exists("DocType", "Payment Tool Detail")