feat: RCM for UAE VAT
This commit is contained in:
parent
2744765757
commit
7b7a8e1309
@ -246,7 +246,10 @@ doc_events = {
|
||||
"on_trash": "erpnext.regional.check_deletion_permission"
|
||||
},
|
||||
"Purchase Invoice": {
|
||||
"validate": "erpnext.regional.india.utils.update_grand_total_for_rcm"
|
||||
"validate": [
|
||||
"erpnext.regional.india.utils.update_grand_total_for_rcm",
|
||||
"erpnext.regional.united_arab_emirates.utils.update_grand_total_for_rcm",
|
||||
]
|
||||
},
|
||||
"Payment Entry": {
|
||||
"on_submit": ["erpnext.regional.create_transaction_log", "erpnext.accounts.doctype.payment_request.payment_request.update_payment_req_status", "erpnext.accounts.doctype.dunning.dunning.resolve_dunning"],
|
||||
@ -379,7 +382,8 @@ regional_overrides = {
|
||||
'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_regional_gl_entries': 'erpnext.regional.india.utils.make_regional_gl_entries'
|
||||
},
|
||||
'United Arab Emirates': {
|
||||
'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.united_arab_emirates.utils.update_itemised_tax_data'
|
||||
'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.united_arab_emirates.utils.update_itemised_tax_data',
|
||||
'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_regional_gl_entries': 'erpnext.regional.united_arab_emirates.utils.make_regional_gl_entries',
|
||||
},
|
||||
'Saudi Arabia': {
|
||||
'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.united_arab_emirates.utils.update_itemised_tax_data'
|
||||
|
@ -1,6 +1,8 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import flt
|
||||
from frappe import _
|
||||
import erpnext
|
||||
from frappe.utils import flt, round_based_on_smallest_currency_fraction, money_in_words
|
||||
from erpnext.controllers.taxes_and_totals import get_itemised_tax
|
||||
from six import iteritems
|
||||
|
||||
@ -26,4 +28,142 @@ def update_itemised_tax_data(doc):
|
||||
|
||||
row.tax_rate = flt(tax_rate, row.precision("tax_rate"))
|
||||
row.tax_amount = flt((row.net_amount * tax_rate) / 100, row.precision("net_amount"))
|
||||
row.total_amount = flt((row.net_amount + row.tax_amount), row.precision("total_amount"))
|
||||
row.total_amount = flt((row.net_amount + row.tax_amount), row.precision("total_amount"))
|
||||
|
||||
def get_account_currency(account):
|
||||
"""Helper function to get account currency"""
|
||||
if not account:
|
||||
return
|
||||
def generator():
|
||||
account_currency, company = frappe.get_cached_value("Account", account, ["account_currency", "company"])
|
||||
if not account_currency:
|
||||
account_currency = frappe.get_cached_value('Company', company, "default_currency")
|
||||
|
||||
return account_currency
|
||||
|
||||
return frappe.local_cache("account_currency", account, generator)
|
||||
|
||||
def get_tax_accounts(company):
|
||||
"""Get the list of tax accounts for a specific company
|
||||
|
||||
Args:
|
||||
company (String): Current Company set as default
|
||||
|
||||
Returns:
|
||||
tax_accounts: List of Tax Accounts for the company
|
||||
"""
|
||||
tax_accounts_dict = frappe._dict()
|
||||
tax_accounts_list = frappe.get_all("Account",
|
||||
filters={"account_type": "Tax", "company": company},
|
||||
fields=["name"])
|
||||
|
||||
if not tax_accounts_list and not frappe.flags.in_test:
|
||||
frappe.throw(_("Please create at least one Account of type Tax"))
|
||||
for d in tax_accounts_list:
|
||||
for key, name in d.items():
|
||||
tax_accounts_dict[name] = name
|
||||
|
||||
return tax_accounts_dict
|
||||
|
||||
def update_grand_total_for_rcm(doc, method):
|
||||
"""If the Reverse Charge is Applicable subtract the tax amount from the grand total and update in the form
|
||||
|
||||
Args:
|
||||
doc (Document): The document for the current Purchase Invoice
|
||||
"""
|
||||
country = frappe.get_cached_value('Company', doc.company, 'country')
|
||||
|
||||
if country != 'United Arab Emirates':
|
||||
return
|
||||
|
||||
if not doc.total_taxes_and_charges:
|
||||
return
|
||||
|
||||
if doc.reverse_charge == 'Y':
|
||||
tax_accounts = get_tax_accounts(doc.company)
|
||||
|
||||
base_vat_tax = 0
|
||||
vat_tax = 0
|
||||
|
||||
for tax in doc.get('taxes'):
|
||||
if tax.category not in ("Total", "Valuation and Total"):
|
||||
continue
|
||||
|
||||
if flt(tax.base_tax_amount_after_discount_amount) and tax.account_head in tax_accounts:
|
||||
base_vat_tax += tax.base_tax_amount_after_discount_amount
|
||||
vat_tax += tax.tax_amount_after_discount_amount
|
||||
|
||||
doc.taxes_and_charges_added -= vat_tax
|
||||
doc.total_taxes_and_charges -= vat_tax
|
||||
doc.base_taxes_and_charges_added -= base_vat_tax
|
||||
doc.base_total_taxes_and_charges -= base_vat_tax
|
||||
|
||||
update_totals(vat_tax, base_vat_tax, doc)
|
||||
|
||||
def update_totals(vat_tax, base_vat_tax, doc):
|
||||
"""Update the grand total values in the form
|
||||
|
||||
Args:
|
||||
vat_tax (float): Vat Tax to be subtracted
|
||||
base_vat_tax (float): Base Vat Tax to be subtracted
|
||||
doc (Document): The document for the current Purchase Invoice
|
||||
"""
|
||||
|
||||
doc.base_grand_total -= base_vat_tax
|
||||
doc.grand_total -= vat_tax
|
||||
|
||||
if doc.meta.get_field("rounded_total"):
|
||||
|
||||
if doc.is_rounded_total_disabled():
|
||||
doc.outstanding_amount = doc.grand_total
|
||||
|
||||
else:
|
||||
doc.rounded_total = round_based_on_smallest_currency_fraction(doc.grand_total,
|
||||
doc.currency, doc.precision("rounded_total"))
|
||||
doc.rounding_adjustment = flt(doc.rounded_total - doc.grand_total,
|
||||
doc.precision("rounding_adjustment"))
|
||||
doc.outstanding_amount = doc.rounded_total or doc.grand_total
|
||||
|
||||
doc.in_words = money_in_words(doc.grand_total, doc.currency)
|
||||
doc.base_in_words = money_in_words(doc.base_grand_total, erpnext.get_company_currency(doc.company))
|
||||
doc.set_payment_schedule()
|
||||
|
||||
def make_regional_gl_entries(gl_entries, doc):
|
||||
"""This method is hooked to the make_regional_gl_entries in Purchase Invoice.
|
||||
It appends the region specific general ledger entries to the list of GL Entries.
|
||||
|
||||
Args:
|
||||
gl_entries (List): List of GL entries to be made
|
||||
doc (Document): The document for the current Purchase Invoice
|
||||
|
||||
Returns:
|
||||
List: Updates list of GL Entries
|
||||
"""
|
||||
country = frappe.get_cached_value('Company', doc.company, 'country')
|
||||
|
||||
if country != 'United Arab Emirates':
|
||||
return gl_entries
|
||||
|
||||
if doc.reverse_charge == 'Y':
|
||||
tax_accounts = get_tax_accounts(doc.company)
|
||||
for tax in doc.get('taxes'):
|
||||
if tax.category not in ("Total", "Valuation and Total"):
|
||||
continue
|
||||
|
||||
dr_or_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
|
||||
if flt(tax.base_tax_amount_after_discount_amount) and tax.account_head in tax_accounts:
|
||||
account_currency = get_account_currency(tax.account_head)
|
||||
|
||||
gl_entries.append(doc.get_gl_dict(
|
||||
{
|
||||
"account": tax.account_head,
|
||||
"cost_center": tax.cost_center,
|
||||
"posting_date": doc.posting_date,
|
||||
"against": doc.supplier,
|
||||
dr_or_cr: tax.base_tax_amount_after_discount_amount,
|
||||
dr_or_cr + "_in_account_currency": tax.base_tax_amount_after_discount_amount \
|
||||
if account_currency==doc.company_currency \
|
||||
else tax.tax_amount_after_discount_amount
|
||||
}, account_currency, item=tax)
|
||||
)
|
||||
return gl_entries
|
Loading…
x
Reference in New Issue
Block a user