Merge branch 'version-13-hotfix' into version-13-pre-release
This commit is contained in:
commit
42d72b55b8
@ -0,0 +1,197 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"creation": "2020-09-12 22:26:19.594367",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"document_type": "Setup",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"add_deduct_tax",
|
||||||
|
"charge_type",
|
||||||
|
"row_id",
|
||||||
|
"account_head",
|
||||||
|
"col_break_1",
|
||||||
|
"description",
|
||||||
|
"included_in_paid_amount",
|
||||||
|
"accounting_dimensions_section",
|
||||||
|
"cost_center",
|
||||||
|
"dimension_col_break",
|
||||||
|
"section_break_8",
|
||||||
|
"rate",
|
||||||
|
"section_break_9",
|
||||||
|
"currency",
|
||||||
|
"tax_amount",
|
||||||
|
"total",
|
||||||
|
"allocated_amount",
|
||||||
|
"column_break_13",
|
||||||
|
"base_tax_amount",
|
||||||
|
"base_total",
|
||||||
|
"base_allocated_amount"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"columns": 2,
|
||||||
|
"fieldname": "charge_type",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Type",
|
||||||
|
"oldfieldname": "charge_type",
|
||||||
|
"oldfieldtype": "Select",
|
||||||
|
"options": "\nActual\nOn Paid Amount\nOn Previous Row Amount\nOn Previous Row Total",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:[\"On Previous Row Amount\", \"On Previous Row Total\"].indexOf(doc.charge_type)!==-1",
|
||||||
|
"fieldname": "row_id",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Reference Row #",
|
||||||
|
"oldfieldname": "row_id",
|
||||||
|
"oldfieldtype": "Data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": 2,
|
||||||
|
"fieldname": "account_head",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Account Head",
|
||||||
|
"oldfieldname": "account_head",
|
||||||
|
"oldfieldtype": "Link",
|
||||||
|
"options": "Account",
|
||||||
|
"reqd": 1,
|
||||||
|
"search_index": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "col_break_1",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"width": "50%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "description",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Description",
|
||||||
|
"oldfieldname": "description",
|
||||||
|
"oldfieldtype": "Small Text",
|
||||||
|
"print_width": "300px",
|
||||||
|
"reqd": 1,
|
||||||
|
"width": "300px"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "accounting_dimensions_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Accounting Dimensions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": ":Company",
|
||||||
|
"fieldname": "cost_center",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Cost Center",
|
||||||
|
"oldfieldname": "cost_center_other_charges",
|
||||||
|
"oldfieldtype": "Link",
|
||||||
|
"options": "Cost Center"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "dimension_col_break",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_8",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": 2,
|
||||||
|
"fieldname": "rate",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Rate",
|
||||||
|
"oldfieldname": "rate",
|
||||||
|
"oldfieldtype": "Currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_9",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": 2,
|
||||||
|
"fieldname": "tax_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Amount",
|
||||||
|
"options": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": 2,
|
||||||
|
"fieldname": "total",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Total",
|
||||||
|
"options": "currency",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_13",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "base_tax_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Amount (Company Currency)",
|
||||||
|
"oldfieldname": "tax_amount",
|
||||||
|
"oldfieldtype": "Currency",
|
||||||
|
"options": "Company:company:default_currency",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "base_total",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Total (Company Currency)",
|
||||||
|
"oldfieldname": "total",
|
||||||
|
"oldfieldtype": "Currency",
|
||||||
|
"options": "Company:company:default_currency",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "add_deduct_tax",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"label": "Add Or Deduct",
|
||||||
|
"options": "Add\nDeduct",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "included_in_paid_amount",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Considered In Paid Amount"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "allocated_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Allocated Amount",
|
||||||
|
"options": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "base_allocated_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Allocated Amount (Company Currency)",
|
||||||
|
"options": "Company:company:default_currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "account_head.account_currency",
|
||||||
|
"fieldname": "currency",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Account Currency",
|
||||||
|
"options": "Currency",
|
||||||
|
"read_only": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"istable": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2021-06-09 11:46:58.373170",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Advance Taxes and Charges",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "ASC"
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
# import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
class AdvanceTaxesandCharges(Document):
|
||||||
|
pass
|
@ -3,6 +3,8 @@
|
|||||||
{% include "erpnext/public/js/controllers/accounts.js" %}
|
{% include "erpnext/public/js/controllers/accounts.js" %}
|
||||||
frappe.provide("erpnext.accounts.dimensions");
|
frappe.provide("erpnext.accounts.dimensions");
|
||||||
|
|
||||||
|
cur_frm.cscript.tax_table = "Advance Taxes and Charges";
|
||||||
|
|
||||||
frappe.ui.form.on('Payment Entry', {
|
frappe.ui.form.on('Payment Entry', {
|
||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
if(frm.doc.__islocal) {
|
if(frm.doc.__islocal) {
|
||||||
@ -91,6 +93,16 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frm.set_query("advance_tax_account", function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
"company": frm.doc.company,
|
||||||
|
"root_type": ["in", ["Asset", "Liability"]],
|
||||||
|
"is_group": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
frm.set_query("reference_doctype", "references", function() {
|
frm.set_query("reference_doctype", "references", function() {
|
||||||
if (frm.doc.party_type == "Customer") {
|
if (frm.doc.party_type == "Customer") {
|
||||||
var doctypes = ["Sales Order", "Sales Invoice", "Journal Entry", "Dunning"];
|
var doctypes = ["Sales Order", "Sales Invoice", "Journal Entry", "Dunning"];
|
||||||
@ -182,6 +194,8 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency));
|
frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency));
|
||||||
|
|
||||||
frm.toggle_display("base_paid_amount", frm.doc.paid_from_account_currency != company_currency);
|
frm.toggle_display("base_paid_amount", frm.doc.paid_from_account_currency != company_currency);
|
||||||
|
frm.toggle_display("base_total_taxes_and_charges", frm.doc.total_taxes_and_charges &&
|
||||||
|
(frm.doc.paid_from_account_currency != company_currency));
|
||||||
|
|
||||||
frm.toggle_display("base_received_amount", (
|
frm.toggle_display("base_received_amount", (
|
||||||
frm.doc.paid_to_account_currency != company_currency
|
frm.doc.paid_to_account_currency != company_currency
|
||||||
@ -216,7 +230,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
var company_currency = frm.doc.company? frappe.get_doc(":Company", frm.doc.company).default_currency: "";
|
var company_currency = frm.doc.company? frappe.get_doc(":Company", frm.doc.company).default_currency: "";
|
||||||
|
|
||||||
frm.set_currency_labels(["base_paid_amount", "base_received_amount", "base_total_allocated_amount",
|
frm.set_currency_labels(["base_paid_amount", "base_received_amount", "base_total_allocated_amount",
|
||||||
"difference_amount"], company_currency);
|
"difference_amount", "base_paid_amount_after_tax", "base_received_amount_after_tax"], company_currency);
|
||||||
|
|
||||||
frm.set_currency_labels(["paid_amount"], frm.doc.paid_from_account_currency);
|
frm.set_currency_labels(["paid_amount"], frm.doc.paid_from_account_currency);
|
||||||
frm.set_currency_labels(["received_amount"], frm.doc.paid_to_account_currency);
|
frm.set_currency_labels(["received_amount"], frm.doc.paid_to_account_currency);
|
||||||
@ -224,11 +238,13 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
var party_account_currency = frm.doc.payment_type=="Receive" ?
|
var party_account_currency = frm.doc.payment_type=="Receive" ?
|
||||||
frm.doc.paid_from_account_currency : frm.doc.paid_to_account_currency;
|
frm.doc.paid_from_account_currency : frm.doc.paid_to_account_currency;
|
||||||
|
|
||||||
frm.set_currency_labels(["total_allocated_amount", "unallocated_amount"], party_account_currency);
|
frm.set_currency_labels(["total_allocated_amount", "unallocated_amount",
|
||||||
|
"total_taxes_and_charges"], party_account_currency);
|
||||||
|
|
||||||
var currency_field = (frm.doc.payment_type=="Receive") ? "paid_from_account_currency" : "paid_to_account_currency"
|
var currency_field = (frm.doc.payment_type=="Receive") ? "paid_from_account_currency" : "paid_to_account_currency"
|
||||||
frm.set_df_property("total_allocated_amount", "options", currency_field);
|
frm.set_df_property("total_allocated_amount", "options", currency_field);
|
||||||
frm.set_df_property("unallocated_amount", "options", currency_field);
|
frm.set_df_property("unallocated_amount", "options", currency_field);
|
||||||
|
frm.set_df_property("total_taxes_and_charges", "options", currency_field);
|
||||||
frm.set_df_property("party_balance", "options", currency_field);
|
frm.set_df_property("party_balance", "options", currency_field);
|
||||||
|
|
||||||
frm.set_currency_labels(["total_amount", "outstanding_amount", "allocated_amount"],
|
frm.set_currency_labels(["total_amount", "outstanding_amount", "allocated_amount"],
|
||||||
@ -364,6 +380,16 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
apply_tax_withholding_amount: function(frm) {
|
||||||
|
if (!frm.doc.apply_tax_withholding_amount) {
|
||||||
|
frm.set_value("tax_withholding_category", '');
|
||||||
|
} else {
|
||||||
|
frappe.db.get_value('Supplier', frm.doc.party, 'tax_withholding_category', (values) => {
|
||||||
|
frm.set_value("tax_withholding_category", values.tax_withholding_category);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
paid_from: function(frm) {
|
paid_from: function(frm) {
|
||||||
if(frm.set_party_account_based_on_party) return;
|
if(frm.set_party_account_based_on_party) return;
|
||||||
|
|
||||||
@ -843,12 +869,12 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
if(frm.doc.payment_type == "Receive"
|
if(frm.doc.payment_type == "Receive"
|
||||||
&& frm.doc.base_total_allocated_amount < frm.doc.base_received_amount + total_deductions
|
&& frm.doc.base_total_allocated_amount < frm.doc.base_received_amount + total_deductions
|
||||||
&& frm.doc.total_allocated_amount < frm.doc.paid_amount + (total_deductions / frm.doc.source_exchange_rate)) {
|
&& frm.doc.total_allocated_amount < frm.doc.paid_amount + (total_deductions / frm.doc.source_exchange_rate)) {
|
||||||
unallocated_amount = (frm.doc.base_received_amount + total_deductions
|
unallocated_amount = (frm.doc.base_received_amount + total_deductions + frm.doc.base_total_taxes_and_charges
|
||||||
- frm.doc.base_total_allocated_amount) / frm.doc.source_exchange_rate;
|
+ frm.doc.base_total_allocated_amount) / frm.doc.source_exchange_rate;
|
||||||
} else if (frm.doc.payment_type == "Pay"
|
} else if (frm.doc.payment_type == "Pay"
|
||||||
&& frm.doc.base_total_allocated_amount < frm.doc.base_paid_amount - total_deductions
|
&& frm.doc.base_total_allocated_amount < frm.doc.base_paid_amount - total_deductions
|
||||||
&& frm.doc.total_allocated_amount < frm.doc.received_amount + (total_deductions / frm.doc.target_exchange_rate)) {
|
&& frm.doc.total_allocated_amount < frm.doc.received_amount + (total_deductions / frm.doc.target_exchange_rate)) {
|
||||||
unallocated_amount = (frm.doc.base_paid_amount - (total_deductions
|
unallocated_amount = (frm.doc.base_paid_amount + frm.doc.base_total_taxes_and_charges - (total_deductions
|
||||||
+ frm.doc.base_total_allocated_amount)) / frm.doc.target_exchange_rate;
|
+ frm.doc.base_total_allocated_amount)) / frm.doc.target_exchange_rate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -874,7 +900,8 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
var total_deductions = frappe.utils.sum($.map(frm.doc.deductions || [],
|
var total_deductions = frappe.utils.sum($.map(frm.doc.deductions || [],
|
||||||
function(d) { return flt(d.amount) }));
|
function(d) { return flt(d.amount) }));
|
||||||
|
|
||||||
frm.set_value("difference_amount", difference_amount - total_deductions);
|
frm.set_value("difference_amount", difference_amount - total_deductions +
|
||||||
|
frm.doc.base_total_taxes_and_charges);
|
||||||
|
|
||||||
frm.events.hide_unhide_fields(frm);
|
frm.events.hide_unhide_fields(frm);
|
||||||
},
|
},
|
||||||
@ -1002,7 +1029,203 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
sales_taxes_and_charges_template: function(frm) {
|
||||||
|
frm.trigger('fetch_taxes_from_template');
|
||||||
|
},
|
||||||
|
|
||||||
|
purchase_taxes_and_charges_template: function(frm) {
|
||||||
|
frm.trigger('fetch_taxes_from_template');
|
||||||
|
},
|
||||||
|
|
||||||
|
fetch_taxes_from_template: function(frm) {
|
||||||
|
let master_doctype = '';
|
||||||
|
let taxes_and_charges = '';
|
||||||
|
|
||||||
|
if (frm.doc.party_type == 'Supplier') {
|
||||||
|
master_doctype = 'Purchase Taxes and Charges Template';
|
||||||
|
taxes_and_charges = frm.doc.purchase_taxes_and_charges_template;
|
||||||
|
} else if (frm.doc.party_type == 'Customer') {
|
||||||
|
master_doctype = 'Sales Taxes and Charges Template';
|
||||||
|
taxes_and_charges = frm.doc.sales_taxes_and_charges_template;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!taxes_and_charges) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
frappe.call({
|
||||||
|
method: "erpnext.controllers.accounts_controller.get_taxes_and_charges",
|
||||||
|
args: {
|
||||||
|
"master_doctype": master_doctype,
|
||||||
|
"master_name": taxes_and_charges
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
if(!r.exc && r.message) {
|
||||||
|
// set taxes table
|
||||||
|
if(r.message) {
|
||||||
|
for (let tax of r.message) {
|
||||||
|
if (tax.charge_type === 'On Net Total') {
|
||||||
|
tax.charge_type = 'On Paid Amount';
|
||||||
|
}
|
||||||
|
me.frm.add_child("taxes", tax);
|
||||||
|
}
|
||||||
|
frm.events.apply_taxes(frm);
|
||||||
|
frm.events.set_unallocated_amount(frm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
apply_taxes: function(frm) {
|
||||||
|
frm.events.initialize_taxes(frm);
|
||||||
|
frm.events.determine_exclusive_rate(frm);
|
||||||
|
frm.events.calculate_taxes(frm);
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize_taxes: function(frm) {
|
||||||
|
$.each(frm.doc["taxes"] || [], function(i, tax) {
|
||||||
|
tax.item_wise_tax_detail = {};
|
||||||
|
let tax_fields = ["total", "tax_fraction_for_current_item",
|
||||||
|
"grand_total_fraction_for_current_item"];
|
||||||
|
|
||||||
|
if (cstr(tax.charge_type) != "Actual") {
|
||||||
|
tax_fields.push("tax_amount");
|
||||||
|
}
|
||||||
|
|
||||||
|
$.each(tax_fields, function(i, fieldname) { tax[fieldname] = 0.0; });
|
||||||
|
|
||||||
|
frm.doc.paid_amount_after_tax = frm.doc.paid_amount;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
determine_exclusive_rate: function(frm) {
|
||||||
|
let has_inclusive_tax = false;
|
||||||
|
$.each(frm.doc["taxes"] || [], function(i, row) {
|
||||||
|
if(cint(row.included_in_paid_amount)) has_inclusive_tax = true;
|
||||||
|
});
|
||||||
|
if(has_inclusive_tax==false) return;
|
||||||
|
|
||||||
|
let cumulated_tax_fraction = 0.0;
|
||||||
|
$.each(frm.doc["taxes"] || [], function(i, tax) {
|
||||||
|
let current_tax_fraction = frm.events.get_current_tax_fraction(frm, tax);
|
||||||
|
tax.tax_fraction_for_current_item = current_tax_fraction[0];
|
||||||
|
|
||||||
|
if(i==0) {
|
||||||
|
tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item;
|
||||||
|
} else {
|
||||||
|
tax.grand_total_fraction_for_current_item =
|
||||||
|
me.frm.doc["taxes"][i-1].grand_total_fraction_for_current_item +
|
||||||
|
tax.tax_fraction_for_current_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
cumulated_tax_fraction += tax.tax_fraction_for_current_item;
|
||||||
|
frm.doc.paid_amount_after_tax = flt(frm.doc.paid_amount/(1+cumulated_tax_fraction))
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
get_current_tax_fraction: function(frm, tax) {
|
||||||
|
let current_tax_fraction = 0.0;
|
||||||
|
|
||||||
|
if(cint(tax.included_in_paid_amount)) {
|
||||||
|
let tax_rate = tax.rate;
|
||||||
|
|
||||||
|
if (tax.charge_type == "Actual") {
|
||||||
|
current_tax_fraction = tax.tax_amount/(frm.doc.paid_amount_after_tax + frm.doc.tax_amount);
|
||||||
|
} else if(tax.charge_type == "On Paid Amount") {
|
||||||
|
current_tax_fraction = (tax_rate / 100.0);
|
||||||
|
} else if(tax.charge_type == "On Previous Row Amount") {
|
||||||
|
current_tax_fraction = (tax_rate / 100.0) *
|
||||||
|
frm.doc["taxes"][cint(tax.row_id) - 1].tax_fraction_for_current_item;
|
||||||
|
} else if(tax.charge_type == "On Previous Row Total") {
|
||||||
|
current_tax_fraction = (tax_rate / 100.0) *
|
||||||
|
frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_fraction_for_current_item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tax.add_deduct_tax && tax.add_deduct_tax == "Deduct") {
|
||||||
|
current_tax_fraction *= -1;
|
||||||
|
inclusive_tax_amount_per_qty *= -1;
|
||||||
|
}
|
||||||
|
return current_tax_fraction;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
calculate_taxes: function(frm) {
|
||||||
|
frm.doc.total_taxes_and_charges = 0.0;
|
||||||
|
frm.doc.base_total_taxes_and_charges = 0.0;
|
||||||
|
|
||||||
|
let actual_tax_dict = {};
|
||||||
|
|
||||||
|
// maintain actual tax rate based on idx
|
||||||
|
$.each(frm.doc["taxes"] || [], function(i, tax) {
|
||||||
|
if (tax.charge_type == "Actual") {
|
||||||
|
actual_tax_dict[tax.idx] = flt(tax.tax_amount, precision("tax_amount", tax));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.each(me.frm.doc["taxes"] || [], function(i, tax) {
|
||||||
|
let current_tax_amount = frm.events.get_current_tax_amount(frm, tax);
|
||||||
|
|
||||||
|
// Adjust divisional loss to the last item
|
||||||
|
if (tax.charge_type == "Actual") {
|
||||||
|
actual_tax_dict[tax.idx] -= current_tax_amount;
|
||||||
|
if (i == frm.doc["taxes"].length - 1) {
|
||||||
|
current_tax_amount += actual_tax_dict[tax.idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tax.tax_amount = current_tax_amount;
|
||||||
|
tax.base_tax_amount = tax.tax_amount * frm.doc.source_exchange_rate;
|
||||||
|
current_tax_amount *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0;
|
||||||
|
|
||||||
|
if(i==0) {
|
||||||
|
tax.total = flt(frm.doc.paid_amount_after_tax + current_tax_amount, precision("total", tax));
|
||||||
|
} else {
|
||||||
|
tax.total = flt(frm.doc["taxes"][i-1].total + current_tax_amount, precision("total", tax));
|
||||||
|
}
|
||||||
|
|
||||||
|
tax.base_total = tax.total * frm.doc.source_exchange_rate;
|
||||||
|
frm.doc.total_taxes_and_charges += current_tax_amount;
|
||||||
|
frm.doc.base_total_taxes_and_charges += current_tax_amount * frm.doc.source_exchange_rate;
|
||||||
|
|
||||||
|
frm.refresh_field('taxes');
|
||||||
|
frm.refresh_field('total_taxes_and_charges');
|
||||||
|
frm.refresh_field('base_total_taxes_and_charges');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
get_current_tax_amount: function(frm, tax) {
|
||||||
|
let tax_rate = tax.rate;
|
||||||
|
let current_tax_amount = 0.0;
|
||||||
|
|
||||||
|
// To set row_id by default as previous row.
|
||||||
|
if(["On Previous Row Amount", "On Previous Row Total"].includes(tax.charge_type)) {
|
||||||
|
if (tax.idx === 1) {
|
||||||
|
frappe.throw(
|
||||||
|
__("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"));
|
||||||
|
}
|
||||||
|
if (!tax.row_id) {
|
||||||
|
tax.row_id = tax.idx - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(tax.charge_type == "Actual") {
|
||||||
|
current_tax_amount = flt(tax.tax_amount, precision("tax_amount", tax))
|
||||||
|
} else if(tax.charge_type == "On Paid Amount") {
|
||||||
|
current_tax_amount = flt((tax_rate / 100.0) * frm.doc.paid_amount_after_tax);
|
||||||
|
} else if(tax.charge_type == "On Previous Row Amount") {
|
||||||
|
current_tax_amount = flt((tax_rate / 100.0) *
|
||||||
|
frm.doc["taxes"][cint(tax.row_id) - 1].tax_amount);
|
||||||
|
|
||||||
|
} else if(tax.charge_type == "On Previous Row Total") {
|
||||||
|
current_tax_amount = flt((tax_rate / 100.0) *
|
||||||
|
frm.doc["taxes"][cint(tax.row_id) - 1].total);
|
||||||
|
}
|
||||||
|
|
||||||
|
return current_tax_amount;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -1049,6 +1272,33 @@ frappe.ui.form.on('Payment Entry Reference', {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
frappe.ui.form.on('Advance Taxes and Charges', {
|
||||||
|
rate: function(frm) {
|
||||||
|
frm.events.apply_taxes(frm);
|
||||||
|
frm.events.set_unallocated_amount(frm);
|
||||||
|
},
|
||||||
|
|
||||||
|
tax_amount : function(frm) {
|
||||||
|
frm.events.apply_taxes(frm);
|
||||||
|
frm.events.set_unallocated_amount(frm);
|
||||||
|
},
|
||||||
|
|
||||||
|
row_id: function(frm) {
|
||||||
|
frm.events.apply_taxes(frm);
|
||||||
|
frm.events.set_unallocated_amount(frm);
|
||||||
|
},
|
||||||
|
|
||||||
|
taxes_remove: function(frm) {
|
||||||
|
frm.events.apply_taxes(frm);
|
||||||
|
frm.events.set_unallocated_amount(frm);
|
||||||
|
},
|
||||||
|
|
||||||
|
included_in_paid_amount: function(frm) {
|
||||||
|
frm.events.apply_taxes(frm);
|
||||||
|
frm.events.set_unallocated_amount(frm);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
frappe.ui.form.on('Payment Entry Deduction', {
|
frappe.ui.form.on('Payment Entry Deduction', {
|
||||||
amount: function(frm) {
|
amount: function(frm) {
|
||||||
frm.events.set_unallocated_amount(frm);
|
frm.events.set_unallocated_amount(frm);
|
||||||
|
@ -35,12 +35,16 @@
|
|||||||
"paid_to_account_balance",
|
"paid_to_account_balance",
|
||||||
"payment_amounts_section",
|
"payment_amounts_section",
|
||||||
"paid_amount",
|
"paid_amount",
|
||||||
|
"paid_amount_after_tax",
|
||||||
"source_exchange_rate",
|
"source_exchange_rate",
|
||||||
"base_paid_amount",
|
"base_paid_amount",
|
||||||
|
"base_paid_amount_after_tax",
|
||||||
"column_break_21",
|
"column_break_21",
|
||||||
"received_amount",
|
"received_amount",
|
||||||
|
"received_amount_after_tax",
|
||||||
"target_exchange_rate",
|
"target_exchange_rate",
|
||||||
"base_received_amount",
|
"base_received_amount",
|
||||||
|
"base_received_amount_after_tax",
|
||||||
"section_break_14",
|
"section_break_14",
|
||||||
"get_outstanding_invoice",
|
"get_outstanding_invoice",
|
||||||
"references",
|
"references",
|
||||||
@ -52,6 +56,17 @@
|
|||||||
"unallocated_amount",
|
"unallocated_amount",
|
||||||
"difference_amount",
|
"difference_amount",
|
||||||
"write_off_difference_amount",
|
"write_off_difference_amount",
|
||||||
|
"taxes_and_charges_section",
|
||||||
|
"purchase_taxes_and_charges_template",
|
||||||
|
"sales_taxes_and_charges_template",
|
||||||
|
"advance_tax_account",
|
||||||
|
"column_break_55",
|
||||||
|
"apply_tax_withholding_amount",
|
||||||
|
"tax_withholding_category",
|
||||||
|
"section_break_56",
|
||||||
|
"taxes",
|
||||||
|
"base_total_taxes_and_charges",
|
||||||
|
"total_taxes_and_charges",
|
||||||
"deductions_or_loss_section",
|
"deductions_or_loss_section",
|
||||||
"deductions",
|
"deductions",
|
||||||
"transaction_references",
|
"transaction_references",
|
||||||
@ -320,6 +335,7 @@
|
|||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "doc.received_amount",
|
||||||
"fieldname": "base_received_amount",
|
"fieldname": "base_received_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Received Amount (Company Currency)",
|
"label": "Received Amount (Company Currency)",
|
||||||
@ -584,12 +600,114 @@
|
|||||||
"fieldname": "custom_remarks",
|
"fieldname": "custom_remarks",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Custom Remarks"
|
"label": "Custom Remarks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.apply_tax_withholding_amount",
|
||||||
|
"fieldname": "tax_withholding_category",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Tax Withholding Category",
|
||||||
|
"mandatory_depends_on": "eval:doc.apply_tax_withholding_amount",
|
||||||
|
"options": "Tax Withholding Category"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"depends_on": "eval:doc.party_type == 'Supplier'",
|
||||||
|
"fieldname": "apply_tax_withholding_amount",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Apply Tax Withholding Amount"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsible": 1,
|
||||||
|
"fieldname": "taxes_and_charges_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Taxes and Charges"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.party_type == 'Supplier'",
|
||||||
|
"fieldname": "purchase_taxes_and_charges_template",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Taxes and Charges Template",
|
||||||
|
"options": "Purchase Taxes and Charges Template"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval: doc.party_type == 'Customer'",
|
||||||
|
"fieldname": "sales_taxes_and_charges_template",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Taxes and Charges Template",
|
||||||
|
"options": "Sales Taxes and Charges Template"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval: doc.party_type == 'Supplier' || doc.party_type == 'Customer'",
|
||||||
|
"fieldname": "taxes",
|
||||||
|
"fieldtype": "Table",
|
||||||
|
"label": "Advance Taxes and Charges",
|
||||||
|
"options": "Advance Taxes and Charges"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "base_total_taxes_and_charges",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Total Taxes and Charges (Company Currency)",
|
||||||
|
"options": "Company:company:default_currency",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "total_taxes_and_charges",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Total Taxes and Charges",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "paid_amount_after_tax",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Paid Amount After Tax",
|
||||||
|
"options": "paid_from_account_currency",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "base_paid_amount_after_tax",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Paid Amount After Tax (Company Currency)",
|
||||||
|
"options": "Company:company:default_currency",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_55",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_56",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hide_border": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.apply_tax_withholding_amount",
|
||||||
|
"description": "Provisional tax account for advance tax. Taxes are parked in this account until payments are allocated to invoices",
|
||||||
|
"fieldname": "advance_tax_account",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Advance Tax Account",
|
||||||
|
"mandatory_depends_on": "eval:doc.apply_tax_withholding_amount",
|
||||||
|
"options": "Account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.received_amount",
|
||||||
|
"fieldname": "received_amount_after_tax",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Received Amount After Tax",
|
||||||
|
"options": "paid_to_account_currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "doc.received_amount",
|
||||||
|
"fieldname": "base_received_amount_after_tax",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Received Amount After Tax (Company Currency)",
|
||||||
|
"options": "Company:company:default_currency"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-03-08 13:05:16.958866",
|
"modified": "2021-06-09 11:55:04.215050",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Payment Entry",
|
"name": "Payment Entry",
|
||||||
@ -633,4 +751,4 @@
|
|||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"title_field": "title",
|
"title_field": "title",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
@ -5,7 +5,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe, erpnext, json
|
import frappe, erpnext, json
|
||||||
from frappe import _, scrub, ValidationError
|
from frappe import _, scrub, ValidationError
|
||||||
from frappe.utils import flt, comma_or, nowdate, getdate
|
from frappe.utils import flt, comma_or, nowdate, getdate, cint
|
||||||
from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on
|
from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on
|
||||||
from erpnext.accounts.party import get_party_account
|
from erpnext.accounts.party import get_party_account
|
||||||
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
|
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
|
||||||
@ -15,6 +15,7 @@ from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amo
|
|||||||
from erpnext.accounts.doctype.bank_account.bank_account import get_party_bank_account, get_bank_account_details
|
from erpnext.accounts.doctype.bank_account.bank_account import get_party_bank_account, get_bank_account_details
|
||||||
from erpnext.controllers.accounts_controller import AccountsController, get_supplier_block_status
|
from erpnext.controllers.accounts_controller import AccountsController, get_supplier_block_status
|
||||||
from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import get_party_account_based_on_invoice_discounting
|
from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import get_party_account_based_on_invoice_discounting
|
||||||
|
from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details
|
||||||
|
|
||||||
from six import string_types, iteritems
|
from six import string_types, iteritems
|
||||||
|
|
||||||
@ -52,6 +53,8 @@ class PaymentEntry(AccountsController):
|
|||||||
self.set_exchange_rate()
|
self.set_exchange_rate()
|
||||||
self.validate_mandatory()
|
self.validate_mandatory()
|
||||||
self.validate_reference_documents()
|
self.validate_reference_documents()
|
||||||
|
self.set_tax_withholding()
|
||||||
|
self.apply_taxes()
|
||||||
self.set_amounts()
|
self.set_amounts()
|
||||||
self.clear_unallocated_reference_document_rows()
|
self.clear_unallocated_reference_document_rows()
|
||||||
self.validate_payment_against_negative_invoice()
|
self.validate_payment_against_negative_invoice()
|
||||||
@ -310,7 +313,6 @@ class PaymentEntry(AccountsController):
|
|||||||
+ "<br><br>" + _("If this is undesirable please cancel the corresponding Payment Entry."),
|
+ "<br><br>" + _("If this is undesirable please cancel the corresponding Payment Entry."),
|
||||||
title=_("Warning"), indicator="orange")
|
title=_("Warning"), indicator="orange")
|
||||||
|
|
||||||
|
|
||||||
def validate_journal_entry(self):
|
def validate_journal_entry(self):
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
if d.allocated_amount and d.reference_doctype == "Journal Entry":
|
if d.allocated_amount and d.reference_doctype == "Journal Entry":
|
||||||
@ -391,12 +393,110 @@ class PaymentEntry(AccountsController):
|
|||||||
|
|
||||||
self.db_set('status', self.status, update_modified = True)
|
self.db_set('status', self.status, update_modified = True)
|
||||||
|
|
||||||
|
def set_tax_withholding(self):
|
||||||
|
if not self.party_type == 'Supplier':
|
||||||
|
return
|
||||||
|
|
||||||
|
if not self.apply_tax_withholding_amount:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not self.advance_tax_account:
|
||||||
|
frappe.throw(_("Advance TDS account is mandatory for advance TDS deduction"))
|
||||||
|
|
||||||
|
reference_doclist = []
|
||||||
|
net_total = self.paid_amount
|
||||||
|
included_in_paid_amount = 0
|
||||||
|
|
||||||
|
if self.get('references'):
|
||||||
|
for doc in self.get('references'):
|
||||||
|
if doc.reference_doctype == 'Purchase Order':
|
||||||
|
reference_doclist.append(doc.reference_name)
|
||||||
|
|
||||||
|
if reference_doclist:
|
||||||
|
order_amount = frappe.db.get_all('Purchase Order', fields=['sum(net_total)'],
|
||||||
|
filters = {'name': ('in', reference_doclist), 'docstatus': 1,
|
||||||
|
'apply_tds': 1}, as_list=1)
|
||||||
|
|
||||||
|
if order_amount:
|
||||||
|
net_total = order_amount[0][0]
|
||||||
|
included_in_paid_amount = 1
|
||||||
|
|
||||||
|
# Adding args as purchase invoice to get TDS amount
|
||||||
|
args = frappe._dict({
|
||||||
|
'company': self.company,
|
||||||
|
'doctype': 'Purchase Invoice',
|
||||||
|
'supplier': self.party,
|
||||||
|
'posting_date': self.posting_date,
|
||||||
|
'net_total': net_total
|
||||||
|
})
|
||||||
|
|
||||||
|
tax_withholding_details = get_party_tax_withholding_details(args, self.tax_withholding_category)
|
||||||
|
|
||||||
|
if not tax_withholding_details:
|
||||||
|
return
|
||||||
|
|
||||||
|
tax_withholding_details.update({
|
||||||
|
'included_in_paid_amount': included_in_paid_amount,
|
||||||
|
'cost_center': self.cost_center or erpnext.get_default_cost_center(self.company)
|
||||||
|
})
|
||||||
|
|
||||||
|
accounts = []
|
||||||
|
for d in self.taxes:
|
||||||
|
if d.account_head == tax_withholding_details.get("account_head"):
|
||||||
|
|
||||||
|
# Preserve user updated included in paid amount
|
||||||
|
if d.included_in_paid_amount:
|
||||||
|
tax_withholding_details.update({'included_in_paid_amount': d.included_in_paid_amount})
|
||||||
|
|
||||||
|
d.update(tax_withholding_details)
|
||||||
|
accounts.append(d.account_head)
|
||||||
|
|
||||||
|
if not accounts or tax_withholding_details.get("account_head") not in accounts:
|
||||||
|
self.append("taxes", tax_withholding_details)
|
||||||
|
|
||||||
|
to_remove = [d for d in self.taxes
|
||||||
|
if not d.tax_amount and d.account_head == tax_withholding_details.get("account_head")]
|
||||||
|
|
||||||
|
for d in to_remove:
|
||||||
|
self.remove(d)
|
||||||
|
|
||||||
|
def apply_taxes(self):
|
||||||
|
self.initialize_taxes()
|
||||||
|
self.determine_exclusive_rate()
|
||||||
|
self.calculate_taxes()
|
||||||
|
|
||||||
def set_amounts(self):
|
def set_amounts(self):
|
||||||
|
self.set_received_amount()
|
||||||
self.set_amounts_in_company_currency()
|
self.set_amounts_in_company_currency()
|
||||||
|
self.set_amounts_after_tax()
|
||||||
self.set_total_allocated_amount()
|
self.set_total_allocated_amount()
|
||||||
self.set_unallocated_amount()
|
self.set_unallocated_amount()
|
||||||
self.set_difference_amount()
|
self.set_difference_amount()
|
||||||
|
|
||||||
|
def set_received_amount(self):
|
||||||
|
self.base_received_amount = self.base_paid_amount
|
||||||
|
|
||||||
|
def set_amounts_after_tax(self):
|
||||||
|
applicable_tax = 0
|
||||||
|
base_applicable_tax = 0
|
||||||
|
for tax in self.get('taxes'):
|
||||||
|
if not tax.included_in_paid_amount:
|
||||||
|
amount = -1 * tax.tax_amount if tax.add_deduct_tax == 'Deduct' else tax.tax_amount
|
||||||
|
base_amount = -1 * tax.base_tax_amount if tax.add_deduct_tax == 'Deduct' else tax.base_tax_amount
|
||||||
|
|
||||||
|
applicable_tax += amount
|
||||||
|
base_applicable_tax += base_amount
|
||||||
|
|
||||||
|
self.paid_amount_after_tax = flt(flt(self.paid_amount) + flt(applicable_tax),
|
||||||
|
self.precision("paid_amount_after_tax"))
|
||||||
|
self.base_paid_amount_after_tax = flt(flt(self.paid_amount_after_tax) * flt(self.source_exchange_rate),
|
||||||
|
self.precision("base_paid_amount_after_tax"))
|
||||||
|
|
||||||
|
self.received_amount_after_tax = flt(flt(self.received_amount) + flt(applicable_tax),
|
||||||
|
self.precision("paid_amount_after_tax"))
|
||||||
|
self.base_received_amount_after_tax = flt(flt(self.received_amount_after_tax) * flt(self.target_exchange_rate),
|
||||||
|
self.precision("base_paid_amount_after_tax"))
|
||||||
|
|
||||||
def set_amounts_in_company_currency(self):
|
def set_amounts_in_company_currency(self):
|
||||||
self.base_paid_amount, self.base_received_amount, self.difference_amount = 0, 0, 0
|
self.base_paid_amount, self.base_received_amount, self.difference_amount = 0, 0, 0
|
||||||
if self.paid_amount:
|
if self.paid_amount:
|
||||||
@ -426,15 +526,15 @@ class PaymentEntry(AccountsController):
|
|||||||
if self.party:
|
if self.party:
|
||||||
total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
|
total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
|
||||||
if self.payment_type == "Receive" \
|
if self.payment_type == "Receive" \
|
||||||
and self.base_total_allocated_amount < self.base_received_amount + total_deductions \
|
and self.base_total_allocated_amount < self.base_received_amount_after_tax + total_deductions \
|
||||||
and self.total_allocated_amount < self.paid_amount + (total_deductions / self.source_exchange_rate):
|
and self.total_allocated_amount < self.paid_amount_after_tax + (total_deductions / self.source_exchange_rate):
|
||||||
self.unallocated_amount = (self.base_received_amount + total_deductions -
|
self.unallocated_amount = (self.received_amount_after_tax + total_deductions -
|
||||||
self.base_total_allocated_amount) / self.source_exchange_rate
|
self.base_total_allocated_amount) / self.source_exchange_rate
|
||||||
elif self.payment_type == "Pay" \
|
elif self.payment_type == "Pay" \
|
||||||
and self.base_total_allocated_amount < (self.base_paid_amount - total_deductions) \
|
and self.base_total_allocated_amount < (self.base_paid_amount_after_tax - total_deductions) \
|
||||||
and self.total_allocated_amount < self.received_amount + (total_deductions / self.target_exchange_rate):
|
and self.total_allocated_amount < self.received_amount_after_tax + (total_deductions / self.target_exchange_rate):
|
||||||
self.unallocated_amount = (self.base_paid_amount - (total_deductions +
|
self.unallocated_amount = (self.base_paid_amount_after_tax - (total_deductions +
|
||||||
self.base_total_allocated_amount)) / self.target_exchange_rate
|
self.base_total_allocated_amount)) / self.target_exchange_rate
|
||||||
|
|
||||||
def set_difference_amount(self):
|
def set_difference_amount(self):
|
||||||
base_unallocated_amount = flt(self.unallocated_amount) * (flt(self.source_exchange_rate)
|
base_unallocated_amount = flt(self.unallocated_amount) * (flt(self.source_exchange_rate)
|
||||||
@ -443,11 +543,11 @@ class PaymentEntry(AccountsController):
|
|||||||
base_party_amount = flt(self.base_total_allocated_amount) + flt(base_unallocated_amount)
|
base_party_amount = flt(self.base_total_allocated_amount) + flt(base_unallocated_amount)
|
||||||
|
|
||||||
if self.payment_type == "Receive":
|
if self.payment_type == "Receive":
|
||||||
self.difference_amount = base_party_amount - self.base_received_amount
|
self.difference_amount = base_party_amount - self.base_received_amount_after_tax
|
||||||
elif self.payment_type == "Pay":
|
elif self.payment_type == "Pay":
|
||||||
self.difference_amount = self.base_paid_amount - base_party_amount
|
self.difference_amount = self.base_paid_amount_after_tax - base_party_amount
|
||||||
else:
|
else:
|
||||||
self.difference_amount = self.base_paid_amount - flt(self.base_received_amount)
|
self.difference_amount = self.base_paid_amount_after_tax - flt(self.base_received_amount_after_tax)
|
||||||
|
|
||||||
total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
|
total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
|
||||||
|
|
||||||
@ -537,6 +637,7 @@ class PaymentEntry(AccountsController):
|
|||||||
self.add_party_gl_entries(gl_entries)
|
self.add_party_gl_entries(gl_entries)
|
||||||
self.add_bank_gl_entries(gl_entries)
|
self.add_bank_gl_entries(gl_entries)
|
||||||
self.add_deductions_gl_entries(gl_entries)
|
self.add_deductions_gl_entries(gl_entries)
|
||||||
|
self.add_tax_gl_entries(gl_entries)
|
||||||
|
|
||||||
make_gl_entries(gl_entries, cancel=cancel, adv_adj=adv_adj)
|
make_gl_entries(gl_entries, cancel=cancel, adv_adj=adv_adj)
|
||||||
|
|
||||||
@ -576,7 +677,7 @@ class PaymentEntry(AccountsController):
|
|||||||
gl_entries.append(gle)
|
gl_entries.append(gle)
|
||||||
|
|
||||||
if self.unallocated_amount:
|
if self.unallocated_amount:
|
||||||
base_unallocated_amount = base_unallocated_amount = self.unallocated_amount * \
|
base_unallocated_amount = self.unallocated_amount * \
|
||||||
(self.source_exchange_rate if self.payment_type=="Receive" else self.target_exchange_rate)
|
(self.source_exchange_rate if self.payment_type=="Receive" else self.target_exchange_rate)
|
||||||
|
|
||||||
gle = party_gl_dict.copy()
|
gle = party_gl_dict.copy()
|
||||||
@ -595,8 +696,8 @@ class PaymentEntry(AccountsController):
|
|||||||
"account": self.paid_from,
|
"account": self.paid_from,
|
||||||
"account_currency": self.paid_from_account_currency,
|
"account_currency": self.paid_from_account_currency,
|
||||||
"against": self.party if self.payment_type=="Pay" else self.paid_to,
|
"against": self.party if self.payment_type=="Pay" else self.paid_to,
|
||||||
"credit_in_account_currency": self.paid_amount,
|
"credit_in_account_currency": self.paid_amount_after_tax,
|
||||||
"credit": self.base_paid_amount,
|
"credit": self.base_paid_amount_after_tax,
|
||||||
"cost_center": self.cost_center
|
"cost_center": self.cost_center
|
||||||
}, item=self)
|
}, item=self)
|
||||||
)
|
)
|
||||||
@ -606,12 +707,48 @@ class PaymentEntry(AccountsController):
|
|||||||
"account": self.paid_to,
|
"account": self.paid_to,
|
||||||
"account_currency": self.paid_to_account_currency,
|
"account_currency": self.paid_to_account_currency,
|
||||||
"against": self.party if self.payment_type=="Receive" else self.paid_from,
|
"against": self.party if self.payment_type=="Receive" else self.paid_from,
|
||||||
"debit_in_account_currency": self.received_amount,
|
"debit_in_account_currency": self.received_amount_after_tax,
|
||||||
"debit": self.base_received_amount,
|
"debit": self.base_received_amount_after_tax,
|
||||||
"cost_center": self.cost_center
|
"cost_center": self.cost_center
|
||||||
}, item=self)
|
}, item=self)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def add_tax_gl_entries(self, gl_entries):
|
||||||
|
for d in self.get('taxes'):
|
||||||
|
account_currency = get_account_currency(d.account_head)
|
||||||
|
if account_currency != self.company_currency:
|
||||||
|
frappe.throw(_("Currency for {0} must be {1}").format(d.account_head, self.company_currency))
|
||||||
|
|
||||||
|
if (self.payment_type == 'Pay' and self.advance_tax_account) or self.payment_type == 'Receive':
|
||||||
|
dr_or_cr = "debit" if d.add_deduct_tax == "Add" else "credit"
|
||||||
|
elif (self.payment_type == 'Receive' and self.advance_tax_account) or self.payment_type == 'Pay':
|
||||||
|
dr_or_cr = "credit" if d.add_deduct_tax == "Add" else "debit"
|
||||||
|
|
||||||
|
payment_or_advance_account = self.get_party_account_for_taxes()
|
||||||
|
|
||||||
|
gl_entries.append(
|
||||||
|
self.get_gl_dict({
|
||||||
|
"account": d.account_head,
|
||||||
|
"against": self.party if self.payment_type=="Receive" else self.paid_from,
|
||||||
|
dr_or_cr: d.base_tax_amount,
|
||||||
|
dr_or_cr + "_in_account_currency": d.base_tax_amount
|
||||||
|
if account_currency==self.company_currency
|
||||||
|
else d.tax_amount,
|
||||||
|
"cost_center": d.cost_center
|
||||||
|
}, account_currency, item=d))
|
||||||
|
|
||||||
|
#Intentionally use -1 to get net values in party account
|
||||||
|
gl_entries.append(
|
||||||
|
self.get_gl_dict({
|
||||||
|
"account": payment_or_advance_account,
|
||||||
|
"against": self.party if self.payment_type=="Receive" else self.paid_from,
|
||||||
|
dr_or_cr: -1 * d.base_tax_amount,
|
||||||
|
dr_or_cr + "_in_account_currency": -1*d.base_tax_amount
|
||||||
|
if account_currency==self.company_currency
|
||||||
|
else d.tax_amount,
|
||||||
|
"cost_center": self.cost_center,
|
||||||
|
}, account_currency, item=d))
|
||||||
|
|
||||||
def add_deductions_gl_entries(self, gl_entries):
|
def add_deductions_gl_entries(self, gl_entries):
|
||||||
for d in self.get("deductions"):
|
for d in self.get("deductions"):
|
||||||
if d.amount:
|
if d.amount:
|
||||||
@ -630,6 +767,14 @@ class PaymentEntry(AccountsController):
|
|||||||
}, item=d)
|
}, item=d)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_party_account_for_taxes(self):
|
||||||
|
if self.advance_tax_account:
|
||||||
|
return self.advance_tax_account
|
||||||
|
elif self.payment_type == 'Pay':
|
||||||
|
return self.paid_from
|
||||||
|
elif self.payment_type == 'Receive':
|
||||||
|
return self.paid_to
|
||||||
|
|
||||||
def update_advance_paid(self):
|
def update_advance_paid(self):
|
||||||
if self.payment_type in ("Receive", "Pay") and self.party:
|
if self.payment_type in ("Receive", "Pay") and self.party:
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
@ -676,6 +821,121 @@ class PaymentEntry(AccountsController):
|
|||||||
self.append('deductions', row)
|
self.append('deductions', row)
|
||||||
self.set_unallocated_amount()
|
self.set_unallocated_amount()
|
||||||
|
|
||||||
|
def initialize_taxes(self):
|
||||||
|
for tax in self.get("taxes"):
|
||||||
|
tax_fields = ["total", "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"]
|
||||||
|
|
||||||
|
if tax.charge_type != "Actual":
|
||||||
|
tax_fields.append("tax_amount")
|
||||||
|
|
||||||
|
for fieldname in tax_fields:
|
||||||
|
tax.set(fieldname, 0.0)
|
||||||
|
|
||||||
|
self.paid_amount_after_tax = self.paid_amount
|
||||||
|
|
||||||
|
def determine_exclusive_rate(self):
|
||||||
|
if not any((cint(tax.included_in_paid_amount) for tax in self.get("taxes"))):
|
||||||
|
return
|
||||||
|
|
||||||
|
cumulated_tax_fraction = 0
|
||||||
|
for i, tax in enumerate(self.get("taxes")):
|
||||||
|
tax.tax_fraction_for_current_item = self.get_current_tax_fraction(tax)
|
||||||
|
if i==0:
|
||||||
|
tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item
|
||||||
|
else:
|
||||||
|
tax.grand_total_fraction_for_current_item = \
|
||||||
|
self.get("taxes")[i-1].grand_total_fraction_for_current_item \
|
||||||
|
+ tax.tax_fraction_for_current_item
|
||||||
|
|
||||||
|
cumulated_tax_fraction += tax.tax_fraction_for_current_item
|
||||||
|
|
||||||
|
self.paid_amount_after_tax = flt(self.paid_amount/(1+cumulated_tax_fraction))
|
||||||
|
|
||||||
|
def calculate_taxes(self):
|
||||||
|
self.total_taxes_and_charges = 0.0
|
||||||
|
self.base_total_taxes_and_charges = 0.0
|
||||||
|
|
||||||
|
actual_tax_dict = dict([[tax.idx, flt(tax.tax_amount, tax.precision("tax_amount"))]
|
||||||
|
for tax in self.get("taxes") if tax.charge_type == "Actual"])
|
||||||
|
|
||||||
|
for i, tax in enumerate(self.get('taxes')):
|
||||||
|
current_tax_amount = self.get_current_tax_amount(tax)
|
||||||
|
|
||||||
|
if tax.charge_type == "Actual":
|
||||||
|
actual_tax_dict[tax.idx] -= current_tax_amount
|
||||||
|
if i == len(self.get("taxes")) - 1:
|
||||||
|
current_tax_amount += actual_tax_dict[tax.idx]
|
||||||
|
|
||||||
|
tax.tax_amount = current_tax_amount
|
||||||
|
tax.base_tax_amount = tax.tax_amount * self.source_exchange_rate
|
||||||
|
|
||||||
|
if tax.add_deduct_tax == "Deduct":
|
||||||
|
current_tax_amount *= -1.0
|
||||||
|
else:
|
||||||
|
current_tax_amount *= 1.0
|
||||||
|
|
||||||
|
if i == 0:
|
||||||
|
tax.total = flt(self.paid_amount_after_tax + current_tax_amount, self.precision("total", tax))
|
||||||
|
else:
|
||||||
|
tax.total = flt(self.get('taxes')[i-1].total + current_tax_amount, self.precision("total", tax))
|
||||||
|
|
||||||
|
tax.base_total = tax.total * self.source_exchange_rate
|
||||||
|
|
||||||
|
self.total_taxes_and_charges += current_tax_amount
|
||||||
|
self.base_total_taxes_and_charges += current_tax_amount * self.source_exchange_rate
|
||||||
|
|
||||||
|
if self.get('taxes'):
|
||||||
|
self.paid_amount_after_tax = self.get('taxes')[-1].base_total
|
||||||
|
|
||||||
|
def get_current_tax_amount(self, tax):
|
||||||
|
tax_rate = tax.rate
|
||||||
|
|
||||||
|
# To set row_id by default as previous row.
|
||||||
|
if tax.charge_type in ["On Previous Row Amount", "On Previous Row Total"]:
|
||||||
|
if tax.idx == 1:
|
||||||
|
frappe.throw(_("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"))
|
||||||
|
|
||||||
|
if not tax.row_id:
|
||||||
|
tax.row_id = tax.idx - 1
|
||||||
|
|
||||||
|
if tax.charge_type == "Actual":
|
||||||
|
current_tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax))
|
||||||
|
elif tax.charge_type == "On Paid Amount":
|
||||||
|
current_tax_amount = (tax_rate / 100.0) * self.paid_amount_after_tax
|
||||||
|
elif tax.charge_type == "On Previous Row Amount":
|
||||||
|
current_tax_amount = (tax_rate / 100.0) * \
|
||||||
|
self.get('taxes')[cint(tax.row_id) - 1].tax_amount
|
||||||
|
|
||||||
|
elif tax.charge_type == "On Previous Row Total":
|
||||||
|
current_tax_amount = (tax_rate / 100.0) * \
|
||||||
|
self.get('taxes')[cint(tax.row_id) - 1].total
|
||||||
|
|
||||||
|
return current_tax_amount
|
||||||
|
|
||||||
|
def get_current_tax_fraction(self, tax):
|
||||||
|
current_tax_fraction = 0
|
||||||
|
|
||||||
|
if cint(tax.included_in_paid_amount):
|
||||||
|
tax_rate = tax.rate
|
||||||
|
|
||||||
|
if tax.charge_type == 'Actual':
|
||||||
|
current_tax_fraction = tax.tax_amount/ (self.paid_amount_after_tax + tax.tax_amount)
|
||||||
|
elif tax.charge_type == "On Paid Amount":
|
||||||
|
current_tax_fraction = tax_rate / 100.0
|
||||||
|
|
||||||
|
elif tax.charge_type == "On Previous Row Amount":
|
||||||
|
current_tax_fraction = (tax_rate / 100.0) * \
|
||||||
|
self.get("taxes")[cint(tax.row_id) - 1].tax_fraction_for_current_item
|
||||||
|
|
||||||
|
elif tax.charge_type == "On Previous Row Total":
|
||||||
|
current_tax_fraction = (tax_rate / 100.0) * \
|
||||||
|
self.get("taxes")[cint(tax.row_id) - 1].grand_total_fraction_for_current_item
|
||||||
|
|
||||||
|
if getattr(tax, "add_deduct_tax", None) and tax.add_deduct_tax == "Deduct":
|
||||||
|
current_tax_fraction *= -1.0
|
||||||
|
|
||||||
|
return current_tax_fraction
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_outstanding_reference_documents(args):
|
def get_outstanding_reference_documents(args):
|
||||||
|
|
||||||
@ -1241,6 +1501,13 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
|||||||
})
|
})
|
||||||
pe.set_difference_amount()
|
pe.set_difference_amount()
|
||||||
|
|
||||||
|
if doc.doctype == 'Purchase Order' and doc.apply_tds:
|
||||||
|
pe.apply_tax_withholding_amount = 1
|
||||||
|
pe.tax_withholding_category = doc.tax_withholding_category
|
||||||
|
|
||||||
|
if not pe.advance_tax_account:
|
||||||
|
pe.advance_tax_account = frappe.db.get_value('Company', pe.company, 'unrealized_profit_loss_account')
|
||||||
|
|
||||||
return pe
|
return pe
|
||||||
|
|
||||||
def get_bank_cash_account(doc, bank_account):
|
def get_bank_cash_account(doc, bank_account):
|
||||||
|
@ -1,140 +1,70 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_events_in_timeline": 0,
|
"creation": "2016-06-15 15:56:30.815503",
|
||||||
"allow_guest_to_view": 0,
|
"doctype": "DocType",
|
||||||
"allow_import": 0,
|
"editable_grid": 1,
|
||||||
"allow_rename": 0,
|
"field_order": [
|
||||||
"beta": 0,
|
"account",
|
||||||
"creation": "2016-06-15 15:56:30.815503",
|
"cost_center",
|
||||||
"custom": 0,
|
"amount",
|
||||||
"docstatus": 0,
|
"column_break_2",
|
||||||
"doctype": "DocType",
|
"description"
|
||||||
"document_type": "",
|
],
|
||||||
"editable_grid": 1,
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "account",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldtype": "Link",
|
||||||
"allow_on_submit": 0,
|
"in_list_view": 1,
|
||||||
"bold": 0,
|
"label": "Account",
|
||||||
"collapsible": 0,
|
"options": "Account",
|
||||||
"columns": 0,
|
"reqd": 1,
|
||||||
"fieldname": "account",
|
"show_days": 1,
|
||||||
"fieldtype": "Link",
|
"show_seconds": 1
|
||||||
"hidden": 0,
|
},
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Account",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Account",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "cost_center",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldtype": "Link",
|
||||||
"allow_on_submit": 0,
|
"in_list_view": 1,
|
||||||
"bold": 0,
|
"label": "Cost Center",
|
||||||
"collapsible": 0,
|
"options": "Cost Center",
|
||||||
"columns": 0,
|
"print_hide": 1,
|
||||||
"fieldname": "cost_center",
|
"reqd": 1,
|
||||||
"fieldtype": "Link",
|
"show_days": 1,
|
||||||
"hidden": 0,
|
"show_seconds": 1
|
||||||
"ignore_user_permissions": 0,
|
},
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Cost Center",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Cost Center",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 1,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "amount",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldtype": "Currency",
|
||||||
"allow_on_submit": 0,
|
"in_list_view": 1,
|
||||||
"bold": 0,
|
"label": "Amount",
|
||||||
"collapsible": 0,
|
"reqd": 1,
|
||||||
"columns": 0,
|
"show_days": 1,
|
||||||
"fieldname": "amount",
|
"show_seconds": 1
|
||||||
"fieldtype": "Currency",
|
},
|
||||||
"hidden": 0,
|
{
|
||||||
"ignore_user_permissions": 0,
|
"fieldname": "column_break_2",
|
||||||
"ignore_xss_filter": 0,
|
"fieldtype": "Column Break",
|
||||||
"in_filter": 0,
|
"show_days": 1,
|
||||||
"in_global_search": 0,
|
"show_seconds": 1
|
||||||
"in_list_view": 1,
|
},
|
||||||
"in_standard_filter": 0,
|
{
|
||||||
"label": "Amount",
|
"fieldname": "description",
|
||||||
"length": 0,
|
"fieldtype": "Small Text",
|
||||||
"no_copy": 0,
|
"label": "Description",
|
||||||
"permlevel": 0,
|
"show_days": 1,
|
||||||
"precision": "",
|
"show_seconds": 1
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"index_web_pages_for_search": 1,
|
||||||
"hide_heading": 0,
|
"istable": 1,
|
||||||
"hide_toolbar": 0,
|
"links": [],
|
||||||
"idx": 0,
|
"modified": "2020-09-12 20:38:08.110674",
|
||||||
"image_view": 0,
|
"modified_by": "Administrator",
|
||||||
"in_create": 0,
|
"module": "Accounts",
|
||||||
"is_submittable": 0,
|
"name": "Payment Entry Deduction",
|
||||||
"issingle": 0,
|
"owner": "Administrator",
|
||||||
"istable": 1,
|
"permissions": [],
|
||||||
"max_attachments": 0,
|
"quick_entry": 1,
|
||||||
"modified": "2019-01-07 16:52:07.040146",
|
"sort_field": "modified",
|
||||||
"modified_by": "Administrator",
|
"sort_order": "DESC"
|
||||||
"module": "Accounts",
|
|
||||||
"name": "Payment Entry Deduction",
|
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [],
|
|
||||||
"quick_entry": 1,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"track_changes": 0,
|
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
@ -68,9 +68,6 @@ class PurchaseInvoice(BuyingController):
|
|||||||
|
|
||||||
super(PurchaseInvoice, self).validate()
|
super(PurchaseInvoice, self).validate()
|
||||||
|
|
||||||
# apply tax withholding only if checked and applicable
|
|
||||||
self.set_tax_withholding()
|
|
||||||
|
|
||||||
if not self.is_return:
|
if not self.is_return:
|
||||||
self.po_required()
|
self.po_required()
|
||||||
self.pr_required()
|
self.pr_required()
|
||||||
@ -251,11 +248,9 @@ class PurchaseInvoice(BuyingController):
|
|||||||
|
|
||||||
if self.update_stock and (not item.from_warehouse):
|
if self.update_stock and (not item.from_warehouse):
|
||||||
if for_validate and item.expense_account and item.expense_account != warehouse_account[item.warehouse]["account"]:
|
if for_validate and item.expense_account and item.expense_account != warehouse_account[item.warehouse]["account"]:
|
||||||
msg = _("Row {}: Expense Head changed to {} ").format(item.idx, frappe.bold(warehouse_account[item.warehouse]["account"]))
|
msg = _("Row {0}: Expense Head changed to {1} because account {2} is not linked to warehouse {3} or it is not the default inventory account").format(
|
||||||
msg += _("because account {} is not linked to warehouse {} ").format(frappe.bold(item.expense_account), frappe.bold(item.warehouse))
|
item.idx, frappe.bold(warehouse_account[item.warehouse]["account"]), frappe.bold(item.expense_account), frappe.bold(item.warehouse))
|
||||||
msg += _("or it is not the default inventory account")
|
|
||||||
frappe.msgprint(msg, title=_("Expense Head Changed"))
|
frappe.msgprint(msg, title=_("Expense Head Changed"))
|
||||||
|
|
||||||
item.expense_account = warehouse_account[item.warehouse]["account"]
|
item.expense_account = warehouse_account[item.warehouse]["account"]
|
||||||
else:
|
else:
|
||||||
# check if 'Stock Received But Not Billed' account is credited in Purchase receipt or not
|
# check if 'Stock Received But Not Billed' account is credited in Purchase receipt or not
|
||||||
@ -266,8 +261,8 @@ class PurchaseInvoice(BuyingController):
|
|||||||
|
|
||||||
if negative_expense_booked_in_pr:
|
if negative_expense_booked_in_pr:
|
||||||
if for_validate and item.expense_account and item.expense_account != stock_not_billed_account:
|
if for_validate and item.expense_account and item.expense_account != stock_not_billed_account:
|
||||||
msg = _("Row {}: Expense Head changed to {} ").format(item.idx, frappe.bold(stock_not_billed_account))
|
msg = _("Row {0}: Expense Head changed to {1} because expense is booked against this account in Purchase Receipt {2}").format(
|
||||||
msg += _("because expense is booked against this account in Purchase Receipt {}").format(frappe.bold(item.purchase_receipt))
|
item.idx, frappe.bold(stock_not_billed_account), frappe.bold(item.purchase_receipt))
|
||||||
frappe.msgprint(msg, title=_("Expense Head Changed"))
|
frappe.msgprint(msg, title=_("Expense Head Changed"))
|
||||||
|
|
||||||
item.expense_account = stock_not_billed_account
|
item.expense_account = stock_not_billed_account
|
||||||
@ -275,8 +270,9 @@ class PurchaseInvoice(BuyingController):
|
|||||||
# If no purchase receipt present then book expense in 'Stock Received But Not Billed'
|
# If no purchase receipt present then book expense in 'Stock Received But Not Billed'
|
||||||
# This is done in cases when Purchase Invoice is created before Purchase Receipt
|
# This is done in cases when Purchase Invoice is created before Purchase Receipt
|
||||||
if for_validate and item.expense_account and item.expense_account != stock_not_billed_account:
|
if for_validate and item.expense_account and item.expense_account != stock_not_billed_account:
|
||||||
msg = _("Row {}: Expense Head changed to {} ").format(item.idx, frappe.bold(stock_not_billed_account))
|
msg = _("Row {0}: Expense Head changed to {1} as no Purchase Receipt is created against Item {2}.").format(
|
||||||
msg += _("as no Purchase Receipt is created against Item {}. ").format(frappe.bold(item.item_code))
|
item.idx, frappe.bold(stock_not_billed_account), frappe.bold(item.item_code))
|
||||||
|
msg += "<br>"
|
||||||
msg += _("This is done to handle accounting for cases when Purchase Receipt is created after Purchase Invoice")
|
msg += _("This is done to handle accounting for cases when Purchase Receipt is created after Purchase Invoice")
|
||||||
frappe.msgprint(msg, title=_("Expense Head Changed"))
|
frappe.msgprint(msg, title=_("Expense Head Changed"))
|
||||||
|
|
||||||
@ -308,8 +304,8 @@ class PurchaseInvoice(BuyingController):
|
|||||||
if not d.purchase_order:
|
if not d.purchase_order:
|
||||||
msg = _("Purchase Order Required for item {}").format(frappe.bold(d.item_code))
|
msg = _("Purchase Order Required for item {}").format(frappe.bold(d.item_code))
|
||||||
msg += "<br><br>"
|
msg += "<br><br>"
|
||||||
msg += _("To submit the invoice without purchase order please set {} ").format(frappe.bold(_('Purchase Order Required')))
|
msg += _("To submit the invoice without purchase order please set {0} as {1} in {2}").format(
|
||||||
msg += _("as {} in {}").format(frappe.bold('No'), get_link_to_form('Buying Settings', 'Buying Settings', 'Buying Settings'))
|
frappe.bold(_('Purchase Order Required')), frappe.bold('No'), get_link_to_form('Buying Settings', 'Buying Settings', 'Buying Settings'))
|
||||||
throw(msg, title=_("Mandatory Purchase Order"))
|
throw(msg, title=_("Mandatory Purchase Order"))
|
||||||
|
|
||||||
def pr_required(self):
|
def pr_required(self):
|
||||||
@ -323,8 +319,8 @@ class PurchaseInvoice(BuyingController):
|
|||||||
if not d.purchase_receipt and d.item_code in stock_items:
|
if not d.purchase_receipt and d.item_code in stock_items:
|
||||||
msg = _("Purchase Receipt Required for item {}").format(frappe.bold(d.item_code))
|
msg = _("Purchase Receipt Required for item {}").format(frappe.bold(d.item_code))
|
||||||
msg += "<br><br>"
|
msg += "<br><br>"
|
||||||
msg += _("To submit the invoice without purchase receipt please set {} ").format(frappe.bold(_('Purchase Receipt Required')))
|
msg += _("To submit the invoice without purchase receipt please set {0} as {1} in {2}").format(
|
||||||
msg += _("as {} in {}").format(frappe.bold('No'), get_link_to_form('Buying Settings', 'Buying Settings', 'Buying Settings'))
|
frappe.bold(_('Purchase Receipt Required')), frappe.bold('No'), get_link_to_form('Buying Settings', 'Buying Settings', 'Buying Settings'))
|
||||||
throw(msg, title=_("Mandatory Purchase Receipt"))
|
throw(msg, title=_("Mandatory Purchase Receipt"))
|
||||||
|
|
||||||
def validate_write_off_account(self):
|
def validate_write_off_account(self):
|
||||||
@ -456,6 +452,8 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.make_tax_gl_entries(gl_entries)
|
self.make_tax_gl_entries(gl_entries)
|
||||||
self.make_internal_transfer_gl_entries(gl_entries)
|
self.make_internal_transfer_gl_entries(gl_entries)
|
||||||
|
|
||||||
|
self.allocate_advance_taxes(gl_entries)
|
||||||
|
|
||||||
gl_entries = make_regional_gl_entries(gl_entries, self)
|
gl_entries = make_regional_gl_entries(gl_entries, self)
|
||||||
|
|
||||||
gl_entries = merge_similar_entries(gl_entries)
|
gl_entries = merge_similar_entries(gl_entries)
|
||||||
@ -1090,6 +1088,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
for d in self.taxes:
|
for d in self.taxes:
|
||||||
if d.account_head == tax_withholding_details.get("account_head"):
|
if d.account_head == tax_withholding_details.get("account_head"):
|
||||||
d.update(tax_withholding_details)
|
d.update(tax_withholding_details)
|
||||||
|
|
||||||
accounts.append(d.account_head)
|
accounts.append(d.account_head)
|
||||||
|
|
||||||
if not accounts or tax_withholding_details.get("account_head") not in accounts:
|
if not accounts or tax_withholding_details.get("account_head") not in accounts:
|
||||||
|
@ -16,6 +16,7 @@ from erpnext.stock.doctype.stock_entry.test_stock_entry import get_qty_after_tra
|
|||||||
from erpnext.projects.doctype.project.test_project import make_project
|
from erpnext.projects.doctype.project.test_project import make_project
|
||||||
from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account
|
from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account
|
||||||
from erpnext.stock.doctype.item.test_item import create_item
|
from erpnext.stock.doctype.item.test_item import create_item
|
||||||
|
from erpnext.buying.doctype.supplier.test_supplier import create_supplier
|
||||||
|
|
||||||
test_dependencies = ["Item", "Cost Center", "Payment Term", "Payment Terms Template"]
|
test_dependencies = ["Item", "Cost Center", "Payment Term", "Payment Terms Template"]
|
||||||
test_ignore = ["Serial No"]
|
test_ignore = ["Serial No"]
|
||||||
@ -950,6 +951,102 @@ class TestPurchaseInvoice(unittest.TestCase):
|
|||||||
acc_settings.submit_journal_entriessubmit_journal_entries = 0
|
acc_settings.submit_journal_entriessubmit_journal_entries = 0
|
||||||
acc_settings.save()
|
acc_settings.save()
|
||||||
|
|
||||||
|
def test_purchase_invoice_advance_taxes(self):
|
||||||
|
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
|
||||||
|
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
|
||||||
|
from erpnext.buying.doctype.purchase_order.purchase_order import get_mapped_purchase_invoice
|
||||||
|
|
||||||
|
# create a new supplier to test
|
||||||
|
supplier = create_supplier(supplier_name = '_Test TDS Advance Supplier',
|
||||||
|
tax_withholding_category = 'TDS - 194 - Dividends - Individual')
|
||||||
|
|
||||||
|
# Update tax withholding category with current fiscal year and rate details
|
||||||
|
update_tax_witholding_category('_Test Company', 'TDS Payable - _TC', nowdate())
|
||||||
|
|
||||||
|
# Create Purchase Order with TDS applied
|
||||||
|
po = create_purchase_order(do_not_save=1, supplier=supplier.name, rate=3000)
|
||||||
|
po.apply_tds = 1
|
||||||
|
po.tax_withholding_category = 'TDS - 194 - Dividends - Individual'
|
||||||
|
po.save()
|
||||||
|
po.submit()
|
||||||
|
|
||||||
|
# Update Unrealized Profit / Loss Account which is used as default advance tax account
|
||||||
|
frappe.db.set_value('Company', '_Test Company', 'unrealized_profit_loss_account', '_Test Account Excise Duty - _TC')
|
||||||
|
|
||||||
|
# Create Payment Entry Against the order
|
||||||
|
payment_entry = get_payment_entry(dt='Purchase Order', dn=po.name)
|
||||||
|
payment_entry.paid_from = 'Cash - _TC'
|
||||||
|
payment_entry.save()
|
||||||
|
payment_entry.submit()
|
||||||
|
|
||||||
|
# Check GLE for Payment Entry
|
||||||
|
expected_gle = [
|
||||||
|
['_Test Account Excise Duty - _TC', 3000, 0],
|
||||||
|
['Cash - _TC', 0, 27000],
|
||||||
|
['Creditors - _TC', 27000, 0],
|
||||||
|
['TDS Payable - _TC', 0, 3000],
|
||||||
|
]
|
||||||
|
|
||||||
|
gl_entries = frappe.db.sql("""select account, debit, credit
|
||||||
|
from `tabGL Entry`
|
||||||
|
where voucher_type='Payment Entry' and voucher_no=%s
|
||||||
|
order by account asc""", (payment_entry.name), as_dict=1)
|
||||||
|
|
||||||
|
for i, gle in enumerate(gl_entries):
|
||||||
|
self.assertEqual(expected_gle[i][0], gle.account)
|
||||||
|
self.assertEqual(expected_gle[i][1], gle.debit)
|
||||||
|
self.assertEqual(expected_gle[i][2], gle.credit)
|
||||||
|
|
||||||
|
# Create Purchase Invoice against Purchase Order
|
||||||
|
purchase_invoice = get_mapped_purchase_invoice(po.name)
|
||||||
|
purchase_invoice.allocate_advances_automatically = 1
|
||||||
|
purchase_invoice.items[0].expense_account = '_Test Account Cost for Goods Sold - _TC'
|
||||||
|
purchase_invoice.save()
|
||||||
|
purchase_invoice.submit()
|
||||||
|
|
||||||
|
# Check GLE for Purchase Invoice
|
||||||
|
# Zero net effect on final TDS Payable on invoice
|
||||||
|
expected_gle = [
|
||||||
|
['_Test Account Cost for Goods Sold - _TC', 30000, 0],
|
||||||
|
['_Test Account Excise Duty - _TC', 0, 3000],
|
||||||
|
['Creditors - _TC', 0, 27000],
|
||||||
|
['TDS Payable - _TC', 3000, 3000]
|
||||||
|
]
|
||||||
|
|
||||||
|
gl_entries = frappe.db.sql("""select account, debit, credit
|
||||||
|
from `tabGL Entry`
|
||||||
|
where voucher_type='Purchase Invoice' and voucher_no=%s
|
||||||
|
order by account asc""", (purchase_invoice.name), as_dict=1)
|
||||||
|
|
||||||
|
for i, gle in enumerate(gl_entries):
|
||||||
|
self.assertEqual(expected_gle[i][0], gle.account)
|
||||||
|
self.assertEqual(expected_gle[i][1], gle.debit)
|
||||||
|
self.assertEqual(expected_gle[i][2], gle.credit)
|
||||||
|
|
||||||
|
def update_tax_witholding_category(company, account, date):
|
||||||
|
from erpnext.accounts.utils import get_fiscal_year
|
||||||
|
|
||||||
|
fiscal_year = get_fiscal_year(date=date, company=company)
|
||||||
|
|
||||||
|
if not frappe.db.get_value('Tax Withholding Rate',
|
||||||
|
{'parent': 'TDS - 194 - Dividends - Individual', 'fiscal_year': fiscal_year[0]}):
|
||||||
|
tds_category = frappe.get_doc('Tax Withholding Category', 'TDS - 194 - Dividends - Individual')
|
||||||
|
tds_category.append('rates', {
|
||||||
|
'fiscal_year': fiscal_year[0],
|
||||||
|
'tax_withholding_rate': 10,
|
||||||
|
'single_threshold': 2500,
|
||||||
|
'cumulative_threshold': 0
|
||||||
|
})
|
||||||
|
tds_category.save()
|
||||||
|
|
||||||
|
if not frappe.db.get_value('Tax Withholding Account',
|
||||||
|
{'parent': 'TDS - 194 - Dividends - Individual', 'account': account}):
|
||||||
|
tds_category = frappe.get_doc('Tax Withholding Category', 'TDS - 194 - Dividends - Individual')
|
||||||
|
tds_category.append('accounts', {
|
||||||
|
'company': company,
|
||||||
|
'account': account
|
||||||
|
})
|
||||||
|
tds_category.save()
|
||||||
|
|
||||||
def unlink_payment_on_cancel_of_invoice(enable=1):
|
def unlink_payment_on_cancel_of_invoice(enable=1):
|
||||||
accounts_settings = frappe.get_doc("Accounts Settings")
|
accounts_settings = frappe.get_doc("Accounts Settings")
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"charge_type",
|
"charge_type",
|
||||||
"row_id",
|
"row_id",
|
||||||
"included_in_print_rate",
|
"included_in_print_rate",
|
||||||
|
"included_in_paid_amount",
|
||||||
"col_break1",
|
"col_break1",
|
||||||
"account_head",
|
"account_head",
|
||||||
"description",
|
"description",
|
||||||
@ -21,6 +22,7 @@
|
|||||||
"cost_center",
|
"cost_center",
|
||||||
"dimension_col_break",
|
"dimension_col_break",
|
||||||
"section_break_9",
|
"section_break_9",
|
||||||
|
"currency",
|
||||||
"tax_amount",
|
"tax_amount",
|
||||||
"tax_amount_after_discount_amount",
|
"tax_amount_after_discount_amount",
|
||||||
"total",
|
"total",
|
||||||
@ -205,12 +207,27 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "dimension_col_break",
|
"fieldname": "dimension_col_break",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "account_head.account_currency",
|
||||||
|
"fieldname": "currency",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Account Currency",
|
||||||
|
"options": "Currency",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"description": "If checked, the tax amount will be considered as already included in the Paid Amount in Payment Entry",
|
||||||
|
"fieldname": "included_in_paid_amount",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Considered In Paid Amount"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-09-18 17:26:09.703215",
|
"modified": "2021-06-09 11:48:25.335733",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Purchase Taxes and Charges",
|
"name": "Purchase Taxes and Charges",
|
||||||
|
@ -842,6 +842,8 @@ class SalesInvoice(SellingController):
|
|||||||
self.make_tax_gl_entries(gl_entries)
|
self.make_tax_gl_entries(gl_entries)
|
||||||
self.make_internal_transfer_gl_entries(gl_entries)
|
self.make_internal_transfer_gl_entries(gl_entries)
|
||||||
|
|
||||||
|
self.allocate_advance_taxes(gl_entries)
|
||||||
|
|
||||||
self.make_item_gl_entries(gl_entries)
|
self.make_item_gl_entries(gl_entries)
|
||||||
|
|
||||||
# merge gl entries before adding pos entries
|
# merge gl entries before adding pos entries
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"creation": "2013-04-24 11:39:32",
|
"creation": "2013-04-24 11:39:32",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Setup",
|
"document_type": "Setup",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"charge_type",
|
"charge_type",
|
||||||
"row_id",
|
"row_id",
|
||||||
@ -10,12 +12,14 @@
|
|||||||
"col_break_1",
|
"col_break_1",
|
||||||
"description",
|
"description",
|
||||||
"included_in_print_rate",
|
"included_in_print_rate",
|
||||||
|
"included_in_paid_amount",
|
||||||
"accounting_dimensions_section",
|
"accounting_dimensions_section",
|
||||||
"cost_center",
|
"cost_center",
|
||||||
"dimension_col_break",
|
"dimension_col_break",
|
||||||
"section_break_8",
|
"section_break_8",
|
||||||
"rate",
|
"rate",
|
||||||
"section_break_9",
|
"section_break_9",
|
||||||
|
"currency",
|
||||||
"tax_amount",
|
"tax_amount",
|
||||||
"total",
|
"total",
|
||||||
"tax_amount_after_discount_amount",
|
"tax_amount_after_discount_amount",
|
||||||
@ -23,8 +27,7 @@
|
|||||||
"base_tax_amount",
|
"base_tax_amount",
|
||||||
"base_total",
|
"base_total",
|
||||||
"base_tax_amount_after_discount_amount",
|
"base_tax_amount_after_discount_amount",
|
||||||
"item_wise_tax_detail",
|
"item_wise_tax_detail"
|
||||||
"parenttype"
|
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@ -173,17 +176,6 @@
|
|||||||
"oldfieldtype": "Small Text",
|
"oldfieldtype": "Small Text",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "parenttype",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 1,
|
|
||||||
"in_filter": 1,
|
|
||||||
"label": "Parenttype",
|
|
||||||
"oldfieldname": "parenttype",
|
|
||||||
"oldfieldtype": "Data",
|
|
||||||
"print_hide": 1,
|
|
||||||
"search_index": 1
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "accounting_dimensions_section",
|
"fieldname": "accounting_dimensions_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
@ -192,15 +184,33 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "dimension_col_break",
|
"fieldname": "dimension_col_break",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "account_head.account_currency",
|
||||||
|
"fieldname": "currency",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Account Currency",
|
||||||
|
"options": "Currency",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"description": "If checked, the tax amount will be considered as already included in the Paid Amount in Payment Entry",
|
||||||
|
"fieldname": "included_in_paid_amount",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Considered In Paid Amount"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-05-25 22:59:38.740883",
|
"links": [],
|
||||||
|
"modified": "2021-06-09 11:48:04.691596",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Taxes and Charges",
|
"name": "Sales Taxes and Charges",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
|
"sort_field": "modified",
|
||||||
"sort_order": "ASC"
|
"sort_order": "ASC"
|
||||||
}
|
}
|
@ -49,7 +49,7 @@ def get_party_tax_withholding_details(inv, tax_withholding_category=None):
|
|||||||
if not parties:
|
if not parties:
|
||||||
parties.append(party)
|
parties.append(party)
|
||||||
|
|
||||||
fiscal_year = get_fiscal_year(inv.posting_date, company=inv.company)
|
fiscal_year = get_fiscal_year(inv.get('posting_date') or inv.get('transaction_date'), company=inv.company)
|
||||||
tax_details = get_tax_withholding_details(tax_withholding_category, fiscal_year[0], inv.company)
|
tax_details = get_tax_withholding_details(tax_withholding_category, fiscal_year[0], inv.company)
|
||||||
|
|
||||||
if not tax_details:
|
if not tax_details:
|
||||||
@ -154,7 +154,7 @@ def get_tax_amount(party_type, parties, inv, tax_details, fiscal_year_details, p
|
|||||||
tax_deducted = get_deducted_tax(taxable_vouchers, fiscal_year, tax_details)
|
tax_deducted = get_deducted_tax(taxable_vouchers, fiscal_year, tax_details)
|
||||||
|
|
||||||
tax_amount = 0
|
tax_amount = 0
|
||||||
posting_date = inv.posting_date
|
posting_date = inv.get('posting_date') or inv.get('transaction_date')
|
||||||
if party_type == 'Supplier':
|
if party_type == 'Supplier':
|
||||||
ldc = get_lower_deduction_certificate(fiscal_year, pan_no)
|
ldc = get_lower_deduction_certificate(fiscal_year, pan_no)
|
||||||
if tax_deducted:
|
if tax_deducted:
|
||||||
@ -257,7 +257,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, fiscal_year_details, tax_dedu
|
|||||||
if ((threshold and inv.net_total >= threshold) or (cumulative_threshold and supp_credit_amt >= cumulative_threshold)):
|
if ((threshold and inv.net_total >= threshold) or (cumulative_threshold and supp_credit_amt >= cumulative_threshold)):
|
||||||
if ldc and is_valid_certificate(
|
if ldc and is_valid_certificate(
|
||||||
ldc.valid_from, ldc.valid_upto,
|
ldc.valid_from, ldc.valid_upto,
|
||||||
inv.posting_date, tax_deducted,
|
inv.get('posting_date') or inv.get('transaction_date'), tax_deducted,
|
||||||
inv.net_total, ldc.certificate_limit
|
inv.net_total, ldc.certificate_limit
|
||||||
):
|
):
|
||||||
tds_amount = get_ltds_amount(supp_credit_amt, 0, ldc.certificate_limit, ldc.rate, tax_details)
|
tds_amount = get_ltds_amount(supp_credit_amt, 0, ldc.certificate_limit, ldc.rate, tax_details)
|
||||||
|
@ -54,6 +54,32 @@ frappe.query_reports["TDS Payable Monthly"] = {
|
|||||||
frappe.query_report.refresh();
|
frappe.query_report.refresh();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"purchase_order",
|
||||||
|
"label": __("Purchase Order"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Purchase Order",
|
||||||
|
"get_query": function() {
|
||||||
|
return {
|
||||||
|
"filters": {
|
||||||
|
"name": ["in", frappe.query_report.invoices]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
on_change: function() {
|
||||||
|
let supplier = frappe.query_report.get_filter_value('supplier');
|
||||||
|
if(!supplier) return; // return if no supplier selected
|
||||||
|
|
||||||
|
// filter invoices based on selected supplier
|
||||||
|
let invoices = [];
|
||||||
|
frappe.query_report.invoice_data.map(d => {
|
||||||
|
if(d.supplier==supplier)
|
||||||
|
invoices.push(d.name)
|
||||||
|
});
|
||||||
|
frappe.query_report.invoices = invoices;
|
||||||
|
frappe.query_report.refresh();
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname":"from_date",
|
"fieldname":"from_date",
|
||||||
"label": __("From Date"),
|
"label": __("From Date"),
|
||||||
@ -75,15 +101,17 @@ frappe.query_reports["TDS Payable Monthly"] = {
|
|||||||
onload: function(report) {
|
onload: function(report) {
|
||||||
// fetch all tds applied invoices
|
// fetch all tds applied invoices
|
||||||
frappe.call({
|
frappe.call({
|
||||||
"method": "erpnext.accounts.report.tds_payable_monthly.tds_payable_monthly.get_tds_invoices",
|
"method": "erpnext.accounts.report.tds_payable_monthly.tds_payable_monthly.get_tds_invoices_and_orders",
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
let invoices = [];
|
let invoices = [];
|
||||||
|
|
||||||
r.message.map(d => {
|
r.message.map(d => {
|
||||||
invoices.push(d.name);
|
invoices.push(d.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
report["invoice_data"] = r.message;
|
report["invoice_data"] = r.message.invoices;
|
||||||
report["invoices"] = invoices;
|
report["invoices"] = invoices;
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,14 @@ def execute(filters=None):
|
|||||||
validate_filters(filters)
|
validate_filters(filters)
|
||||||
set_filters(filters)
|
set_filters(filters)
|
||||||
|
|
||||||
|
# TDS payment entries
|
||||||
|
payment_entries = get_payment_entires(filters)
|
||||||
|
|
||||||
columns = get_columns(filters)
|
columns = get_columns(filters)
|
||||||
if not filters["invoices"]:
|
if not filters.get("invoices"):
|
||||||
return columns, []
|
return columns, []
|
||||||
|
|
||||||
res = get_result(filters)
|
res = get_result(filters, payment_entries)
|
||||||
|
|
||||||
return columns, res
|
return columns, res
|
||||||
|
|
||||||
@ -27,8 +30,9 @@ def validate_filters(filters):
|
|||||||
def set_filters(filters):
|
def set_filters(filters):
|
||||||
invoices = []
|
invoices = []
|
||||||
|
|
||||||
if not filters["invoices"]:
|
if not filters.get("invoices"):
|
||||||
filters["invoices"] = get_tds_invoices()
|
filters["invoices"] = get_tds_invoices_and_orders()
|
||||||
|
|
||||||
if filters.supplier and filters.purchase_invoice:
|
if filters.supplier and filters.purchase_invoice:
|
||||||
for d in filters["invoices"]:
|
for d in filters["invoices"]:
|
||||||
if d.name == filters.purchase_invoice and d.supplier == filters.supplier:
|
if d.name == filters.purchase_invoice and d.supplier == filters.supplier:
|
||||||
@ -41,13 +45,29 @@ def set_filters(filters):
|
|||||||
for d in filters["invoices"]:
|
for d in filters["invoices"]:
|
||||||
if d.name == filters.purchase_invoice:
|
if d.name == filters.purchase_invoice:
|
||||||
invoices.append(d)
|
invoices.append(d)
|
||||||
|
elif filters.supplier and filters.purchase_order:
|
||||||
|
for d in filters.get("invoices"):
|
||||||
|
if d.name == filters.purchase_order and d.supplier == filters.supplier:
|
||||||
|
invoices.append(d)
|
||||||
|
elif filters.supplier and not filters.purchase_order:
|
||||||
|
for d in filters.get("invoices"):
|
||||||
|
if d.supplier == filters.supplier:
|
||||||
|
invoices.append(d)
|
||||||
|
elif filters.purchase_order and not filters.supplier:
|
||||||
|
for d in filters.get("invoices"):
|
||||||
|
if d.name == filters.purchase_order:
|
||||||
|
invoices.append(d)
|
||||||
|
|
||||||
filters["invoices"] = invoices if invoices else filters["invoices"]
|
filters["invoices"] = invoices if invoices else filters["invoices"]
|
||||||
filters.naming_series = frappe.db.get_single_value('Buying Settings', 'supp_master_name')
|
filters.naming_series = frappe.db.get_single_value('Buying Settings', 'supp_master_name')
|
||||||
|
|
||||||
def get_result(filters):
|
#print(filters.get('invoices'))
|
||||||
supplier_map, tds_docs = get_supplier_map(filters)
|
|
||||||
gle_map = get_gle_map(filters)
|
def get_result(filters, payment_entries):
|
||||||
|
supplier_map, tds_docs = get_supplier_map(filters, payment_entries)
|
||||||
|
documents = [d.get('name') for d in filters.get('invoices')] + [d.get('name') for d in payment_entries]
|
||||||
|
|
||||||
|
gle_map = get_gle_map(filters, documents)
|
||||||
|
|
||||||
out = []
|
out = []
|
||||||
for d in gle_map:
|
for d in gle_map:
|
||||||
@ -62,10 +82,11 @@ def get_result(filters):
|
|||||||
|
|
||||||
for k in gle_map[d]:
|
for k in gle_map[d]:
|
||||||
if k.party == supplier_map[d] and k.credit > 0:
|
if k.party == supplier_map[d] and k.credit > 0:
|
||||||
total_amount_credited += k.credit
|
total_amount_credited += (k.credit - k.debit)
|
||||||
elif account_list and k.account == account and k.credit > 0:
|
elif account_list and k.account == account and (k.credit - k.debit) > 0:
|
||||||
tds_deducted = k.credit
|
tds_deducted = (k.credit - k.debit)
|
||||||
total_amount_credited += k.credit
|
total_amount_credited += (k.credit - k.debit)
|
||||||
|
voucher_type = k.voucher_type
|
||||||
|
|
||||||
rate = [i.tax_withholding_rate for i in tds_doc.rates
|
rate = [i.tax_withholding_rate for i in tds_doc.rates
|
||||||
if i.fiscal_year == gle_map[d][0].fiscal_year]
|
if i.fiscal_year == gle_map[d][0].fiscal_year]
|
||||||
@ -73,32 +94,36 @@ def get_result(filters):
|
|||||||
if rate and len(rate) > 0 and tds_deducted:
|
if rate and len(rate) > 0 and tds_deducted:
|
||||||
rate = rate[0]
|
rate = rate[0]
|
||||||
|
|
||||||
if getdate(filters.from_date) <= gle_map[d][0].posting_date \
|
row = [supplier.pan, supplier.name]
|
||||||
and getdate(filters.to_date) >= gle_map[d][0].posting_date:
|
|
||||||
row = [supplier.pan, supplier.name]
|
|
||||||
|
|
||||||
if filters.naming_series == 'Naming Series':
|
if filters.naming_series == 'Naming Series':
|
||||||
row.append(supplier.supplier_name)
|
row.append(supplier.supplier_name)
|
||||||
|
|
||||||
row.extend([tds_doc.name, supplier.supplier_type, rate, total_amount_credited,
|
row.extend([tds_doc.name, supplier.supplier_type, rate, total_amount_credited,
|
||||||
tds_deducted, gle_map[d][0].posting_date, "Purchase Invoice", d])
|
tds_deducted, gle_map[d][0].posting_date, voucher_type, d])
|
||||||
out.append(row)
|
out.append(row)
|
||||||
|
|
||||||
return out
|
return out
|
||||||
|
|
||||||
def get_supplier_map(filters):
|
def get_supplier_map(filters, payment_entries):
|
||||||
# create a supplier_map of the form {"purchase_invoice": {supplier_name, pan, tds_name}}
|
# create a supplier_map of the form {"purchase_invoice": {supplier_name, pan, tds_name}}
|
||||||
# pre-fetch all distinct applicable tds docs
|
# pre-fetch all distinct applicable tds docs
|
||||||
supplier_map, tds_docs = {}, {}
|
supplier_map, tds_docs = {}, {}
|
||||||
pan = "pan" if frappe.db.has_column("Supplier", "pan") else "tax_id"
|
pan = "pan" if frappe.db.has_column("Supplier", "pan") else "tax_id"
|
||||||
|
supplier_list = [d.supplier for d in filters["invoices"]]
|
||||||
|
|
||||||
supplier_detail = frappe.db.get_all('Supplier',
|
supplier_detail = frappe.db.get_all('Supplier',
|
||||||
{"name": ["in", [d.supplier for d in filters["invoices"]]]},
|
{"name": ["in", supplier_list]},
|
||||||
["tax_withholding_category", "name", pan+" as pan", "supplier_type", "supplier_name"])
|
["tax_withholding_category", "name", pan+" as pan", "supplier_type", "supplier_name"])
|
||||||
|
|
||||||
for d in filters["invoices"]:
|
for d in filters["invoices"]:
|
||||||
supplier_map[d.get("name")] = [k for k in supplier_detail
|
supplier_map[d.get("name")] = [k for k in supplier_detail
|
||||||
if k.name == d.get("supplier")][0]
|
if k.name == d.get("supplier")][0]
|
||||||
|
|
||||||
|
for d in payment_entries:
|
||||||
|
supplier_map[d.get("name")] = [k for k in supplier_detail
|
||||||
|
if k.name == d.get("supplier")][0]
|
||||||
|
|
||||||
for d in supplier_detail:
|
for d in supplier_detail:
|
||||||
if d.get("tax_withholding_category") not in tds_docs:
|
if d.get("tax_withholding_category") not in tds_docs:
|
||||||
tds_docs[d.get("tax_withholding_category")] = \
|
tds_docs[d.get("tax_withholding_category")] = \
|
||||||
@ -106,13 +131,19 @@ def get_supplier_map(filters):
|
|||||||
|
|
||||||
return supplier_map, tds_docs
|
return supplier_map, tds_docs
|
||||||
|
|
||||||
def get_gle_map(filters):
|
def get_gle_map(filters, documents):
|
||||||
# create gle_map of the form
|
# create gle_map of the form
|
||||||
# {"purchase_invoice": list of dict of all gle created for this invoice}
|
# {"purchase_invoice": list of dict of all gle created for this invoice}
|
||||||
gle_map = {}
|
gle_map = {}
|
||||||
gle = frappe.db.get_all('GL Entry',\
|
|
||||||
{"voucher_no": ["in", [d.get("name") for d in filters["invoices"]]], 'is_cancelled': 0},
|
gle = frappe.db.get_all('GL Entry',
|
||||||
["fiscal_year", "credit", "debit", "account", "voucher_no", "posting_date"])
|
{
|
||||||
|
"voucher_no": ["in", documents],
|
||||||
|
'is_cancelled': 0,
|
||||||
|
'posting_date': ("between", [filters.get('from_date'), filters.get('to_date')]),
|
||||||
|
},
|
||||||
|
["fiscal_year", "credit", "debit", "account", "voucher_no", "posting_date", "voucher_type"],
|
||||||
|
)
|
||||||
|
|
||||||
for d in gle:
|
for d in gle:
|
||||||
if not d.voucher_no in gle_map:
|
if not d.voucher_no in gle_map:
|
||||||
@ -201,8 +232,26 @@ def get_columns(filters):
|
|||||||
|
|
||||||
return columns
|
return columns
|
||||||
|
|
||||||
|
def get_payment_entires(filters):
|
||||||
|
filter_dict = {
|
||||||
|
'posting_date': ("between", [filters.get('from_date'), filters.get('to_date')]),
|
||||||
|
'party_type': 'Supplier',
|
||||||
|
'apply_tax_withholding_amount': 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if filters.get('purchase_invoice') or filters.get('purchase_order'):
|
||||||
|
parent = frappe.db.get_all('Payment Entry Reference',
|
||||||
|
{'reference_name': ('in', [d.get('name') for d in filters.get('invoices')])}, ['parent'])
|
||||||
|
|
||||||
|
filter_dict.update({'name': ('in', [d.get('parent') for d in parent])})
|
||||||
|
|
||||||
|
payment_entries = frappe.get_all('Payment Entry', fields=['name', 'party_name as supplier'],
|
||||||
|
filters=filter_dict)
|
||||||
|
|
||||||
|
return payment_entries
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_tds_invoices():
|
def get_tds_invoices_and_orders():
|
||||||
# fetch tds applicable supplier and fetch invoices for these suppliers
|
# fetch tds applicable supplier and fetch invoices for these suppliers
|
||||||
suppliers = [d.name for d in frappe.db.get_list("Supplier",
|
suppliers = [d.name for d in frappe.db.get_list("Supplier",
|
||||||
{"tax_withholding_category": ["!=", ""]}, ["name"])]
|
{"tax_withholding_category": ["!=", ""]}, ["name"])]
|
||||||
@ -210,7 +259,12 @@ def get_tds_invoices():
|
|||||||
invoices = frappe.db.get_list("Purchase Invoice",
|
invoices = frappe.db.get_list("Purchase Invoice",
|
||||||
{"supplier": ["in", suppliers]}, ["name", "supplier"])
|
{"supplier": ["in", suppliers]}, ["name", "supplier"])
|
||||||
|
|
||||||
|
orders = frappe.db.get_list("Purchase Order",
|
||||||
|
{"supplier": ["in", suppliers]}, ["name", "supplier"])
|
||||||
|
|
||||||
|
invoices = invoices + orders
|
||||||
invoices = [d for d in invoices if d.supplier]
|
invoices = [d for d in invoices if d.supplier]
|
||||||
|
|
||||||
frappe.cache().hset("invoices", frappe.session.user, invoices)
|
frappe.cache().hset("invoices", frappe.session.user, invoices)
|
||||||
|
|
||||||
return invoices
|
return invoices
|
||||||
|
@ -45,6 +45,14 @@ frappe.ui.form.on("Purchase Order", {
|
|||||||
});
|
});
|
||||||
|
|
||||||
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
|
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
|
||||||
|
},
|
||||||
|
|
||||||
|
apply_tds: function(frm) {
|
||||||
|
if (!frm.doc.apply_tds) {
|
||||||
|
frm.set_value("tax_withholding_category", '');
|
||||||
|
} else {
|
||||||
|
frm.set_value("tax_withholding_category", frm.supplier_tds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -313,7 +321,8 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
|
|||||||
if(me.values) {
|
if(me.values) {
|
||||||
me.values.sub_con_rm_items.map((row,i) => {
|
me.values.sub_con_rm_items.map((row,i) => {
|
||||||
if (!row.item_code || !row.rm_item_code || !row.warehouse || !row.qty || row.qty === 0) {
|
if (!row.item_code || !row.rm_item_code || !row.warehouse || !row.qty || row.qty === 0) {
|
||||||
frappe.throw(__("Item Code, warehouse, quantity are required on row {0}", [i+1]));
|
let row_id = i+1;
|
||||||
|
frappe.throw(__("Item Code, warehouse and quantity are required on row {0}", [row_id]));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
me._make_rm_stock_entry(me.dialog.fields_dict.sub_con_rm_items.grid.get_selected_children())
|
me._make_rm_stock_entry(me.dialog.fields_dict.sub_con_rm_items.grid.get_selected_children())
|
||||||
@ -509,7 +518,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
|
|||||||
args: {
|
args: {
|
||||||
reference_doctype: me.frm.doctype,
|
reference_doctype: me.frm.doctype,
|
||||||
reference_name: me.frm.docname,
|
reference_name: me.frm.docname,
|
||||||
content: __('Reason for hold: ')+data.reason_for_hold,
|
content: __('Reason for hold:') + " " +data.reason_for_hold,
|
||||||
comment_email: frappe.session.user,
|
comment_email: frappe.session.user,
|
||||||
comment_by: frappe.session.user_fullname
|
comment_by: frappe.session.user_fullname
|
||||||
},
|
},
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,7 @@ from erpnext.accounts.party import get_party_account_currency
|
|||||||
from six import string_types
|
from six import string_types
|
||||||
from erpnext.stock.doctype.item.item import get_item_defaults
|
from erpnext.stock.doctype.item.item import get_item_defaults
|
||||||
from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
|
from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
|
||||||
|
from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details
|
||||||
from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_doc,\
|
from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_doc,\
|
||||||
unlink_inter_company_doc
|
unlink_inter_company_doc
|
||||||
|
|
||||||
@ -39,11 +40,18 @@ class PurchaseOrder(BuyingController):
|
|||||||
'percent_join_field': 'material_request'
|
'percent_join_field': 'material_request'
|
||||||
}]
|
}]
|
||||||
|
|
||||||
|
def onload(self):
|
||||||
|
supplier_tds = frappe.db.get_value("Supplier", self.supplier, "tax_withholding_category")
|
||||||
|
self.set_onload("supplier_tds", supplier_tds)
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
super(PurchaseOrder, self).validate()
|
super(PurchaseOrder, self).validate()
|
||||||
|
|
||||||
self.set_status()
|
self.set_status()
|
||||||
|
|
||||||
|
# apply tax withholding only if checked and applicable
|
||||||
|
self.set_tax_withholding()
|
||||||
|
|
||||||
self.validate_supplier()
|
self.validate_supplier()
|
||||||
self.validate_schedule_date()
|
self.validate_schedule_date()
|
||||||
validate_for_items(self)
|
validate_for_items(self)
|
||||||
@ -87,6 +95,33 @@ class PurchaseOrder(BuyingController):
|
|||||||
if cint(frappe.db.get_single_value('Buying Settings', 'maintain_same_rate')):
|
if cint(frappe.db.get_single_value('Buying Settings', 'maintain_same_rate')):
|
||||||
self.validate_rate_with_reference_doc([["Supplier Quotation", "supplier_quotation", "supplier_quotation_item"]])
|
self.validate_rate_with_reference_doc([["Supplier Quotation", "supplier_quotation", "supplier_quotation_item"]])
|
||||||
|
|
||||||
|
def set_tax_withholding(self):
|
||||||
|
if not self.apply_tds:
|
||||||
|
return
|
||||||
|
|
||||||
|
tax_withholding_details = get_party_tax_withholding_details(self, self.tax_withholding_category)
|
||||||
|
|
||||||
|
if not tax_withholding_details:
|
||||||
|
return
|
||||||
|
|
||||||
|
accounts = []
|
||||||
|
for d in self.taxes:
|
||||||
|
if d.account_head == tax_withholding_details.get("account_head"):
|
||||||
|
d.update(tax_withholding_details)
|
||||||
|
accounts.append(d.account_head)
|
||||||
|
|
||||||
|
if not accounts or tax_withholding_details.get("account_head") not in accounts:
|
||||||
|
self.append("taxes", tax_withholding_details)
|
||||||
|
|
||||||
|
to_remove = [d for d in self.taxes
|
||||||
|
if not d.tax_amount and d.account_head == tax_withholding_details.get("account_head")]
|
||||||
|
|
||||||
|
for d in to_remove:
|
||||||
|
self.remove(d)
|
||||||
|
|
||||||
|
# calculate totals again after applying TDS
|
||||||
|
self.calculate_taxes_and_totals()
|
||||||
|
|
||||||
def validate_supplier(self):
|
def validate_supplier(self):
|
||||||
prevent_po = frappe.db.get_value("Supplier", self.supplier, 'prevent_pos')
|
prevent_po = frappe.db.get_value("Supplier", self.supplier, 'prevent_pos')
|
||||||
if prevent_po:
|
if prevent_po:
|
||||||
|
@ -1111,7 +1111,7 @@ def create_purchase_order(**args):
|
|||||||
|
|
||||||
po.schedule_date = add_days(nowdate(), 1)
|
po.schedule_date = add_days(nowdate(), 1)
|
||||||
po.company = args.company or "_Test Company"
|
po.company = args.company or "_Test Company"
|
||||||
po.supplier = args.customer or "_Test Supplier"
|
po.supplier = args.supplier or "_Test Supplier"
|
||||||
po.is_subcontracted = args.is_subcontracted or "No"
|
po.is_subcontracted = args.is_subcontracted or "No"
|
||||||
po.currency = args.currency or frappe.get_cached_value('Company', po.company, "default_currency")
|
po.currency = args.currency or frappe.get_cached_value('Company', po.company, "default_currency")
|
||||||
po.conversion_factor = args.conversion_factor or 1
|
po.conversion_factor = args.conversion_factor or 1
|
||||||
|
@ -116,6 +116,8 @@ class AccountsController(TransactionBase):
|
|||||||
|
|
||||||
if self.doctype == 'Purchase Invoice':
|
if self.doctype == 'Purchase Invoice':
|
||||||
self.calculate_paid_amount()
|
self.calculate_paid_amount()
|
||||||
|
# apply tax withholding only if checked and applicable
|
||||||
|
self.set_tax_withholding()
|
||||||
|
|
||||||
if self.doctype in ['Purchase Invoice', 'Sales Invoice']:
|
if self.doctype in ['Purchase Invoice', 'Sales Invoice']:
|
||||||
pos_check_field = "is_pos" if self.doctype=="Sales Invoice" else "is_paid"
|
pos_check_field = "is_pos" if self.doctype=="Sales Invoice" else "is_paid"
|
||||||
@ -700,6 +702,7 @@ class AccountsController(TransactionBase):
|
|||||||
from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries
|
from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries
|
||||||
|
|
||||||
if self.doctype in ["Sales Invoice", "Purchase Invoice"]:
|
if self.doctype in ["Sales Invoice", "Purchase Invoice"]:
|
||||||
|
self.update_allocated_advance_taxes_on_cancel()
|
||||||
if frappe.db.get_single_value('Accounts Settings', 'unlink_payment_on_cancellation_of_invoice'):
|
if frappe.db.get_single_value('Accounts Settings', 'unlink_payment_on_cancellation_of_invoice'):
|
||||||
unlink_ref_doc_from_payment_entries(self)
|
unlink_ref_doc_from_payment_entries(self)
|
||||||
|
|
||||||
@ -707,6 +710,87 @@ class AccountsController(TransactionBase):
|
|||||||
if frappe.db.get_single_value('Accounts Settings', 'unlink_advance_payment_on_cancelation_of_order'):
|
if frappe.db.get_single_value('Accounts Settings', 'unlink_advance_payment_on_cancelation_of_order'):
|
||||||
unlink_ref_doc_from_payment_entries(self)
|
unlink_ref_doc_from_payment_entries(self)
|
||||||
|
|
||||||
|
def get_tax_map(self):
|
||||||
|
tax_map = {}
|
||||||
|
for tax in self.get('taxes'):
|
||||||
|
tax_map.setdefault(tax.account_head, 0.0)
|
||||||
|
tax_map[tax.account_head] += tax.tax_amount
|
||||||
|
|
||||||
|
return tax_map
|
||||||
|
|
||||||
|
def update_allocated_advance_taxes_on_cancel(self):
|
||||||
|
if self.get('advances'):
|
||||||
|
tax_accounts = [d.account_head for d in self.get('taxes')]
|
||||||
|
allocated_tax_map = frappe._dict(frappe.get_all('GL Entry', fields=['account', 'sum(credit - debit)'],
|
||||||
|
filters={'voucher_no': self.name, 'account': ('in', tax_accounts)},
|
||||||
|
group_by='account', as_list=1))
|
||||||
|
|
||||||
|
tax_map = self.get_tax_map()
|
||||||
|
|
||||||
|
for pe in self.get('advances'):
|
||||||
|
if pe.reference_type == 'Payment Entry':
|
||||||
|
pe = frappe.get_doc('Payment Entry', pe.reference_name)
|
||||||
|
for tax in pe.get('taxes'):
|
||||||
|
allocated_amount = tax_map.get(tax.account_head) - allocated_tax_map.get(tax.account_head)
|
||||||
|
if allocated_amount > tax.tax_amount:
|
||||||
|
allocated_amount = tax.tax_amount
|
||||||
|
|
||||||
|
if allocated_amount:
|
||||||
|
frappe.db.set_value('Advance Taxes and Charges', tax.name, 'allocated_amount',
|
||||||
|
tax.allocated_amount - allocated_amount)
|
||||||
|
tax_map[tax.account_head] -= allocated_amount
|
||||||
|
allocated_tax_map[tax.account_head] -= allocated_amount
|
||||||
|
|
||||||
|
def allocate_advance_taxes(self, gl_entries):
|
||||||
|
tax_map = self.get_tax_map()
|
||||||
|
for pe in self.get("advances"):
|
||||||
|
if pe.reference_type == "Payment Entry" and \
|
||||||
|
frappe.db.get_value('Payment Entry', pe.reference_name, 'advance_tax_account'):
|
||||||
|
pe = frappe.get_doc("Payment Entry", pe.reference_name)
|
||||||
|
for tax in pe.get("taxes"):
|
||||||
|
account_currency = get_account_currency(tax.account_head)
|
||||||
|
|
||||||
|
if self.doctype == "Purchase Invoice":
|
||||||
|
dr_or_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
|
||||||
|
rev_dr_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
|
||||||
|
else:
|
||||||
|
dr_or_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
|
||||||
|
rev_dr_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
|
||||||
|
|
||||||
|
party = self.supplier if self.doctype == "Purchase Invoice" else self.customer
|
||||||
|
unallocated_amount = tax.tax_amount - tax.allocated_amount
|
||||||
|
if tax_map.get(tax.account_head):
|
||||||
|
amount = tax_map.get(tax.account_head)
|
||||||
|
if amount < unallocated_amount:
|
||||||
|
unallocated_amount = amount
|
||||||
|
|
||||||
|
gl_entries.append(
|
||||||
|
self.get_gl_dict({
|
||||||
|
"account": tax.account_head,
|
||||||
|
"against": party,
|
||||||
|
dr_or_cr: unallocated_amount,
|
||||||
|
dr_or_cr + "_in_account_currency": unallocated_amount
|
||||||
|
if account_currency==self.company_currency
|
||||||
|
else unallocated_amount,
|
||||||
|
"cost_center": tax.cost_center
|
||||||
|
}, account_currency, item=tax))
|
||||||
|
|
||||||
|
gl_entries.append(
|
||||||
|
self.get_gl_dict({
|
||||||
|
"account": pe.advance_tax_account,
|
||||||
|
"against": party,
|
||||||
|
rev_dr_cr: unallocated_amount,
|
||||||
|
rev_dr_cr + "_in_account_currency": unallocated_amount
|
||||||
|
if account_currency==self.company_currency
|
||||||
|
else unallocated_amount,
|
||||||
|
"cost_center": tax.cost_center
|
||||||
|
}, account_currency, item=tax))
|
||||||
|
|
||||||
|
frappe.db.set_value("Advance Taxes and Charges", tax.name, "allocated_amount",
|
||||||
|
tax.allocated_amount + unallocated_amount)
|
||||||
|
|
||||||
|
tax_map[tax.account_head] -= unallocated_amount
|
||||||
|
|
||||||
def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield):
|
def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield):
|
||||||
from erpnext.controllers.status_updater import get_allowance_for
|
from erpnext.controllers.status_updater import get_allowance_for
|
||||||
item_allowance = {}
|
item_allowance = {}
|
||||||
@ -1240,7 +1324,6 @@ def get_advance_payment_entries(party_type, party, party_account, order_doctype,
|
|||||||
|
|
||||||
return list(payment_entries_against_order) + list(unallocated_payment_entries)
|
return list(payment_entries_against_order) + list(unallocated_payment_entries)
|
||||||
|
|
||||||
|
|
||||||
def update_invoice_status():
|
def update_invoice_status():
|
||||||
# Daily update the status of the invoices
|
# Daily update the status of the invoices
|
||||||
|
|
||||||
|
@ -686,7 +686,6 @@ class calculate_taxes_and_totals(object):
|
|||||||
|
|
||||||
self.calculate_paid_amount()
|
self.calculate_paid_amount()
|
||||||
|
|
||||||
|
|
||||||
def get_itemised_tax_breakup_html(doc):
|
def get_itemised_tax_breakup_html(doc):
|
||||||
if not doc.taxes:
|
if not doc.taxes:
|
||||||
return
|
return
|
||||||
|
@ -156,31 +156,31 @@ cur_frm.cscript.validate_taxes_and_charges = function(cdt, cdn) {
|
|||||||
var d = locals[cdt][cdn];
|
var d = locals[cdt][cdn];
|
||||||
var msg = "";
|
var msg = "";
|
||||||
|
|
||||||
if(d.account_head && !d.description) {
|
if (d.account_head && !d.description) {
|
||||||
// set description from account head
|
// set description from account head
|
||||||
d.description = d.account_head.split(' - ').slice(0, -1).join(' - ');
|
d.description = d.account_head.split(' - ').slice(0, -1).join(' - ');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!d.charge_type && (d.row_id || d.rate || d.tax_amount)) {
|
if (!d.charge_type && (d.row_id || d.rate || d.tax_amount)) {
|
||||||
msg = __("Please select Charge Type first");
|
msg = __("Please select Charge Type first");
|
||||||
d.row_id = "";
|
d.row_id = "";
|
||||||
d.rate = d.tax_amount = 0.0;
|
d.rate = d.tax_amount = 0.0;
|
||||||
} else if((d.charge_type == 'Actual' || d.charge_type == 'On Net Total') && d.row_id) {
|
} else if ((d.charge_type == 'Actual' || d.charge_type == 'On Net Total' || d.charge_type == 'On Paid Amount') && d.row_id) {
|
||||||
msg = __("Can refer row only if the charge type is 'On Previous Row Amount' or 'Previous Row Total'");
|
msg = __("Can refer row only if the charge type is 'On Previous Row Amount' or 'Previous Row Total'");
|
||||||
d.row_id = "";
|
d.row_id = "";
|
||||||
} else if((d.charge_type == 'On Previous Row Amount' || d.charge_type == 'On Previous Row Total') && d.row_id) {
|
} else if ((d.charge_type == 'On Previous Row Amount' || d.charge_type == 'On Previous Row Total') && d.row_id) {
|
||||||
if (d.idx == 1) {
|
if (d.idx == 1) {
|
||||||
msg = __("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row");
|
msg = __("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row");
|
||||||
d.charge_type = '';
|
d.charge_type = '';
|
||||||
} else if (!d.row_id) {
|
} else if (!d.row_id) {
|
||||||
msg = __("Please specify a valid Row ID for row {0} in table {1}", [d.idx, __(d.doctype)]);
|
msg = __("Please specify a valid Row ID for row {0} in table {1}", [d.idx, __(d.doctype)]);
|
||||||
d.row_id = "";
|
d.row_id = "";
|
||||||
} else if(d.row_id && d.row_id >= d.idx) {
|
} else if (d.row_id && d.row_id >= d.idx) {
|
||||||
msg = __("Cannot refer row number greater than or equal to current row number for this Charge type");
|
msg = __("Cannot refer row number greater than or equal to current row number for this Charge type");
|
||||||
d.row_id = "";
|
d.row_id = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(msg) {
|
if (msg) {
|
||||||
frappe.validated = false;
|
frappe.validated = false;
|
||||||
refresh_field("taxes");
|
refresh_field("taxes");
|
||||||
frappe.throw(msg);
|
frappe.throw(msg);
|
||||||
|
@ -531,7 +531,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
calculate_totals: function() {
|
calculate_totals: function() {
|
||||||
// Changing sequence can cause rounding_adjustmentng issue and on-screen discrepency
|
// Changing sequence can because of rounding adjustment issue and on-screen discrepancy
|
||||||
var me = this;
|
var me = this;
|
||||||
var tax_count = this.frm.doc["taxes"] ? this.frm.doc["taxes"].length : 0;
|
var tax_count = this.frm.doc["taxes"] ? this.frm.doc["taxes"].length : 0;
|
||||||
this.frm.doc.grand_total = flt(tax_count
|
this.frm.doc.grand_total = flt(tax_count
|
||||||
|
@ -8,24 +8,23 @@ erpnext.payments = erpnext.stock.StockController.extend({
|
|||||||
this.dialog = new frappe.ui.Dialog({
|
this.dialog = new frappe.ui.Dialog({
|
||||||
title: 'Payment'
|
title: 'Payment'
|
||||||
});
|
});
|
||||||
|
|
||||||
this.dialog.show();
|
this.dialog.show();
|
||||||
this.$body = this.dialog.body;
|
this.$body = this.dialog.body;
|
||||||
this.set_payment_primary_action();
|
this.set_payment_primary_action();
|
||||||
this.make_keyboard();
|
this.make_keyboard();
|
||||||
this.select_text()
|
this.select_text();
|
||||||
},
|
},
|
||||||
|
|
||||||
select_text: function(){
|
select_text() {
|
||||||
var me = this;
|
$(this.$body).find('.form-control').click(function() {
|
||||||
$(this.$body).find('.form-control').click(function(){
|
|
||||||
$(this).select();
|
$(this).select();
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
set_payment_primary_action: function(){
|
set_payment_primary_action: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
|
|
||||||
this.dialog.set_primary_action(__("Submit"), function() {
|
this.dialog.set_primary_action(__("Submit"), function() {
|
||||||
// Allow no ZERO payment
|
// Allow no ZERO payment
|
||||||
$.each(me.frm.doc.payments, function (index, data) {
|
$.each(me.frm.doc.payments, function (index, data) {
|
||||||
@ -38,20 +37,20 @@ erpnext.payments = erpnext.stock.StockController.extend({
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
make_keyboard: function(){
|
make_keyboard: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
$(this.$body).empty();
|
$(this.$body).empty();
|
||||||
$(this.$body).html(frappe.render_template('pos_payment', this.frm.doc))
|
$(this.$body).html(frappe.render_template('pos_payment', this.frm.doc))
|
||||||
this.show_payment_details();
|
this.show_payment_details();
|
||||||
this.bind_keyboard_event()
|
this.bind_keyboard_event();
|
||||||
this.clear_amount()
|
this.clear_amount();
|
||||||
},
|
},
|
||||||
|
|
||||||
make_multimode_payment: function(){
|
make_multimode_payment: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
|
|
||||||
if(this.frm.doc.change_amount > 0){
|
if (this.frm.doc.change_amount > 0) {
|
||||||
me.payment_val = me.doc.outstanding_amount
|
me.payment_val = me.doc.outstanding_amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.payments = frappe.model.add_child(this.frm.doc, 'Multi Mode Payment', "payments");
|
this.payments = frappe.model.add_child(this.frm.doc, 'Multi Mode Payment', "payments");
|
||||||
@ -59,11 +58,11 @@ erpnext.payments = erpnext.stock.StockController.extend({
|
|||||||
this.payments.amount = flt(this.payment_val);
|
this.payments.amount = flt(this.payment_val);
|
||||||
},
|
},
|
||||||
|
|
||||||
show_payment_details: function(){
|
show_payment_details: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
var multimode_payments = $(this.$body).find('.multimode-payments').empty();
|
var multimode_payments = $(this.$body).find('.multimode-payments').empty();
|
||||||
if(this.frm.doc.payments.length){
|
if (this.frm.doc.payments.length) {
|
||||||
$.each(this.frm.doc.payments, function(index, data){
|
$.each(this.frm.doc.payments, function(index, data) {
|
||||||
$(frappe.render_template('payment_details', {
|
$(frappe.render_template('payment_details', {
|
||||||
mode_of_payment: data.mode_of_payment,
|
mode_of_payment: data.mode_of_payment,
|
||||||
amount: data.amount,
|
amount: data.amount,
|
||||||
@ -84,92 +83,90 @@ erpnext.payments = erpnext.stock.StockController.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
set_outstanding_amount: function(){
|
set_outstanding_amount: function() {
|
||||||
this.selected_mode = $(this.$body).find(repl("input[idx='%(idx)s']",{'idx': this.idx}));
|
this.selected_mode = $(this.$body).find(repl("input[idx='%(idx)s']",{'idx': this.idx}));
|
||||||
this.highlight_selected_row()
|
this.highlight_selected_row();
|
||||||
this.payment_val = 0.0
|
this.payment_val = 0.0;
|
||||||
if(this.frm.doc.outstanding_amount > 0 && flt(this.selected_mode.val()) == 0.0){
|
if (this.frm.doc.outstanding_amount > 0 && flt(this.selected_mode.val()) == 0.0) {
|
||||||
//When user first time click on row
|
//When user first time click on row
|
||||||
this.payment_val = flt(this.frm.doc.outstanding_amount / this.frm.doc.conversion_rate, precision("outstanding_amount"))
|
this.payment_val = flt(this.frm.doc.outstanding_amount / this.frm.doc.conversion_rate, precision("outstanding_amount"))
|
||||||
this.selected_mode.val(format_currency(this.payment_val, this.frm.doc.currency));
|
this.selected_mode.val(format_currency(this.payment_val, this.frm.doc.currency));
|
||||||
this.update_payment_amount()
|
this.update_payment_amount();
|
||||||
}else if(flt(this.selected_mode.val()) > 0){
|
} else if (flt(this.selected_mode.val()) > 0) {
|
||||||
//If user click on existing row which has value
|
//If user click on existing row which has value
|
||||||
this.payment_val = flt(this.selected_mode.val());
|
this.payment_val = flt(this.selected_mode.val());
|
||||||
}
|
}
|
||||||
this.selected_mode.select()
|
this.selected_mode.select()
|
||||||
this.bind_amount_change_event();
|
this.bind_amount_change_event();
|
||||||
},
|
},
|
||||||
|
|
||||||
bind_keyboard_event: function(){
|
bind_keyboard_event() {
|
||||||
var me = this;
|
|
||||||
this.payment_val = '';
|
this.payment_val = '';
|
||||||
this.bind_form_control_event();
|
this.bind_form_control_event();
|
||||||
this.bind_numeric_keys_event();
|
this.bind_numeric_keys_event();
|
||||||
},
|
},
|
||||||
|
|
||||||
bind_form_control_event: function(){
|
bind_form_control_event: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
$(this.$body).find('.pos-payment-row').click(function(){
|
$(this.$body).find('.pos-payment-row').click(function() {
|
||||||
me.idx = $(this).attr("idx");
|
me.idx = $(this).attr("idx");
|
||||||
me.set_outstanding_amount()
|
me.set_outstanding_amount();
|
||||||
})
|
});
|
||||||
|
|
||||||
$(this.$body).find('.form-control').click(function(){
|
$(this.$body).find('.form-control').click(function() {
|
||||||
me.idx = $(this).attr("idx");
|
me.idx = $(this).attr("idx");
|
||||||
me.set_outstanding_amount();
|
me.set_outstanding_amount();
|
||||||
me.update_paid_amount(true);
|
me.update_paid_amount(true);
|
||||||
})
|
});
|
||||||
|
|
||||||
$(this.$body).find('.write_off_amount').change(function(){
|
$(this.$body).find('.write_off_amount').change(function() {
|
||||||
me.write_off_amount(flt($(this).val()), precision("write_off_amount"));
|
me.write_off_amount(flt($(this).val()), precision("write_off_amount"));
|
||||||
})
|
});
|
||||||
|
|
||||||
$(this.$body).find('.change_amount').change(function(){
|
$(this.$body).find('.change_amount').change(function() {
|
||||||
me.change_amount(flt($(this).val()), precision("change_amount"));
|
me.change_amount(flt($(this).val()), precision("change_amount"));
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
highlight_selected_row: function(){
|
highlight_selected_row() {
|
||||||
var me = this;
|
var selected_row = $(this.$body).find(repl(".pos-payment-row[idx='%(idx)s']", {'idx': this.idx}));
|
||||||
var selected_row = $(this.$body).find(repl(".pos-payment-row[idx='%(idx)s']",{'idx': this.idx}));
|
$(this.$body).find('.pos-payment-row').removeClass('selected-payment-mode');
|
||||||
$(this.$body).find('.pos-payment-row').removeClass('selected-payment-mode')
|
selected_row.addClass('selected-payment-mode');
|
||||||
selected_row.addClass('selected-payment-mode')
|
|
||||||
$(this.$body).find('.amount').attr('disabled', true);
|
$(this.$body).find('.amount').attr('disabled', true);
|
||||||
this.selected_mode.attr('disabled', false);
|
this.selected_mode.attr('disabled', false);
|
||||||
},
|
},
|
||||||
|
|
||||||
bind_numeric_keys_event: function(){
|
bind_numeric_keys_event: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
$(this.$body).find('.pos-keyboard-key').click(function(){
|
$(this.$body).find('.pos-keyboard-key').click(function(){
|
||||||
me.payment_val += $(this).text();
|
me.payment_val += $(this).text();
|
||||||
me.selected_mode.val(format_currency(me.payment_val, me.frm.doc.currency))
|
me.selected_mode.val(format_currency(me.payment_val, me.frm.doc.currency));
|
||||||
me.idx = me.selected_mode.attr("idx")
|
me.idx = me.selected_mode.attr("idx");
|
||||||
me.update_paid_amount()
|
me.update_paid_amount();
|
||||||
})
|
});
|
||||||
|
|
||||||
$(this.$body).find('.delete-btn').click(function(){
|
$(this.$body).find('.delete-btn').click(function() {
|
||||||
me.payment_val = cstr(flt(me.selected_mode.val())).slice(0, -1);
|
me.payment_val = cstr(flt(me.selected_mode.val())).slice(0, -1);
|
||||||
me.selected_mode.val(format_currency(me.payment_val, me.frm.doc.currency));
|
me.selected_mode.val(format_currency(me.payment_val, me.frm.doc.currency));
|
||||||
me.idx = me.selected_mode.attr("idx")
|
me.idx = me.selected_mode.attr("idx");
|
||||||
me.update_paid_amount();
|
me.update_paid_amount();
|
||||||
})
|
})
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
bind_amount_change_event: function(){
|
bind_amount_change_event() {
|
||||||
var me = this;
|
var me = this;
|
||||||
this.selected_mode.change(function(){
|
this.selected_mode.change(function() {
|
||||||
me.payment_val = flt($(this).val()) || 0.0;
|
me.payment_val = flt($(this).val()) || 0.0;
|
||||||
me.selected_mode.val(format_currency(me.payment_val, me.frm.doc.currency))
|
me.selected_mode.val(format_currency(me.payment_val, me.frm.doc.currency));
|
||||||
me.idx = me.selected_mode.attr("idx")
|
me.idx = me.selected_mode.attr("idx");
|
||||||
me.update_payment_amount()
|
me.update_payment_amount();
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
clear_amount: function() {
|
clear_amount: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
$(this.$body).find('.clr').click(function(e){
|
$(this.$body).find('.clr').click(function(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
me.idx = $(this).attr("idx");
|
me.idx = $(this).attr("idx");
|
||||||
me.selected_mode = $(me.$body).find(repl("input[idx='%(idx)s']",{'idx': me.idx}));
|
me.selected_mode = $(me.$body).find(repl("input[idx='%(idx)s']",{'idx': me.idx}));
|
||||||
@ -177,50 +174,48 @@ erpnext.payments = erpnext.stock.StockController.extend({
|
|||||||
me.selected_mode.val(0.0);
|
me.selected_mode.val(0.0);
|
||||||
me.highlight_selected_row();
|
me.highlight_selected_row();
|
||||||
me.update_payment_amount();
|
me.update_payment_amount();
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
write_off_amount: function(write_off_amount) {
|
write_off_amount(write_off_amount) {
|
||||||
var me = this;
|
|
||||||
|
|
||||||
this.frm.doc.write_off_amount = flt(write_off_amount, precision("write_off_amount"));
|
this.frm.doc.write_off_amount = flt(write_off_amount, precision("write_off_amount"));
|
||||||
this.frm.doc.base_write_off_amount = flt(this.frm.doc.write_off_amount * this.frm.doc.conversion_rate,
|
this.frm.doc.base_write_off_amount = flt(this.frm.doc.write_off_amount * this.frm.doc.conversion_rate,
|
||||||
precision("base_write_off_amount"));
|
precision("base_write_off_amount"));
|
||||||
this.calculate_outstanding_amount(false)
|
this.calculate_outstanding_amount(false);
|
||||||
this.show_amounts()
|
this.show_amounts();
|
||||||
},
|
},
|
||||||
|
|
||||||
change_amount: function(change_amount) {
|
change_amount: function(change_amount) {
|
||||||
var me = this;
|
var me = this;
|
||||||
|
|
||||||
this.frm.doc.change_amount = flt(change_amount, precision("change_amount"));
|
this.frm.doc.change_amount = flt(change_amount, precision("change_amount"));
|
||||||
this.calculate_write_off_amount()
|
this.calculate_write_off_amount();
|
||||||
this.show_amounts()
|
this.show_amounts();
|
||||||
},
|
},
|
||||||
|
|
||||||
update_paid_amount: function(update_write_off) {
|
update_paid_amount: function(update_write_off) {
|
||||||
var me = this;
|
var me = this;
|
||||||
if(in_list(['change_amount', 'write_off_amount'], this.idx)){
|
if (in_list(['change_amount', 'write_off_amount'], this.idx)) {
|
||||||
var value = me.selected_mode.val();
|
var value = me.selected_mode.val();
|
||||||
if(me.idx == 'change_amount'){
|
if (me.idx == 'change_amount') {
|
||||||
me.change_amount(value)
|
me.change_amount(value);
|
||||||
} else{
|
} else {
|
||||||
if(flt(value) == 0 && update_write_off && me.frm.doc.outstanding_amount > 0) {
|
if(flt(value) == 0 && update_write_off && me.frm.doc.outstanding_amount > 0) {
|
||||||
value = flt(me.frm.doc.outstanding_amount / me.frm.doc.conversion_rate, precision(me.idx));
|
value = flt(me.frm.doc.outstanding_amount / me.frm.doc.conversion_rate, precision(me.idx));
|
||||||
}
|
}
|
||||||
me.write_off_amount(value)
|
me.write_off_amount(value);
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
this.update_payment_amount()
|
this.update_payment_amount();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
update_payment_amount: function(){
|
update_payment_amount: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
|
|
||||||
$.each(this.frm.doc.payments, function(index, data){
|
$.each(this.frm.doc.payments, function(index, data) {
|
||||||
if(cint(me.idx) == cint(data.idx)){
|
if (cint(me.idx) == cint(data.idx)) {
|
||||||
data.amount = flt(me.selected_mode.val(), 2)
|
data.amount = flt(me.selected_mode.val(), 2);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -228,12 +223,12 @@ erpnext.payments = erpnext.stock.StockController.extend({
|
|||||||
this.show_amounts();
|
this.show_amounts();
|
||||||
},
|
},
|
||||||
|
|
||||||
show_amounts: function(){
|
show_amounts: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
$(this.$body).find(".write_off_amount").val(format_currency(this.frm.doc.write_off_amount, this.frm.doc.currency));
|
$(this.$body).find(".write_off_amount").val(format_currency(this.frm.doc.write_off_amount, this.frm.doc.currency));
|
||||||
$(this.$body).find('.paid_amount').text(format_currency(this.frm.doc.paid_amount, this.frm.doc.currency));
|
$(this.$body).find('.paid_amount').text(format_currency(this.frm.doc.paid_amount, this.frm.doc.currency));
|
||||||
$(this.$body).find('.change_amount').val(format_currency(this.frm.doc.change_amount, this.frm.doc.currency))
|
$(this.$body).find('.change_amount').val(format_currency(this.frm.doc.change_amount, this.frm.doc.currency));
|
||||||
$(this.$body).find('.outstanding_amount').text(format_currency(this.frm.doc.outstanding_amount, frappe.get_doc(":Company", this.frm.doc.company).default_currency))
|
$(this.$body).find('.outstanding_amount').text(format_currency(this.frm.doc.outstanding_amount, frappe.get_doc(":Company", this.frm.doc.company).default_currency));
|
||||||
this.update_invoice();
|
this.update_invoice();
|
||||||
}
|
}
|
||||||
})
|
})
|
@ -269,7 +269,7 @@ erpnext.company.setup_queries = function(frm) {
|
|||||||
["expenses_included_in_asset_valuation", {"account_type": "Expenses Included In Asset Valuation"}],
|
["expenses_included_in_asset_valuation", {"account_type": "Expenses Included In Asset Valuation"}],
|
||||||
["capital_work_in_progress_account", {"account_type": "Capital Work in Progress"}],
|
["capital_work_in_progress_account", {"account_type": "Capital Work in Progress"}],
|
||||||
["asset_received_but_not_billed", {"account_type": "Asset Received But Not Billed"}],
|
["asset_received_but_not_billed", {"account_type": "Asset Received But Not Billed"}],
|
||||||
["unrealized_profit_loss_account", {"root_type": "Liability"},]
|
["unrealized_profit_loss_account", {"root_type": ["in", ["Liability", "Asset"]]}]
|
||||||
], function(i, v) {
|
], function(i, v) {
|
||||||
erpnext.company.set_custom_query(frm, v);
|
erpnext.company.set_custom_query(frm, v);
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user