fix: TDS against Purhase Orders

This commit is contained in:
Deepesh Garg 2020-11-02 19:57:27 +05:30
parent 61c5e478af
commit c26de28613
10 changed files with 635 additions and 209 deletions

View File

@ -33,7 +33,7 @@
"label": "Type", "label": "Type",
"oldfieldname": "charge_type", "oldfieldname": "charge_type",
"oldfieldtype": "Select", "oldfieldtype": "Select",
"options": "\nActual\nOn Paid Amount\nOn Previous Row Amount\nOn Previous Row Total", "options": "\nActual\nOn Paid Amount\nIncluded In Paid Amount\nOn Previous Row Amount\nOn Previous Row Total",
"reqd": 1, "reqd": 1,
"show_days": 1, "show_days": 1,
"show_seconds": 1 "show_seconds": 1
@ -190,7 +190,7 @@
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2020-09-12 22:30:36.150935", "modified": "2020-10-27 20:02:34.734260",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Advance Taxes and Charges", "name": "Advance Taxes and Charges",

View File

@ -220,7 +220,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"], 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);
@ -368,6 +368,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;

View File

@ -25,9 +25,9 @@
"contact_person", "contact_person",
"contact_email", "contact_email",
"tds_details_section", "tds_details_section",
"tax_withholding_category",
"column_break_20",
"apply_tax_withholding_amount", "apply_tax_withholding_amount",
"column_break_20",
"tax_withholding_category",
"payment_accounts_section", "payment_accounts_section",
"party_balance", "party_balance",
"paid_from", "paid_from",
@ -39,8 +39,10 @@
"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",
"target_exchange_rate", "target_exchange_rate",
@ -580,7 +582,9 @@
"fieldtype": "Small Text", "fieldtype": "Small Text",
"label": "Remarks", "label": "Remarks",
"no_copy": 1, "no_copy": 1,
"read_only_depends_on": "eval:doc.custom_remarks == 0" "read_only_depends_on": "eval:doc.custom_remarks == 0",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "column_break_16", "fieldname": "column_break_16",
@ -736,6 +740,7 @@
"show_seconds": 1 "show_seconds": 1
}, },
{ {
"depends_on": "eval:doc.apply_tax_withholding_amount",
"fieldname": "tax_withholding_category", "fieldname": "tax_withholding_category",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Tax Withholding Category", "label": "Tax Withholding Category",
@ -808,12 +813,30 @@
"read_only": 1, "read_only": 1,
"show_days": 1, "show_days": 1,
"show_seconds": 1 "show_seconds": 1
},
{
"fieldname": "paid_amount_after_tax",
"fieldtype": "Currency",
"hidden": 1,
"label": "Paid Amount After Tax",
"options": "paid_from_account_currency",
"read_only": 1,
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "base_paid_amount_after_tax",
"fieldtype": "Currency",
"label": "Paid Amount After Tax (Company Currency)",
"options": "Company:company:default_currency",
"show_days": 1,
"show_seconds": 1
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2020-09-13 22:33:59.860146", "modified": "2020-10-25 20:50:14.896628",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Payment Entry", "name": "Payment Entry",

View File

@ -396,9 +396,6 @@ class PaymentEntry(AccountsController):
if not self.apply_tax_withholding_amount: if not self.apply_tax_withholding_amount:
return return
if self.references:
return
args = frappe._dict({ args = frappe._dict({
'company': self.company, 'company': self.company,
'supplier': self.party, 'supplier': self.party,
@ -427,11 +424,18 @@ class PaymentEntry(AccountsController):
self.remove(d) self.remove(d)
def set_amounts(self): def set_amounts(self):
self.set_amounts_after_tax()
self.set_amounts_in_company_currency() self.set_amounts_in_company_currency()
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_amounts_after_tax(self):
self.paid_amount_after_tax = flt(flt(self.paid_amount) + flt(self.total_taxes_and_charges),
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"))
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:
@ -463,12 +467,12 @@ class PaymentEntry(AccountsController):
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 + total_deductions \
and self.total_allocated_amount < self.paid_amount + (total_deductions / self.source_exchange_rate): and self.total_allocated_amount < self.paid_amount + (total_deductions / self.source_exchange_rate):
self.unallocated_amount = (self.base_received_amount + self.base_total_taxes_and_charges + total_deductions - self.unallocated_amount = (self.base_received_amount + 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 - total_deductions) \
and self.total_allocated_amount < self.received_amount + (total_deductions / self.target_exchange_rate): and self.total_allocated_amount < self.received_amount + (total_deductions / self.target_exchange_rate):
self.unallocated_amount = (self.base_paid_amount + self.base_total_taxes_and_charges - (total_deductions + self.unallocated_amount = (self.base_paid_amount - (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):
@ -486,7 +490,7 @@ class PaymentEntry(AccountsController):
total_deductions = sum([flt(d.amount) for d in self.get("deductions")]) total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
self.difference_amount = flt(self.difference_amount - total_deductions + self.base_total_taxes_and_charges, self.difference_amount = flt(self.difference_amount - total_deductions,
self.precision("difference_amount")) self.precision("difference_amount"))
# Paid amount is auto allocated in the reference document by default. # Paid amount is auto allocated in the reference document by default.
@ -631,8 +635,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)
) )
@ -654,7 +658,10 @@ class PaymentEntry(AccountsController):
if account_currency != self.company_currency: if account_currency != self.company_currency:
frappe.throw(_("Currency for {0} must be {1}").format(d.account_head, self.company_currency)) frappe.throw(_("Currency for {0} must be {1}").format(d.account_head, self.company_currency))
dr_or_cr = "credit" if d.add_deduct_tax == "Add" else "debit" if self.payment_type == 'Pay':
dr_or_cr = "debit" if d.add_deduct_tax == "Add" else "credit"
elif self.payment_type == 'Receive':
dr_or_cr = "credit" if d.add_deduct_tax == "Add" else "debit"
gl_entries.append( gl_entries.append(
self.get_gl_dict({ self.get_gl_dict({

View File

@ -1088,9 +1088,10 @@ class PurchaseInvoice(BuyingController):
accounts = [] accounts = []
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") and not d.is_advance_tax:
d.update(tax_withholding_details) d.update(tax_withholding_details)
accounts.append(d.account_head) if not d.is_advance_tax:
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:
self.append("taxes", tax_withholding_details) self.append("taxes", tax_withholding_details)

View File

@ -28,7 +28,8 @@
"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",
"is_advance_tax"
], ],
"fields": [ "fields": [
{ {
@ -39,7 +40,9 @@
"oldfieldname": "category", "oldfieldname": "category",
"oldfieldtype": "Select", "oldfieldtype": "Select",
"options": "Valuation and Total\nValuation\nTotal", "options": "Valuation and Total\nValuation\nTotal",
"reqd": 1 "reqd": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"default": "Add", "default": "Add",
@ -49,7 +52,9 @@
"oldfieldname": "add_deduct_tax", "oldfieldname": "add_deduct_tax",
"oldfieldtype": "Select", "oldfieldtype": "Select",
"options": "Add\nDeduct", "options": "Add\nDeduct",
"reqd": 1 "reqd": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"columns": 2, "columns": 2,
@ -61,7 +66,9 @@
"oldfieldname": "charge_type", "oldfieldname": "charge_type",
"oldfieldtype": "Select", "oldfieldtype": "Select",
"options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total\nOn Item Quantity", "options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total\nOn Item Quantity",
"reqd": 1 "reqd": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"depends_on": "eval:[\"On Previous Row Amount\", \"On Previous Row Total\"].indexOf(doc.charge_type)!==-1", "depends_on": "eval:[\"On Previous Row Amount\", \"On Previous Row Total\"].indexOf(doc.charge_type)!==-1",
@ -69,7 +76,9 @@
"fieldtype": "Data", "fieldtype": "Data",
"label": "Reference Row #", "label": "Reference Row #",
"oldfieldname": "row_id", "oldfieldname": "row_id",
"oldfieldtype": "Data" "oldfieldtype": "Data",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"default": "0", "default": "0",
@ -77,11 +86,15 @@
"fieldname": "included_in_print_rate", "fieldname": "included_in_print_rate",
"fieldtype": "Check", "fieldtype": "Check",
"label": "Is this Tax included in Basic Rate?", "label": "Is this Tax included in Basic Rate?",
"report_hide": 1 "report_hide": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "col_break1", "fieldname": "col_break1",
"fieldtype": "Column Break" "fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"columns": 2, "columns": 2,
@ -92,7 +105,9 @@
"oldfieldname": "account_head", "oldfieldname": "account_head",
"oldfieldtype": "Link", "oldfieldtype": "Link",
"options": "Account", "options": "Account",
"reqd": 1 "reqd": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"default": ":Company", "default": ":Company",
@ -101,7 +116,9 @@
"label": "Cost Center", "label": "Cost Center",
"oldfieldname": "cost_center", "oldfieldname": "cost_center",
"oldfieldtype": "Link", "oldfieldtype": "Link",
"options": "Cost Center" "options": "Cost Center",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "description", "fieldname": "description",
@ -111,11 +128,15 @@
"oldfieldtype": "Small Text", "oldfieldtype": "Small Text",
"print_width": "300px", "print_width": "300px",
"reqd": 1, "reqd": 1,
"show_days": 1,
"show_seconds": 1,
"width": "300px" "width": "300px"
}, },
{ {
"fieldname": "section_break_10", "fieldname": "section_break_10",
"fieldtype": "Section Break" "fieldtype": "Section Break",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"columns": 2, "columns": 2,
@ -124,11 +145,15 @@
"in_list_view": 1, "in_list_view": 1,
"label": "Rate", "label": "Rate",
"oldfieldname": "rate", "oldfieldname": "rate",
"oldfieldtype": "Currency" "oldfieldtype": "Currency",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "section_break_9", "fieldname": "section_break_9",
"fieldtype": "Section Break" "fieldtype": "Section Break",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"columns": 2, "columns": 2,
@ -138,7 +163,9 @@
"label": "Amount", "label": "Amount",
"oldfieldname": "tax_amount", "oldfieldname": "tax_amount",
"oldfieldtype": "Currency", "oldfieldtype": "Currency",
"options": "currency" "options": "currency",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "tax_amount_after_discount_amount", "fieldname": "tax_amount_after_discount_amount",
@ -146,7 +173,9 @@
"label": "Tax Amount After Discount Amount", "label": "Tax Amount After Discount Amount",
"options": "currency", "options": "currency",
"print_hide": 1, "print_hide": 1,
"read_only": 1 "read_only": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"columns": 2, "columns": 2,
@ -157,11 +186,15 @@
"oldfieldname": "total", "oldfieldname": "total",
"oldfieldtype": "Currency", "oldfieldtype": "Currency",
"options": "currency", "options": "currency",
"read_only": 1 "read_only": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "column_break_14", "fieldname": "column_break_14",
"fieldtype": "Column Break" "fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "base_tax_amount", "fieldname": "base_tax_amount",
@ -169,7 +202,9 @@
"label": "Amount (Company Currency)", "label": "Amount (Company Currency)",
"options": "Company:company:default_currency", "options": "Company:company:default_currency",
"print_hide": 1, "print_hide": 1,
"read_only": 1 "read_only": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "base_total", "fieldname": "base_total",
@ -177,7 +212,9 @@
"hidden": 1, "hidden": 1,
"label": "Total (Company Currency)", "label": "Total (Company Currency)",
"options": "Company:company:default_currency", "options": "Company:company:default_currency",
"print_hide": 1 "print_hide": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "base_tax_amount_after_discount_amount", "fieldname": "base_tax_amount_after_discount_amount",
@ -185,7 +222,9 @@
"label": "Tax Amount After Discount Amount", "label": "Tax Amount After Discount Amount",
"options": "Company:company:default_currency", "options": "Company:company:default_currency",
"print_hide": 1, "print_hide": 1,
"read_only": 1 "read_only": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "item_wise_tax_detail", "fieldname": "item_wise_tax_detail",
@ -195,22 +234,38 @@
"oldfieldname": "item_wise_tax_detail", "oldfieldname": "item_wise_tax_detail",
"oldfieldtype": "Small Text", "oldfieldtype": "Small Text",
"print_hide": 1, "print_hide": 1,
"read_only": 1 "read_only": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "accounting_dimensions_section", "fieldname": "accounting_dimensions_section",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"label": "Accounting Dimensions" "label": "Accounting Dimensions",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "dimension_col_break", "fieldname": "dimension_col_break",
"fieldtype": "Column Break" "fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1
},
{
"default": "0",
"fieldname": "is_advance_tax",
"fieldtype": "Check",
"hidden": 1,
"label": "Is Advance Tax",
"read_only": 1,
"show_days": 1,
"show_seconds": 1
} }
], ],
"idx": 1, "idx": 1,
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2020-09-18 17:26:09.703215", "modified": "2020-10-25 18:24:43.487567",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Purchase Taxes and Charges", "name": "Purchase Taxes and Charges",

View File

@ -617,10 +617,6 @@ class AccountsController(TransactionBase):
payment_entries = get_advance_payment_entries(party_type, party, party_account, payment_entries = get_advance_payment_entries(party_type, party, party_account,
order_doctype, order_list, include_unallocated) order_doctype, order_list, include_unallocated)
payment_entry_list = [d.reference_name for d in payment_entries]
payment_entry_taxes = get_payment_entry_taxes(payment_entry_list)
res = journal_entries + payment_entries res = journal_entries + payment_entries
return res return res
@ -1245,13 +1241,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 get_payment_entry_taxes(payment_entry_list):
taxes = frappe.db.sql("""
SELECT t.parent, t.add_deduct_tax, t.charge_type, t.account_head, t.cost_center,
t.tax_amount FROM `tabAdvance Taxes and Charges` where t.parent in %s"""
,(payment_entry_list, ), as_dict=1)
def update_invoice_status(): def update_invoice_status():
# Daily update the status of the invoices # Daily update the status of the invoices

View File

@ -40,6 +40,7 @@ class calculate_taxes_and_totals(object):
self.validate_conversion_rate() self.validate_conversion_rate()
self.calculate_item_values() self.calculate_item_values()
self.validate_item_tax_template() self.validate_item_tax_template()
self.apply_advance_taxes()
self.initialize_taxes() self.initialize_taxes()
self.determine_exclusive_rate() self.determine_exclusive_rate()
self.calculate_net_total() self.calculate_net_total()
@ -683,6 +684,32 @@ class calculate_taxes_and_totals(object):
self.calculate_paid_amount() self.calculate_paid_amount()
def apply_advance_taxes(self):
if cint(self.doc.get('adjust_advance_taxes')):
if self.doc.get('advances'):
payment_entry_list = [d.reference_name for d in self.doc.get('advances')]
advance_taxes = get_advance_taxes(payment_entry_list)
accounts = []
# Remove already added advance taxes if any
for tax in self.doc.get('taxes'):
if tax.is_advance_tax:
self.doc.remove(tax)
else:
accounts.append(tax.account_head)
for tax in advance_taxes:
# Reverse add deduct from payment entry in invoice
if tax.account_head in accounts:
add_deduct_tax = 'Deduct' if tax.add_deduct_tax == 'Add' else 'Add'
tax.update({
'add_deduct_tax': add_deduct_tax,
'category': tax.get('category') or 'Total',
'is_advance_tax': 1,
'charge_type': 'On Net Total' if tax.charge_type == 'On Paid Amount' else tax.charge_type
})
self.doc.append('taxes', tax)
def get_itemised_tax_breakup_html(doc): def get_itemised_tax_breakup_html(doc):
if not doc.taxes: if not doc.taxes:
@ -820,3 +847,16 @@ class init_landed_taxes_and_totals(object):
for d in self.doc.get(self.tax_field): for d in self.doc.get(self.tax_field):
d.amount = flt(d.amount, d.precision("amount")) d.amount = flt(d.amount, d.precision("amount"))
d.base_amount = flt(d.amount * flt(d.exchange_rate), d.precision("base_amount")) d.base_amount = flt(d.amount * flt(d.exchange_rate), d.precision("base_amount"))
def get_advance_taxes(payment_entry_list):
taxes = []
if payment_entry_list:
taxes = frappe.db.sql(
"""
SELECT t.parent, t.add_deduct_tax, t.charge_type, t.rate,
t.account_head, t.cost_center, t.tax_amount, t.description
FROM `tabAdvance Taxes and Charges` t, `tabPayment Entry` p
WHERE t.parent = p.name AND t.parent in %s
""", (payment_entry_list, ), as_dict=1)
return taxes