From 2744765757cfeb9a2f9e9671d91e945ad4b6bcaf Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Mon, 7 Sep 2020 12:31:19 +0530 Subject: [PATCH 01/60] feat(UAE VAT Format): add fields for emirates in address and sales invoice --- erpnext/regional/united_arab_emirates/setup.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index 250659e54da..a2938bb3003 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -41,6 +41,8 @@ def make_custom_fields(): dict(fieldname='customer_name_in_arabic', label='Customer Name in Arabic', fieldtype='Read Only', insert_after='customer_name', fetch_from='customer.customer_name_in_arabic', print_hide=1), + dict(fieldname='emirate', label='Emirate', insert_after='customer_address', + fetch_from='customer_address.emirates'), ] invoice_item_fields = [ @@ -76,6 +78,10 @@ def make_custom_fields(): dict(fieldname='supplier_name_in_arabic', label='Supplier Name in Arabic', fieldtype='Data', insert_after='supplier_name'), ], + 'Address': [ + dict(fieldname='emirates', label='Emirates', + fieldtype='Data', insert_after='state'), + ], 'Purchase Invoice': purchase_invoice_fields + invoice_fields, 'Purchase Order': purchase_invoice_fields + invoice_fields, 'Purchase Receipt': purchase_invoice_fields + invoice_fields, From 7b7a8e1309ba0c262da7de07424858f5de9751d3 Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Wed, 9 Sep 2020 20:54:30 +0530 Subject: [PATCH 02/60] feat: RCM for UAE VAT --- erpnext/hooks.py | 8 +- .../regional/united_arab_emirates/utils.py | 144 +++++++++++++++++- 2 files changed, 148 insertions(+), 4 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 463ad6c94b4..72be2dcc754 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -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' diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index a0425f6b1c2..05a99d190a9 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -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")) \ No newline at end of file + 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 \ No newline at end of file From 91f1e266726c20abd2afc797c0c12f0e8793a3c5 Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Thu, 10 Sep 2020 13:55:14 +0530 Subject: [PATCH 03/60] feat: Add rated supplies rows in UAE VAT report --- erpnext/regional/report/uae_vat/__init__.py | 0 erpnext/regional/report/uae_vat/uae_vat.js | 31 ++++++ erpnext/regional/report/uae_vat/uae_vat.json | 22 ++++ erpnext/regional/report/uae_vat/uae_vat.py | 108 +++++++++++++++++++ 4 files changed, 161 insertions(+) create mode 100644 erpnext/regional/report/uae_vat/__init__.py create mode 100644 erpnext/regional/report/uae_vat/uae_vat.js create mode 100644 erpnext/regional/report/uae_vat/uae_vat.json create mode 100644 erpnext/regional/report/uae_vat/uae_vat.py diff --git a/erpnext/regional/report/uae_vat/__init__.py b/erpnext/regional/report/uae_vat/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/regional/report/uae_vat/uae_vat.js b/erpnext/regional/report/uae_vat/uae_vat.js new file mode 100644 index 00000000000..45df167823e --- /dev/null +++ b/erpnext/regional/report/uae_vat/uae_vat.js @@ -0,0 +1,31 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["UAE VAT"] = { + "filters": [ + { + "fieldname": "company", + "label": __("Company"), + "fieldtype": "Link", + "options": "Company", + "reqd": 1, + "default": frappe.defaults.get_user_default("Company") + }, + { + "fieldname": "from_date", + "label": __("From Date"), + "fieldtype": "Date", + "reqd": 1, + "default": frappe.datetime.add_months(frappe.datetime.get_today(), -3), + "width": "80" + }, + { + "fieldname": "to_date", + "label": __("To Date"), + "fieldtype": "Date", + "reqd": 1, + "default": frappe.datetime.get_today() + }, + ] +}; diff --git a/erpnext/regional/report/uae_vat/uae_vat.json b/erpnext/regional/report/uae_vat/uae_vat.json new file mode 100644 index 00000000000..8807405a983 --- /dev/null +++ b/erpnext/regional/report/uae_vat/uae_vat.json @@ -0,0 +1,22 @@ +{ + "add_total_row": 0, + "columns": [], + "creation": "2020-09-10 08:51:02.298482", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "filters": [], + "idx": 0, + "is_standard": "Yes", + "modified": "2020-09-10 08:51:02.298482", + "modified_by": "Administrator", + "module": "Regional", + "name": "UAE VAT", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "GL Entry", + "report_name": "UAE VAT", + "report_type": "Script Report", + "roles": [] +} \ No newline at end of file diff --git a/erpnext/regional/report/uae_vat/uae_vat.py b/erpnext/regional/report/uae_vat/uae_vat.py new file mode 100644 index 00000000000..6e9565b1e5f --- /dev/null +++ b/erpnext/regional/report/uae_vat/uae_vat.py @@ -0,0 +1,108 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe + +def execute(filters=None): + columns = get_columns() + data = get_data(filters) + + return columns, data + +def get_columns(): + return [ + { + "fieldname": "no", + "label": "No", + "fieldtype": "Data", + "width": 50 + }, + { + "fieldname": "legend", + "label": "Legend", + "fieldtype": "Data", + "width": 300 + }, + { + "fieldname": "amount", + "label": "Amount (AED)", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "vat_amount", + "label": "VAT Amount (AED)", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "adjustment", + "label": "Adjustment (AED)", + "fieldtype": "Currency", + "width": 100 + } + ] + +def get_data(filters = None): + data = [] + total_emiratewise = get_total_emiratewise(filters) + emirates = get_emirates() + amounts_by_emirate = {} + for d in total_emiratewise: + emirate, amount, vat= d + amounts_by_emirate[emirate] = { + "legend": emirate, + "amount": amount, + "vat_amount": vat + } + for d, emirate in enumerate(emirates, 97): + if emirate in amounts_by_emirate: + amounts_by_emirate[emirate]["no"] = f'1{chr(d)}' + amounts_by_emirate[emirate]["legend"] = f'Standard rated supplies in {emirate}' + data.append(amounts_by_emirate[emirate]) + else: + data.append( + { + "no": f'1{chr(d)}', + "legend": f'Standard rated supplies in {emirate}', + "amount": 0, + "vat_amount": 0 + } + ) + return data + + +def get_total_emiratewise(filters): + conditions = get_conditions(filters) + print(f""" + select emirate, sum(total), sum(total_taxes_and_charges) from `tabSales Invoice` + where docstatus = 1 {conditions} + group by `tabSales Invoice`.emirate; + """) + return frappe.db.sql(f""" + select emirate, sum(total), sum(total_taxes_and_charges) from `tabSales Invoice` + where docstatus = 1 {conditions} + group by `tabSales Invoice`.emirate; + """, filters) + +def get_emirates(): + return [ + 'Abu Dhabi', + 'Dubai', + 'Sharjah', + 'Ajman', + 'Umm Al Quwain', + 'Ras Al Khaimah', + 'Fujairah' + ] + +def get_conditions(filters): + conditions = "" + + for opts in (("company", " and company=%(company)s"), + ("from_date", " and posting_date>=%(from_date)s"), + ("to_date", " and posting_date<=%(to_date)s")): + if filters.get(opts[0]): + conditions += opts[1] + return conditions \ No newline at end of file From 031d77be2e58a033786a81354f08607ea07e4910 Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Thu, 10 Sep 2020 17:40:01 +0530 Subject: [PATCH 04/60] feat: add reverse charge to uae vat report --- erpnext/regional/report/uae_vat/uae_vat.py | 53 +++++++++++++++---- .../regional/united_arab_emirates/setup.py | 8 +-- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/erpnext/regional/report/uae_vat/uae_vat.py b/erpnext/regional/report/uae_vat/uae_vat.py index 6e9565b1e5f..50d1ddd3510 100644 --- a/erpnext/regional/report/uae_vat/uae_vat.py +++ b/erpnext/regional/report/uae_vat/uae_vat.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals import frappe +from erpnext.regional.united_arab_emirates.utils import get_tax_accounts def execute(filters=None): columns = get_columns() @@ -70,19 +71,21 @@ def get_data(filters = None): "vat_amount": 0 } ) + data.append( + { + "no": '3', + "legend": f'Supplies subject to the reverse charge provision', + "amount": get_reverse_charge_total(filters), + "vat_amount": get_reverse_charge_tax(filters) + } + ) return data def get_total_emiratewise(filters): - conditions = get_conditions(filters) - print(f""" - select emirate, sum(total), sum(total_taxes_and_charges) from `tabSales Invoice` - where docstatus = 1 {conditions} - group by `tabSales Invoice`.emirate; - """) return frappe.db.sql(f""" select emirate, sum(total), sum(total_taxes_and_charges) from `tabSales Invoice` - where docstatus = 1 {conditions} + where docstatus = 1 {get_conditions(filters)} group by `tabSales Invoice`.emirate; """, filters) @@ -99,10 +102,40 @@ def get_emirates(): def get_conditions(filters): conditions = "" + for opts in (("company", f' and company="{filters.get("company")}"'), + ("from_date", f' and posting_date>="{filters.get("from_date")}"'), + ("to_date", f' and posting_date<="{filters.get("to_date")}"')): + if filters.get(opts[0]): + conditions += opts[1] + return conditions - for opts in (("company", " and company=%(company)s"), - ("from_date", " and posting_date>=%(from_date)s"), - ("to_date", " and posting_date<=%(to_date)s")): +def get_reverse_charge_tax(filters): + return frappe.db.sql(f""" + select sum(debit) from + `tabPurchase Invoice` inner join `tabGL Entry` + on `tabGL Entry`.voucher_no = `tabPurchase Invoice`.name + where + `tabPurchase Invoice`.reverse_charge = "Y" + and `tabPurchase Invoice`.docstatus = 1 + and `tabGL Entry`.docstatus = 1 {get_conditions_join(filters)} + and account in ("{'", "'.join(get_tax_accounts(filters['company']))}"); + """)[0][0] + + +def get_reverse_charge_total(filters): + return frappe.db.sql(f""" + select sum(total) from + `tabPurchase Invoice` + where + reverse_charge = "Y" + and docstatus = 1 {get_conditions(filters)} ; + """)[0][0] + +def get_conditions_join(filters): + conditions = "" + for opts in (("company", f' and `tabPurchase Invoice`.company="{filters.get("company")}"'), + ("from_date", f' and `tabPurchase Invoice`.posting_date>="{filters.get("from_date")}"'), + ("to_date", f' and `tabPurchase Invoice`.posting_date<="{filters.get("to_date")}"')): if filters.get(opts[0]): conditions += opts[1] return conditions \ No newline at end of file diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index a2938bb3003..d38d647277c 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -20,7 +20,7 @@ def make_custom_fields(): insert_after='group_same_items', print_hide=1, collapsible=1), dict(fieldname='permit_no', label='Permit Number', fieldtype='Data', insert_after='vat_section', print_hide=1), - dict(fieldname='reverse_charge_applicable', label='Reverse Charge Applicable', + dict(fieldname='reverse_charge', label='Reverse Charge Applicable', fieldtype='Select', insert_after='permit_no', print_hide=1, options='Y\nN', default='N') ] @@ -42,7 +42,7 @@ def make_custom_fields(): fieldtype='Read Only', insert_after='customer_name', fetch_from='customer.customer_name_in_arabic', print_hide=1), dict(fieldname='emirate', label='Emirate', insert_after='customer_address', - fetch_from='customer_address.emirates'), + fieldtype='Read Only', fetch_from='customer_address.emirates'), ] invoice_item_fields = [ @@ -79,8 +79,8 @@ def make_custom_fields(): fieldtype='Data', insert_after='supplier_name'), ], 'Address': [ - dict(fieldname='emirates', label='Emirates', - fieldtype='Data', insert_after='state'), + dict(fieldname='emirates', label='Emirates', fieldtype='Select', insert_after='state', + options='Abu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain') ], 'Purchase Invoice': purchase_invoice_fields + invoice_fields, 'Purchase Order': purchase_invoice_fields + invoice_fields, From 323791d123e63e9a7b61109d7a727137e7fe81d0 Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Thu, 10 Sep 2020 17:53:29 +0530 Subject: [PATCH 05/60] refactor: added docstrings --- erpnext/regional/report/uae_vat/uae_vat.py | 75 +++++++++++++++++++--- 1 file changed, 67 insertions(+), 8 deletions(-) diff --git a/erpnext/regional/report/uae_vat/uae_vat.py b/erpnext/regional/report/uae_vat/uae_vat.py index 50d1ddd3510..4c4c6bc2abc 100644 --- a/erpnext/regional/report/uae_vat/uae_vat.py +++ b/erpnext/regional/report/uae_vat/uae_vat.py @@ -12,6 +12,11 @@ def execute(filters=None): return columns, data def get_columns(): + """Creates a list of dictionaries that are used to generate column headers of the data table + + Returns: + List(Dict): list of dictionaries that are used to generate column headers of the data table + """ return [ { "fieldname": "no", @@ -46,6 +51,14 @@ def get_columns(): ] def get_data(filters = None): + """Returns the list of dictionaries. Each dictionary is a row in the datatable + + Args: + filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. + + Returns: + List(Dict): Each dictionary is a row in the datatable + """ data = [] total_emiratewise = get_total_emiratewise(filters) emirates = get_emirates() @@ -90,6 +103,11 @@ def get_total_emiratewise(filters): """, filters) def get_emirates(): + """Returns a List of emirates in the order that they are to be displayed + + Returns: + List(String): List of emirates in the order that they are to be displayed + """ return [ 'Abu Dhabi', 'Dubai', @@ -101,6 +119,14 @@ def get_emirates(): ] def get_conditions(filters): + """The conditions to be used to filter data to calculate the total sale + + Args: + filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. + + Returns: + String: Concatenated list of conditions to be applied to calculate the total sale + """ conditions = "" for opts in (("company", f' and company="{filters.get("company")}"'), ("from_date", f' and posting_date>="{filters.get("from_date")}"'), @@ -109,7 +135,40 @@ def get_conditions(filters): conditions += opts[1] return conditions +def get_reverse_charge_total(filters): + """Returns the sum of the total of each Purchase invoice made + + Args: + filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. + + Returns: + Float: sum of the total of each Purchase invoice made + """ + conditions = """ + for opts in (("company", f' and company="{filters.get("company")}"'), + ("from_date", f' and posting_date>="{filters.get("from_date")}"'), + ("to_date", f' and posting_date<="{filters.get("to_date")}"')): + if filters.get(opts[0]): + conditions += opts[1] + return conditions + """ + return frappe.db.sql(f""" + select sum(total) from + `tabPurchase Invoice` + where + reverse_charge = "Y" + and docstatus = 1 {get_conditions(filters)} ; + """)[0][0] + def get_reverse_charge_tax(filters): + """Returns the sum of the tax of each Purchase invoice made + + Args: + filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. + + Returns: + Float: sum of the tax of each Purchase invoice made + """ return frappe.db.sql(f""" select sum(debit) from `tabPurchase Invoice` inner join `tabGL Entry` @@ -122,16 +181,16 @@ def get_reverse_charge_tax(filters): """)[0][0] -def get_reverse_charge_total(filters): - return frappe.db.sql(f""" - select sum(total) from - `tabPurchase Invoice` - where - reverse_charge = "Y" - and docstatus = 1 {get_conditions(filters)} ; - """)[0][0] def get_conditions_join(filters): + """The conditions to be used to filter data to calculate the total vat + + Args: + filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. + + Returns: + String: Concatenated list of conditions to be applied to calculate the total vat + """ conditions = "" for opts in (("company", f' and `tabPurchase Invoice`.company="{filters.get("company")}"'), ("from_date", f' and `tabPurchase Invoice`.posting_date>="{filters.get("from_date")}"'), From f44524dd3e3ed87ed112d99ea7fef8cf450c9dcd Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Thu, 10 Sep 2020 18:35:04 +0530 Subject: [PATCH 06/60] feat: Added a Chart to compare Vat and sales between emirates --- erpnext/regional/report/uae_vat/uae_vat.py | 48 +++++++++++++++++++--- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/erpnext/regional/report/uae_vat/uae_vat.py b/erpnext/regional/report/uae_vat/uae_vat.py index 4c4c6bc2abc..8eeff517238 100644 --- a/erpnext/regional/report/uae_vat/uae_vat.py +++ b/erpnext/regional/report/uae_vat/uae_vat.py @@ -4,12 +4,12 @@ from __future__ import unicode_literals import frappe from erpnext.regional.united_arab_emirates.utils import get_tax_accounts +from frappe import _ def execute(filters=None): columns = get_columns() - data = get_data(filters) - - return columns, data + data, chart = get_data(filters) + return columns, data, None, chart def get_columns(): """Creates a list of dictionaries that are used to generate column headers of the data table @@ -51,13 +51,14 @@ def get_columns(): ] def get_data(filters = None): - """Returns the list of dictionaries. Each dictionary is a row in the datatable + """Returns the list of dictionaries. Each dictionary is a row in the datatable and chart data Args: filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. Returns: List(Dict): Each dictionary is a row in the datatable + Dict: Dictionary containing chart data """ data = [] total_emiratewise = get_total_emiratewise(filters) @@ -70,6 +71,9 @@ def get_data(filters = None): "amount": amount, "vat_amount": vat } + + chart = get_chart_data(emirates, amounts_by_emirate) + for d, emirate in enumerate(emirates, 97): if emirate in amounts_by_emirate: amounts_by_emirate[emirate]["no"] = f'1{chr(d)}' @@ -92,9 +96,43 @@ def get_data(filters = None): "vat_amount": get_reverse_charge_tax(filters) } ) - return data + return data, chart +def get_chart_data(emirates, amounts_by_emirate): + """Returns chart data + + Args: + emirates (List): List of Emirates + amounts_by_emirate (Dict): Vat and Tax amount by emirates with emirates as key + + Returns: + [Dict]: Chart Data + """ + labels = [] + amount = [] + vat_amount = [] + for d in emirates: + if d in amounts_by_emirate: + amount.append(amounts_by_emirate[d]["amount"]) + vat_amount.append(amounts_by_emirate[d]["vat_amount"]) + labels.append(d) + + datasets = [] + datasets.append({'name': _('Amount (AED)'), 'values': amount}) + datasets.append({'name': _('Vat Amount (AED)'), 'values': vat_amount}) + + chart = { + "data": { + 'labels': labels, + 'datasets': datasets + } + } + + chart["type"] = "bar" + chart["fieldtype"] = "Currency" + return chart + def get_total_emiratewise(filters): return frappe.db.sql(f""" select emirate, sum(total), sum(total_taxes_and_charges) from `tabSales Invoice` From 3ef11b1d647666b2eed836fd7f449e1b1bb88f8f Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Thu, 24 Sep 2020 13:21:23 +0530 Subject: [PATCH 07/60] feat(UAE VAT 21): Add region fields for UAE VAT 21 --- erpnext/hooks.py | 3 +++ .../regional/united_arab_emirates/setup.py | 20 +++++++++++++++---- .../regional/united_arab_emirates/utils.py | 12 ++++++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 72be2dcc754..ec34c4e126e 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -243,6 +243,9 @@ doc_events = { "erpnext.regional.italy.utils.sales_invoice_on_cancel", "erpnext.erpnext_integrations.taxjar_integration.delete_transaction" ], + "validate": [ + "erpnext.regional.united_arab_emirates.utils.validate_returns", + ], "on_trash": "erpnext.regional.check_deletion_permission" }, "Purchase Invoice": { diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index d38d647277c..f116303d80a 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -20,9 +20,6 @@ def make_custom_fields(): insert_after='group_same_items', print_hide=1, collapsible=1), dict(fieldname='permit_no', label='Permit Number', fieldtype='Data', insert_after='vat_section', print_hide=1), - dict(fieldname='reverse_charge', label='Reverse Charge Applicable', - fieldtype='Select', insert_after='permit_no', print_hide=1, - options='Y\nN', default='N') ] purchase_invoice_fields = [ @@ -31,7 +28,12 @@ def make_custom_fields(): fetch_from='company.tax_id', print_hide=1), dict(fieldname='supplier_name_in_arabic', label='Supplier Name in Arabic', fieldtype='Read Only', insert_after='supplier_name', - fetch_from='supplier.supplier_name_in_arabic', print_hide=1) + fetch_from='supplier.supplier_name_in_arabic', print_hide=1), + dict(fieldname='reverse_charge', label='Reverse Charge Applicable', + fieldtype='Select', insert_after='permit_no', print_hide=1, + options='Y\nN', default='N'), + dict(fieldname='claimable_reverse_charge', label='Claimable Reverse Charge (Percentage)', + insert_after='reverse_charge', fieldtype='Percent'), ] sales_invoice_fields = [ @@ -43,6 +45,12 @@ def make_custom_fields(): fetch_from='customer.customer_name_in_arabic', print_hide=1), dict(fieldname='emirate', label='Emirate', insert_after='customer_address', fieldtype='Read Only', fetch_from='customer_address.emirates'), + dict(fieldname='returns_column_break', fieldtype='Column Break', + insert_after='select_print_heading'), + dict(fieldname='tourist_tax_return', label='Tax Refund provided to Tourists (AED)', + insert_after='returns_column_break', fieldtype='Currency',), + dict(fieldname='standard_rated_expenses', label='Standard Rated Expenses (AED)', + insert_after='tourist_tax_return', fieldtype='Currency',), ] invoice_item_fields = [ @@ -69,6 +77,10 @@ def make_custom_fields(): 'Item': [ dict(fieldname='tax_code', label='Tax Code', fieldtype='Data', insert_after='item_group'), + # dict(fieldname='is_zero_rated', label='Is Zero Rated', + # fieldtype='Check', insert_after='tax_code'), + # dict(fieldname='is_exempt', label='Is Exempt ', + # fieldtype='Check', insert_after='is_zero_rated') ], 'Customer': [ dict(fieldname='customer_name_in_arabic', label='Customer Name in Arabic', diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index 05a99d190a9..5242c63e63f 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -166,4 +166,14 @@ def make_regional_gl_entries(gl_entries, doc): else tax.tax_amount_after_discount_amount }, account_currency, item=tax) ) - return gl_entries \ No newline at end of file + return gl_entries + +def validate_returns(doc, method): + print("validate_returns") + country = frappe.get_cached_value('Company', doc.company, 'country') + + if country != 'United Arab Emirates': + return + + if flt(doc.tourist_tax_return) + flt(doc.standard_rated_expenses) > flt(doc.total_taxes_and_charges): + frappe.throw(_("The Total Returns(Tax Refund provided to Tourists (AED) + Standard Rated Expenses (AED)) should be less than the Total Taxes and Charges (Company Currency)")) \ No newline at end of file From 5225215d3116cefd45f5c1ed7a7fce2fddab9522 Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Thu, 24 Sep 2020 18:41:43 +0530 Subject: [PATCH 08/60] feat(UAE VAT 21): Add rows for inputs and tourists --- erpnext/regional/report/uae_vat/uae_vat.py | 168 +++++++++++++++++- .../regional/united_arab_emirates/setup.py | 11 +- 2 files changed, 173 insertions(+), 6 deletions(-) diff --git a/erpnext/regional/report/uae_vat/uae_vat.py b/erpnext/regional/report/uae_vat/uae_vat.py index 8eeff517238..b3e52be3e5a 100644 --- a/erpnext/regional/report/uae_vat/uae_vat.py +++ b/erpnext/regional/report/uae_vat/uae_vat.py @@ -61,6 +61,7 @@ def get_data(filters = None): Dict: Dictionary containing chart data """ data = [] + data.append({"legend": f'VAT on Sales and All Other Outputs',}) total_emiratewise = get_total_emiratewise(filters) emirates = get_emirates() amounts_by_emirate = {} @@ -88,6 +89,16 @@ def get_data(filters = None): "vat_amount": 0 } ) + + data.append( + { + "no": '2', + "legend": f'Tax Refunds provided to Tourists under the Tax Refunds for Tourists Scheme', + "amount": (-1) * get_tourist_tax_return_total(filters), + "vat_amount": (-1) * get_tourist_tax_return_tax(filters) + } + ) + data.append( { "no": '3', @@ -96,6 +107,25 @@ def get_data(filters = None): "vat_amount": get_reverse_charge_tax(filters) } ) + + data.append({"legend": f'VAT on Expenses and All Other Inputs'}) + data.append( + { + "no": '9', + "legend": f'Standard Rated Expenses', + "amount": get_standard_rated_expenses_total(filters), + "vat_amount": get_standard_rated_expenses_tax(filters) + } + ) + data.append( + { + "no": '10', + "legend": f'Supplies subject to the reverse charge provision', + "amount": get_reverse_charge_recoverable_total(filters), + "vat_amount": get_reverse_charge_recoverable_tax(filters) + } + ) + return data, chart @@ -235,4 +265,140 @@ def get_conditions_join(filters): ("to_date", f' and `tabPurchase Invoice`.posting_date<="{filters.get("to_date")}"')): if filters.get(opts[0]): conditions += opts[1] - return conditions \ No newline at end of file + return conditions + + +def get_reverse_charge_recoverable_total(filters): + """Returns the sum of the total of each Purchase invoice made with claimable reverse charge + + Args: + filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. + + Returns: + Float: sum of the total of each Purchase invoice made with claimable reverse charge + """ + conditions = """ + for opts in (("company", f' and company="{filters.get("company")}"'), + ("from_date", f' and posting_date>="{filters.get("from_date")}"'), + ("to_date", f' and posting_date<="{filters.get("to_date")}"')): + if filters.get(opts[0]): + conditions += opts[1] + return conditions + """ + return frappe.db.sql(f""" + select sum(total) from + `tabPurchase Invoice` + where + reverse_charge = "Y" + and claimable_reverse_charge > 0 + and docstatus = 1 {get_conditions(filters)} ; + """)[0][0] + + +def get_reverse_charge_recoverable_tax(filters): + """Returns the sum of the tax of each Purchase invoice made + + Args: + filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. + + Returns: + Float: sum of the tax of each Purchase invoice made + """ + return frappe.db.sql(f""" + select sum(debit * `tabPurchase Invoice`.claimable_reverse_charge / 100) from + `tabPurchase Invoice` inner join `tabGL Entry` + on `tabGL Entry`.voucher_no = `tabPurchase Invoice`.name + where + `tabPurchase Invoice`.reverse_charge = "Y" + and `tabPurchase Invoice`.docstatus = 1 + and `tabPurchase Invoice`.claimable_reverse_charge > 0 + and `tabGL Entry`.docstatus = 1 {get_conditions_join(filters)} + and account in ("{'", "'.join(get_tax_accounts(filters['company']))}"); + """)[0][0] + + +def get_standard_rated_expenses_total(filters): + """Returns the sum of the total of each Purchase invoice made with claimable reverse charge + + Args: + filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. + + Returns: + Float: sum of the total of each Purchase invoice made with claimable reverse charge + """ + conditions = """ + for opts in (("company", f' and company="{filters.get("company")}"'), + ("from_date", f' and posting_date>="{filters.get("from_date")}"'), + ("to_date", f' and posting_date<="{filters.get("to_date")}"')): + if filters.get(opts[0]): + conditions += opts[1] + return conditions + """ + return frappe.db.sql(f""" + select sum(total) from + `tabSales Invoice` + where + standard_rated_expenses > 0 + and docstatus = 1 {get_conditions(filters)} ; + """)[0][0] + + +def get_standard_rated_expenses_tax(filters): + """Returns the sum of the tax of each Purchase invoice made + + Args: + filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. + + Returns: + Float: sum of the tax of each Purchase invoice made + """ + return frappe.db.sql(f""" + select sum(standard_rated_expenses) from + `tabSales Invoice` + where + standard_rated_expenses > 0 + and docstatus = 1 {get_conditions(filters)} ; + """)[0][0] + +def get_tourist_tax_return_total(filters): + """Returns the sum of the total of each Sales invoice with non zero tourist_tax_return + + Args: + filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. + + Returns: + Float: sum of the total of each Sales invoice with non zero tourist_tax_return + """ + conditions = """ + for opts in (("company", f' and company="{filters.get("company")}"'), + ("from_date", f' and posting_date>="{filters.get("from_date")}"'), + ("to_date", f' and posting_date<="{filters.get("to_date")}"')): + if filters.get(opts[0]): + conditions += opts[1] + return conditions + """ + return frappe.db.sql(f""" + select sum(total) from + `tabSales Invoice` + where + tourist_tax_return > 0 + and docstatus = 1 {get_conditions(filters)} ; + """)[0][0] + + +def get_tourist_tax_return_tax(filters): + """Returns the sum of the tax of each Sales invoice with non zero tourist_tax_return + + Args: + filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. + + Returns: + Float: sum of the tax of each Sales invoice with non zero tourist_tax_return + """ + return frappe.db.sql(f""" + select sum(tourist_tax_return) from + `tabSales Invoice` + where + tourist_tax_return > 0 + and docstatus = 1 {get_conditions(filters)} ; + """)[0][0] \ No newline at end of file diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index f116303d80a..01763402b11 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -33,7 +33,8 @@ def make_custom_fields(): fieldtype='Select', insert_after='permit_no', print_hide=1, options='Y\nN', default='N'), dict(fieldname='claimable_reverse_charge', label='Claimable Reverse Charge (Percentage)', - insert_after='reverse_charge', fieldtype='Percent'), + insert_after='reverse_charge', fieldtype='Percent', print_hide=1, + depends_on="eval:doc.reverse_charge=='Y'", default='100.000'), ] sales_invoice_fields = [ @@ -45,12 +46,12 @@ def make_custom_fields(): fetch_from='customer.customer_name_in_arabic', print_hide=1), dict(fieldname='emirate', label='Emirate', insert_after='customer_address', fieldtype='Read Only', fetch_from='customer_address.emirates'), - dict(fieldname='returns_column_break', fieldtype='Column Break', - insert_after='select_print_heading'), + # dict(fieldname='returns_column_break', fieldtype='Column Break', + # insert_after='select_print_heading'), dict(fieldname='tourist_tax_return', label='Tax Refund provided to Tourists (AED)', - insert_after='returns_column_break', fieldtype='Currency',), + insert_after='permit_no', fieldtype='Currency', print_hide=1, default='0'), dict(fieldname='standard_rated_expenses', label='Standard Rated Expenses (AED)', - insert_after='tourist_tax_return', fieldtype='Currency',), + insert_after='tourist_tax_return', fieldtype='Currency', print_hide=1, default='0'), ] invoice_item_fields = [ From 72cad2a8abd173b2c84029bfdff6df38d6e87a6f Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Fri, 25 Sep 2020 13:13:38 +0530 Subject: [PATCH 09/60] feat(UAE VAT 21): Add zero rated and vat exempt --- erpnext/regional/report/uae_vat/uae_vat.js | 12 ++- erpnext/regional/report/uae_vat/uae_vat.py | 87 +++++++++++++++---- .../regional/united_arab_emirates/setup.py | 21 +++-- 3 files changed, 96 insertions(+), 24 deletions(-) diff --git a/erpnext/regional/report/uae_vat/uae_vat.js b/erpnext/regional/report/uae_vat/uae_vat.js index 45df167823e..0213956d44b 100644 --- a/erpnext/regional/report/uae_vat/uae_vat.js +++ b/erpnext/regional/report/uae_vat/uae_vat.js @@ -27,5 +27,15 @@ frappe.query_reports["UAE VAT"] = { "reqd": 1, "default": frappe.datetime.get_today() }, - ] + ], + "formatter": function(value, row, column, data, default_formatter) { + if (data + && (data.legend=='VAT on Sales and All Other Outputs' || data.legend=='VAT on Expenses and All Other Inputs') + && data.legend==value) { + value = $(`${value}`); + var $value = $(value).css("font-weight", "bold"); + value = $value.wrap("

").parent().html(); + } + return value; + }, }; diff --git a/erpnext/regional/report/uae_vat/uae_vat.py b/erpnext/regional/report/uae_vat/uae_vat.py index b3e52be3e5a..1a3537c268a 100644 --- a/erpnext/regional/report/uae_vat/uae_vat.py +++ b/erpnext/regional/report/uae_vat/uae_vat.py @@ -41,12 +41,6 @@ def get_columns(): "label": "VAT Amount (AED)", "fieldtype": "Currency", "width": 100 - }, - { - "fieldname": "adjustment", - "label": "Adjustment (AED)", - "fieldtype": "Currency", - "width": 100 } ] @@ -61,7 +55,12 @@ def get_data(filters = None): Dict: Dictionary containing chart data """ data = [] - data.append({"legend": f'VAT on Sales and All Other Outputs',}) + data.append({ + "no": '', + "legend": f'VAT on Sales and All Other Outputs', + "amount": '', + "vat_amount": '' + }) total_emiratewise = get_total_emiratewise(filters) emirates = get_emirates() amounts_by_emirate = {} @@ -108,7 +107,30 @@ def get_data(filters = None): } ) - data.append({"legend": f'VAT on Expenses and All Other Inputs'}) + data.append( + { + "no": '4', + "legend": f'Zero Rated', + "amount": get_zero_rated_total(filters), + "vat_amount": "-" + } + ) + + data.append( + { + "no": '5', + "legend": f'Exempt Supplies', + "amount": get_exempt_total(filters), + "vat_amount": "-" + } + ) + + data.append({ + "no": '', + "legend": f'VAT on Expenses and All Other Inputs', + "amount": '', + "vat_amount": '' + }) data.append( { "no": '9', @@ -226,7 +248,7 @@ def get_reverse_charge_total(filters): where reverse_charge = "Y" and docstatus = 1 {get_conditions(filters)} ; - """)[0][0] + """)[0][0] or 0 def get_reverse_charge_tax(filters): """Returns the sum of the tax of each Purchase invoice made @@ -246,7 +268,7 @@ def get_reverse_charge_tax(filters): and `tabPurchase Invoice`.docstatus = 1 and `tabGL Entry`.docstatus = 1 {get_conditions_join(filters)} and account in ("{'", "'.join(get_tax_accounts(filters['company']))}"); - """)[0][0] + """)[0][0] or 0 @@ -292,7 +314,7 @@ def get_reverse_charge_recoverable_total(filters): reverse_charge = "Y" and claimable_reverse_charge > 0 and docstatus = 1 {get_conditions(filters)} ; - """)[0][0] + """)[0][0] or 0 def get_reverse_charge_recoverable_tax(filters): @@ -314,7 +336,7 @@ def get_reverse_charge_recoverable_tax(filters): and `tabPurchase Invoice`.claimable_reverse_charge > 0 and `tabGL Entry`.docstatus = 1 {get_conditions_join(filters)} and account in ("{'", "'.join(get_tax_accounts(filters['company']))}"); - """)[0][0] + """)[0][0] or 0 def get_standard_rated_expenses_total(filters): @@ -340,7 +362,7 @@ def get_standard_rated_expenses_total(filters): where standard_rated_expenses > 0 and docstatus = 1 {get_conditions(filters)} ; - """)[0][0] + """)[0][0] or 0 def get_standard_rated_expenses_tax(filters): @@ -358,7 +380,7 @@ def get_standard_rated_expenses_tax(filters): where standard_rated_expenses > 0 and docstatus = 1 {get_conditions(filters)} ; - """)[0][0] + """)[0][0] or 0 def get_tourist_tax_return_total(filters): """Returns the sum of the total of each Sales invoice with non zero tourist_tax_return @@ -383,7 +405,7 @@ def get_tourist_tax_return_total(filters): where tourist_tax_return > 0 and docstatus = 1 {get_conditions(filters)} ; - """)[0][0] + """)[0][0] or 0 def get_tourist_tax_return_tax(filters): @@ -401,4 +423,37 @@ def get_tourist_tax_return_tax(filters): where tourist_tax_return > 0 and docstatus = 1 {get_conditions(filters)} ; - """)[0][0] \ No newline at end of file + """)[0][0] or 0 + +def get_zero_rated_total(filters): + """Returns the sum of each Sales Invoice Item Amount which is zero rated + + Args: + filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. + + Returns: + Float: sum of each Sales Invoice Item Amount which is zero rated + """ + return frappe.db.sql(f""" + select sum(i.base_amount) as total from + `tabSales Invoice Item` i, `tabSales Invoice` s + where s.docstatus = 1 and i.parent = s.name and i.is_zero_rated = 1 + {get_conditions(filters)} ; + """)[0][0] or 0 + + +def get_exempt_total(filters): + """Returns the sum of each Sales Invoice Item Amount which is Vat Exempt + + Args: + filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. + + Returns: + Float: sum of each Sales Invoice Item Amount which is Vat Exempt + """ + return frappe.db.sql(f""" + select sum(i.base_amount) as total from + `tabSales Invoice Item` i, `tabSales Invoice` s + where s.docstatus = 1 and i.parent = s.name and i.is_exempt = 1 + {get_conditions(filters)} ; + """)[0][0] or 0 \ No newline at end of file diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index 01763402b11..29ad41c9afc 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -15,6 +15,13 @@ def setup(company=None, patch=True): create_sales_tax(company) def make_custom_fields(): + is_zero_rated = dict(fieldname='is_zero_rated', label='Is Zero Rated', + fieldtype='Check', fetch_from='item_code.is_zero_rated', insert_after='description', + print_hide=1) + is_exempt = dict(fieldname='is_exempt', label='Is Exempt', + fieldtype='Check', fetch_from='item_code.is_exempt', insert_after='is_zero_rated', + print_hide=1) + invoice_fields = [ dict(fieldname='vat_section', label='VAT Details', fieldtype='Section Break', insert_after='group_same_items', print_hide=1, collapsible=1), @@ -46,8 +53,6 @@ def make_custom_fields(): fetch_from='customer.customer_name_in_arabic', print_hide=1), dict(fieldname='emirate', label='Emirate', insert_after='customer_address', fieldtype='Read Only', fetch_from='customer_address.emirates'), - # dict(fieldname='returns_column_break', fieldtype='Column Break', - # insert_after='select_print_heading'), dict(fieldname='tourist_tax_return', label='Tax Refund provided to Tourists (AED)', insert_after='permit_no', fieldtype='Currency', print_hide=1, default='0'), dict(fieldname='standard_rated_expenses', label='Standard Rated Expenses (AED)', @@ -78,10 +83,12 @@ def make_custom_fields(): 'Item': [ dict(fieldname='tax_code', label='Tax Code', fieldtype='Data', insert_after='item_group'), - # dict(fieldname='is_zero_rated', label='Is Zero Rated', - # fieldtype='Check', insert_after='tax_code'), - # dict(fieldname='is_exempt', label='Is Exempt ', - # fieldtype='Check', insert_after='is_zero_rated') + dict(fieldname='is_zero_rated', label='Is Zero Rated', + fieldtype='Check', insert_after='tax_code', + print_hide=1), + dict(fieldname='is_exempt', label='Is Exempt ', + fieldtype='Check', insert_after='is_zero_rated', + print_hide=1) ], 'Customer': [ dict(fieldname='customer_name_in_arabic', label='Customer Name in Arabic', @@ -101,7 +108,7 @@ def make_custom_fields(): 'Sales Invoice': sales_invoice_fields + invoice_fields, 'Sales Order': sales_invoice_fields + invoice_fields, 'Delivery Note': sales_invoice_fields + invoice_fields, - 'Sales Invoice Item': invoice_item_fields + delivery_date_field, + 'Sales Invoice Item': invoice_item_fields + delivery_date_field + [is_zero_rated, is_exempt], 'Purchase Invoice Item': invoice_item_fields, 'Sales Order Item': invoice_item_fields, 'Delivery Note Item': invoice_item_fields, From 321b5f54aef19c66460657552695af65b4a977a6 Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Fri, 25 Sep 2020 14:24:57 +0530 Subject: [PATCH 10/60] feat(UAE VAT 21): Add Roles for UAE VAT 21 Report --- erpnext/regional/united_arab_emirates/setup.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index 29ad41c9afc..95fde3ab9fc 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -10,6 +10,7 @@ from erpnext.setup.setup_wizard.operations.taxes_setup import create_sales_tax def setup(company=None, patch=True): make_custom_fields() add_print_formats() + add_custom_roles_for_reports() if company: create_sales_tax(company) @@ -127,3 +128,15 @@ def add_print_formats(): frappe.db.sql(""" update `tabPrint Format` set disabled = 0 where name in('Simplified Tax Invoice', 'Detailed Tax Invoice', 'Tax Invoice') """) + +def add_custom_roles_for_reports(): + if not frappe.db.get_value('Custom Role', dict(report='UAE VAT')): + frappe.get_doc(dict( + doctype='Custom Role', + report='UAE VAT', + roles= [ + dict(role='Accounts User'), + dict(role='Accounts Manager'), + dict(role='Auditor') + ] + )).insert() \ No newline at end of file From 127fbfcb931f4a7ed215a6102dfa3e8ff18155f7 Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Fri, 25 Sep 2020 20:42:54 +0530 Subject: [PATCH 11/60] feat(UAE VAT 21): Added Print Format --- erpnext/regional/report/uae_vat/uae_vat.html | 68 ++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 erpnext/regional/report/uae_vat/uae_vat.html diff --git a/erpnext/regional/report/uae_vat/uae_vat.html b/erpnext/regional/report/uae_vat/uae_vat.html new file mode 100644 index 00000000000..861c0c818de --- /dev/null +++ b/erpnext/regional/report/uae_vat/uae_vat.html @@ -0,0 +1,68 @@ +{% + var report_columns = report.get_columns_for_print(); + report_columns = report_columns.filter(col => !col.hidden); + + if (report_columns.length > 8) { + frappe.throw(__("Too many columns. Export the report and print it using a spreadsheet application.")); + } +%} + +

{%= __(report.report_name) %}

+ +

{%= __("VAT on Sales and All Other Outputs") %}

+ + + + + {% for (let i=0; i{%= report_columns[i].label %} + {% } %} + + + + {% for (let j=1; j<12; j++) { %} + {% + var row = data[j]; + %} + + {% for (let i=0; i + {% const fieldname = report_columns[i].fieldname; %} + {% if (!is_null(row[fieldname])) { %} + {%= frappe.format(row[fieldname], report_columns[i], {}, row) %} + {% } %} + + {% } %} + + {% } %} + +
+ +

{%= __("VAT on Expenses and All Other Inputs") %}

+ + + + {% for (let i=0; i{%= report_columns[i].label %} + {% } %} + + + + {% for (let j=12; j + {% for (let i=0; i + {% const fieldname = report_columns[i].fieldname; %} + {% if (!is_null(row[fieldname])) { %} + {%= frappe.format(row[fieldname], report_columns[i], {}, row) %} + {% } %} + + {% } %} + + {% } %} + + +
\ No newline at end of file From 79aca28453c2eb5a7d8c917459269c2efcb0a96d Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Mon, 28 Sep 2020 12:27:41 +0530 Subject: [PATCH 12/60] refactor(UAE VAT 21): rename UAE VAT - UAE VAT 21 --- erpnext/regional/report/{uae_vat => uae_vat_21}/__init__.py | 0 .../{uae_vat/uae_vat.html => uae_vat_21/uae_vat_21.html} | 0 .../report/{uae_vat/uae_vat.js => uae_vat_21/uae_vat_21.js} | 2 +- .../{uae_vat/uae_vat.json => uae_vat_21/uae_vat_21.json} | 4 ++-- .../report/{uae_vat/uae_vat.py => uae_vat_21/uae_vat_21.py} | 0 erpnext/regional/united_arab_emirates/setup.py | 4 ++-- 6 files changed, 5 insertions(+), 5 deletions(-) rename erpnext/regional/report/{uae_vat => uae_vat_21}/__init__.py (100%) rename erpnext/regional/report/{uae_vat/uae_vat.html => uae_vat_21/uae_vat_21.html} (100%) rename erpnext/regional/report/{uae_vat/uae_vat.js => uae_vat_21/uae_vat_21.js} (96%) rename erpnext/regional/report/{uae_vat/uae_vat.json => uae_vat_21/uae_vat_21.json} (89%) rename erpnext/regional/report/{uae_vat/uae_vat.py => uae_vat_21/uae_vat_21.py} (100%) diff --git a/erpnext/regional/report/uae_vat/__init__.py b/erpnext/regional/report/uae_vat_21/__init__.py similarity index 100% rename from erpnext/regional/report/uae_vat/__init__.py rename to erpnext/regional/report/uae_vat_21/__init__.py diff --git a/erpnext/regional/report/uae_vat/uae_vat.html b/erpnext/regional/report/uae_vat_21/uae_vat_21.html similarity index 100% rename from erpnext/regional/report/uae_vat/uae_vat.html rename to erpnext/regional/report/uae_vat_21/uae_vat_21.html diff --git a/erpnext/regional/report/uae_vat/uae_vat.js b/erpnext/regional/report/uae_vat_21/uae_vat_21.js similarity index 96% rename from erpnext/regional/report/uae_vat/uae_vat.js rename to erpnext/regional/report/uae_vat_21/uae_vat_21.js index 0213956d44b..3e6cdd85e51 100644 --- a/erpnext/regional/report/uae_vat/uae_vat.js +++ b/erpnext/regional/report/uae_vat_21/uae_vat_21.js @@ -2,7 +2,7 @@ // For license information, please see license.txt /* eslint-disable */ -frappe.query_reports["UAE VAT"] = { +frappe.query_reports["UAE VAT 21"] = { "filters": [ { "fieldname": "company", diff --git a/erpnext/regional/report/uae_vat/uae_vat.json b/erpnext/regional/report/uae_vat_21/uae_vat_21.json similarity index 89% rename from erpnext/regional/report/uae_vat/uae_vat.json rename to erpnext/regional/report/uae_vat_21/uae_vat_21.json index 8807405a983..421990cc4ab 100644 --- a/erpnext/regional/report/uae_vat/uae_vat.json +++ b/erpnext/regional/report/uae_vat_21/uae_vat_21.json @@ -12,11 +12,11 @@ "modified": "2020-09-10 08:51:02.298482", "modified_by": "Administrator", "module": "Regional", - "name": "UAE VAT", + "name": "UAE VAT 21", "owner": "Administrator", "prepared_report": 0, "ref_doctype": "GL Entry", - "report_name": "UAE VAT", + "report_name": "UAE VAT 21", "report_type": "Script Report", "roles": [] } \ No newline at end of file diff --git a/erpnext/regional/report/uae_vat/uae_vat.py b/erpnext/regional/report/uae_vat_21/uae_vat_21.py similarity index 100% rename from erpnext/regional/report/uae_vat/uae_vat.py rename to erpnext/regional/report/uae_vat_21/uae_vat_21.py diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index 95fde3ab9fc..e7a0609f4a1 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -130,10 +130,10 @@ def add_print_formats(): name in('Simplified Tax Invoice', 'Detailed Tax Invoice', 'Tax Invoice') """) def add_custom_roles_for_reports(): - if not frappe.db.get_value('Custom Role', dict(report='UAE VAT')): + if not frappe.db.get_value('Custom Role', dict(report='UAE VAT 21')): frappe.get_doc(dict( doctype='Custom Role', - report='UAE VAT', + report='UAE VAT 21', roles= [ dict(role='Accounts User'), dict(role='Accounts Manager'), From 815b7584dddbe4c29cc453c98d80d697035103c7 Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Mon, 28 Sep 2020 13:24:40 +0530 Subject: [PATCH 13/60] refactor(UAE VAT 21): seperate get_chart, get_data --- erpnext/regional/report/uae_vat_21/uae_vat_21.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/regional/report/uae_vat_21/uae_vat_21.py b/erpnext/regional/report/uae_vat_21/uae_vat_21.py index 1a3537c268a..d21cecd8263 100644 --- a/erpnext/regional/report/uae_vat_21/uae_vat_21.py +++ b/erpnext/regional/report/uae_vat_21/uae_vat_21.py @@ -8,7 +8,9 @@ from frappe import _ def execute(filters=None): columns = get_columns() - data, chart = get_data(filters) + data, emirates, amounts_by_emirate = get_data(filters) + chart = get_chart(emirates, amounts_by_emirate) + return columns, data, None, chart def get_columns(): @@ -72,8 +74,6 @@ def get_data(filters = None): "vat_amount": vat } - chart = get_chart_data(emirates, amounts_by_emirate) - for d, emirate in enumerate(emirates, 97): if emirate in amounts_by_emirate: amounts_by_emirate[emirate]["no"] = f'1{chr(d)}' @@ -148,10 +148,10 @@ def get_data(filters = None): } ) - return data, chart + return data, emirates, amounts_by_emirate -def get_chart_data(emirates, amounts_by_emirate): +def get_chart(emirates, amounts_by_emirate): """Returns chart data Args: From bed1add349cf571a912f8956ba7d86b91f48cfbe Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Mon, 28 Sep 2020 13:26:05 +0530 Subject: [PATCH 14/60] docs(UAE VAT 21): add docstrings --- erpnext/regional/united_arab_emirates/setup.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index e7a0609f4a1..07543b31ea6 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -130,6 +130,8 @@ def add_print_formats(): name in('Simplified Tax Invoice', 'Detailed Tax Invoice', 'Tax Invoice') """) def add_custom_roles_for_reports(): + """Add Access Control to UAE VAT 21 + """ if not frappe.db.get_value('Custom Role', dict(report='UAE VAT 21')): frappe.get_doc(dict( doctype='Custom Role', From 2a601e59bfb78d74551fb02af82fb17d8acef725 Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Mon, 28 Sep 2020 13:26:43 +0530 Subject: [PATCH 15/60] fix(UAE VAT 21): remove extra legend --- erpnext/regional/report/uae_vat_21/uae_vat_21.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/report/uae_vat_21/uae_vat_21.html b/erpnext/regional/report/uae_vat_21/uae_vat_21.html index 861c0c818de..aa6a2559321 100644 --- a/erpnext/regional/report/uae_vat_21/uae_vat_21.html +++ b/erpnext/regional/report/uae_vat_21/uae_vat_21.html @@ -48,7 +48,7 @@ - {% for (let j=12; j Date: Mon, 28 Sep 2020 14:38:14 +0530 Subject: [PATCH 16/60] feat(UAE VAT 21): Add vat settings --- .../doctype/uae_vat_account/__init__.py | 0 .../uae_vat_account/uae_vat_account.json | 35 ++++++++++++ .../uae_vat_account/uae_vat_account.py | 10 ++++ .../doctype/uae_vat_setting/__init__.py | 0 .../uae_vat_setting/test_uae_vat_setting.py | 10 ++++ .../uae_vat_setting/uae_vat_setting.js | 8 +++ .../uae_vat_setting/uae_vat_setting.json | 55 +++++++++++++++++++ .../uae_vat_setting/uae_vat_setting.py | 10 ++++ .../regional/united_arab_emirates/utils.py | 9 +-- 9 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 erpnext/regional/doctype/uae_vat_account/__init__.py create mode 100644 erpnext/regional/doctype/uae_vat_account/uae_vat_account.json create mode 100644 erpnext/regional/doctype/uae_vat_account/uae_vat_account.py create mode 100644 erpnext/regional/doctype/uae_vat_setting/__init__.py create mode 100644 erpnext/regional/doctype/uae_vat_setting/test_uae_vat_setting.py create mode 100644 erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.js create mode 100644 erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.json create mode 100644 erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.py diff --git a/erpnext/regional/doctype/uae_vat_account/__init__.py b/erpnext/regional/doctype/uae_vat_account/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/regional/doctype/uae_vat_account/uae_vat_account.json b/erpnext/regional/doctype/uae_vat_account/uae_vat_account.json new file mode 100644 index 00000000000..73a81692073 --- /dev/null +++ b/erpnext/regional/doctype/uae_vat_account/uae_vat_account.json @@ -0,0 +1,35 @@ +{ + "actions": [], + "autoname": "account", + "creation": "2020-09-28 11:30:45.472053", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "account" + ], + "fields": [ + { + "allow_in_quick_entry": 1, + "fieldname": "account", + "fieldtype": "Link", + "in_list_view": 1, + "in_preview": 1, + "label": "Account", + "options": "Account" + } + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2020-09-28 12:02:56.444007", + "modified_by": "Administrator", + "module": "Regional", + "name": "UAE VAT Account", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/regional/doctype/uae_vat_account/uae_vat_account.py b/erpnext/regional/doctype/uae_vat_account/uae_vat_account.py new file mode 100644 index 00000000000..80d6b3a5f1f --- /dev/null +++ b/erpnext/regional/doctype/uae_vat_account/uae_vat_account.py @@ -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 UAEVATAccount(Document): + pass diff --git a/erpnext/regional/doctype/uae_vat_setting/__init__.py b/erpnext/regional/doctype/uae_vat_setting/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/regional/doctype/uae_vat_setting/test_uae_vat_setting.py b/erpnext/regional/doctype/uae_vat_setting/test_uae_vat_setting.py new file mode 100644 index 00000000000..a5f151dc730 --- /dev/null +++ b/erpnext/regional/doctype/uae_vat_setting/test_uae_vat_setting.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +# import frappe +import unittest + +class TestUAEVATSetting(unittest.TestCase): + pass diff --git a/erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.js b/erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.js new file mode 100644 index 00000000000..f910e1f6620 --- /dev/null +++ b/erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.js @@ -0,0 +1,8 @@ +// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('UAE VAT Setting', { + // refresh: function(frm) { + + // } +}); diff --git a/erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.json b/erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.json new file mode 100644 index 00000000000..e2e2ab8245c --- /dev/null +++ b/erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.json @@ -0,0 +1,55 @@ +{ + "actions": [], + "autoname": "field:company", + "creation": "2020-09-25 12:48:51.463265", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "company", + "uae_vat_account" + ], + "fields": [ + { + "fieldname": "company", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Company", + "options": "Company", + "reqd": 1, + "unique": 1 + }, + { + "fieldname": "uae_vat_account", + "fieldtype": "Table", + "label": "UAE VAT Account", + "options": "UAE VAT Account", + "reqd": 1 + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2020-09-28 12:19:11.493138", + "modified_by": "Administrator", + "module": "Regional", + "name": "UAE VAT Setting", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.py b/erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.py new file mode 100644 index 00000000000..9549de9466c --- /dev/null +++ b/erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.py @@ -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 UAEVATSetting(Document): + pass diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index 5242c63e63f..4424d2efec8 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -53,12 +53,13 @@ def get_tax_accounts(company): 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"]) + tax_accounts_list = frappe.get_all("UAE VAT Account", + filters={"parent": company}, + fields=["Account"] + ) if not tax_accounts_list and not frappe.flags.in_test: - frappe.throw(_("Please create at least one Account of type Tax")) + frappe.throw(_(f'Please set Vat Accounts for Company: "{company}" in UAE VAT Setting')) for d in tax_accounts_list: for key, name in d.items(): tax_accounts_dict[name] = name From 0860c74c824e337a2e5e689d67614a2644e663b8 Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Mon, 28 Sep 2020 14:38:45 +0530 Subject: [PATCH 17/60] feat(UAE VAT 21): Add permissions for doctypes --- erpnext/regional/united_arab_emirates/setup.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index 07543b31ea6..1c947d2fb0c 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -5,13 +5,14 @@ from __future__ import unicode_literals import frappe, os, json from frappe.custom.doctype.custom_field.custom_field import create_custom_fields +from frappe.permissions import add_permission, update_permission_property from erpnext.setup.setup_wizard.operations.taxes_setup import create_sales_tax def setup(company=None, patch=True): make_custom_fields() add_print_formats() add_custom_roles_for_reports() - + add_permissions() if company: create_sales_tax(company) @@ -141,4 +142,14 @@ def add_custom_roles_for_reports(): dict(role='Accounts Manager'), dict(role='Auditor') ] - )).insert() \ No newline at end of file + )).insert() + +def add_permissions(): + """Add Permissions for UAE VAT Settings and UAE VAT Account + """ + for doctype in ('UAE VAT Setting', 'UAE VAT Account'): + add_permission(doctype, 'All', 0) + for role in ('Accounts Manager', 'Accounts User', 'System Manager'): + add_permission(doctype, role, 0) + update_permission_property(doctype, role, 0, 'write', 1) + update_permission_property(doctype, role, 0, 'create', 1) From 587bb05a37a068962620526c47450731ee09d83f Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Mon, 28 Sep 2020 14:52:29 +0530 Subject: [PATCH 18/60] feat(UAE VAT 21): Add desk page for UAE VAT 21 --- erpnext/accounts/desk_page/accounting/accounting.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/desk_page/accounting/accounting.json b/erpnext/accounts/desk_page/accounting/accounting.json index 2c5231491cd..6621e8e0cef 100644 --- a/erpnext/accounts/desk_page/accounting/accounting.json +++ b/erpnext/accounts/desk_page/accounting/accounting.json @@ -79,6 +79,11 @@ "hidden": 0, "label": "Profitability", "links": "[\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Gross Profit\",\n \"name\": \"Gross Profit\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Profitability Analysis\",\n \"name\": \"Profitability Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Invoice Trends\",\n \"name\": \"Sales Invoice Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Purchase Invoice Trends\",\n \"name\": \"Purchase Invoice Trends\",\n \"type\": \"report\"\n }\n]" + }, + { + "hidden": 0, + "label": "Value-Added Tax (VAT UAE)", + "links": "[\n {\n \"label\": \"UAE VAT Setting\",\n \"name\": \"UAE VAT Setting\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"UAE VAT 21\",\n \"name\": \"UAE VAT 21\",\n \"type\": \"report\"\n }\n]" } ], "category": "Modules", @@ -98,7 +103,7 @@ "idx": 0, "is_standard": 1, "label": "Accounting", - "modified": "2020-09-03 10:37:07.865801", + "modified": "2020-09-28 13:19:27.703992", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting", From 80068e16e856ebd37c782132be1d68c0c9d2e923 Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Mon, 28 Sep 2020 18:58:27 +0530 Subject: [PATCH 19/60] Refactor(UAE VAT 21): Replace f-strings by format --- .../regional/report/uae_vat_21/uae_vat_21.py | 135 ++++++++---------- 1 file changed, 57 insertions(+), 78 deletions(-) diff --git a/erpnext/regional/report/uae_vat_21/uae_vat_21.py b/erpnext/regional/report/uae_vat_21/uae_vat_21.py index d21cecd8263..6cb39e08351 100644 --- a/erpnext/regional/report/uae_vat_21/uae_vat_21.py +++ b/erpnext/regional/report/uae_vat_21/uae_vat_21.py @@ -218,9 +218,9 @@ def get_conditions(filters): String: Concatenated list of conditions to be applied to calculate the total sale """ conditions = "" - for opts in (("company", f' and company="{filters.get("company")}"'), - ("from_date", f' and posting_date>="{filters.get("from_date")}"'), - ("to_date", f' and posting_date<="{filters.get("to_date")}"')): + for opts in (("company", " and company=%(company)s"), + ("from_date", " and posting_date>=%(from_date)s"), + ("to_date", " and posting_date<=%(to_date)s")): if filters.get(opts[0]): conditions += opts[1] return conditions @@ -234,21 +234,21 @@ def get_reverse_charge_total(filters): Returns: Float: sum of the total of each Purchase invoice made """ - conditions = """ - for opts in (("company", f' and company="{filters.get("company")}"'), - ("from_date", f' and posting_date>="{filters.get("from_date")}"'), - ("to_date", f' and posting_date<="{filters.get("to_date")}"')): - if filters.get(opts[0]): - conditions += opts[1] - return conditions - """ - return frappe.db.sql(f""" + conditions = get_conditions(filters) + print(""" select sum(total) from `tabPurchase Invoice` where reverse_charge = "Y" - and docstatus = 1 {get_conditions(filters)} ; - """)[0][0] or 0 + and docstatus = 1 {where_conditions} ; + """.format(where_conditions=conditions)) + return frappe.db.sql(""" + select sum(total) from + `tabPurchase Invoice` + where + reverse_charge = "Y" + and docstatus = 1 {where_conditions} ; + """.format(where_conditions=conditions), filters)[0][0] or 0 def get_reverse_charge_tax(filters): """Returns the sum of the tax of each Purchase invoice made @@ -259,18 +259,18 @@ def get_reverse_charge_tax(filters): Returns: Float: sum of the tax of each Purchase invoice made """ - return frappe.db.sql(f""" + conditions = get_conditions_join(filters) + return frappe.db.sql(""" select sum(debit) from `tabPurchase Invoice` inner join `tabGL Entry` on `tabGL Entry`.voucher_no = `tabPurchase Invoice`.name where `tabPurchase Invoice`.reverse_charge = "Y" and `tabPurchase Invoice`.docstatus = 1 - and `tabGL Entry`.docstatus = 1 {get_conditions_join(filters)} - and account in ("{'", "'.join(get_tax_accounts(filters['company']))}"); - """)[0][0] or 0 - - + and `tabGL Entry`.docstatus = 1 + and account in (select account from `tabUAE VAT Account` where parent=%(company)s) + {where_conditions} ; + """.format(where_conditions=conditions), filters)[0][0] or 0 def get_conditions_join(filters): """The conditions to be used to filter data to calculate the total vat @@ -282,14 +282,13 @@ def get_conditions_join(filters): String: Concatenated list of conditions to be applied to calculate the total vat """ conditions = "" - for opts in (("company", f' and `tabPurchase Invoice`.company="{filters.get("company")}"'), - ("from_date", f' and `tabPurchase Invoice`.posting_date>="{filters.get("from_date")}"'), - ("to_date", f' and `tabPurchase Invoice`.posting_date<="{filters.get("to_date")}"')): + for opts in (("company", " and `tabPurchase Invoice`.company=%(company)s"), + ("from_date", " and `tabPurchase Invoice`.posting_date>=%(from_date)s"), + ("to_date", " and `tabPurchase Invoice`.posting_date<=%(to_date)s")): if filters.get(opts[0]): conditions += opts[1] return conditions - def get_reverse_charge_recoverable_total(filters): """Returns the sum of the total of each Purchase invoice made with claimable reverse charge @@ -299,23 +298,15 @@ def get_reverse_charge_recoverable_total(filters): Returns: Float: sum of the total of each Purchase invoice made with claimable reverse charge """ - conditions = """ - for opts in (("company", f' and company="{filters.get("company")}"'), - ("from_date", f' and posting_date>="{filters.get("from_date")}"'), - ("to_date", f' and posting_date<="{filters.get("to_date")}"')): - if filters.get(opts[0]): - conditions += opts[1] - return conditions - """ - return frappe.db.sql(f""" + conditions = get_conditions(filters) + return frappe.db.sql(""" select sum(total) from `tabPurchase Invoice` where reverse_charge = "Y" and claimable_reverse_charge > 0 - and docstatus = 1 {get_conditions(filters)} ; - """)[0][0] or 0 - + and docstatus = 1 {where_conditions} ; + """.format(where_conditions=conditions), filters)[0][0] or 0 def get_reverse_charge_recoverable_tax(filters): """Returns the sum of the tax of each Purchase invoice made @@ -326,7 +317,8 @@ def get_reverse_charge_recoverable_tax(filters): Returns: Float: sum of the tax of each Purchase invoice made """ - return frappe.db.sql(f""" + conditions = get_conditions_join(filters) + return frappe.db.sql(""" select sum(debit * `tabPurchase Invoice`.claimable_reverse_charge / 100) from `tabPurchase Invoice` inner join `tabGL Entry` on `tabGL Entry`.voucher_no = `tabPurchase Invoice`.name @@ -334,10 +326,10 @@ def get_reverse_charge_recoverable_tax(filters): `tabPurchase Invoice`.reverse_charge = "Y" and `tabPurchase Invoice`.docstatus = 1 and `tabPurchase Invoice`.claimable_reverse_charge > 0 - and `tabGL Entry`.docstatus = 1 {get_conditions_join(filters)} - and account in ("{'", "'.join(get_tax_accounts(filters['company']))}"); - """)[0][0] or 0 - + and `tabGL Entry`.docstatus = 1 + and account in (select account from `tabUAE VAT Account` where parent=%(company)s) + {where_conditions} ; + """.format(where_conditions=conditions), filters)[0][0] or 0 def get_standard_rated_expenses_total(filters): """Returns the sum of the total of each Purchase invoice made with claimable reverse charge @@ -348,22 +340,14 @@ def get_standard_rated_expenses_total(filters): Returns: Float: sum of the total of each Purchase invoice made with claimable reverse charge """ - conditions = """ - for opts in (("company", f' and company="{filters.get("company")}"'), - ("from_date", f' and posting_date>="{filters.get("from_date")}"'), - ("to_date", f' and posting_date<="{filters.get("to_date")}"')): - if filters.get(opts[0]): - conditions += opts[1] - return conditions - """ - return frappe.db.sql(f""" + conditions = get_conditions(filters) + return frappe.db.sql(""" select sum(total) from `tabSales Invoice` where standard_rated_expenses > 0 - and docstatus = 1 {get_conditions(filters)} ; - """)[0][0] or 0 - + and docstatus = 1 {where_conditions} ; + """.format(where_conditions=conditions), filters)[0][0] or 0 def get_standard_rated_expenses_tax(filters): """Returns the sum of the tax of each Purchase invoice made @@ -374,13 +358,14 @@ def get_standard_rated_expenses_tax(filters): Returns: Float: sum of the tax of each Purchase invoice made """ - return frappe.db.sql(f""" + conditions = get_conditions(filters) + return frappe.db.sql(""" select sum(standard_rated_expenses) from `tabSales Invoice` where standard_rated_expenses > 0 - and docstatus = 1 {get_conditions(filters)} ; - """)[0][0] or 0 + and docstatus = 1 {where_conditions} ; + """.format(where_conditions=conditions), filters)[0][0] or 0 def get_tourist_tax_return_total(filters): """Returns the sum of the total of each Sales invoice with non zero tourist_tax_return @@ -391,22 +376,14 @@ def get_tourist_tax_return_total(filters): Returns: Float: sum of the total of each Sales invoice with non zero tourist_tax_return """ - conditions = """ - for opts in (("company", f' and company="{filters.get("company")}"'), - ("from_date", f' and posting_date>="{filters.get("from_date")}"'), - ("to_date", f' and posting_date<="{filters.get("to_date")}"')): - if filters.get(opts[0]): - conditions += opts[1] - return conditions - """ - return frappe.db.sql(f""" + conditions = get_conditions(filters) + return frappe.db.sql(""" select sum(total) from `tabSales Invoice` where tourist_tax_return > 0 - and docstatus = 1 {get_conditions(filters)} ; - """)[0][0] or 0 - + and docstatus = 1 {where_conditions} ; + """.format(where_conditions=conditions), filters)[0][0] or 0 def get_tourist_tax_return_tax(filters): """Returns the sum of the tax of each Sales invoice with non zero tourist_tax_return @@ -417,13 +394,14 @@ def get_tourist_tax_return_tax(filters): Returns: Float: sum of the tax of each Sales invoice with non zero tourist_tax_return """ - return frappe.db.sql(f""" + conditions = get_conditions(filters) + return frappe.db.sql(""" select sum(tourist_tax_return) from `tabSales Invoice` where tourist_tax_return > 0 - and docstatus = 1 {get_conditions(filters)} ; - """)[0][0] or 0 + and docstatus = 1 {where_conditions} ; + """.format(where_conditions=conditions), filters)[0][0] or 0 def get_zero_rated_total(filters): """Returns the sum of each Sales Invoice Item Amount which is zero rated @@ -434,13 +412,13 @@ def get_zero_rated_total(filters): Returns: Float: sum of each Sales Invoice Item Amount which is zero rated """ - return frappe.db.sql(f""" + conditions = get_conditions(filters) + return frappe.db.sql(""" select sum(i.base_amount) as total from `tabSales Invoice Item` i, `tabSales Invoice` s where s.docstatus = 1 and i.parent = s.name and i.is_zero_rated = 1 - {get_conditions(filters)} ; - """)[0][0] or 0 - + {where_conditions} ; + """.format(where_conditions=conditions), filters)[0][0] or 0 def get_exempt_total(filters): """Returns the sum of each Sales Invoice Item Amount which is Vat Exempt @@ -451,9 +429,10 @@ def get_exempt_total(filters): Returns: Float: sum of each Sales Invoice Item Amount which is Vat Exempt """ - return frappe.db.sql(f""" + conditions = get_conditions(filters) + return frappe.db.sql(""" select sum(i.base_amount) as total from `tabSales Invoice Item` i, `tabSales Invoice` s where s.docstatus = 1 and i.parent = s.name and i.is_exempt = 1 - {get_conditions(filters)} ; - """)[0][0] or 0 \ No newline at end of file + {where_conditions} ; + """.format(where_conditions=conditions), filters)[0][0] or 0 \ No newline at end of file From a5e8e449eea1266b225d1616b0b400cd51feeb01 Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Mon, 28 Sep 2020 20:43:03 +0530 Subject: [PATCH 20/60] chore: Merge branch 'develop' into UAE-VAT-Format --- erpnext/accounts/desk_page/accounting/accounting.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/erpnext/accounts/desk_page/accounting/accounting.json b/erpnext/accounts/desk_page/accounting/accounting.json index 29d1331b5d4..85635572b1e 100644 --- a/erpnext/accounts/desk_page/accounting/accounting.json +++ b/erpnext/accounts/desk_page/accounting/accounting.json @@ -103,11 +103,7 @@ "idx": 0, "is_standard": 1, "label": "Accounting", -<<<<<<< HEAD "modified": "2020-09-28 13:19:27.703992", -======= - "modified": "2020-09-09 11:45:33.766400", ->>>>>>> develop "modified_by": "Administrator", "module": "Accounts", "name": "Accounting", From 3294f86b9235d57f9f143e7cc33cf367816d4aa1 Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Wed, 30 Sep 2020 12:15:07 +0530 Subject: [PATCH 21/60] refactor: fix linting --- .../regional/report/uae_vat_21/uae_vat_21.py | 168 +++--------------- .../regional/united_arab_emirates/setup.py | 6 +- .../regional/united_arab_emirates/utils.py | 39 +--- 3 files changed, 36 insertions(+), 177 deletions(-) diff --git a/erpnext/regional/report/uae_vat_21/uae_vat_21.py b/erpnext/regional/report/uae_vat_21/uae_vat_21.py index 6cb39e08351..d400732f395 100644 --- a/erpnext/regional/report/uae_vat_21/uae_vat_21.py +++ b/erpnext/regional/report/uae_vat_21/uae_vat_21.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import frappe -from erpnext.regional.united_arab_emirates.utils import get_tax_accounts from frappe import _ def execute(filters=None): @@ -14,11 +13,7 @@ def execute(filters=None): return columns, data, None, chart def get_columns(): - """Creates a list of dictionaries that are used to generate column headers of the data table - - Returns: - List(Dict): list of dictionaries that are used to generate column headers of the data table - """ + """Creates a list of dictionaries that are used to generate column headers of the data table.""" return [ { "fieldname": "no", @@ -47,22 +42,15 @@ def get_columns(): ] def get_data(filters = None): - """Returns the list of dictionaries. Each dictionary is a row in the datatable and chart data - - Args: - filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. - - Returns: - List(Dict): Each dictionary is a row in the datatable - Dict: Dictionary containing chart data - """ + """Returns the list of dictionaries. Each dictionary is a row in the datatable and chart data.""" data = [] data.append({ "no": '', - "legend": f'VAT on Sales and All Other Outputs', + "legend": 'VAT on Sales and All Other Outputs', "amount": '', "vat_amount": '' }) + total_emiratewise = get_total_emiratewise(filters) emirates = get_emirates() amounts_by_emirate = {} @@ -92,7 +80,7 @@ def get_data(filters = None): data.append( { "no": '2', - "legend": f'Tax Refunds provided to Tourists under the Tax Refunds for Tourists Scheme', + "legend": 'Tax Refunds provided to Tourists under the Tax Refunds for Tourists Scheme', "amount": (-1) * get_tourist_tax_return_total(filters), "vat_amount": (-1) * get_tourist_tax_return_tax(filters) } @@ -101,7 +89,7 @@ def get_data(filters = None): data.append( { "no": '3', - "legend": f'Supplies subject to the reverse charge provision', + "legend": 'Supplies subject to the reverse charge provision', "amount": get_reverse_charge_total(filters), "vat_amount": get_reverse_charge_tax(filters) } @@ -110,7 +98,7 @@ def get_data(filters = None): data.append( { "no": '4', - "legend": f'Zero Rated', + "legend": 'Zero Rated', "amount": get_zero_rated_total(filters), "vat_amount": "-" } @@ -119,7 +107,7 @@ def get_data(filters = None): data.append( { "no": '5', - "legend": f'Exempt Supplies', + "legend": 'Exempt Supplies', "amount": get_exempt_total(filters), "vat_amount": "-" } @@ -127,22 +115,24 @@ def get_data(filters = None): data.append({ "no": '', - "legend": f'VAT on Expenses and All Other Inputs', + "legend": 'VAT on Expenses and All Other Inputs', "amount": '', "vat_amount": '' }) + data.append( { "no": '9', - "legend": f'Standard Rated Expenses', + "legend": 'Standard Rated Expenses', "amount": get_standard_rated_expenses_total(filters), "vat_amount": get_standard_rated_expenses_tax(filters) } ) + data.append( { "no": '10', - "legend": f'Supplies subject to the reverse charge provision', + "legend": 'Supplies subject to the reverse charge provision', "amount": get_reverse_charge_recoverable_total(filters), "vat_amount": get_reverse_charge_recoverable_tax(filters) } @@ -152,15 +142,7 @@ def get_data(filters = None): def get_chart(emirates, amounts_by_emirate): - """Returns chart data - - Args: - emirates (List): List of Emirates - amounts_by_emirate (Dict): Vat and Tax amount by emirates with emirates as key - - Returns: - [Dict]: Chart Data - """ + """Returns chart data.""" labels = [] amount = [] vat_amount = [] @@ -186,6 +168,7 @@ def get_chart(emirates, amounts_by_emirate): return chart def get_total_emiratewise(filters): + """Returns Emiratewise Amount and Taxes.""" return frappe.db.sql(f""" select emirate, sum(total), sum(total_taxes_and_charges) from `tabSales Invoice` where docstatus = 1 {get_conditions(filters)} @@ -193,11 +176,7 @@ def get_total_emiratewise(filters): """, filters) def get_emirates(): - """Returns a List of emirates in the order that they are to be displayed - - Returns: - List(String): List of emirates in the order that they are to be displayed - """ + """Returns a List of emirates in the order that they are to be displayed.""" return [ 'Abu Dhabi', 'Dubai', @@ -209,14 +188,7 @@ def get_emirates(): ] def get_conditions(filters): - """The conditions to be used to filter data to calculate the total sale - - Args: - filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. - - Returns: - String: Concatenated list of conditions to be applied to calculate the total sale - """ + """The conditions to be used to filter data to calculate the total sale.""" conditions = "" for opts in (("company", " and company=%(company)s"), ("from_date", " and posting_date>=%(from_date)s"), @@ -226,22 +198,8 @@ def get_conditions(filters): return conditions def get_reverse_charge_total(filters): - """Returns the sum of the total of each Purchase invoice made - - Args: - filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. - - Returns: - Float: sum of the total of each Purchase invoice made - """ + """Returns the sum of the total of each Purchase invoice made.""" conditions = get_conditions(filters) - print(""" - select sum(total) from - `tabPurchase Invoice` - where - reverse_charge = "Y" - and docstatus = 1 {where_conditions} ; - """.format(where_conditions=conditions)) return frappe.db.sql(""" select sum(total) from `tabPurchase Invoice` @@ -251,14 +209,7 @@ def get_reverse_charge_total(filters): """.format(where_conditions=conditions), filters)[0][0] or 0 def get_reverse_charge_tax(filters): - """Returns the sum of the tax of each Purchase invoice made - - Args: - filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. - - Returns: - Float: sum of the tax of each Purchase invoice made - """ + """Returns the sum of the tax of each Purchase invoice made.""" conditions = get_conditions_join(filters) return frappe.db.sql(""" select sum(debit) from @@ -273,14 +224,7 @@ def get_reverse_charge_tax(filters): """.format(where_conditions=conditions), filters)[0][0] or 0 def get_conditions_join(filters): - """The conditions to be used to filter data to calculate the total vat - - Args: - filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. - - Returns: - String: Concatenated list of conditions to be applied to calculate the total vat - """ + """The conditions to be used to filter data to calculate the total vat.""" conditions = "" for opts in (("company", " and `tabPurchase Invoice`.company=%(company)s"), ("from_date", " and `tabPurchase Invoice`.posting_date>=%(from_date)s"), @@ -290,14 +234,7 @@ def get_conditions_join(filters): return conditions def get_reverse_charge_recoverable_total(filters): - """Returns the sum of the total of each Purchase invoice made with claimable reverse charge - - Args: - filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. - - Returns: - Float: sum of the total of each Purchase invoice made with claimable reverse charge - """ + """Returns the sum of the total of each Purchase invoice made with claimable reverse charge.""" conditions = get_conditions(filters) return frappe.db.sql(""" select sum(total) from @@ -309,14 +246,7 @@ def get_reverse_charge_recoverable_total(filters): """.format(where_conditions=conditions), filters)[0][0] or 0 def get_reverse_charge_recoverable_tax(filters): - """Returns the sum of the tax of each Purchase invoice made - - Args: - filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. - - Returns: - Float: sum of the tax of each Purchase invoice made - """ + """Returns the sum of the tax of each Purchase invoice made.""" conditions = get_conditions_join(filters) return frappe.db.sql(""" select sum(debit * `tabPurchase Invoice`.claimable_reverse_charge / 100) from @@ -332,14 +262,7 @@ def get_reverse_charge_recoverable_tax(filters): """.format(where_conditions=conditions), filters)[0][0] or 0 def get_standard_rated_expenses_total(filters): - """Returns the sum of the total of each Purchase invoice made with claimable reverse charge - - Args: - filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. - - Returns: - Float: sum of the total of each Purchase invoice made with claimable reverse charge - """ + """Returns the sum of the total of each Purchase invoice made with claimable reverse charge.""" conditions = get_conditions(filters) return frappe.db.sql(""" select sum(total) from @@ -350,14 +273,7 @@ def get_standard_rated_expenses_total(filters): """.format(where_conditions=conditions), filters)[0][0] or 0 def get_standard_rated_expenses_tax(filters): - """Returns the sum of the tax of each Purchase invoice made - - Args: - filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. - - Returns: - Float: sum of the tax of each Purchase invoice made - """ + """Returns the sum of the tax of each Purchase invoice made.""" conditions = get_conditions(filters) return frappe.db.sql(""" select sum(standard_rated_expenses) from @@ -368,14 +284,7 @@ def get_standard_rated_expenses_tax(filters): """.format(where_conditions=conditions), filters)[0][0] or 0 def get_tourist_tax_return_total(filters): - """Returns the sum of the total of each Sales invoice with non zero tourist_tax_return - - Args: - filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. - - Returns: - Float: sum of the total of each Sales invoice with non zero tourist_tax_return - """ + """Returns the sum of the total of each Sales invoice with non zero tourist_tax_return.""" conditions = get_conditions(filters) return frappe.db.sql(""" select sum(total) from @@ -386,14 +295,7 @@ def get_tourist_tax_return_total(filters): """.format(where_conditions=conditions), filters)[0][0] or 0 def get_tourist_tax_return_tax(filters): - """Returns the sum of the tax of each Sales invoice with non zero tourist_tax_return - - Args: - filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. - - Returns: - Float: sum of the tax of each Sales invoice with non zero tourist_tax_return - """ + """Returns the sum of the tax of each Sales invoice with non zero tourist_tax_return.""" conditions = get_conditions(filters) return frappe.db.sql(""" select sum(tourist_tax_return) from @@ -404,14 +306,7 @@ def get_tourist_tax_return_tax(filters): """.format(where_conditions=conditions), filters)[0][0] or 0 def get_zero_rated_total(filters): - """Returns the sum of each Sales Invoice Item Amount which is zero rated - - Args: - filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. - - Returns: - Float: sum of each Sales Invoice Item Amount which is zero rated - """ + """Returns the sum of each Sales Invoice Item Amount which is zero rated.""" conditions = get_conditions(filters) return frappe.db.sql(""" select sum(i.base_amount) as total from @@ -421,14 +316,7 @@ def get_zero_rated_total(filters): """.format(where_conditions=conditions), filters)[0][0] or 0 def get_exempt_total(filters): - """Returns the sum of each Sales Invoice Item Amount which is Vat Exempt - - Args: - filters (Dict, optional): Dictionary consisting of the filters selected by the user. Defaults to None. - - Returns: - Float: sum of each Sales Invoice Item Amount which is Vat Exempt - """ + """Returns the sum of each Sales Invoice Item Amount which is Vat Exempt.""" conditions = get_conditions(filters) return frappe.db.sql(""" select sum(i.base_amount) as total from diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index 1c947d2fb0c..70030c736cf 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -131,8 +131,7 @@ def add_print_formats(): name in('Simplified Tax Invoice', 'Detailed Tax Invoice', 'Tax Invoice') """) def add_custom_roles_for_reports(): - """Add Access Control to UAE VAT 21 - """ + """Add Access Control to UAE VAT 21.""" if not frappe.db.get_value('Custom Role', dict(report='UAE VAT 21')): frappe.get_doc(dict( doctype='Custom Role', @@ -145,8 +144,7 @@ def add_custom_roles_for_reports(): )).insert() def add_permissions(): - """Add Permissions for UAE VAT Settings and UAE VAT Account - """ + """Add Permissions for UAE VAT Settings and UAE VAT Account.""" for doctype in ('UAE VAT Setting', 'UAE VAT Account'): add_permission(doctype, 'All', 0) for role in ('Accounts Manager', 'Accounts User', 'System Manager'): diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index 4424d2efec8..f75efd1aaeb 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -31,7 +31,7 @@ def update_itemised_tax_data(doc): 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""" + """Helper function to get account currency.""" if not account: return def generator(): @@ -44,14 +44,7 @@ def get_account_currency(account): 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 - """ + """Get the list of tax accounts for a specific company.""" tax_accounts_dict = frappe._dict() tax_accounts_list = frappe.get_all("UAE VAT Account", filters={"parent": company}, @@ -67,11 +60,7 @@ def get_tax_accounts(company): 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 - """ + """If the Reverse Charge is Applicable subtract the tax amount from the grand total and update in the form.""" country = frappe.get_cached_value('Company', doc.company, 'country') if country != 'United Arab Emirates': @@ -102,14 +91,7 @@ def update_grand_total_for_rcm(doc, method): 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 - """ - + """Update the grand total values in the form.""" doc.base_grand_total -= base_vat_tax doc.grand_total -= vat_tax @@ -130,16 +112,7 @@ def update_totals(vat_tax, base_vat_tax, doc): 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 - """ + """Hooked to make_regional_gl_entries in Purchase Invoice.It appends the region specific general ledger entries to the list of GL Entries.""" country = frappe.get_cached_value('Company', doc.company, 'country') if country != 'United Arab Emirates': @@ -170,7 +143,7 @@ def make_regional_gl_entries(gl_entries, doc): return gl_entries def validate_returns(doc, method): - print("validate_returns") + """Sum of Tourist Returns and Standard Rated Expenses should be less than Total Tax.""" country = frappe.get_cached_value('Company', doc.company, 'country') if country != 'United Arab Emirates': From 10a3a338b6a98d68e3d68d090801d08e7d240891 Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Wed, 30 Sep 2020 21:51:00 +0530 Subject: [PATCH 22/60] refactor: change uae vat settingplural --- .../{uae_vat_setting => uae_vat_settings}/__init__.py | 0 .../test_uae_vat_settings.py} | 2 +- .../uae_vat_settings.js} | 2 +- .../uae_vat_settings.json} | 10 +++++----- .../uae_vat_settings.py} | 2 +- erpnext/regional/united_arab_emirates/setup.py | 2 +- erpnext/regional/united_arab_emirates/utils.py | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) rename erpnext/regional/doctype/{uae_vat_setting => uae_vat_settings}/__init__.py (100%) rename erpnext/regional/doctype/{uae_vat_setting/test_uae_vat_setting.py => uae_vat_settings/test_uae_vat_settings.py} (80%) rename erpnext/regional/doctype/{uae_vat_setting/uae_vat_setting.js => uae_vat_settings/uae_vat_settings.js} (80%) rename erpnext/regional/doctype/{uae_vat_setting/uae_vat_setting.json => uae_vat_settings/uae_vat_settings.json} (84%) rename erpnext/regional/doctype/{uae_vat_setting/uae_vat_setting.py => uae_vat_settings/uae_vat_settings.py} (88%) diff --git a/erpnext/regional/doctype/uae_vat_setting/__init__.py b/erpnext/regional/doctype/uae_vat_settings/__init__.py similarity index 100% rename from erpnext/regional/doctype/uae_vat_setting/__init__.py rename to erpnext/regional/doctype/uae_vat_settings/__init__.py diff --git a/erpnext/regional/doctype/uae_vat_setting/test_uae_vat_setting.py b/erpnext/regional/doctype/uae_vat_settings/test_uae_vat_settings.py similarity index 80% rename from erpnext/regional/doctype/uae_vat_setting/test_uae_vat_setting.py rename to erpnext/regional/doctype/uae_vat_settings/test_uae_vat_settings.py index a5f151dc730..b88439f9b85 100644 --- a/erpnext/regional/doctype/uae_vat_setting/test_uae_vat_setting.py +++ b/erpnext/regional/doctype/uae_vat_settings/test_uae_vat_settings.py @@ -6,5 +6,5 @@ from __future__ import unicode_literals # import frappe import unittest -class TestUAEVATSetting(unittest.TestCase): +class TestUAEVATSettings(unittest.TestCase): pass diff --git a/erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.js b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.js similarity index 80% rename from erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.js rename to erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.js index f910e1f6620..07a93010b51 100644 --- a/erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.js +++ b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.js @@ -1,7 +1,7 @@ // Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt -frappe.ui.form.on('UAE VAT Setting', { +frappe.ui.form.on('UAE VAT Settings', { // refresh: function(frm) { // } diff --git a/erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.json b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.json similarity index 84% rename from erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.json rename to erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.json index e2e2ab8245c..ce2c1d4e142 100644 --- a/erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.json +++ b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.json @@ -7,7 +7,7 @@ "engine": "InnoDB", "field_order": [ "company", - "uae_vat_account" + "uae_vat_accounts" ], "fields": [ { @@ -20,19 +20,19 @@ "unique": 1 }, { - "fieldname": "uae_vat_account", + "fieldname": "uae_vat_accounts", "fieldtype": "Table", - "label": "UAE VAT Account", + "label": "UAE VAT Accounts", "options": "UAE VAT Account", "reqd": 1 } ], "index_web_pages_for_search": 1, "links": [], - "modified": "2020-09-28 12:19:11.493138", + "modified": "2020-09-30 20:08:18.764798", "modified_by": "Administrator", "module": "Regional", - "name": "UAE VAT Setting", + "name": "UAE VAT Settings", "owner": "Administrator", "permissions": [ { diff --git a/erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.py b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.py similarity index 88% rename from erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.py rename to erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.py index 9549de9466c..20dc604510b 100644 --- a/erpnext/regional/doctype/uae_vat_setting/uae_vat_setting.py +++ b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.py @@ -6,5 +6,5 @@ from __future__ import unicode_literals # import frappe from frappe.model.document import Document -class UAEVATSetting(Document): +class UAEVATSettings(Document): pass diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index 70030c736cf..0de42120c4c 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -145,7 +145,7 @@ def add_custom_roles_for_reports(): def add_permissions(): """Add Permissions for UAE VAT Settings and UAE VAT Account.""" - for doctype in ('UAE VAT Setting', 'UAE VAT Account'): + for doctype in ('UAE VAT Settings', 'UAE VAT Account'): add_permission(doctype, 'All', 0) for role in ('Accounts Manager', 'Accounts User', 'System Manager'): add_permission(doctype, role, 0) diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index f75efd1aaeb..5a8c3c47fbb 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -52,7 +52,7 @@ def get_tax_accounts(company): ) if not tax_accounts_list and not frappe.flags.in_test: - frappe.throw(_(f'Please set Vat Accounts for Company: "{company}" in UAE VAT Setting')) + frappe.throw(_(f'Please set Vat Accounts for Company: "{company}" in UAE VAT Settings')) for d in tax_accounts_list: for key, name in d.items(): tax_accounts_dict[name] = name From 8cc6f2b38881f1bcd53cf558a362486e564648f1 Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Thu, 1 Oct 2020 12:44:39 +0530 Subject: [PATCH 23/60] feat(UAE VAT 21): add fixed width to columns --- .../report/uae_vat_21/uae_vat_21.html | 31 ++++++---- .../regional/report/uae_vat_21/uae_vat_21.js | 1 - .../regional/report/uae_vat_21/uae_vat_21.py | 57 +++++++++++-------- 3 files changed, 53 insertions(+), 36 deletions(-) diff --git a/erpnext/regional/report/uae_vat_21/uae_vat_21.html b/erpnext/regional/report/uae_vat_21/uae_vat_21.html index aa6a2559321..d9b9968d90c 100644 --- a/erpnext/regional/report/uae_vat_21/uae_vat_21.html +++ b/erpnext/regional/report/uae_vat_21/uae_vat_21.html @@ -1,21 +1,27 @@ {% var report_columns = report.get_columns_for_print(); report_columns = report_columns.filter(col => !col.hidden); - - if (report_columns.length > 8) { - frappe.throw(__("Too many columns. Export the report and print it using a spreadsheet application.")); - } %} +

{%= __(report.report_name) %}

-

{%= __("VAT on Sales and All Other Outputs") %}

+

{%= __("VAT on Sales and All Other Outputs") %}

- {% for (let i=0; i{%= report_columns[i].label %} + + + + {% for (let i=2; i{%= report_columns[i].label %} {% } %} @@ -38,17 +44,20 @@
{%= report_columns[0].label %}{%= report_columns[1].label %}
-

{%= __("VAT on Expenses and All Other Inputs") %}

+

{%= __("VAT on Expenses and All Other Inputs") %}

- {% for (let i=0; i{%= report_columns[i].label %} + + + + {% for (let i=2; i{%= report_columns[i].label %} {% } %} - {% for (let j=13; j Date: Thu, 1 Oct 2020 12:59:39 +0530 Subject: [PATCH 24/60] feat(UAE VAT 21): Add currency formatting --- .../regional/report/uae_vat_21/uae_vat_21.py | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/erpnext/regional/report/uae_vat_21/uae_vat_21.py b/erpnext/regional/report/uae_vat_21/uae_vat_21.py index 211bf16734c..2bded71ec20 100644 --- a/erpnext/regional/report/uae_vat_21/uae_vat_21.py +++ b/erpnext/regional/report/uae_vat_21/uae_vat_21.py @@ -60,8 +60,10 @@ def get_data(filters = None): emirate, amount, vat= d amounts_by_emirate[emirate] = { "legend": emirate, - "amount": amount, - "vat_amount": vat + "raw_amount": amount, + "raw_vat_amount": vat, + "amount": frappe.format(amount, 'Currency'), + "vat_amount": frappe.format(vat, 'Currency'), } for d, emirate in enumerate(emirates, 97): @@ -74,8 +76,8 @@ def get_data(filters = None): { "no": _(f'1{chr(d)}'), "legend": _(f'Standard rated supplies in {emirate}'), - "amount": 0, - "vat_amount": 0 + "amount": frappe.format(0, 'Currency'), + "vat_amount": frappe.format(0, 'Currency') } ) @@ -83,8 +85,8 @@ def get_data(filters = None): { "no": _('2'), "legend": _('Tax Refunds provided to Tourists under the Tax Refunds for Tourists Scheme'), - "amount": (-1) * get_tourist_tax_return_total(filters), - "vat_amount": (-1) * get_tourist_tax_return_tax(filters) + "amount": frappe.format((-1) * get_tourist_tax_return_total(filters), 'Currency'), + "vat_amount": frappe.format((-1) * get_tourist_tax_return_tax(filters), 'Currency') } ) @@ -92,8 +94,8 @@ def get_data(filters = None): { "no": _('3'), "legend": _('Supplies subject to the reverse charge provision'), - "amount": get_reverse_charge_total(filters), - "vat_amount": get_reverse_charge_tax(filters) + "amount": frappe.format(get_reverse_charge_total(filters), 'Currency'), + "vat_amount": frappe.format(get_reverse_charge_tax(filters), 'Currency') } ) @@ -101,7 +103,7 @@ def get_data(filters = None): { "no": _('4'), "legend": _('Zero Rated'), - "amount": get_zero_rated_total(filters), + "amount": frappe.format(get_zero_rated_total(filters), 'Currency'), "vat_amount": "-" } ) @@ -110,7 +112,7 @@ def get_data(filters = None): { "no": _('5'), "legend": _('Exempt Supplies'), - "amount": get_exempt_total(filters), + "amount": frappe.format(get_exempt_total(filters), 'Currency'), "vat_amount": "-" } ) @@ -133,8 +135,8 @@ def get_data(filters = None): { "no": '9', "legend": _('Standard Rated Expenses'), - "amount": get_standard_rated_expenses_total(filters), - "vat_amount": get_standard_rated_expenses_tax(filters) + "amount": frappe.format(get_standard_rated_expenses_total(filters), 'Currency'), + "vat_amount": frappe.format(get_standard_rated_expenses_tax(filters), 'Currency') } ) @@ -142,8 +144,8 @@ def get_data(filters = None): { "no": _('10'), "legend": _('Supplies subject to the reverse charge provision'), - "amount": get_reverse_charge_recoverable_total(filters), - "vat_amount": get_reverse_charge_recoverable_tax(filters) + "amount": frappe.format(get_reverse_charge_recoverable_total(filters), 'Currency'), + "vat_amount": frappe.format(get_reverse_charge_recoverable_tax(filters), 'Currency') } ) @@ -157,8 +159,8 @@ def get_chart(emirates, amounts_by_emirate): vat_amount = [] for d in emirates: if d in amounts_by_emirate: - amount.append(amounts_by_emirate[d]["amount"]) - vat_amount.append(amounts_by_emirate[d]["vat_amount"]) + amount.append(amounts_by_emirate[d]["raw_amount"]) + vat_amount.append(amounts_by_emirate[d]["raw_vat_amount"]) labels.append(d) datasets = [] From ac451b3a5435b2927f1a60f3e0901a45c3fceb07 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Sun, 11 Oct 2020 01:40:22 +0530 Subject: [PATCH 25/60] feat(UAE VAT 21): Move standard rated expense from Sales invoice to Purchase invoice --- erpnext/hooks.py | 4 +--- erpnext/regional/report/uae_vat_21/uae_vat_21.py | 4 ++-- erpnext/regional/united_arab_emirates/setup.py | 7 ++++--- erpnext/regional/united_arab_emirates/utils.py | 10 ++++++---- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index a0242c175ca..8d08c900472 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -242,15 +242,13 @@ doc_events = { "erpnext.regional.italy.utils.sales_invoice_on_cancel", "erpnext.erpnext_integrations.taxjar_integration.delete_transaction" ], - "validate": [ - "erpnext.regional.united_arab_emirates.utils.validate_returns", - ], "on_trash": "erpnext.regional.check_deletion_permission" }, "Purchase Invoice": { "validate": [ "erpnext.regional.india.utils.update_grand_total_for_rcm", "erpnext.regional.united_arab_emirates.utils.update_grand_total_for_rcm", + "erpnext.regional.united_arab_emirates.utils.validate_returns" ] }, "Payment Entry": { diff --git a/erpnext/regional/report/uae_vat_21/uae_vat_21.py b/erpnext/regional/report/uae_vat_21/uae_vat_21.py index 2bded71ec20..227c2fb5a16 100644 --- a/erpnext/regional/report/uae_vat_21/uae_vat_21.py +++ b/erpnext/regional/report/uae_vat_21/uae_vat_21.py @@ -277,7 +277,7 @@ def get_standard_rated_expenses_total(filters): conditions = get_conditions(filters) return frappe.db.sql(""" select sum(total) from - `tabSales Invoice` + `tabPurchase Invoice` where standard_rated_expenses > 0 and docstatus = 1 {where_conditions} ; @@ -288,7 +288,7 @@ def get_standard_rated_expenses_tax(filters): conditions = get_conditions(filters) return frappe.db.sql(""" select sum(standard_rated_expenses) from - `tabSales Invoice` + `tabPurchase Invoice` where standard_rated_expenses > 0 and docstatus = 1 {where_conditions} ; diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index 0de42120c4c..e48b9a9ce13 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -38,8 +38,11 @@ def make_custom_fields(): dict(fieldname='supplier_name_in_arabic', label='Supplier Name in Arabic', fieldtype='Read Only', insert_after='supplier_name', fetch_from='supplier.supplier_name_in_arabic', print_hide=1), + dict(fieldname='standard_rated_expenses', label='Standard Rated Expenses (AED)', + insert_after='permit_no', fieldtype='Currency', print_hide=1, default='0', + depends_on="eval:doc.reverse_charge=='N'",), dict(fieldname='reverse_charge', label='Reverse Charge Applicable', - fieldtype='Select', insert_after='permit_no', print_hide=1, + fieldtype='Select', insert_after='standard_rated_expenses', print_hide=1, options='Y\nN', default='N'), dict(fieldname='claimable_reverse_charge', label='Claimable Reverse Charge (Percentage)', insert_after='reverse_charge', fieldtype='Percent', print_hide=1, @@ -57,8 +60,6 @@ def make_custom_fields(): fieldtype='Read Only', fetch_from='customer_address.emirates'), dict(fieldname='tourist_tax_return', label='Tax Refund provided to Tourists (AED)', insert_after='permit_no', fieldtype='Currency', print_hide=1, default='0'), - dict(fieldname='standard_rated_expenses', label='Standard Rated Expenses (AED)', - insert_after='tourist_tax_return', fieldtype='Currency', print_hide=1, default='0'), ] invoice_item_fields = [ diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index 5a8c3c47fbb..dbe283f226e 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -143,11 +143,13 @@ def make_regional_gl_entries(gl_entries, doc): return gl_entries def validate_returns(doc, method): - """Sum of Tourist Returns and Standard Rated Expenses should be less than Total Tax.""" + """Standard Rated expenses should not be set when Reverse Charge Applicable is set.""" country = frappe.get_cached_value('Company', doc.company, 'country') - + print("-"*50) + print(doc.reverse_charge) + print(flt(doc.standard_rated_expenses)) if country != 'United Arab Emirates': return - if flt(doc.tourist_tax_return) + flt(doc.standard_rated_expenses) > flt(doc.total_taxes_and_charges): - frappe.throw(_("The Total Returns(Tax Refund provided to Tourists (AED) + Standard Rated Expenses (AED)) should be less than the Total Taxes and Charges (Company Currency)")) \ No newline at end of file + if doc.reverse_charge == 'Y' and flt(doc.standard_rated_expenses) != 0: + frappe.throw(_("Standard Rated expenses should not be set when Reverse Charge Applicable is Y")) \ No newline at end of file From dfc3993cecdd7f0e7d9cbd80734fbf8c6b8021f2 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Wed, 14 Oct 2020 12:21:36 +0530 Subject: [PATCH 26/60] chore(UAE VAT 21): rename report --- erpnext/accounts/desk_page/accounting/accounting.json | 2 +- .../report/{uae_vat_21 => uae_vat_201}/__init__.py | 0 .../uae_vat_21.html => uae_vat_201/uae_vat_201.html} | 0 .../uae_vat_21.js => uae_vat_201/uae_vat_201.js} | 2 +- .../uae_vat_21.json => uae_vat_201/uae_vat_201.json} | 4 ++-- .../uae_vat_21.py => uae_vat_201/uae_vat_201.py} | 6 +++--- erpnext/regional/united_arab_emirates/setup.py | 10 +++++----- erpnext/regional/united_arab_emirates/utils.py | 8 ++------ 8 files changed, 14 insertions(+), 18 deletions(-) rename erpnext/regional/report/{uae_vat_21 => uae_vat_201}/__init__.py (100%) rename erpnext/regional/report/{uae_vat_21/uae_vat_21.html => uae_vat_201/uae_vat_201.html} (100%) rename erpnext/regional/report/{uae_vat_21/uae_vat_21.js => uae_vat_201/uae_vat_201.js} (96%) rename erpnext/regional/report/{uae_vat_21/uae_vat_21.json => uae_vat_201/uae_vat_201.json} (88%) rename erpnext/regional/report/{uae_vat_21/uae_vat_21.py => uae_vat_201/uae_vat_201.py} (98%) diff --git a/erpnext/accounts/desk_page/accounting/accounting.json b/erpnext/accounts/desk_page/accounting/accounting.json index 214e31f21fd..7d25b27e776 100644 --- a/erpnext/accounts/desk_page/accounting/accounting.json +++ b/erpnext/accounts/desk_page/accounting/accounting.json @@ -83,7 +83,7 @@ { "hidden": 0, "label": "Value-Added Tax (VAT UAE)", - "links": "[\n {\n \"label\": \"UAE VAT Setting\",\n \"name\": \"UAE VAT Setting\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"UAE VAT 21\",\n \"name\": \"UAE VAT 21\",\n \"type\": \"report\"\n }\n]" + "links": "[\n {\n \"label\": \"UAE VAT Setting\",\n \"name\": \"UAE VAT Setting\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"UAE VAT 201\",\n \"name\": \"UAE VAT 201\",\n \"type\": \"report\"\n }\n]" } ], "category": "Modules", diff --git a/erpnext/regional/report/uae_vat_21/__init__.py b/erpnext/regional/report/uae_vat_201/__init__.py similarity index 100% rename from erpnext/regional/report/uae_vat_21/__init__.py rename to erpnext/regional/report/uae_vat_201/__init__.py diff --git a/erpnext/regional/report/uae_vat_21/uae_vat_21.html b/erpnext/regional/report/uae_vat_201/uae_vat_201.html similarity index 100% rename from erpnext/regional/report/uae_vat_21/uae_vat_21.html rename to erpnext/regional/report/uae_vat_201/uae_vat_201.html diff --git a/erpnext/regional/report/uae_vat_21/uae_vat_21.js b/erpnext/regional/report/uae_vat_201/uae_vat_201.js similarity index 96% rename from erpnext/regional/report/uae_vat_21/uae_vat_21.js rename to erpnext/regional/report/uae_vat_201/uae_vat_201.js index 5fc54496552..59574247701 100644 --- a/erpnext/regional/report/uae_vat_21/uae_vat_21.js +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.js @@ -2,7 +2,7 @@ // For license information, please see license.txt /* eslint-disable */ -frappe.query_reports["UAE VAT 21"] = { +frappe.query_reports["UAE VAT 201"] = { "filters": [ { "fieldname": "company", diff --git a/erpnext/regional/report/uae_vat_21/uae_vat_21.json b/erpnext/regional/report/uae_vat_201/uae_vat_201.json similarity index 88% rename from erpnext/regional/report/uae_vat_21/uae_vat_21.json rename to erpnext/regional/report/uae_vat_201/uae_vat_201.json index 421990cc4ab..8a88bcd3e23 100644 --- a/erpnext/regional/report/uae_vat_21/uae_vat_21.json +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.json @@ -12,11 +12,11 @@ "modified": "2020-09-10 08:51:02.298482", "modified_by": "Administrator", "module": "Regional", - "name": "UAE VAT 21", + "name": "UAE VAT 201", "owner": "Administrator", "prepared_report": 0, "ref_doctype": "GL Entry", - "report_name": "UAE VAT 21", + "report_name": "UAE VAT 201", "report_type": "Script Report", "roles": [] } \ No newline at end of file diff --git a/erpnext/regional/report/uae_vat_21/uae_vat_21.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py similarity index 98% rename from erpnext/regional/report/uae_vat_21/uae_vat_21.py rename to erpnext/regional/report/uae_vat_201/uae_vat_201.py index 227c2fb5a16..bcd31351eaf 100644 --- a/erpnext/regional/report/uae_vat_21/uae_vat_21.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -279,7 +279,7 @@ def get_standard_rated_expenses_total(filters): select sum(total) from `tabPurchase Invoice` where - standard_rated_expenses > 0 + claimable_standard_rated_expenses > 0 and docstatus = 1 {where_conditions} ; """.format(where_conditions=conditions), filters)[0][0] or 0 @@ -287,10 +287,10 @@ def get_standard_rated_expenses_tax(filters): """Returns the sum of the tax of each Purchase invoice made.""" conditions = get_conditions(filters) return frappe.db.sql(""" - select sum(standard_rated_expenses) from + select sum(claimable_standard_rated_expenses) from `tabPurchase Invoice` where - standard_rated_expenses > 0 + claimable_standard_rated_expenses > 0 and docstatus = 1 {where_conditions} ; """.format(where_conditions=conditions), filters)[0][0] or 0 diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index e48b9a9ce13..a0e76209191 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -38,11 +38,11 @@ def make_custom_fields(): dict(fieldname='supplier_name_in_arabic', label='Supplier Name in Arabic', fieldtype='Read Only', insert_after='supplier_name', fetch_from='supplier.supplier_name_in_arabic', print_hide=1), - dict(fieldname='standard_rated_expenses', label='Standard Rated Expenses (AED)', + dict(fieldname='claimable_standard_rated_expenses', label='Claimable Standard Rated Expenses (AED)', insert_after='permit_no', fieldtype='Currency', print_hide=1, default='0', depends_on="eval:doc.reverse_charge=='N'",), dict(fieldname='reverse_charge', label='Reverse Charge Applicable', - fieldtype='Select', insert_after='standard_rated_expenses', print_hide=1, + fieldtype='Select', insert_after='claimable_standard_rated_expenses', print_hide=1, options='Y\nN', default='N'), dict(fieldname='claimable_reverse_charge', label='Claimable Reverse Charge (Percentage)', insert_after='reverse_charge', fieldtype='Percent', print_hide=1, @@ -132,11 +132,11 @@ def add_print_formats(): name in('Simplified Tax Invoice', 'Detailed Tax Invoice', 'Tax Invoice') """) def add_custom_roles_for_reports(): - """Add Access Control to UAE VAT 21.""" - if not frappe.db.get_value('Custom Role', dict(report='UAE VAT 21')): + """Add Access Control to UAE VAT 201.""" + if not frappe.db.get_value('Custom Role', dict(report='UAE VAT 201')): frappe.get_doc(dict( doctype='Custom Role', - report='UAE VAT 21', + report='UAE VAT 201', roles= [ dict(role='Accounts User'), dict(role='Accounts Manager'), diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index dbe283f226e..37501a2638f 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -145,11 +145,7 @@ def make_regional_gl_entries(gl_entries, doc): def validate_returns(doc, method): """Standard Rated expenses should not be set when Reverse Charge Applicable is set.""" country = frappe.get_cached_value('Company', doc.company, 'country') - print("-"*50) - print(doc.reverse_charge) - print(flt(doc.standard_rated_expenses)) if country != 'United Arab Emirates': return - - if doc.reverse_charge == 'Y' and flt(doc.standard_rated_expenses) != 0: - frappe.throw(_("Standard Rated expenses should not be set when Reverse Charge Applicable is Y")) \ No newline at end of file + if doc.reverse_charge == 'Y' and flt(doc.claimable_standard_rated_expenses) != 0: + frappe.throw(_("Claimable Standard Rated expenses should not be set when Reverse Charge Applicable is Y")) \ No newline at end of file From b9dc13294d7233eebe37783394550a3bdbe0a334 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Wed, 14 Oct 2020 16:56:26 +0530 Subject: [PATCH 27/60] chore(UAE VAT 201) solve translations issues --- .../report/uae_vat_201/uae_vat_201.py | 24 +++++++++---------- .../regional/united_arab_emirates/utils.py | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index bcd31351eaf..a2518c38c6e 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -68,14 +68,14 @@ def get_data(filters = None): for d, emirate in enumerate(emirates, 97): if emirate in amounts_by_emirate: - amounts_by_emirate[emirate]["no"] = _(f'1{chr(d)}') - amounts_by_emirate[emirate]["legend"] = _(f'Standard rated supplies in {emirate}') + amounts_by_emirate[emirate]["no"] = _('1{0}').format(chr(d)) + amounts_by_emirate[emirate]["legend"] = _('Standard rated supplies in {0}').format(emirate) data.append(amounts_by_emirate[emirate]) else: data.append( { - "no": _(f'1{chr(d)}'), - "legend": _(f'Standard rated supplies in {emirate}'), + "no": _('1{0}').format(chr(d)), + "legend": _('Standard rated supplies in {0}').format(emirate), "amount": frappe.format(0, 'Currency'), "vat_amount": frappe.format(0, 'Currency') } @@ -83,7 +83,7 @@ def get_data(filters = None): data.append( { - "no": _('2'), + "no": '2', "legend": _('Tax Refunds provided to Tourists under the Tax Refunds for Tourists Scheme'), "amount": frappe.format((-1) * get_tourist_tax_return_total(filters), 'Currency'), "vat_amount": frappe.format((-1) * get_tourist_tax_return_tax(filters), 'Currency') @@ -92,7 +92,7 @@ def get_data(filters = None): data.append( { - "no": _('3'), + "no": '3', "legend": _('Supplies subject to the reverse charge provision'), "amount": frappe.format(get_reverse_charge_total(filters), 'Currency'), "vat_amount": frappe.format(get_reverse_charge_tax(filters), 'Currency') @@ -101,7 +101,7 @@ def get_data(filters = None): data.append( { - "no": _('4'), + "no": '4', "legend": _('Zero Rated'), "amount": frappe.format(get_zero_rated_total(filters), 'Currency'), "vat_amount": "-" @@ -110,7 +110,7 @@ def get_data(filters = None): data.append( { - "no": _('5'), + "no": '5', "legend": _('Exempt Supplies'), "amount": frappe.format(get_exempt_total(filters), 'Currency'), "vat_amount": "-" @@ -118,14 +118,14 @@ def get_data(filters = None): ) data.append({ - "no": _(''), - "legend": _(''), + "no": '', + "legend": '', "amount": '', "vat_amount": '' }) data.append({ - "no": _(''), + "no": '', "legend": _('VAT on Expenses and All Other Inputs'), "amount": '', "vat_amount": '' @@ -142,7 +142,7 @@ def get_data(filters = None): data.append( { - "no": _('10'), + "no": '10', "legend": _('Supplies subject to the reverse charge provision'), "amount": frappe.format(get_reverse_charge_recoverable_total(filters), 'Currency'), "vat_amount": frappe.format(get_reverse_charge_recoverable_tax(filters), 'Currency') diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index 37501a2638f..847bda8271f 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -52,7 +52,7 @@ def get_tax_accounts(company): ) if not tax_accounts_list and not frappe.flags.in_test: - frappe.throw(_(f'Please set Vat Accounts for Company: "{company}" in UAE VAT Settings')) + frappe.throw(_('Please set Vat Accounts for Company: "{0}" in UAE VAT Settings').format(company)) for d in tax_accounts_list: for key, name in d.items(): tax_accounts_dict[name] = name From 32eb9a78930d2771f68ee25ad1930bda5929545f Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Mon, 19 Oct 2020 17:58:50 +0530 Subject: [PATCH 28/60] feat(UAE VAT 201): claimable to recoverable --- erpnext/regional/united_arab_emirates/setup.py | 10 +++++----- erpnext/regional/united_arab_emirates/utils.py | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index a0e76209191..efa39bd3c5d 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -38,13 +38,13 @@ def make_custom_fields(): dict(fieldname='supplier_name_in_arabic', label='Supplier Name in Arabic', fieldtype='Read Only', insert_after='supplier_name', fetch_from='supplier.supplier_name_in_arabic', print_hide=1), - dict(fieldname='claimable_standard_rated_expenses', label='Claimable Standard Rated Expenses (AED)', + dict(fieldname='recoverable_standard_rated_expenses', label='Recoverable Standard Rated Expenses (AED)', insert_after='permit_no', fieldtype='Currency', print_hide=1, default='0', depends_on="eval:doc.reverse_charge=='N'",), dict(fieldname='reverse_charge', label='Reverse Charge Applicable', - fieldtype='Select', insert_after='claimable_standard_rated_expenses', print_hide=1, + fieldtype='Select', insert_after='recoverable_standard_rated_expenses', print_hide=1, options='Y\nN', default='N'), - dict(fieldname='claimable_reverse_charge', label='Claimable Reverse Charge (Percentage)', + dict(fieldname='recoverable_reverse_charge', label='Recoverable Reverse Charge (Percentage)', insert_after='reverse_charge', fieldtype='Percent', print_hide=1, depends_on="eval:doc.reverse_charge=='Y'", default='100.000'), ] @@ -57,7 +57,7 @@ def make_custom_fields(): fieldtype='Read Only', insert_after='customer_name', fetch_from='customer.customer_name_in_arabic', print_hide=1), dict(fieldname='emirate', label='Emirate', insert_after='customer_address', - fieldtype='Read Only', fetch_from='customer_address.emirates'), + fieldtype='Read Only', fetch_from='customer_address.emirate'), dict(fieldname='tourist_tax_return', label='Tax Refund provided to Tourists (AED)', insert_after='permit_no', fieldtype='Currency', print_hide=1, default='0'), ] @@ -102,7 +102,7 @@ def make_custom_fields(): fieldtype='Data', insert_after='supplier_name'), ], 'Address': [ - dict(fieldname='emirates', label='Emirates', fieldtype='Select', insert_after='state', + dict(fieldname='emirate', label='Emirate', fieldtype='Select', insert_after='state', options='Abu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain') ], 'Purchase Invoice': purchase_invoice_fields + invoice_fields, diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index 847bda8271f..7edc2b6720a 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -147,5 +147,5 @@ def validate_returns(doc, method): country = frappe.get_cached_value('Company', doc.company, 'country') if country != 'United Arab Emirates': return - if doc.reverse_charge == 'Y' and flt(doc.claimable_standard_rated_expenses) != 0: - frappe.throw(_("Claimable Standard Rated expenses should not be set when Reverse Charge Applicable is Y")) \ No newline at end of file + if doc.reverse_charge == 'Y' and flt(doc.recoverable_standard_rated_expenses) != 0: + frappe.throw(_("Recoverable Standard Rated expenses should not be set when Reverse Charge Applicable is Y")) \ No newline at end of file From c1b80047571a579c34899ad4e458c28e89bf4c31 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Mon, 19 Oct 2020 20:47:56 +0530 Subject: [PATCH 29/60] feat(UAE VAT 21): claimable to recoverable --- .../regional/report/uae_vat_201/uae_vat_201.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index a2518c38c6e..b5ff8389e38 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -245,14 +245,14 @@ def get_conditions_join(filters): return conditions def get_reverse_charge_recoverable_total(filters): - """Returns the sum of the total of each Purchase invoice made with claimable reverse charge.""" + """Returns the sum of the total of each Purchase invoice made with recoverable reverse charge.""" conditions = get_conditions(filters) return frappe.db.sql(""" select sum(total) from `tabPurchase Invoice` where reverse_charge = "Y" - and claimable_reverse_charge > 0 + and recoverable_reverse_charge > 0 and docstatus = 1 {where_conditions} ; """.format(where_conditions=conditions), filters)[0][0] or 0 @@ -260,26 +260,26 @@ def get_reverse_charge_recoverable_tax(filters): """Returns the sum of the tax of each Purchase invoice made.""" conditions = get_conditions_join(filters) return frappe.db.sql(""" - select sum(debit * `tabPurchase Invoice`.claimable_reverse_charge / 100) from + select sum(debit * `tabPurchase Invoice`.recoverable_reverse_charge / 100) from `tabPurchase Invoice` inner join `tabGL Entry` on `tabGL Entry`.voucher_no = `tabPurchase Invoice`.name where `tabPurchase Invoice`.reverse_charge = "Y" and `tabPurchase Invoice`.docstatus = 1 - and `tabPurchase Invoice`.claimable_reverse_charge > 0 + and `tabPurchase Invoice`.recoverable_reverse_charge > 0 and `tabGL Entry`.docstatus = 1 and account in (select account from `tabUAE VAT Account` where parent=%(company)s) {where_conditions} ; """.format(where_conditions=conditions), filters)[0][0] or 0 def get_standard_rated_expenses_total(filters): - """Returns the sum of the total of each Purchase invoice made with claimable reverse charge.""" + """Returns the sum of the total of each Purchase invoice made with recoverable reverse charge.""" conditions = get_conditions(filters) return frappe.db.sql(""" select sum(total) from `tabPurchase Invoice` where - claimable_standard_rated_expenses > 0 + recoverable_standard_rated_expenses > 0 and docstatus = 1 {where_conditions} ; """.format(where_conditions=conditions), filters)[0][0] or 0 @@ -287,10 +287,10 @@ def get_standard_rated_expenses_tax(filters): """Returns the sum of the tax of each Purchase invoice made.""" conditions = get_conditions(filters) return frappe.db.sql(""" - select sum(claimable_standard_rated_expenses) from + select sum(recoverable_standard_rated_expenses) from `tabPurchase Invoice` where - claimable_standard_rated_expenses > 0 + recoverable_standard_rated_expenses > 0 and docstatus = 1 {where_conditions} ; """.format(where_conditions=conditions), filters)[0][0] or 0 From 33cdfdfb7f21661997cef6fa70095f436b348054 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Mon, 19 Oct 2020 20:48:43 +0530 Subject: [PATCH 30/60] feat(UAE VAT 201): Add tests for report --- .../purchase_invoice/test_purchase_invoice.py | 3 +- .../report/uae_vat_201/test_uae_vat_201.py | 370 ++++++++++++++++++ 2 files changed, 372 insertions(+), 1 deletion(-) create mode 100644 erpnext/regional/report/uae_vat_201/test_uae_vat_201.py diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 2e5a7142a33..8276c1fc03b 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1040,7 +1040,8 @@ def make_purchase_invoice_against_cost_center(**args): pi.is_return = args.is_return pi.credit_to = args.return_against or "Creditors - _TC" pi.is_subcontracted = args.is_subcontracted or "No" - pi.supplier_warehouse = "_Test Warehouse 1 - _TC" + if args.supplier_warehouse: + pi.supplier_warehouse = "_Test Warehouse 1 - _TC" pi.append("items", { "item_code": args.item or args.item_code or "_Test Item", diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py new file mode 100644 index 00000000000..8e845d74321 --- /dev/null +++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py @@ -0,0 +1,370 @@ +# coding=utf-8 +from __future__ import unicode_literals + +import erpnext +import frappe +from unittest import TestCase +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice +from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice +from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse_account +from erpnext.regional.report.uae_vat_201.uae_vat_201 import ( + get_total_emiratewise, + get_tourist_tax_return_total, + get_tourist_tax_return_tax, + get_reverse_charge_total, + get_reverse_charge_tax, + get_zero_rated_total, + get_exempt_total, + get_standard_rated_expenses_total, + get_standard_rated_expenses_tax, + get_reverse_charge_recoverable_total, + get_reverse_charge_recoverable_tax + ) + + + +class TestUaeVat201(TestCase): + def setUp(self): + frappe.set_user("Administrator") + + frappe.db.sql("delete from `tabSales Invoice` where company='_Test Company UAE VAT'") + frappe.db.sql("delete from `tabPurchase Invoice` where company='_Test Company UAE VAT'") + + + make_company("_Test Company UAE VAT", "_TCUV") + set_vat_accounts() + + make_customers() + + make_supplier() + + create_warehouse("_Test UAE VAT Supplier Warehouse", company="_Test Company UAE VAT") + + + make_item("_Test UAE VAT Item", properties = {"is_zero_rated": 0, "is_exempt": 0}) + make_item("_Test UAE VAT Zero Rated Item", properties = {"is_zero_rated": 1, "is_exempt": 0}) + make_item("_Test UAE VAT Exempt Item", properties = {"is_zero_rated": 0, "is_exempt": 1}) + + make_sales_invoices() + + create_purchase_invoices() + + def test_uae_vat_201_report(self): + filters = {"company": "_Test Company UAE VAT"} + total_emiratewise = get_total_emiratewise(filters) + amounts_by_emirate = {} + for d in total_emiratewise: + emirate, amount, vat= d + amounts_by_emirate[emirate] = { + "raw_amount": amount, + "raw_vat_amount": vat, + } + self.assertEqual(amounts_by_emirate["Sharjah"]["raw_amount"],300) + self.assertEqual(amounts_by_emirate["Sharjah"]["raw_vat_amount"],5) + self.assertEqual(amounts_by_emirate["Dubai"]["raw_amount"],200) + self.assertEqual(amounts_by_emirate["Dubai"]["raw_vat_amount"],10) + + self.assertEqual(get_tourist_tax_return_tax(filters),2) + self.assertEqual(get_reverse_charge_total(filters),250) + self.assertEqual(get_reverse_charge_tax(filters),12.5) + self.assertEqual(get_zero_rated_total(filters),100) + self.assertEqual(get_exempt_total(filters),100) + self.assertEqual(get_standard_rated_expenses_total(filters),250) + self.assertEqual(get_standard_rated_expenses_tax(filters),1) + self.assertEqual(get_reverse_charge_recoverable_total(filters),250) + self.assertEqual(get_reverse_charge_recoverable_tax(filters),12.5) + +def make_company(company_name, abbr): + if not frappe.db.exists("Company", company_name): + company = frappe.get_doc({ + "doctype": "Company", + "company_name": company_name, + "abbr": abbr, + "default_currency": "AED", + "country": "United Arab Emirates", + "create_chart_of_accounts_based_on": "Standard Template", + }) + company.insert() + else: + company = frappe.get_doc("Company", company_name) + + # indempotent + company.create_default_warehouses() + + if not frappe.db.get_value("Cost Center", {"is_group": 0, "company": company.name}): + company.create_default_cost_center() + + company.save() + return company + +def set_vat_accounts(): + if not frappe.db.exists("UAE VAT Settings", "_Test Company UAE VAT"): + vat_accounts = frappe.get_all( + "Account", + fields=["name"], + filters = { + "company": "_Test Company UAE VAT", + "is_group":0, + "account_type": "Tax"}) + + uae_vat_accounts = [] + for d in vat_accounts: + uae_vat_accounts.append( + { + "doctype": "UAE VAT Account", + "account":d.name + }) + + frappe.get_doc({ + "company": "_Test Company UAE VAT", + "uae_vat_accounts": uae_vat_accounts, + "doctype": "UAE VAT Settings", + }).insert() + +def make_customers(): + if not frappe.db.exists("Customer", "_Test Dubai Customer"): + customer = frappe.get_doc({ + "doctype": "Customer", + "customer_name": "_Test Dubai Customer", + "customer_type": "Company", + }) + customer.insert() + else: + customer = frappe.get_doc("Customer", "_Test Dubai Customer") + + if not frappe.db.exists("Customer", "_Test Sharjah Customer"): + customer = frappe.get_doc({ + "doctype": "Customer", + "customer_name": "_Test Sharjah Customer", + "customer_type": "Company", + }) + customer.insert() + else: + customer = frappe.get_doc("Customer", "_Test Sharjah Customer") + + if not frappe.db.exists('Address', '_Test Dubai Address'): + address = frappe.get_doc({ + "address_line1": "_Test Address Line 1", + "address_title": "_Test Dubai Address", + "address_type": "Billing", + "city": "_Test City", + "state": "Test State", + "country": "United Arab Emirates", + "doctype": "Address", + "emirate": "Dubai" + }).insert() + + address.append("links", { + "link_doctype": "Customer", + "link_name": "_Test Dubai Customer" + }) + + address.save() + + if not frappe.db.exists('Address', '_Test Sharjah Address'): + address = frappe.get_doc({ + "address_line1": "_Test Address Line 1", + "address_title": "_Test Sharjah Address", + "address_type": "Billing", + "city": "_Test City", + "state": "Test State", + "country": "United Arab Emirates", + "doctype": "Address", + "emirate": "Sharjah" + }).insert() + + address.append("links", { + "link_doctype": "Customer", + "link_name": "_Test Sharjah Customer" + }) + + address.save() + +def make_supplier(): + + if not frappe.db.exists("Supplier", "_Test UAE Supplier"): + frappe.get_doc({ + "supplier_group": "Local", + "supplier_name": "_Test UAE Supplier", + "supplier_type": "Individual", + "doctype": "Supplier", + }).insert() + +def create_warehouse(warehouse_name, properties=None, company=None): + if not company: + company = "_Test Company" + + warehouse_id = erpnext.encode_company_abbr(warehouse_name, company) + if not frappe.db.exists("Warehouse", warehouse_id): + w = frappe.new_doc("Warehouse") + w.warehouse_name = warehouse_name + w.parent_warehouse = "All Warehouses - _TCUV" + w.company = company + w.account = get_warehouse_account(warehouse_name, company) + if properties: + w.update(properties) + w.save() + return w.name + else: + return warehouse_id + +def make_item(item_code, properties=None): + if frappe.db.exists("Item", item_code): + return frappe.get_doc("Item", item_code) + + item = frappe.get_doc({ + "doctype": "Item", + "item_code": item_code, + "item_name": item_code, + "description": item_code, + "item_group": "Products" + }) + + if properties: + item.update(properties) + + item.insert() + + return item + +def make_sales_invoices(): + si = create_sales_invoice(company="_Test Company UAE VAT", + customer = '_Test Dubai Customer', + currency = 'AED', + warehouse = 'Finished Goods - _TCUV', + debit_to = 'Debtors - _TCUV', + income_account = 'Sales - _TCUV', + expense_account = 'Cost of Goods Sold - _TCUV', + cost_center = 'Main - _TCUV', + sales_taxes_and_charges_template = "UAE VAT 5% - _TCUV", + item = "_Test UAE VAT Item", + do_not_save=1 + ) + si.append("taxes", { + "charge_type": "On Net Total", + "account_head": "VAT 5% - _TCUV", + "cost_center": "Main - _TCUV", + "description": "VAT 5% @ 5.0", + "rate": 5.0 + }) + si.submit() + + si = create_sales_invoice(company="_Test Company UAE VAT", + customer = '_Test Sharjah Customer', + currency = 'AED', + warehouse = 'Finished Goods - _TCUV', + debit_to = 'Debtors - _TCUV', + income_account = 'Sales - _TCUV', + expense_account = 'Cost of Goods Sold - _TCUV', + cost_center = 'Main - _TCUV', + sales_taxes_and_charges_template = "UAE VAT 5% - _TCUV", + item = "_Test UAE VAT Item", + do_not_save=1 + ) + si.append("taxes", { + "charge_type": "On Net Total", + "account_head": "VAT 5% - _TCUV", + "cost_center": "Main - _TCUV", + "description": "VAT 5% @ 5.0", + "rate": 5.0 + }) + si.submit() + + si = create_sales_invoice(company="_Test Company UAE VAT", + customer = '_Test Dubai Customer', + currency = 'AED', + warehouse = 'Finished Goods - _TCUV', + debit_to = 'Debtors - _TCUV', + income_account = 'Sales - _TCUV', + expense_account = 'Cost of Goods Sold - _TCUV', + cost_center = 'Main - _TCUV', + sales_taxes_and_charges_template = "UAE VAT 5% - _TCUV", + item = "_Test UAE VAT Item", + do_not_save=1 + ) + + si.tourist_tax_return = 2 + + si.append("taxes", { + "charge_type": "On Net Total", + "account_head": "VAT 5% - _TCUV", + "cost_center": "Main - _TCUV", + "description": "VAT 5% @ 5.0", + "rate": 5.0 + }) + si.submit() + + si = create_sales_invoice(company="_Test Company UAE VAT", + customer = '_Test Sharjah Customer', + currency = 'AED', + warehouse = 'Finished Goods - _TCUV', + debit_to = 'Debtors - _TCUV', + income_account = 'Sales - _TCUV', + expense_account = 'Cost of Goods Sold - _TCUV', + cost_center = 'Main - _TCUV', + sales_taxes_and_charges_template = "UAE VAT 5% - _TCUV", + item = "_Test UAE VAT Zero Rated Item", + ) + + si = create_sales_invoice(company="_Test Company UAE VAT", + customer = '_Test Sharjah Customer', + currency = 'AED', + warehouse = 'Finished Goods - _TCUV', + debit_to = 'Debtors - _TCUV', + income_account = 'Sales - _TCUV', + expense_account = 'Cost of Goods Sold - _TCUV', + cost_center = 'Main - _TCUV', + sales_taxes_and_charges_template = "UAE VAT 5% - _TCUV", + item = "_Test UAE VAT Exempt Item", + ) + +def create_purchase_invoices(): + + pi = make_purchase_invoice( + company="_Test Company UAE VAT", + supplier = '_Test UAE Supplier', + warehouse = '_Test UAE VAT Supplier Warehouse - _TCUV', + currency = 'AED', + cost_center = 'Main - _TCUV', + expense_account = 'Cost of Goods Sold - _TCUV', + item = "_Test UAE VAT Item", + do_not_save=1, + ) + pi.append("taxes", { + "charge_type": "On Net Total", + "account_head": "VAT 5% - _TCUV", + "cost_center": "Main - _TCUV", + "description": "VAT 5% @ 5.0", + "rate": 5.0 + }) + + pi.recoverable_standard_rated_expenses = 1 + + pi.submit() + + pi = make_purchase_invoice( + company="_Test Company UAE VAT", + supplier = '_Test UAE Supplier', + warehouse = '_Test UAE VAT Supplier Warehouse - _TCUV', + currency = 'AED', + cost_center = 'Main - _TCUV', + expense_account = 'Cost of Goods Sold - _TCUV', + item = "_Test UAE VAT Item", + do_not_save=1, + ) + + pi.append("taxes", { + "charge_type": "On Net Total", + "account_head": "VAT 5% - _TCUV", + "cost_center": "Main - _TCUV", + "description": "VAT 5% @ 5.0", + "rate": 5.0 + }) + + pi.reverse_charge = "Y" + + pi.recoverable_reverse_charge = 100 + + pi.submit() + + From 853fd03f4910c9bd8641085ba876152e11f7728b Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Mon, 19 Oct 2020 22:35:16 +0530 Subject: [PATCH 31/60] feat(uae vat 201): fix linter issues --- erpnext/regional/report/uae_vat_201/test_uae_vat_201.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py index 8e845d74321..6a255b8a0b1 100644 --- a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py @@ -64,6 +64,7 @@ class TestUaeVat201(TestCase): self.assertEqual(amounts_by_emirate["Dubai"]["raw_amount"],200) self.assertEqual(amounts_by_emirate["Dubai"]["raw_vat_amount"],10) + self.assertEqual(get_tourist_tax_return_total(filters),100) self.assertEqual(get_tourist_tax_return_tax(filters),2) self.assertEqual(get_reverse_charge_total(filters),250) self.assertEqual(get_reverse_charge_tax(filters),12.5) From 234036df32fc6db164cf930dbc1e37dfabf1fee6 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Tue, 20 Oct 2020 07:42:10 +0530 Subject: [PATCH 32/60] chore(uae vat 201): solve travis issues --- erpnext/regional/report/uae_vat_201/test_uae_vat_201.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py index 6a255b8a0b1..648d98e2045 100644 --- a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py @@ -341,6 +341,7 @@ def create_purchase_invoices(): pi.recoverable_standard_rated_expenses = 1 + pi.insert() pi.submit() pi = make_purchase_invoice( @@ -366,6 +367,7 @@ def create_purchase_invoices(): pi.recoverable_reverse_charge = 100 + pi.insert() pi.submit() From c08591124c172da56a2e917644d864f4c6dc0ef5 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Tue, 20 Oct 2020 10:17:48 +0530 Subject: [PATCH 33/60] chore(UAE VAT 21): solve merge conflicts --- .../doctype/purchase_invoice/test_purchase_invoice.py | 2 +- erpnext/regional/report/uae_vat_201/test_uae_vat_201.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 8276c1fc03b..f2499d24b5b 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -998,7 +998,7 @@ def make_purchase_invoice(**args): 'expense_account': args.expense_account or '_Test Account Cost for Goods Sold - _TC', "conversion_factor": 1.0, "serial_no": args.serial_no, - "stock_uom": "_Test UOM", + "stock_uom": args.uom or "_Test UOM", "cost_center": args.cost_center or "_Test Cost Center - _TC", "project": args.project, "rejected_warehouse": args.rejected_warehouse or "", diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py index 648d98e2045..68c163d5bc1 100644 --- a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py @@ -324,12 +324,14 @@ def create_purchase_invoices(): pi = make_purchase_invoice( company="_Test Company UAE VAT", supplier = '_Test UAE Supplier', + supplier_warehouse = '_Test UAE VAT Supplier Warehouse - _TCUV', warehouse = '_Test UAE VAT Supplier Warehouse - _TCUV', currency = 'AED', cost_center = 'Main - _TCUV', expense_account = 'Cost of Goods Sold - _TCUV', item = "_Test UAE VAT Item", do_not_save=1, + uom = "Nos" ) pi.append("taxes", { "charge_type": "On Net Total", @@ -341,18 +343,19 @@ def create_purchase_invoices(): pi.recoverable_standard_rated_expenses = 1 - pi.insert() pi.submit() pi = make_purchase_invoice( company="_Test Company UAE VAT", supplier = '_Test UAE Supplier', + supplier_warehouse = '_Test UAE VAT Supplier Warehouse - _TCUV', warehouse = '_Test UAE VAT Supplier Warehouse - _TCUV', currency = 'AED', cost_center = 'Main - _TCUV', expense_account = 'Cost of Goods Sold - _TCUV', item = "_Test UAE VAT Item", do_not_save=1, + uom = "Nos" ) pi.append("taxes", { @@ -367,7 +370,6 @@ def create_purchase_invoices(): pi.recoverable_reverse_charge = 100 - pi.insert() pi.submit() From 6a24da4efd860b9f32ea61bb3cfc7ab23d787909 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Tue, 20 Oct 2020 11:53:06 +0530 Subject: [PATCH 34/60] refactor(UAE VAT 201): break functions --- .../report/uae_vat_201/uae_vat_201.py | 172 +++++++----------- 1 file changed, 69 insertions(+), 103 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index b5ff8389e38..90e75012918 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -46,109 +46,8 @@ def get_columns(): def get_data(filters = None): """Returns the list of dictionaries. Each dictionary is a row in the datatable and chart data.""" data = [] - data.append({ - "no": '', - "legend": _('VAT on Sales and All Other Outputs'), - "amount": '', - "vat_amount": '' - }) - - total_emiratewise = get_total_emiratewise(filters) - emirates = get_emirates() - amounts_by_emirate = {} - for d in total_emiratewise: - emirate, amount, vat= d - amounts_by_emirate[emirate] = { - "legend": emirate, - "raw_amount": amount, - "raw_vat_amount": vat, - "amount": frappe.format(amount, 'Currency'), - "vat_amount": frappe.format(vat, 'Currency'), - } - - for d, emirate in enumerate(emirates, 97): - if emirate in amounts_by_emirate: - amounts_by_emirate[emirate]["no"] = _('1{0}').format(chr(d)) - amounts_by_emirate[emirate]["legend"] = _('Standard rated supplies in {0}').format(emirate) - data.append(amounts_by_emirate[emirate]) - else: - data.append( - { - "no": _('1{0}').format(chr(d)), - "legend": _('Standard rated supplies in {0}').format(emirate), - "amount": frappe.format(0, 'Currency'), - "vat_amount": frappe.format(0, 'Currency') - } - ) - - data.append( - { - "no": '2', - "legend": _('Tax Refunds provided to Tourists under the Tax Refunds for Tourists Scheme'), - "amount": frappe.format((-1) * get_tourist_tax_return_total(filters), 'Currency'), - "vat_amount": frappe.format((-1) * get_tourist_tax_return_tax(filters), 'Currency') - } - ) - - data.append( - { - "no": '3', - "legend": _('Supplies subject to the reverse charge provision'), - "amount": frappe.format(get_reverse_charge_total(filters), 'Currency'), - "vat_amount": frappe.format(get_reverse_charge_tax(filters), 'Currency') - } - ) - - data.append( - { - "no": '4', - "legend": _('Zero Rated'), - "amount": frappe.format(get_zero_rated_total(filters), 'Currency'), - "vat_amount": "-" - } - ) - - data.append( - { - "no": '5', - "legend": _('Exempt Supplies'), - "amount": frappe.format(get_exempt_total(filters), 'Currency'), - "vat_amount": "-" - } - ) - - data.append({ - "no": '', - "legend": '', - "amount": '', - "vat_amount": '' - }) - - data.append({ - "no": '', - "legend": _('VAT on Expenses and All Other Inputs'), - "amount": '', - "vat_amount": '' - }) - - data.append( - { - "no": '9', - "legend": _('Standard Rated Expenses'), - "amount": frappe.format(get_standard_rated_expenses_total(filters), 'Currency'), - "vat_amount": frappe.format(get_standard_rated_expenses_tax(filters), 'Currency') - } - ) - - data.append( - { - "no": '10', - "legend": _('Supplies subject to the reverse charge provision'), - "amount": frappe.format(get_reverse_charge_recoverable_total(filters), 'Currency'), - "vat_amount": frappe.format(get_reverse_charge_recoverable_tax(filters), 'Currency') - } - ) - + emirates, amounts_by_emirate = append_vat_on_sales(data, filters) + append_vat_on_expenses(data, filters) return data, emirates, amounts_by_emirate @@ -178,6 +77,73 @@ def get_chart(emirates, amounts_by_emirate): chart["fieldtype"] = "Currency" return chart +def append_vat_on_sales(data, filters): + """Appends Sales and All Other Outputs""" + append_data(data, '', _('VAT on Sales and All Other Outputs'), '', '') + + emirates, amounts_by_emirate = standard_rated_expenses_emiratewise(data, filters) + + append_data(data, '2', _('Tax Refunds provided to Tourists under the Tax Refunds for Tourists Scheme'), + frappe.format((-1) * get_tourist_tax_return_total(filters), 'Currency'), + frappe.format((-1) * get_tourist_tax_return_tax(filters), 'Currency')) + + append_data(data, '3', _('Supplies subject to the reverse charge provision'), + frappe.format(get_reverse_charge_total(filters), 'Currency'), + frappe.format(get_reverse_charge_tax(filters), 'Currency')) + + append_data(data, '4', _('Zero Rated'), + frappe.format(get_zero_rated_total(filters), 'Currency'), "-") + + append_data(data, '5', _('Exempt Supplies'), + frappe.format(get_exempt_total(filters), 'Currency'),"-") + + append_data(data, '', '', '', '') + + return emirates, amounts_by_emirate + +def standard_rated_expenses_emiratewise(data, filters): + """"Append emiratewise standard rated expenses and vat""" + total_emiratewise = get_total_emiratewise(filters) + emirates = get_emirates() + amounts_by_emirate = {} + for d in total_emiratewise: + emirate, amount, vat= d + amounts_by_emirate[emirate] = { + "legend": emirate, + "raw_amount": amount, + "raw_vat_amount": vat, + "amount": frappe.format(amount, 'Currency'), + "vat_amount": frappe.format(vat, 'Currency'), + } + + for d, emirate in enumerate(emirates, 97): + if emirate in amounts_by_emirate: + amounts_by_emirate[emirate]["no"] = _('1{0}').format(chr(d)) + amounts_by_emirate[emirate]["legend"] = _('Standard rated supplies in {0}').format(emirate) + data.append(amounts_by_emirate[emirate]) + else: + append_data(data, _('1{0}').format(chr(d)), + _('Standard rated supplies in {0}').format(emirate), + frappe.format(0, 'Currency'), frappe.format(0, 'Currency')) + return emirates, amounts_by_emirate + + +def append_vat_on_expenses(data, filters): + """Appends Expenses and All Other Inputs""" + append_data(data, '', _('VAT on Expenses and All Other Inputs'), '', '') + append_data(data, '9', _('Standard Rated Expenses'), + frappe.format(get_standard_rated_expenses_total(filters), 'Currency'), + frappe.format(get_standard_rated_expenses_tax(filters), 'Currency')) + + append_data(data, '10', _('Supplies subject to the reverse charge provision'), + frappe.format(get_reverse_charge_recoverable_total(filters), 'Currency'), + frappe.format(get_reverse_charge_recoverable_tax(filters), 'Currency') +) + +def append_data(data, no, legend, amount, vat_amount): + """Returns data with appended value.""" + data.append({"no": no, "legend":legend, "amount": amount, "vat_amount": vat_amount}) + def get_total_emiratewise(filters): """Returns Emiratewise Amount and Taxes.""" return frappe.db.sql(f""" From 33e9a1ab31f5d22c2a865f84bdc8aa931c071545 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Tue, 20 Oct 2020 13:04:38 +0530 Subject: [PATCH 35/60] refactor(UAE VAT 201): solve linting issues --- erpnext/regional/report/uae_vat_201/uae_vat_201.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index 90e75012918..82032461ce7 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -78,7 +78,7 @@ def get_chart(emirates, amounts_by_emirate): return chart def append_vat_on_sales(data, filters): - """Appends Sales and All Other Outputs""" + """Appends Sales and All Other Outputs.""" append_data(data, '', _('VAT on Sales and All Other Outputs'), '', '') emirates, amounts_by_emirate = standard_rated_expenses_emiratewise(data, filters) @@ -102,7 +102,7 @@ def append_vat_on_sales(data, filters): return emirates, amounts_by_emirate def standard_rated_expenses_emiratewise(data, filters): - """"Append emiratewise standard rated expenses and vat""" + """Append emiratewise standard rated expenses and vat""" total_emiratewise = get_total_emiratewise(filters) emirates = get_emirates() amounts_by_emirate = {} @@ -129,7 +129,7 @@ def standard_rated_expenses_emiratewise(data, filters): def append_vat_on_expenses(data, filters): - """Appends Expenses and All Other Inputs""" + """Appends Expenses and All Other Inputs.""" append_data(data, '', _('VAT on Expenses and All Other Inputs'), '', '') append_data(data, '9', _('Standard Rated Expenses'), frappe.format(get_standard_rated_expenses_total(filters), 'Currency'), From 8796567b4207195a4b24353470595e39ce1e56fd Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Tue, 20 Oct 2020 16:35:28 +0530 Subject: [PATCH 36/60] chore(UAE VAT 201): add puctuation --- erpnext/regional/report/uae_vat_201/uae_vat_201.py | 2 +- erpnext/regional/united_arab_emirates/setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index 82032461ce7..5bed0e24636 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -102,7 +102,7 @@ def append_vat_on_sales(data, filters): return emirates, amounts_by_emirate def standard_rated_expenses_emiratewise(data, filters): - """Append emiratewise standard rated expenses and vat""" + """Append emiratewise standard rated expenses and vat.""" total_emiratewise = get_total_emiratewise(filters) emirates = get_emirates() amounts_by_emirate = {} diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index efa39bd3c5d..fac6e270dbb 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -89,7 +89,7 @@ def make_custom_fields(): dict(fieldname='is_zero_rated', label='Is Zero Rated', fieldtype='Check', insert_after='tax_code', print_hide=1), - dict(fieldname='is_exempt', label='Is Exempt ', + dict(fieldname='is_exempt', label='Is Exempt', fieldtype='Check', insert_after='is_zero_rated', print_hide=1) ], From 0ac40c75aabbbe2ee31dfd0b4f4881e9846dcf6d Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Sun, 25 Oct 2020 01:16:06 +0530 Subject: [PATCH 37/60] chore(UAE VAT): update tesr dependencies --- erpnext/regional/report/uae_vat_201/test_uae_vat_201.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py index 68c163d5bc1..05bb701dc26 100644 --- a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py @@ -21,7 +21,7 @@ from erpnext.regional.report.uae_vat_201.uae_vat_201 import ( get_reverse_charge_recoverable_tax ) - +test_dependencies = ["Territory", "Customer Group", "Supplier Group", "Item"] class TestUaeVat201(TestCase): def setUp(self): From 0ceae0bd66e7bbd1f8af8f4b20bc50450fbc2202 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Sun, 25 Oct 2020 13:06:42 +0530 Subject: [PATCH 38/60] feat(UAE VAT 201): emirate customizable --- .../report/uae_vat_201/test_uae_vat_201.py | 79 +++++-------------- .../regional/united_arab_emirates/setup.py | 10 +-- 2 files changed, 23 insertions(+), 66 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py index 05bb701dc26..ceaa3b3dcb9 100644 --- a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py @@ -34,13 +34,12 @@ class TestUaeVat201(TestCase): make_company("_Test Company UAE VAT", "_TCUV") set_vat_accounts() - make_customers() + make_customer() make_supplier() create_warehouse("_Test UAE VAT Supplier Warehouse", company="_Test Company UAE VAT") - make_item("_Test UAE VAT Item", properties = {"is_zero_rated": 0, "is_exempt": 0}) make_item("_Test UAE VAT Zero Rated Item", properties = {"is_zero_rated": 1, "is_exempt": 0}) make_item("_Test UAE VAT Exempt Item", properties = {"is_zero_rated": 0, "is_exempt": 1}) @@ -122,64 +121,16 @@ def set_vat_accounts(): "doctype": "UAE VAT Settings", }).insert() -def make_customers(): - if not frappe.db.exists("Customer", "_Test Dubai Customer"): +def make_customer(): + if not frappe.db.exists("Customer", "_Test UAE Customer"): customer = frappe.get_doc({ "doctype": "Customer", - "customer_name": "_Test Dubai Customer", + "customer_name": "_Test UAE Customer", "customer_type": "Company", }) customer.insert() else: - customer = frappe.get_doc("Customer", "_Test Dubai Customer") - - if not frappe.db.exists("Customer", "_Test Sharjah Customer"): - customer = frappe.get_doc({ - "doctype": "Customer", - "customer_name": "_Test Sharjah Customer", - "customer_type": "Company", - }) - customer.insert() - else: - customer = frappe.get_doc("Customer", "_Test Sharjah Customer") - - if not frappe.db.exists('Address', '_Test Dubai Address'): - address = frappe.get_doc({ - "address_line1": "_Test Address Line 1", - "address_title": "_Test Dubai Address", - "address_type": "Billing", - "city": "_Test City", - "state": "Test State", - "country": "United Arab Emirates", - "doctype": "Address", - "emirate": "Dubai" - }).insert() - - address.append("links", { - "link_doctype": "Customer", - "link_name": "_Test Dubai Customer" - }) - - address.save() - - if not frappe.db.exists('Address', '_Test Sharjah Address'): - address = frappe.get_doc({ - "address_line1": "_Test Address Line 1", - "address_title": "_Test Sharjah Address", - "address_type": "Billing", - "city": "_Test City", - "state": "Test State", - "country": "United Arab Emirates", - "doctype": "Address", - "emirate": "Sharjah" - }).insert() - - address.append("links", { - "link_doctype": "Customer", - "link_name": "_Test Sharjah Customer" - }) - - address.save() + customer = frappe.get_doc("Customer", "_Test UAE Customer") def make_supplier(): @@ -230,7 +181,7 @@ def make_item(item_code, properties=None): def make_sales_invoices(): si = create_sales_invoice(company="_Test Company UAE VAT", - customer = '_Test Dubai Customer', + customer = '_Test UAE Customer', currency = 'AED', warehouse = 'Finished Goods - _TCUV', debit_to = 'Debtors - _TCUV', @@ -248,10 +199,11 @@ def make_sales_invoices(): "description": "VAT 5% @ 5.0", "rate": 5.0 }) + si.emirate = 'Dubai' si.submit() si = create_sales_invoice(company="_Test Company UAE VAT", - customer = '_Test Sharjah Customer', + customer = '_Test UAE Customer', currency = 'AED', warehouse = 'Finished Goods - _TCUV', debit_to = 'Debtors - _TCUV', @@ -262,6 +214,7 @@ def make_sales_invoices(): item = "_Test UAE VAT Item", do_not_save=1 ) + si.emirate = 'Sharjah' si.append("taxes", { "charge_type": "On Net Total", "account_head": "VAT 5% - _TCUV", @@ -272,7 +225,7 @@ def make_sales_invoices(): si.submit() si = create_sales_invoice(company="_Test Company UAE VAT", - customer = '_Test Dubai Customer', + customer = '_Test UAE Customer', currency = 'AED', warehouse = 'Finished Goods - _TCUV', debit_to = 'Debtors - _TCUV', @@ -286,6 +239,8 @@ def make_sales_invoices(): si.tourist_tax_return = 2 + si.emirate = 'Dubai' + si.append("taxes", { "charge_type": "On Net Total", "account_head": "VAT 5% - _TCUV", @@ -296,7 +251,7 @@ def make_sales_invoices(): si.submit() si = create_sales_invoice(company="_Test Company UAE VAT", - customer = '_Test Sharjah Customer', + customer = '_Test UAE Customer', currency = 'AED', warehouse = 'Finished Goods - _TCUV', debit_to = 'Debtors - _TCUV', @@ -305,10 +260,13 @@ def make_sales_invoices(): cost_center = 'Main - _TCUV', sales_taxes_and_charges_template = "UAE VAT 5% - _TCUV", item = "_Test UAE VAT Zero Rated Item", + do_not_save=1 ) + si.emirate = 'Sharjah' + si.submit() si = create_sales_invoice(company="_Test Company UAE VAT", - customer = '_Test Sharjah Customer', + customer = '_Test UAE Customer', currency = 'AED', warehouse = 'Finished Goods - _TCUV', debit_to = 'Debtors - _TCUV', @@ -317,7 +275,10 @@ def make_sales_invoices(): cost_center = 'Main - _TCUV', sales_taxes_and_charges_template = "UAE VAT 5% - _TCUV", item = "_Test UAE VAT Exempt Item", + do_not_save=1 ) + si.emirate = 'Sharjah' + si.submit() def create_purchase_invoices(): diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index fac6e270dbb..7f890d68673 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -56,10 +56,10 @@ def make_custom_fields(): dict(fieldname='customer_name_in_arabic', label='Customer Name in Arabic', fieldtype='Read Only', insert_after='customer_name', fetch_from='customer.customer_name_in_arabic', print_hide=1), - dict(fieldname='emirate', label='Emirate', insert_after='customer_address', - fieldtype='Read Only', fetch_from='customer_address.emirate'), + dict(fieldname='emirate', label='Emirate', insert_after='permit_no', fieldtype='Select', + options='\nAbu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain'), dict(fieldname='tourist_tax_return', label='Tax Refund provided to Tourists (AED)', - insert_after='permit_no', fieldtype='Currency', print_hide=1, default='0'), + insert_after='emirate', fieldtype='Currency', print_hide=1, default='0'), ] invoice_item_fields = [ @@ -101,10 +101,6 @@ def make_custom_fields(): dict(fieldname='supplier_name_in_arabic', label='Supplier Name in Arabic', fieldtype='Data', insert_after='supplier_name'), ], - 'Address': [ - dict(fieldname='emirate', label='Emirate', fieldtype='Select', insert_after='state', - options='Abu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain') - ], 'Purchase Invoice': purchase_invoice_fields + invoice_fields, 'Purchase Order': purchase_invoice_fields + invoice_fields, 'Purchase Receipt': purchase_invoice_fields + invoice_fields, From 5953acab8bb4a9efbbca7649db62d3fce38779f0 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Sun, 25 Oct 2020 15:43:21 +0530 Subject: [PATCH 39/60] chore(UAE VAT 201): cleanup --- .../report/uae_vat_201/test_uae_vat_201.py | 40 +------------------ .../regional/united_arab_emirates/setup.py | 3 +- 2 files changed, 2 insertions(+), 41 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py index ceaa3b3dcb9..3b5d388e25c 100644 --- a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py @@ -11,14 +11,10 @@ from erpnext.regional.report.uae_vat_201.uae_vat_201 import ( get_total_emiratewise, get_tourist_tax_return_total, get_tourist_tax_return_tax, - get_reverse_charge_total, - get_reverse_charge_tax, get_zero_rated_total, get_exempt_total, get_standard_rated_expenses_total, get_standard_rated_expenses_tax, - get_reverse_charge_recoverable_total, - get_reverse_charge_recoverable_tax ) test_dependencies = ["Territory", "Customer Group", "Supplier Group", "Item"] @@ -62,17 +58,12 @@ class TestUaeVat201(TestCase): self.assertEqual(amounts_by_emirate["Sharjah"]["raw_vat_amount"],5) self.assertEqual(amounts_by_emirate["Dubai"]["raw_amount"],200) self.assertEqual(amounts_by_emirate["Dubai"]["raw_vat_amount"],10) - self.assertEqual(get_tourist_tax_return_total(filters),100) self.assertEqual(get_tourist_tax_return_tax(filters),2) - self.assertEqual(get_reverse_charge_total(filters),250) - self.assertEqual(get_reverse_charge_tax(filters),12.5) self.assertEqual(get_zero_rated_total(filters),100) self.assertEqual(get_exempt_total(filters),100) self.assertEqual(get_standard_rated_expenses_total(filters),250) self.assertEqual(get_standard_rated_expenses_tax(filters),1) - self.assertEqual(get_reverse_charge_recoverable_total(filters),250) - self.assertEqual(get_reverse_charge_recoverable_tax(filters),12.5) def make_company(company_name, abbr): if not frappe.db.exists("Company", company_name): @@ -304,33 +295,4 @@ def create_purchase_invoices(): pi.recoverable_standard_rated_expenses = 1 - pi.submit() - - pi = make_purchase_invoice( - company="_Test Company UAE VAT", - supplier = '_Test UAE Supplier', - supplier_warehouse = '_Test UAE VAT Supplier Warehouse - _TCUV', - warehouse = '_Test UAE VAT Supplier Warehouse - _TCUV', - currency = 'AED', - cost_center = 'Main - _TCUV', - expense_account = 'Cost of Goods Sold - _TCUV', - item = "_Test UAE VAT Item", - do_not_save=1, - uom = "Nos" - ) - - pi.append("taxes", { - "charge_type": "On Net Total", - "account_head": "VAT 5% - _TCUV", - "cost_center": "Main - _TCUV", - "description": "VAT 5% @ 5.0", - "rate": 5.0 - }) - - pi.reverse_charge = "Y" - - pi.recoverable_reverse_charge = 100 - - pi.submit() - - + pi.submit() \ No newline at end of file diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index 7f890d68673..c1188d6ccd8 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -39,8 +39,7 @@ def make_custom_fields(): fieldtype='Read Only', insert_after='supplier_name', fetch_from='supplier.supplier_name_in_arabic', print_hide=1), dict(fieldname='recoverable_standard_rated_expenses', label='Recoverable Standard Rated Expenses (AED)', - insert_after='permit_no', fieldtype='Currency', print_hide=1, default='0', - depends_on="eval:doc.reverse_charge=='N'",), + insert_after='permit_no', fieldtype='Currency', print_hide=1, default='0'), dict(fieldname='reverse_charge', label='Reverse Charge Applicable', fieldtype='Select', insert_after='recoverable_standard_rated_expenses', print_hide=1, options='Y\nN', default='N'), From 81f2efd9b04b307af66b45cf69ca8a06021617f5 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Wed, 28 Oct 2020 10:28:25 +0530 Subject: [PATCH 40/60] chore(UAE VAT 201): Rename emirate to vat emirate --- .../regional/report/uae_vat_201/test_uae_vat_201.py | 10 +++++----- erpnext/regional/report/uae_vat_201/uae_vat_201.py | 4 ++-- erpnext/regional/united_arab_emirates/setup.py | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py index 3b5d388e25c..3037a076983 100644 --- a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py @@ -190,7 +190,7 @@ def make_sales_invoices(): "description": "VAT 5% @ 5.0", "rate": 5.0 }) - si.emirate = 'Dubai' + si.vat_emirate = 'Dubai' si.submit() si = create_sales_invoice(company="_Test Company UAE VAT", @@ -205,7 +205,7 @@ def make_sales_invoices(): item = "_Test UAE VAT Item", do_not_save=1 ) - si.emirate = 'Sharjah' + si.vat_emirate = 'Sharjah' si.append("taxes", { "charge_type": "On Net Total", "account_head": "VAT 5% - _TCUV", @@ -230,7 +230,7 @@ def make_sales_invoices(): si.tourist_tax_return = 2 - si.emirate = 'Dubai' + si.vat_emirate = 'Dubai' si.append("taxes", { "charge_type": "On Net Total", @@ -253,7 +253,7 @@ def make_sales_invoices(): item = "_Test UAE VAT Zero Rated Item", do_not_save=1 ) - si.emirate = 'Sharjah' + si.vat_emirate = 'Sharjah' si.submit() si = create_sales_invoice(company="_Test Company UAE VAT", @@ -268,7 +268,7 @@ def make_sales_invoices(): item = "_Test UAE VAT Exempt Item", do_not_save=1 ) - si.emirate = 'Sharjah' + si.vat_emirate = 'Sharjah' si.submit() def create_purchase_invoices(): diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index 5bed0e24636..ddbdf96c6a0 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -147,9 +147,9 @@ def append_data(data, no, legend, amount, vat_amount): def get_total_emiratewise(filters): """Returns Emiratewise Amount and Taxes.""" return frappe.db.sql(f""" - select emirate, sum(total), sum(total_taxes_and_charges) from `tabSales Invoice` + select vat_emirate as emirate, sum(total), sum(total_taxes_and_charges) from `tabSales Invoice` where docstatus = 1 {get_conditions(filters)} - group by `tabSales Invoice`.emirate; + group by `tabSales Invoice`.vat_emirate; """, filters) def get_emirates(): diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index c1188d6ccd8..62156e46be5 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -55,10 +55,10 @@ def make_custom_fields(): dict(fieldname='customer_name_in_arabic', label='Customer Name in Arabic', fieldtype='Read Only', insert_after='customer_name', fetch_from='customer.customer_name_in_arabic', print_hide=1), - dict(fieldname='emirate', label='Emirate', insert_after='permit_no', fieldtype='Select', + dict(fieldname='vat_emirate', label='VAT Emirate', insert_after='permit_no', fieldtype='Select', options='\nAbu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain'), dict(fieldname='tourist_tax_return', label='Tax Refund provided to Tourists (AED)', - insert_after='emirate', fieldtype='Currency', print_hide=1, default='0'), + insert_after='vat_emirate', fieldtype='Currency', print_hide=1, default='0'), ] invoice_item_fields = [ From 2c00549dfe9d87ed1b21a600df7275d0459c86c8 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Wed, 28 Oct 2020 22:54:56 +0530 Subject: [PATCH 41/60] refactor(UAE VAT 201): Use frappe api instead sql --- .../report/uae_vat_201/uae_vat_201.py | 152 ++++++++++-------- 1 file changed, 86 insertions(+), 66 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index ddbdf96c6a0..744eb87d555 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -146,11 +146,14 @@ def append_data(data, no, legend, amount, vat_amount): def get_total_emiratewise(filters): """Returns Emiratewise Amount and Taxes.""" - return frappe.db.sql(f""" - select vat_emirate as emirate, sum(total), sum(total_taxes_and_charges) from `tabSales Invoice` - where docstatus = 1 {get_conditions(filters)} - group by `tabSales Invoice`.vat_emirate; - """, filters) + query_filters = get_filters(filters) + query_filters['docstatus'] = ['=', 1] + return frappe.db.get_list('Sales Invoice', + filters = query_filters, + fields = ['vat_emirate as emirate','sum(total)', 'sum(total_taxes_and_charges)'], + group_by='vat_emirate', + as_list=True + ) def get_emirates(): """Returns a List of emirates in the order that they are to be displayed.""" @@ -174,28 +177,40 @@ def get_conditions(filters): conditions += opts[1] return conditions +def get_filters(filters): + """The conditions to be used to filter data to calculate the total sale.""" + query_filters = {} + if filters.get("company"): + query_filters["company"] = ['=', filters['company']] + if filters.get("from_date"): + query_filters["posting_date"] = ['>=', filters['from_date']] + if filters.get("from_date"): + query_filters["posting_date"] = ['<=', filters['to_date']] + return query_filters + def get_reverse_charge_total(filters): """Returns the sum of the total of each Purchase invoice made.""" - conditions = get_conditions(filters) - return frappe.db.sql(""" - select sum(total) from - `tabPurchase Invoice` - where - reverse_charge = "Y" - and docstatus = 1 {where_conditions} ; - """.format(where_conditions=conditions), filters)[0][0] or 0 + query_filters = get_filters(filters) + query_filters['reverse_charge'] = ['=', 'Y'] + query_filters['docstatus'] = ['=', 1] + return frappe.db.get_list('Purchase Invoice', + filters = query_filters, + fields = ['sum(total)'], + as_list=True, + limit = 1 + )[0][0] or 0 def get_reverse_charge_tax(filters): """Returns the sum of the tax of each Purchase invoice made.""" conditions = get_conditions_join(filters) return frappe.db.sql(""" select sum(debit) from - `tabPurchase Invoice` inner join `tabGL Entry` - on `tabGL Entry`.voucher_no = `tabPurchase Invoice`.name + `tabPurchase Invoice` p inner join `tabGL Entry` gl + on gl.voucher_no = p.name where - `tabPurchase Invoice`.reverse_charge = "Y" - and `tabPurchase Invoice`.docstatus = 1 - and `tabGL Entry`.docstatus = 1 + p.reverse_charge = "Y" + and p.docstatus = 1 + and gl.docstatus = 1 and account in (select account from `tabUAE VAT Account` where parent=%(company)s) {where_conditions} ; """.format(where_conditions=conditions), filters)[0][0] or 0 @@ -212,75 +227,80 @@ def get_conditions_join(filters): def get_reverse_charge_recoverable_total(filters): """Returns the sum of the total of each Purchase invoice made with recoverable reverse charge.""" - conditions = get_conditions(filters) - return frappe.db.sql(""" - select sum(total) from - `tabPurchase Invoice` - where - reverse_charge = "Y" - and recoverable_reverse_charge > 0 - and docstatus = 1 {where_conditions} ; - """.format(where_conditions=conditions), filters)[0][0] or 0 + query_filters = get_filters(filters) + query_filters['reverse_charge'] = ['=', 'Y'] + query_filters['recoverable_reverse_charge'] = ['>', '0'] + query_filters['docstatus'] = ['=', 1] + return frappe.db.get_list('Purchase Invoice', + filters = query_filters, + fields = ['sum(total)'], + as_list=True, + limit = 1 + )[0][0] or 0 def get_reverse_charge_recoverable_tax(filters): """Returns the sum of the tax of each Purchase invoice made.""" conditions = get_conditions_join(filters) return frappe.db.sql(""" - select sum(debit * `tabPurchase Invoice`.recoverable_reverse_charge / 100) from - `tabPurchase Invoice` inner join `tabGL Entry` - on `tabGL Entry`.voucher_no = `tabPurchase Invoice`.name + select sum(debit * p.recoverable_reverse_charge / 100) from + `tabPurchase Invoice` p inner join `tabGL Entry` gl + on gl.voucher_no = p.name where - `tabPurchase Invoice`.reverse_charge = "Y" - and `tabPurchase Invoice`.docstatus = 1 - and `tabPurchase Invoice`.recoverable_reverse_charge > 0 - and `tabGL Entry`.docstatus = 1 + p.reverse_charge = "Y" + and p.docstatus = 1 + and p.recoverable_reverse_charge > 0 + and gl.docstatus = 1 and account in (select account from `tabUAE VAT Account` where parent=%(company)s) {where_conditions} ; """.format(where_conditions=conditions), filters)[0][0] or 0 def get_standard_rated_expenses_total(filters): """Returns the sum of the total of each Purchase invoice made with recoverable reverse charge.""" - conditions = get_conditions(filters) - return frappe.db.sql(""" - select sum(total) from - `tabPurchase Invoice` - where - recoverable_standard_rated_expenses > 0 - and docstatus = 1 {where_conditions} ; - """.format(where_conditions=conditions), filters)[0][0] or 0 + query_filters = get_filters(filters) + query_filters['recoverable_standard_rated_expenses'] = ['>', 0] + query_filters['docstatus'] = ['=', 1] + return frappe.db.get_list('Purchase Invoice', + filters = query_filters, + fields = ['sum(total)'], + as_list=True, + limit = 1 + )[0][0] or 0 def get_standard_rated_expenses_tax(filters): """Returns the sum of the tax of each Purchase invoice made.""" - conditions = get_conditions(filters) - return frappe.db.sql(""" - select sum(recoverable_standard_rated_expenses) from - `tabPurchase Invoice` - where - recoverable_standard_rated_expenses > 0 - and docstatus = 1 {where_conditions} ; - """.format(where_conditions=conditions), filters)[0][0] or 0 + query_filters = get_filters(filters) + query_filters['recoverable_standard_rated_expenses'] = ['>', 0] + query_filters['docstatus'] = ['=', 1] + return frappe.db.get_list('Purchase Invoice', + filters = query_filters, + fields = ['sum(recoverable_standard_rated_expenses)'], + as_list=True, + limit = 1 + )[0][0] or 0 def get_tourist_tax_return_total(filters): """Returns the sum of the total of each Sales invoice with non zero tourist_tax_return.""" - conditions = get_conditions(filters) - return frappe.db.sql(""" - select sum(total) from - `tabSales Invoice` - where - tourist_tax_return > 0 - and docstatus = 1 {where_conditions} ; - """.format(where_conditions=conditions), filters)[0][0] or 0 + query_filters = get_filters(filters) + query_filters['tourist_tax_return'] = ['>', 0] + query_filters['docstatus'] = ['=', 1] + return frappe.db.get_list('Sales Invoice', + filters = query_filters, + fields = ['sum(total)'], + as_list=True, + limit = 1 + )[0][0] or 0 def get_tourist_tax_return_tax(filters): """Returns the sum of the tax of each Sales invoice with non zero tourist_tax_return.""" - conditions = get_conditions(filters) - return frappe.db.sql(""" - select sum(tourist_tax_return) from - `tabSales Invoice` - where - tourist_tax_return > 0 - and docstatus = 1 {where_conditions} ; - """.format(where_conditions=conditions), filters)[0][0] or 0 + query_filters = get_filters(filters) + query_filters['tourist_tax_return'] = ['>', 0] + query_filters['docstatus'] = ['=', 1] + return frappe.db.get_list('Sales Invoice', + filters = query_filters, + fields = ['sum(tourist_tax_return)'], + as_list=True, + limit = 1 + )[0][0] or 0 def get_zero_rated_total(filters): """Returns the sum of each Sales Invoice Item Amount which is zero rated.""" From 08846f6b11d88a0cd81888dc7747d3da992cff16 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Wed, 28 Oct 2020 23:33:56 +0530 Subject: [PATCH 42/60] refactor(UAE VAT 201): replace cartesian product to inner joins --- .../report/uae_vat_201/uae_vat_201.py | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index 744eb87d555..ba6ff693619 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -9,7 +9,6 @@ def execute(filters=None): columns = get_columns() data, emirates, amounts_by_emirate = get_data(filters) chart = get_chart(emirates, amounts_by_emirate) - return columns, data, None, chart def get_columns(): @@ -50,7 +49,6 @@ def get_data(filters = None): append_vat_on_expenses(data, filters) return data, emirates, amounts_by_emirate - def get_chart(emirates, amounts_by_emirate): """Returns chart data.""" labels = [] @@ -167,16 +165,6 @@ def get_emirates(): 'Fujairah' ] -def get_conditions(filters): - """The conditions to be used to filter data to calculate the total sale.""" - conditions = "" - for opts in (("company", " and company=%(company)s"), - ("from_date", " and posting_date>=%(from_date)s"), - ("to_date", " and posting_date<=%(to_date)s")): - if filters.get(opts[0]): - conditions += opts[1] - return conditions - def get_filters(filters): """The conditions to be used to filter data to calculate the total sale.""" query_filters = {} @@ -215,16 +203,6 @@ def get_reverse_charge_tax(filters): {where_conditions} ; """.format(where_conditions=conditions), filters)[0][0] or 0 -def get_conditions_join(filters): - """The conditions to be used to filter data to calculate the total vat.""" - conditions = "" - for opts in (("company", " and `tabPurchase Invoice`.company=%(company)s"), - ("from_date", " and `tabPurchase Invoice`.posting_date>=%(from_date)s"), - ("to_date", " and `tabPurchase Invoice`.posting_date<=%(to_date)s")): - if filters.get(opts[0]): - conditions += opts[1] - return conditions - def get_reverse_charge_recoverable_total(filters): """Returns the sum of the total of each Purchase invoice made with recoverable reverse charge.""" query_filters = get_filters(filters) @@ -254,6 +232,16 @@ def get_reverse_charge_recoverable_tax(filters): {where_conditions} ; """.format(where_conditions=conditions), filters)[0][0] or 0 +def get_conditions_join(filters): + """The conditions to be used to filter data to calculate the total vat.""" + conditions = "" + for opts in (("company", " and `tabPurchase Invoice`.company=%(company)s"), + ("from_date", " and `tabPurchase Invoice`.posting_date>=%(from_date)s"), + ("to_date", " and `tabPurchase Invoice`.posting_date<=%(to_date)s")): + if filters.get(opts[0]): + conditions += opts[1] + return conditions + def get_standard_rated_expenses_total(filters): """Returns the sum of the total of each Purchase invoice made with recoverable reverse charge.""" query_filters = get_filters(filters) @@ -307,8 +295,9 @@ def get_zero_rated_total(filters): conditions = get_conditions(filters) return frappe.db.sql(""" select sum(i.base_amount) as total from - `tabSales Invoice Item` i, `tabSales Invoice` s - where s.docstatus = 1 and i.parent = s.name and i.is_zero_rated = 1 + `tabSales Invoice Item` i inner join `tabSales Invoice` s + on i.parent = s.name + where s.docstatus = 1 and i.is_zero_rated = 1 {where_conditions} ; """.format(where_conditions=conditions), filters)[0][0] or 0 @@ -317,7 +306,18 @@ def get_exempt_total(filters): conditions = get_conditions(filters) return frappe.db.sql(""" select sum(i.base_amount) as total from - `tabSales Invoice Item` i, `tabSales Invoice` s - where s.docstatus = 1 and i.parent = s.name and i.is_exempt = 1 + `tabSales Invoice Item` i inner join `tabSales Invoice` s + on i.parent = s.name + where s.docstatus = 1 and i.is_exempt = 1 {where_conditions} ; - """.format(where_conditions=conditions), filters)[0][0] or 0 \ No newline at end of file + """.format(where_conditions=conditions), filters)[0][0] or 0 + +def get_conditions(filters): + """The conditions to be used to filter data to calculate the total sale.""" + conditions = "" + for opts in (("company", " and company=%(company)s"), + ("from_date", " and posting_date>=%(from_date)s"), + ("to_date", " and posting_date<=%(to_date)s")): + if filters.get(opts[0]): + conditions += opts[1] + return conditions \ No newline at end of file From bf261a6c394569ec34874a28eff7be511e67ba88 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Thu, 29 Oct 2020 00:07:52 +0530 Subject: [PATCH 43/60] fix(UAE VAT 201): fix helper --- erpnext/regional/report/uae_vat_201/uae_vat_201.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index ba6ff693619..758da4205a1 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -235,9 +235,9 @@ def get_reverse_charge_recoverable_tax(filters): def get_conditions_join(filters): """The conditions to be used to filter data to calculate the total vat.""" conditions = "" - for opts in (("company", " and `tabPurchase Invoice`.company=%(company)s"), - ("from_date", " and `tabPurchase Invoice`.posting_date>=%(from_date)s"), - ("to_date", " and `tabPurchase Invoice`.posting_date<=%(to_date)s")): + for opts in (("company", " and p.company=%(company)s"), + ("from_date", " and p.posting_date>=%(from_date)s"), + ("to_date", " and p.posting_date<=%(to_date)s")): if filters.get(opts[0]): conditions += opts[1] return conditions From eb3084b072654573ff4dd3ad97590f15878e48b0 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Thu, 29 Oct 2020 09:52:17 +0530 Subject: [PATCH 44/60] refactor(UAE VAT 201): break functions --- .../report/uae_vat_201/uae_vat_201.py | 13 +++++++ .../regional/united_arab_emirates/utils.py | 38 ++++++++++--------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index 758da4205a1..216762bc8da 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -113,6 +113,7 @@ def standard_rated_expenses_emiratewise(data, filters): "amount": frappe.format(amount, 'Currency'), "vat_amount": frappe.format(vat, 'Currency'), } + amounts_by_emirate = append_emiratewise_expenses(data, emirates, amounts_by_emirate) for d, emirate in enumerate(emirates, 97): if emirate in amounts_by_emirate: @@ -125,6 +126,18 @@ def standard_rated_expenses_emiratewise(data, filters): frappe.format(0, 'Currency'), frappe.format(0, 'Currency')) return emirates, amounts_by_emirate +def append_emiratewise_expenses(data, emirates, amounts_by_emirate): + """Append emiratewise standard rated expenses and vat.""" + for d, emirate in enumerate(emirates, 97): + if emirate in amounts_by_emirate: + amounts_by_emirate[emirate]["no"] = _('1{0}').format(chr(d)) + amounts_by_emirate[emirate]["legend"] = _('Standard rated supplies in {0}').format(emirate) + data.append(amounts_by_emirate[emirate]) + else: + append_data(data, _('1{0}').format(chr(d)), + _('Standard rated supplies in {0}').format(emirate), + frappe.format(0, 'Currency'), frappe.format(0, 'Currency')) + return amounts_by_emirate def append_vat_on_expenses(data, filters): """Appends Expenses and All Other Inputs.""" diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index 7edc2b6720a..7430db4fce0 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -123,25 +123,29 @@ def make_regional_gl_entries(gl_entries, doc): 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) - ) + gl_entries = make_gl_entry(tax, gl_entries, doc, tax_accounts) return gl_entries +def make_gl_entry(tax, gl_entries, doc, tax_accounts): + 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 + + def validate_returns(doc, method): """Standard Rated expenses should not be set when Reverse Charge Applicable is set.""" country = frappe.get_cached_value('Company', doc.company, 'country') From 55c78b17bab76b9feb6aa5bb870858ad9e7df93c Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Thu, 29 Oct 2020 12:43:43 +0530 Subject: [PATCH 45/60] fix(UAE VAT 201): change desk page record --- erpnext/accounts/desk_page/accounting/accounting.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/desk_page/accounting/accounting.json b/erpnext/accounts/desk_page/accounting/accounting.json index db012549193..64e2b246a70 100644 --- a/erpnext/accounts/desk_page/accounting/accounting.json +++ b/erpnext/accounts/desk_page/accounting/accounting.json @@ -83,7 +83,7 @@ { "hidden": 0, "label": "Value-Added Tax (VAT UAE)", - "links": "[\n {\n \"label\": \"UAE VAT Setting\",\n \"name\": \"UAE VAT Setting\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"UAE VAT 201\",\n \"name\": \"UAE VAT 201\",\n \"type\": \"report\"\n }\n]" + "links": "[\n {\n \"label\": \"UAE VAT Settings\",\n \"name\": \"UAE VAT Settings\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"UAE VAT 201\",\n \"name\": \"UAE VAT 201\",\n \"type\": \"report\"\n }\n]" } ], "category": "Modules", @@ -158,4 +158,4 @@ "type": "Dashboard" } ] -} \ No newline at end of file +} From f116fbf84d9e4ec6c6d8694463faa96d0e7c1ee0 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Mon, 2 Nov 2020 10:27:54 +0530 Subject: [PATCH 46/60] refactor(UAE VAT 201): Update erpnext/regional/report/uae_vat_201/test_uae_vat_201.py Co-authored-by: Shivam Mishra --- erpnext/regional/report/uae_vat_201/test_uae_vat_201.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py index 3037a076983..70c6b74f5ed 100644 --- a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py @@ -15,7 +15,7 @@ from erpnext.regional.report.uae_vat_201.uae_vat_201 import ( get_exempt_total, get_standard_rated_expenses_total, get_standard_rated_expenses_tax, - ) +) test_dependencies = ["Territory", "Customer Group", "Supplier Group", "Item"] @@ -295,4 +295,4 @@ def create_purchase_invoices(): pi.recoverable_standard_rated_expenses = 1 - pi.submit() \ No newline at end of file + pi.submit() From be7a4c8b0aaf5d33e23bbb6f635f47484425637d Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Mon, 2 Nov 2020 10:28:14 +0530 Subject: [PATCH 47/60] refactor(UAE VAT 201): Update erpnext/regional/report/uae_vat_201/test_uae_vat_201.py Co-authored-by: Shivam Mishra --- erpnext/regional/report/uae_vat_201/test_uae_vat_201.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py index 70c6b74f5ed..84db9146cc2 100644 --- a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py @@ -95,8 +95,10 @@ def set_vat_accounts(): fields=["name"], filters = { "company": "_Test Company UAE VAT", - "is_group":0, - "account_type": "Tax"}) + "is_group": 0, + "account_type": "Tax" + } + ) uae_vat_accounts = [] for d in vat_accounts: From 46265d3fc7e1101cea4960e5b593b393ada9deb7 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Mon, 2 Nov 2020 10:28:41 +0530 Subject: [PATCH 48/60] refactor(UAE VAT 201): Update erpnext/regional/report/uae_vat_201/test_uae_vat_201.py Co-authored-by: Shivam Mishra --- .../regional/report/uae_vat_201/test_uae_vat_201.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py index 84db9146cc2..75146528944 100644 --- a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py @@ -48,12 +48,12 @@ class TestUaeVat201(TestCase): filters = {"company": "_Test Company UAE VAT"} total_emiratewise = get_total_emiratewise(filters) amounts_by_emirate = {} - for d in total_emiratewise: - emirate, amount, vat= d + for data in total_emiratewise: + emirate, amount, vat = data amounts_by_emirate[emirate] = { - "raw_amount": amount, - "raw_vat_amount": vat, - } + "raw_amount": amount, + "raw_vat_amount": vat, + } self.assertEqual(amounts_by_emirate["Sharjah"]["raw_amount"],300) self.assertEqual(amounts_by_emirate["Sharjah"]["raw_vat_amount"],5) self.assertEqual(amounts_by_emirate["Dubai"]["raw_amount"],200) From 7b771d139c66ce2251941349ffb4e4db88ce47c9 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Mon, 2 Nov 2020 10:29:14 +0530 Subject: [PATCH 49/60] refactor(UAE VAT 201): Update erpnext/regional/report/uae_vat_201/test_uae_vat_201.py Co-authored-by: Shivam Mishra --- erpnext/regional/report/uae_vat_201/test_uae_vat_201.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py index 75146528944..5fdb2645f70 100644 --- a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py @@ -101,12 +101,11 @@ def set_vat_accounts(): ) uae_vat_accounts = [] - for d in vat_accounts: - uae_vat_accounts.append( - { + for account in vat_accounts: + uae_vat_accounts.append({ "doctype": "UAE VAT Account", - "account":d.name - }) + "account": account.name + }) frappe.get_doc({ "company": "_Test Company UAE VAT", From d322181fd7d2d6cce9301b41094b314803ce7973 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Mon, 2 Nov 2020 10:29:38 +0530 Subject: [PATCH 50/60] refactor(UAE VAT 201): Update erpnext/regional/report/uae_vat_201/uae_vat_201.py Co-authored-by: Shivam Mishra --- .../regional/report/uae_vat_201/uae_vat_201.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index 216762bc8da..201ddf63f5b 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -65,14 +65,14 @@ def get_chart(emirates, amounts_by_emirate): datasets.append({'name': _('Vat Amount (AED)'), 'values': vat_amount}) chart = { - "data": { - 'labels': labels, - 'datasets': datasets - } + "type": "bar", + "fieldtype": "Currency" + "data": { + 'labels': labels, + 'datasets': datasets } - - chart["type"] = "bar" - chart["fieldtype"] = "Currency" + } + return chart def append_vat_on_sales(data, filters): @@ -333,4 +333,4 @@ def get_conditions(filters): ("to_date", " and posting_date<=%(to_date)s")): if filters.get(opts[0]): conditions += opts[1] - return conditions \ No newline at end of file + return conditions From c53237f5e0177a5e2a5aef39e476a58077067e9b Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Mon, 2 Nov 2020 11:02:41 +0530 Subject: [PATCH 51/60] refactor(UAE VAT 201): solve syntax errors --- .../report/uae_vat_201/uae_vat_201.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index 201ddf63f5b..f641e652a6b 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -66,13 +66,13 @@ def get_chart(emirates, amounts_by_emirate): chart = { "type": "bar", - "fieldtype": "Currency" + "fieldtype": "Currency", "data": { 'labels': labels, 'datasets': datasets } } - + return chart def append_vat_on_sales(data, filters): @@ -89,14 +89,14 @@ def append_vat_on_sales(data, filters): frappe.format(get_reverse_charge_total(filters), 'Currency'), frappe.format(get_reverse_charge_tax(filters), 'Currency')) - append_data(data, '4', _('Zero Rated'), + append_data(data, '4', _('Zero Rated'), frappe.format(get_zero_rated_total(filters), 'Currency'), "-") append_data(data, '5', _('Exempt Supplies'), frappe.format(get_exempt_total(filters), 'Currency'),"-") append_data(data, '', '', '', '') - + return emirates, amounts_by_emirate def standard_rated_expenses_emiratewise(data, filters): @@ -159,7 +159,7 @@ def get_total_emiratewise(filters): """Returns Emiratewise Amount and Taxes.""" query_filters = get_filters(filters) query_filters['docstatus'] = ['=', 1] - return frappe.db.get_list('Sales Invoice', + return frappe.db.get_list('Sales Invoice', filters = query_filters, fields = ['vat_emirate as emirate','sum(total)', 'sum(total_taxes_and_charges)'], group_by='vat_emirate', @@ -194,7 +194,7 @@ def get_reverse_charge_total(filters): query_filters = get_filters(filters) query_filters['reverse_charge'] = ['=', 'Y'] query_filters['docstatus'] = ['=', 1] - return frappe.db.get_list('Purchase Invoice', + return frappe.db.get_list('Purchase Invoice', filters = query_filters, fields = ['sum(total)'], as_list=True, @@ -222,7 +222,7 @@ def get_reverse_charge_recoverable_total(filters): query_filters['reverse_charge'] = ['=', 'Y'] query_filters['recoverable_reverse_charge'] = ['>', '0'] query_filters['docstatus'] = ['=', 1] - return frappe.db.get_list('Purchase Invoice', + return frappe.db.get_list('Purchase Invoice', filters = query_filters, fields = ['sum(total)'], as_list=True, @@ -260,7 +260,7 @@ def get_standard_rated_expenses_total(filters): query_filters = get_filters(filters) query_filters['recoverable_standard_rated_expenses'] = ['>', 0] query_filters['docstatus'] = ['=', 1] - return frappe.db.get_list('Purchase Invoice', + return frappe.db.get_list('Purchase Invoice', filters = query_filters, fields = ['sum(total)'], as_list=True, @@ -272,7 +272,7 @@ def get_standard_rated_expenses_tax(filters): query_filters = get_filters(filters) query_filters['recoverable_standard_rated_expenses'] = ['>', 0] query_filters['docstatus'] = ['=', 1] - return frappe.db.get_list('Purchase Invoice', + return frappe.db.get_list('Purchase Invoice', filters = query_filters, fields = ['sum(recoverable_standard_rated_expenses)'], as_list=True, @@ -284,7 +284,7 @@ def get_tourist_tax_return_total(filters): query_filters = get_filters(filters) query_filters['tourist_tax_return'] = ['>', 0] query_filters['docstatus'] = ['=', 1] - return frappe.db.get_list('Sales Invoice', + return frappe.db.get_list('Sales Invoice', filters = query_filters, fields = ['sum(total)'], as_list=True, @@ -296,7 +296,7 @@ def get_tourist_tax_return_tax(filters): query_filters = get_filters(filters) query_filters['tourist_tax_return'] = ['>', 0] query_filters['docstatus'] = ['=', 1] - return frappe.db.get_list('Sales Invoice', + return frappe.db.get_list('Sales Invoice', filters = query_filters, fields = ['sum(tourist_tax_return)'], as_list=True, From b0eca23485b9319754e33af11727605df2f97c82 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Mon, 2 Nov 2020 12:47:10 +0530 Subject: [PATCH 52/60] Refactor(UAE VAT 201): Fix fomatiing --- .../report/uae_vat_201/test_uae_vat_201.py | 184 +++++--------- .../report/uae_vat_201/uae_vat_201.py | 227 ++++++++++-------- .../regional/united_arab_emirates/utils.py | 22 +- 3 files changed, 201 insertions(+), 232 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py index 5fdb2645f70..b0a21de613d 100644 --- a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py @@ -8,8 +8,8 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sal from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse_account from erpnext.regional.report.uae_vat_201.uae_vat_201 import ( - get_total_emiratewise, - get_tourist_tax_return_total, + get_total_emiratewise, + get_tourist_tax_return_total, get_tourist_tax_return_tax, get_zero_rated_total, get_exempt_total, @@ -26,7 +26,6 @@ class TestUaeVat201(TestCase): frappe.db.sql("delete from `tabSales Invoice` where company='_Test Company UAE VAT'") frappe.db.sql("delete from `tabPurchase Invoice` where company='_Test Company UAE VAT'") - make_company("_Test Company UAE VAT", "_TCUV") set_vat_accounts() @@ -79,7 +78,6 @@ def make_company(company_name, abbr): else: company = frappe.get_doc("Company", company_name) - # indempotent company.create_default_warehouses() if not frappe.db.get_value("Cost Center", {"is_group": 0, "company": company.name}): @@ -95,7 +93,7 @@ def set_vat_accounts(): fields=["name"], filters = { "company": "_Test Company UAE VAT", - "is_group": 0, + "is_group": 0, "account_type": "Tax" } ) @@ -103,7 +101,7 @@ def set_vat_accounts(): uae_vat_accounts = [] for account in vat_accounts: uae_vat_accounts.append({ - "doctype": "UAE VAT Account", + "doctype": "UAE VAT Account", "account": account.name }) @@ -125,7 +123,6 @@ def make_customer(): customer = frappe.get_doc("Customer", "_Test UAE Customer") def make_supplier(): - if not frappe.db.exists("Supplier", "_Test UAE Supplier"): frappe.get_doc({ "supplier_group": "Local", @@ -140,15 +137,15 @@ def create_warehouse(warehouse_name, properties=None, company=None): warehouse_id = erpnext.encode_company_abbr(warehouse_name, company) if not frappe.db.exists("Warehouse", warehouse_id): - w = frappe.new_doc("Warehouse") - w.warehouse_name = warehouse_name - w.parent_warehouse = "All Warehouses - _TCUV" - w.company = company - w.account = get_warehouse_account(warehouse_name, company) + warehouse = frappe.new_doc("Warehouse") + warehouse.warehouse_name = warehouse_name + warehouse.parent_warehouse = "All Warehouses - _TCUV" + warehouse.company = company + warehouse.account = get_warehouse_account(warehouse_name, company) if properties: - w.update(properties) - w.save() - return w.name + warehouse.update(properties) + warehouse.save() + return warehouse.name else: return warehouse_id @@ -166,13 +163,15 @@ def make_item(item_code, properties=None): if properties: item.update(properties) - + item.insert() return item def make_sales_invoices(): - si = create_sales_invoice(company="_Test Company UAE VAT", + def make_sales_invoices_wrapper(emirate, item, tax = True, tourist_tax= False): + si = create_sales_invoice( + company="_Test Company UAE VAT", customer = '_Test UAE Customer', currency = 'AED', warehouse = 'Finished Goods - _TCUV', @@ -180,119 +179,60 @@ def make_sales_invoices(): income_account = 'Sales - _TCUV', expense_account = 'Cost of Goods Sold - _TCUV', cost_center = 'Main - _TCUV', - sales_taxes_and_charges_template = "UAE VAT 5% - _TCUV", - item = "_Test UAE VAT Item", + item = item, do_not_save=1 ) - si.append("taxes", { - "charge_type": "On Net Total", - "account_head": "VAT 5% - _TCUV", - "cost_center": "Main - _TCUV", - "description": "VAT 5% @ 5.0", - "rate": 5.0 - }) - si.vat_emirate = 'Dubai' - si.submit() + si.vat_emirate = emirate + if tax: + si.append( + "taxes", { + "charge_type": "On Net Total", + "account_head": "VAT 5% - _TCUV", + "cost_center": "Main - _TCUV", + "description": "VAT 5% @ 5.0", + "rate": 5.0 + } + ) + if tourist_tax: + si.tourist_tax_return = 2 + si.submit() - si = create_sales_invoice(company="_Test Company UAE VAT", - customer = '_Test UAE Customer', - currency = 'AED', - warehouse = 'Finished Goods - _TCUV', - debit_to = 'Debtors - _TCUV', - income_account = 'Sales - _TCUV', - expense_account = 'Cost of Goods Sold - _TCUV', - cost_center = 'Main - _TCUV', - sales_taxes_and_charges_template = "UAE VAT 5% - _TCUV", - item = "_Test UAE VAT Item", - do_not_save=1 - ) - si.vat_emirate = 'Sharjah' - si.append("taxes", { - "charge_type": "On Net Total", - "account_head": "VAT 5% - _TCUV", - "cost_center": "Main - _TCUV", - "description": "VAT 5% @ 5.0", - "rate": 5.0 - }) - si.submit() + #Define Item Names + uae_item = "_Test UAE VAT Item" + uae_exempt_item = "_Test UAE VAT Exempt Item" + uae_zero_rated_item = "_Test UAE VAT Zero Rated Item" - si = create_sales_invoice(company="_Test Company UAE VAT", - customer = '_Test UAE Customer', - currency = 'AED', - warehouse = 'Finished Goods - _TCUV', - debit_to = 'Debtors - _TCUV', - income_account = 'Sales - _TCUV', - expense_account = 'Cost of Goods Sold - _TCUV', - cost_center = 'Main - _TCUV', - sales_taxes_and_charges_template = "UAE VAT 5% - _TCUV", - item = "_Test UAE VAT Item", - do_not_save=1 - ) - - si.tourist_tax_return = 2 - - si.vat_emirate = 'Dubai' - - si.append("taxes", { - "charge_type": "On Net Total", - "account_head": "VAT 5% - _TCUV", - "cost_center": "Main - _TCUV", - "description": "VAT 5% @ 5.0", - "rate": 5.0 - }) - si.submit() - - si = create_sales_invoice(company="_Test Company UAE VAT", - customer = '_Test UAE Customer', - currency = 'AED', - warehouse = 'Finished Goods - _TCUV', - debit_to = 'Debtors - _TCUV', - income_account = 'Sales - _TCUV', - expense_account = 'Cost of Goods Sold - _TCUV', - cost_center = 'Main - _TCUV', - sales_taxes_and_charges_template = "UAE VAT 5% - _TCUV", - item = "_Test UAE VAT Zero Rated Item", - do_not_save=1 - ) - si.vat_emirate = 'Sharjah' - si.submit() - - si = create_sales_invoice(company="_Test Company UAE VAT", - customer = '_Test UAE Customer', - currency = 'AED', - warehouse = 'Finished Goods - _TCUV', - debit_to = 'Debtors - _TCUV', - income_account = 'Sales - _TCUV', - expense_account = 'Cost of Goods Sold - _TCUV', - cost_center = 'Main - _TCUV', - sales_taxes_and_charges_template = "UAE VAT 5% - _TCUV", - item = "_Test UAE VAT Exempt Item", - do_not_save=1 - ) - si.vat_emirate = 'Sharjah' - si.submit() + #Sales Invoice with standard rated expense in Dubai + make_sales_invoices_wrapper('Dubai', uae_item) + #Sales Invoice with standard rated expense in Sharjah + make_sales_invoices_wrapper('Sharjah', uae_item) + #Sales Invoice with Tourist Tax Return + make_sales_invoices_wrapper('Dubai', uae_item, True, True) + #Sales Invoice with Exempt Item + make_sales_invoices_wrapper('Sharjah', uae_exempt_item, False) + #Sales Invoice with Zero Rated Item + make_sales_invoices_wrapper('Sharjah', uae_zero_rated_item, False) def create_purchase_invoices(): - pi = make_purchase_invoice( - company="_Test Company UAE VAT", - supplier = '_Test UAE Supplier', - supplier_warehouse = '_Test UAE VAT Supplier Warehouse - _TCUV', - warehouse = '_Test UAE VAT Supplier Warehouse - _TCUV', - currency = 'AED', - cost_center = 'Main - _TCUV', - expense_account = 'Cost of Goods Sold - _TCUV', - item = "_Test UAE VAT Item", - do_not_save=1, - uom = "Nos" - ) + company="_Test Company UAE VAT", + supplier = '_Test UAE Supplier', + supplier_warehouse = '_Test UAE VAT Supplier Warehouse - _TCUV', + warehouse = '_Test UAE VAT Supplier Warehouse - _TCUV', + currency = 'AED', + cost_center = 'Main - _TCUV', + expense_account = 'Cost of Goods Sold - _TCUV', + item = "_Test UAE VAT Item", + do_not_save=1, + uom = "Nos" + ) pi.append("taxes", { - "charge_type": "On Net Total", - "account_head": "VAT 5% - _TCUV", - "cost_center": "Main - _TCUV", - "description": "VAT 5% @ 5.0", - "rate": 5.0 - }) + "charge_type": "On Net Total", + "account_head": "VAT 5% - _TCUV", + "cost_center": "Main - _TCUV", + "description": "VAT 5% @ 5.0", + "rate": 5.0 + }) pi.recoverable_standard_rated_expenses = 1 diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index f641e652a6b..78dcb367a4b 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -54,11 +54,11 @@ def get_chart(emirates, amounts_by_emirate): labels = [] amount = [] vat_amount = [] - for d in emirates: - if d in amounts_by_emirate: - amount.append(amounts_by_emirate[d]["raw_amount"]) - vat_amount.append(amounts_by_emirate[d]["raw_vat_amount"]) - labels.append(d) + for emirate in emirates: + if emirate in amounts_by_emirate: + amount.append(amounts_by_emirate[emirate]["raw_amount"]) + vat_amount.append(amounts_by_emirate[emirate]["raw_vat_amount"]) + labels.append(emirate) datasets = [] datasets.append({'name': _('Amount (AED)'), 'values': amount}) @@ -81,7 +81,8 @@ def append_vat_on_sales(data, filters): emirates, amounts_by_emirate = standard_rated_expenses_emiratewise(data, filters) - append_data(data, '2', _('Tax Refunds provided to Tourists under the Tax Refunds for Tourists Scheme'), + append_data(data, '2', + _('Tax Refunds provided to Tourists under the Tax Refunds for Tourists Scheme'), frappe.format((-1) * get_tourist_tax_return_total(filters), 'Currency'), frappe.format((-1) * get_tourist_tax_return_tax(filters), 'Currency')) @@ -104,37 +105,26 @@ def standard_rated_expenses_emiratewise(data, filters): total_emiratewise = get_total_emiratewise(filters) emirates = get_emirates() amounts_by_emirate = {} - for d in total_emiratewise: - emirate, amount, vat= d + for emirate, amount, vat in total_emiratewise: amounts_by_emirate[emirate] = { - "legend": emirate, - "raw_amount": amount, - "raw_vat_amount": vat, - "amount": frappe.format(amount, 'Currency'), - "vat_amount": frappe.format(vat, 'Currency'), - } + "legend": emirate, + "raw_amount": amount, + "raw_vat_amount": vat, + "amount": frappe.format(amount, 'Currency'), + "vat_amount": frappe.format(vat, 'Currency'), + } amounts_by_emirate = append_emiratewise_expenses(data, emirates, amounts_by_emirate) - - for d, emirate in enumerate(emirates, 97): - if emirate in amounts_by_emirate: - amounts_by_emirate[emirate]["no"] = _('1{0}').format(chr(d)) - amounts_by_emirate[emirate]["legend"] = _('Standard rated supplies in {0}').format(emirate) - data.append(amounts_by_emirate[emirate]) - else: - append_data(data, _('1{0}').format(chr(d)), - _('Standard rated supplies in {0}').format(emirate), - frappe.format(0, 'Currency'), frappe.format(0, 'Currency')) return emirates, amounts_by_emirate def append_emiratewise_expenses(data, emirates, amounts_by_emirate): """Append emiratewise standard rated expenses and vat.""" - for d, emirate in enumerate(emirates, 97): + for no, emirate in enumerate(emirates, 97): if emirate in amounts_by_emirate: - amounts_by_emirate[emirate]["no"] = _('1{0}').format(chr(d)) + amounts_by_emirate[emirate]["no"] = _('1{0}').format(chr(no)) amounts_by_emirate[emirate]["legend"] = _('Standard rated supplies in {0}').format(emirate) data.append(amounts_by_emirate[emirate]) else: - append_data(data, _('1{0}').format(chr(d)), + append_data(data, _('1{0}').format(chr(no)), _('Standard rated supplies in {0}').format(emirate), frappe.format(0, 'Currency'), frappe.format(0, 'Currency')) return amounts_by_emirate @@ -145,11 +135,9 @@ def append_vat_on_expenses(data, filters): append_data(data, '9', _('Standard Rated Expenses'), frappe.format(get_standard_rated_expenses_total(filters), 'Currency'), frappe.format(get_standard_rated_expenses_tax(filters), 'Currency')) - append_data(data, '10', _('Supplies subject to the reverse charge provision'), frappe.format(get_reverse_charge_recoverable_total(filters), 'Currency'), - frappe.format(get_reverse_charge_recoverable_tax(filters), 'Currency') -) + frappe.format(get_reverse_charge_recoverable_tax(filters), 'Currency')) def append_data(data, no, legend, amount, vat_amount): """Returns data with appended value.""" @@ -159,7 +147,7 @@ def get_total_emiratewise(filters): """Returns Emiratewise Amount and Taxes.""" query_filters = get_filters(filters) query_filters['docstatus'] = ['=', 1] - return frappe.db.get_list('Sales Invoice', + return frappe.db.get_all('Sales Invoice', filters = query_filters, fields = ['vat_emirate as emirate','sum(total)', 'sum(total_taxes_and_charges)'], group_by='vat_emirate', @@ -194,26 +182,30 @@ def get_reverse_charge_total(filters): query_filters = get_filters(filters) query_filters['reverse_charge'] = ['=', 'Y'] query_filters['docstatus'] = ['=', 1] - return frappe.db.get_list('Purchase Invoice', - filters = query_filters, - fields = ['sum(total)'], - as_list=True, - limit = 1 - )[0][0] or 0 + try: + return frappe.db.get_all('Purchase Invoice', + filters = query_filters, + fields = ['sum(total)'], + as_list=True, + limit = 1 + )[0][0] or 0 + except (IndexError, TypeError): + return 0 def get_reverse_charge_tax(filters): """Returns the sum of the tax of each Purchase invoice made.""" conditions = get_conditions_join(filters) return frappe.db.sql(""" select sum(debit) from - `tabPurchase Invoice` p inner join `tabGL Entry` gl - on gl.voucher_no = p.name + `tabPurchase Invoice` p inner join `tabGL Entry` gl + on + gl.voucher_no = p.name where - p.reverse_charge = "Y" - and p.docstatus = 1 - and gl.docstatus = 1 - and account in (select account from `tabUAE VAT Account` where parent=%(company)s) - {where_conditions} ; + p.reverse_charge = "Y" + and p.docstatus = 1 + and gl.docstatus = 1 + and account in (select account from `tabUAE VAT Account` where parent=%(company)s) + {where_conditions} ; """.format(where_conditions=conditions), filters)[0][0] or 0 def get_reverse_charge_recoverable_total(filters): @@ -222,27 +214,33 @@ def get_reverse_charge_recoverable_total(filters): query_filters['reverse_charge'] = ['=', 'Y'] query_filters['recoverable_reverse_charge'] = ['>', '0'] query_filters['docstatus'] = ['=', 1] - return frappe.db.get_list('Purchase Invoice', - filters = query_filters, - fields = ['sum(total)'], - as_list=True, - limit = 1 - )[0][0] or 0 + try: + return frappe.db.get_all('Purchase Invoice', + filters = query_filters, + fields = ['sum(total)'], + as_list=True, + limit = 1 + )[0][0] or 0 + except (IndexError, TypeError): + return 0 def get_reverse_charge_recoverable_tax(filters): """Returns the sum of the tax of each Purchase invoice made.""" conditions = get_conditions_join(filters) return frappe.db.sql(""" - select sum(debit * p.recoverable_reverse_charge / 100) from - `tabPurchase Invoice` p inner join `tabGL Entry` gl - on gl.voucher_no = p.name + select + sum(debit * p.recoverable_reverse_charge / 100) + from + `tabPurchase Invoice` p inner join `tabGL Entry` gl + on + gl.voucher_no = p.name where - p.reverse_charge = "Y" - and p.docstatus = 1 - and p.recoverable_reverse_charge > 0 - and gl.docstatus = 1 - and account in (select account from `tabUAE VAT Account` where parent=%(company)s) - {where_conditions} ; + p.reverse_charge = "Y" + and p.docstatus = 1 + and p.recoverable_reverse_charge > 0 + and gl.docstatus = 1 + and account in (select account from `tabUAE VAT Account` where parent=%(company)s) + {where_conditions} ; """.format(where_conditions=conditions), filters)[0][0] or 0 def get_conditions_join(filters): @@ -251,8 +249,8 @@ def get_conditions_join(filters): for opts in (("company", " and p.company=%(company)s"), ("from_date", " and p.posting_date>=%(from_date)s"), ("to_date", " and p.posting_date<=%(to_date)s")): - if filters.get(opts[0]): - conditions += opts[1] + if filters.get(opts[0]): + conditions += opts[1] return conditions def get_standard_rated_expenses_total(filters): @@ -260,77 +258,102 @@ def get_standard_rated_expenses_total(filters): query_filters = get_filters(filters) query_filters['recoverable_standard_rated_expenses'] = ['>', 0] query_filters['docstatus'] = ['=', 1] - return frappe.db.get_list('Purchase Invoice', - filters = query_filters, - fields = ['sum(total)'], - as_list=True, - limit = 1 - )[0][0] or 0 + try: + return frappe.db.get_all('Purchase Invoice', + filters = query_filters, + fields = ['sum(total)'], + as_list=True, + limit = 1 + )[0][0] or 0 + except (IndexError, TypeError): + return 0 def get_standard_rated_expenses_tax(filters): """Returns the sum of the tax of each Purchase invoice made.""" query_filters = get_filters(filters) query_filters['recoverable_standard_rated_expenses'] = ['>', 0] query_filters['docstatus'] = ['=', 1] - return frappe.db.get_list('Purchase Invoice', - filters = query_filters, - fields = ['sum(recoverable_standard_rated_expenses)'], - as_list=True, - limit = 1 - )[0][0] or 0 + try: + return frappe.db.get_all('Purchase Invoice', + filters = query_filters, + fields = ['sum(recoverable_standard_rated_expenses)'], + as_list=True, + limit = 1 + )[0][0] or 0 + except (IndexError, TypeError): + return 0 def get_tourist_tax_return_total(filters): """Returns the sum of the total of each Sales invoice with non zero tourist_tax_return.""" query_filters = get_filters(filters) query_filters['tourist_tax_return'] = ['>', 0] query_filters['docstatus'] = ['=', 1] - return frappe.db.get_list('Sales Invoice', - filters = query_filters, - fields = ['sum(total)'], - as_list=True, - limit = 1 - )[0][0] or 0 + try: + return frappe.db.get_all('Sales Invoice', + filters = query_filters, + fields = ['sum(total)'], + as_list=True, + limit = 1 + )[0][0] or 0 + except (IndexError, TypeError): + return 0 def get_tourist_tax_return_tax(filters): """Returns the sum of the tax of each Sales invoice with non zero tourist_tax_return.""" query_filters = get_filters(filters) query_filters['tourist_tax_return'] = ['>', 0] query_filters['docstatus'] = ['=', 1] - return frappe.db.get_list('Sales Invoice', - filters = query_filters, - fields = ['sum(tourist_tax_return)'], - as_list=True, - limit = 1 - )[0][0] or 0 + try: + return frappe.db.get_all('Sales Invoice', + filters = query_filters, + fields = ['sum(tourist_tax_return)'], + as_list=True, + limit = 1 + )[0][0] or 0 + except (IndexError, TypeError): + return 0 def get_zero_rated_total(filters): """Returns the sum of each Sales Invoice Item Amount which is zero rated.""" conditions = get_conditions(filters) - return frappe.db.sql(""" - select sum(i.base_amount) as total from - `tabSales Invoice Item` i inner join `tabSales Invoice` s - on i.parent = s.name - where s.docstatus = 1 and i.is_zero_rated = 1 - {where_conditions} ; - """.format(where_conditions=conditions), filters)[0][0] or 0 + try: + return frappe.db.sql(""" + select + sum(i.base_amount) as total + from + `tabSales Invoice Item` i inner join `tabSales Invoice` s + on + i.parent = s.name + where + s.docstatus = 1 and i.is_zero_rated = 1 + {where_conditions} ; + """.format(where_conditions=conditions), filters)[0][0] or 0 + except (IndexError, TypeError): + return 0 def get_exempt_total(filters): """Returns the sum of each Sales Invoice Item Amount which is Vat Exempt.""" conditions = get_conditions(filters) - return frappe.db.sql(""" - select sum(i.base_amount) as total from - `tabSales Invoice Item` i inner join `tabSales Invoice` s - on i.parent = s.name - where s.docstatus = 1 and i.is_exempt = 1 - {where_conditions} ; - """.format(where_conditions=conditions), filters)[0][0] or 0 - + try: + return frappe.db.sql(""" + select + sum(i.base_amount) as total + from + `tabSales Invoice Item` i inner join `tabSales Invoice` s + on + i.parent = s.name + where + s.docstatus = 1 and i.is_exempt = 1 + {where_conditions} ; + """.format(where_conditions=conditions), filters)[0][0] or 0 + except (IndexError, TypeError): + return 0 def get_conditions(filters): """The conditions to be used to filter data to calculate the total sale.""" conditions = "" for opts in (("company", " and company=%(company)s"), ("from_date", " and posting_date>=%(from_date)s"), ("to_date", " and posting_date<=%(to_date)s")): - if filters.get(opts[0]): - conditions += opts[1] + if filters.get(opts[0]): + conditions += opts[1] return conditions diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index 7430db4fce0..872839495a0 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -35,7 +35,12 @@ def get_account_currency(account): if not account: return def generator(): - account_currency, company = frappe.get_cached_value("Account", account, ["account_currency", "company"]) + 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") @@ -53,8 +58,8 @@ def get_tax_accounts(company): if not tax_accounts_list and not frappe.flags.in_test: frappe.throw(_('Please set Vat Accounts for Company: "{0}" in UAE VAT Settings').format(company)) - for d in tax_accounts_list: - for key, name in d.items(): + for tax_account in tax_accounts_list: + for _, name in tax_account.items(): tax_accounts_dict[name] = name return tax_accounts_dict @@ -131,8 +136,7 @@ def make_gl_entry(tax, gl_entries, doc, tax_accounts): 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( - { + gl_entries.append(doc.get_gl_dict({ "account": tax.account_head, "cost_center": tax.cost_center, "posting_date": doc.posting_date, @@ -141,8 +145,8 @@ def make_gl_entry(tax, gl_entries, doc, tax_accounts): 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) - ) + }, account_currency, item=tax + )) return gl_entries @@ -152,4 +156,6 @@ def validate_returns(doc, method): if country != 'United Arab Emirates': return if doc.reverse_charge == 'Y' and flt(doc.recoverable_standard_rated_expenses) != 0: - frappe.throw(_("Recoverable Standard Rated expenses should not be set when Reverse Charge Applicable is Y")) \ No newline at end of file + frappe.throw(_( + "Recoverable Standard Rated expenses should not be set when Reverse Charge Applicable is Y" + )) From 7a034595fe7c2f60090e9bbdc185a98ecd0f4f38 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Mon, 2 Nov 2020 13:12:27 +0530 Subject: [PATCH 53/60] fix(UAE VAT 201): Remove Chart --- .../report/uae_vat_201/uae_vat_201.py | 29 +------------------ .../regional/united_arab_emirates/utils.py | 2 +- 2 files changed, 2 insertions(+), 29 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index 78dcb367a4b..c151c622a6c 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -8,8 +8,7 @@ from frappe import _ def execute(filters=None): columns = get_columns() data, emirates, amounts_by_emirate = get_data(filters) - chart = get_chart(emirates, amounts_by_emirate) - return columns, data, None, chart + return columns, data def get_columns(): """Creates a list of dictionaries that are used to generate column headers of the data table.""" @@ -49,32 +48,6 @@ def get_data(filters = None): append_vat_on_expenses(data, filters) return data, emirates, amounts_by_emirate -def get_chart(emirates, amounts_by_emirate): - """Returns chart data.""" - labels = [] - amount = [] - vat_amount = [] - for emirate in emirates: - if emirate in amounts_by_emirate: - amount.append(amounts_by_emirate[emirate]["raw_amount"]) - vat_amount.append(amounts_by_emirate[emirate]["raw_vat_amount"]) - labels.append(emirate) - - datasets = [] - datasets.append({'name': _('Amount (AED)'), 'values': amount}) - datasets.append({'name': _('Vat Amount (AED)'), 'values': vat_amount}) - - chart = { - "type": "bar", - "fieldtype": "Currency", - "data": { - 'labels': labels, - 'datasets': datasets - } - } - - return chart - def append_vat_on_sales(data, filters): """Appends Sales and All Other Outputs.""" append_data(data, '', _('VAT on Sales and All Other Outputs'), '', '') diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index 872839495a0..7d5fd6ecf86 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -59,7 +59,7 @@ def get_tax_accounts(company): if not tax_accounts_list and not frappe.flags.in_test: frappe.throw(_('Please set Vat Accounts for Company: "{0}" in UAE VAT Settings').format(company)) for tax_account in tax_accounts_list: - for _, name in tax_account.items(): + for account, name in tax_account.items(): tax_accounts_dict[name] = name return tax_accounts_dict From f2c895ddb5b9d7b5b8f07e1d590e07ff5a745b7c Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Wed, 4 Nov 2020 10:31:37 +0530 Subject: [PATCH 54/60] feat(uae vat 201): do not take zero and nil rated items in standard rated expense emiratewise --- .../report/uae_vat_201/test_uae_vat_201.py | 2 +- .../report/uae_vat_201/uae_vat_201.py | 25 +++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py index b0a21de613d..daa69768c57 100644 --- a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py @@ -53,7 +53,7 @@ class TestUaeVat201(TestCase): "raw_amount": amount, "raw_vat_amount": vat, } - self.assertEqual(amounts_by_emirate["Sharjah"]["raw_amount"],300) + self.assertEqual(amounts_by_emirate["Sharjah"]["raw_amount"],100) self.assertEqual(amounts_by_emirate["Sharjah"]["raw_vat_amount"],5) self.assertEqual(amounts_by_emirate["Dubai"]["raw_amount"],200) self.assertEqual(amounts_by_emirate["Dubai"]["raw_vat_amount"],10) diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index c151c622a6c..f2d5a5e1138 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -118,14 +118,23 @@ def append_data(data, no, legend, amount, vat_amount): def get_total_emiratewise(filters): """Returns Emiratewise Amount and Taxes.""" - query_filters = get_filters(filters) - query_filters['docstatus'] = ['=', 1] - return frappe.db.get_all('Sales Invoice', - filters = query_filters, - fields = ['vat_emirate as emirate','sum(total)', 'sum(total_taxes_and_charges)'], - group_by='vat_emirate', - as_list=True - ) + conditions = get_conditions(filters) + try: + return frappe.db.sql(""" + select + s.vat_emirate as emirate, sum(i.base_amount) as total, sum(s.total_taxes_and_charges) + from + `tabSales Invoice Item` i inner join `tabSales Invoice` s + on + i.parent = s.name + where + s.docstatus = 1 and i.is_exempt != 1 and i.is_zero_rated != 1 + {where_conditions} + group by + s.vat_emirate; + """.format(where_conditions=conditions), filters) + except (IndexError, TypeError): + return 0 def get_emirates(): """Returns a List of emirates in the order that they are to be displayed.""" From bed4e85aec2b8475ab817916f0d357c6e977fe55 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Wed, 4 Nov 2020 10:44:22 +0530 Subject: [PATCH 55/60] fix(uae vat 201): date filters were not working --- .../report/uae_vat_201/uae_vat_201.py | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index f2d5a5e1138..de727d2ecda 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -150,20 +150,20 @@ def get_emirates(): def get_filters(filters): """The conditions to be used to filter data to calculate the total sale.""" - query_filters = {} + query_filters = [] if filters.get("company"): - query_filters["company"] = ['=', filters['company']] + query_filters.append(["company", '=', filters['company']]) if filters.get("from_date"): - query_filters["posting_date"] = ['>=', filters['from_date']] + query_filters.append(["posting_date", '>=', filters['from_date']]) if filters.get("from_date"): - query_filters["posting_date"] = ['<=', filters['to_date']] + query_filters.append(["posting_date", '<=', filters['to_date']]) return query_filters def get_reverse_charge_total(filters): """Returns the sum of the total of each Purchase invoice made.""" query_filters = get_filters(filters) - query_filters['reverse_charge'] = ['=', 'Y'] - query_filters['docstatus'] = ['=', 1] + query_filters.append(['reverse_charge', '=', 'Y']) + query_filters.append(['docstatus', '=', 1]) try: return frappe.db.get_all('Purchase Invoice', filters = query_filters, @@ -193,9 +193,9 @@ def get_reverse_charge_tax(filters): def get_reverse_charge_recoverable_total(filters): """Returns the sum of the total of each Purchase invoice made with recoverable reverse charge.""" query_filters = get_filters(filters) - query_filters['reverse_charge'] = ['=', 'Y'] - query_filters['recoverable_reverse_charge'] = ['>', '0'] - query_filters['docstatus'] = ['=', 1] + query_filters.append(['reverse_charge', '=', 'Y']) + query_filters.append(['recoverable_reverse_charge', '>', '0']) + query_filters.append(['docstatus', '=', 1]) try: return frappe.db.get_all('Purchase Invoice', filters = query_filters, @@ -238,8 +238,8 @@ def get_conditions_join(filters): def get_standard_rated_expenses_total(filters): """Returns the sum of the total of each Purchase invoice made with recoverable reverse charge.""" query_filters = get_filters(filters) - query_filters['recoverable_standard_rated_expenses'] = ['>', 0] - query_filters['docstatus'] = ['=', 1] + query_filters.append(['recoverable_standard_rated_expenses', '>', 0]) + query_filters.append(['docstatus', '=', 1]) try: return frappe.db.get_all('Purchase Invoice', filters = query_filters, @@ -253,8 +253,8 @@ def get_standard_rated_expenses_total(filters): def get_standard_rated_expenses_tax(filters): """Returns the sum of the tax of each Purchase invoice made.""" query_filters = get_filters(filters) - query_filters['recoverable_standard_rated_expenses'] = ['>', 0] - query_filters['docstatus'] = ['=', 1] + query_filters.append(['recoverable_standard_rated_expenses', '>', 0]) + query_filters.append(['docstatus', '=', 1]) try: return frappe.db.get_all('Purchase Invoice', filters = query_filters, @@ -268,8 +268,8 @@ def get_standard_rated_expenses_tax(filters): def get_tourist_tax_return_total(filters): """Returns the sum of the total of each Sales invoice with non zero tourist_tax_return.""" query_filters = get_filters(filters) - query_filters['tourist_tax_return'] = ['>', 0] - query_filters['docstatus'] = ['=', 1] + query_filters.append(['tourist_tax_return', '>', 0]) + query_filters.append(['docstatus', '=', 1]) try: return frappe.db.get_all('Sales Invoice', filters = query_filters, @@ -283,8 +283,8 @@ def get_tourist_tax_return_total(filters): def get_tourist_tax_return_tax(filters): """Returns the sum of the tax of each Sales invoice with non zero tourist_tax_return.""" query_filters = get_filters(filters) - query_filters['tourist_tax_return'] = ['>', 0] - query_filters['docstatus'] = ['=', 1] + query_filters.append(['tourist_tax_return', '>', 0]) + query_filters.append(['docstatus', '=', 1]) try: return frappe.db.get_all('Sales Invoice', filters = query_filters, @@ -300,7 +300,7 @@ def get_zero_rated_total(filters): conditions = get_conditions(filters) try: return frappe.db.sql(""" - select + select sum(i.base_amount) as total from `tabSales Invoice Item` i inner join `tabSales Invoice` s From 4d99d695a38d40087e2f9051084f1c9b9016f187 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Fri, 6 Nov 2020 23:33:19 +0530 Subject: [PATCH 56/60] feat(uae vat 201): update desk page entry --- erpnext/accounts/desk_page/accounting/accounting.json | 8 ++++---- erpnext/regional/report/uae_vat_201/uae_vat_201.py | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/desk_page/accounting/accounting.json b/erpnext/accounts/desk_page/accounting/accounting.json index 64e2b246a70..de9ed9fca16 100644 --- a/erpnext/accounts/desk_page/accounting/accounting.json +++ b/erpnext/accounts/desk_page/accounting/accounting.json @@ -83,7 +83,7 @@ { "hidden": 0, "label": "Value-Added Tax (VAT UAE)", - "links": "[\n {\n \"label\": \"UAE VAT Settings\",\n \"name\": \"UAE VAT Settings\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"UAE VAT 201\",\n \"name\": \"UAE VAT 201\",\n \"type\": \"report\"\n }\n]" + "links": "[\n {\n \"country\": \"United Arab Emirates\",\n \"is_query_report\": true,\n \"label\": \"UAE VAT 201\",\n \"name\": \"UAE VAT 201\",\n \"type\": \"report\"\n },\n {\n \"country\": \"United Arab Emirates\",\n \"label\": \"UAE VAT Settings\",\n \"name\": \"UAE VAT Settings\",\n \"type\": \"doctype\"\n }\n]" } ], "category": "Modules", @@ -103,8 +103,8 @@ "idx": 0, "is_standard": 1, "label": "Accounting", - "modified": "2020-10-08 20:31:46.022470", - "modified_by": "Administrator", + "modified": "2020-11-06 23:30:39.515679", + "modified_by": "moha@gmail.com", "module": "Accounts", "name": "Accounting", "onboarding": "Accounts", @@ -158,4 +158,4 @@ "type": "Dashboard" } ] -} +} \ No newline at end of file diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index de727d2ecda..b0614238ba0 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -30,14 +30,12 @@ def get_columns(): "label": _("Amount (AED)"), "fieldtype": "Currency", "width": 125, - "options": "currency" }, { "fieldname": "vat_amount", "label": _("VAT Amount (AED)"), "fieldtype": "Currency", "width": 150, - "options": "currency" } ] From c5aad7b6e5f8419c4a2201fff60e20f05362897a Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Fri, 6 Nov 2020 23:36:50 +0530 Subject: [PATCH 57/60] feat(UAE VAT 201): reorder desk page listing --- erpnext/accounts/desk_page/accounting/accounting.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/desk_page/accounting/accounting.json b/erpnext/accounts/desk_page/accounting/accounting.json index de9ed9fca16..993d2a625b0 100644 --- a/erpnext/accounts/desk_page/accounting/accounting.json +++ b/erpnext/accounts/desk_page/accounting/accounting.json @@ -83,7 +83,7 @@ { "hidden": 0, "label": "Value-Added Tax (VAT UAE)", - "links": "[\n {\n \"country\": \"United Arab Emirates\",\n \"is_query_report\": true,\n \"label\": \"UAE VAT 201\",\n \"name\": \"UAE VAT 201\",\n \"type\": \"report\"\n },\n {\n \"country\": \"United Arab Emirates\",\n \"label\": \"UAE VAT Settings\",\n \"name\": \"UAE VAT Settings\",\n \"type\": \"doctype\"\n }\n]" + "links": "[\n {\n \"country\": \"United Arab Emirates\",\n \"label\": \"UAE VAT Settings\",\n \"name\": \"UAE VAT Settings\",\n \"type\": \"doctype\"\n },\n {\n \"country\": \"United Arab Emirates\",\n \"is_query_report\": true,\n \"label\": \"UAE VAT 201\",\n \"name\": \"UAE VAT 201\",\n \"type\": \"report\"\n }\n\n]" } ], "category": "Modules", @@ -103,7 +103,7 @@ "idx": 0, "is_standard": 1, "label": "Accounting", - "modified": "2020-11-06 23:30:39.515679", + "modified": "2020-11-06 23:34:50.325014", "modified_by": "moha@gmail.com", "module": "Accounts", "name": "Accounting", From b8d0b546a7851fd24c9815a9e797a7717adab2b0 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Mon, 16 Nov 2020 12:58:38 +0530 Subject: [PATCH 58/60] feat(UAE VAT Format): use company address for emir --- erpnext/regional/united_arab_emirates/setup.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index 62156e46be5..6f520f6ad6e 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -56,7 +56,8 @@ def make_custom_fields(): fieldtype='Read Only', insert_after='customer_name', fetch_from='customer.customer_name_in_arabic', print_hide=1), dict(fieldname='vat_emirate', label='VAT Emirate', insert_after='permit_no', fieldtype='Select', - options='\nAbu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain'), + options='\nAbu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain', + fetch_from='company_address.emirate'), dict(fieldname='tourist_tax_return', label='Tax Refund provided to Tourists (AED)', insert_after='vat_emirate', fieldtype='Currency', print_hide=1, default='0'), ] @@ -100,6 +101,10 @@ def make_custom_fields(): dict(fieldname='supplier_name_in_arabic', label='Supplier Name in Arabic', fieldtype='Data', insert_after='supplier_name'), ], + 'Address': [ + dict(fieldname='emirate', label='Emirate', fieldtype='Select', insert_after='state', + options='Abu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain') + ], 'Purchase Invoice': purchase_invoice_fields + invoice_fields, 'Purchase Order': purchase_invoice_fields + invoice_fields, 'Purchase Receipt': purchase_invoice_fields + invoice_fields, From 2e1787300d1b881d638e9786c52d6f43f85f780a Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Mon, 16 Nov 2020 17:36:27 +0530 Subject: [PATCH 59/60] feat(UAE VAT 201): emirate according to branch --- .../doctype/sales_invoice/sales_invoice.js | 23 +++++++++++++++++++ .../regional/united_arab_emirates/setup.py | 13 ++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 502e65ed8d0..803312072c7 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -446,6 +446,29 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte this.frm.refresh_field("outstanding_amount"); this.frm.refresh_field("paid_amount"); this.frm.refresh_field("base_paid_amount"); + }, + + branch: function(){ + const me = this + if (this.frm.doc.branch) { + frappe.call({ + async: false, + method: "frappe.client.get_value", + args: { + "doctype": "Branch", + "filters": { + 'name': this.frm.doc.branch + }, + "fieldname": ['emirate'] + }, + callback: function (res) { + if (res.message && res.message['emirate']) { + me.frm.set_value("vat_emirate", res.message['emirate']) + me.frm.refresh_field("vat_emirate") + } + } + }) + } } }); diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index 6f520f6ad6e..2e546deb82c 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -38,8 +38,9 @@ def make_custom_fields(): dict(fieldname='supplier_name_in_arabic', label='Supplier Name in Arabic', fieldtype='Read Only', insert_after='supplier_name', fetch_from='supplier.supplier_name_in_arabic', print_hide=1), - dict(fieldname='recoverable_standard_rated_expenses', label='Recoverable Standard Rated Expenses (AED)', - insert_after='permit_no', fieldtype='Currency', print_hide=1, default='0'), + dict(fieldname='recoverable_standard_rated_expenses', print_hide=1, default='0', + label='Recoverable Standard Rated Expenses (AED)', insert_after='permit_no', + fieldtype='Currency', ), dict(fieldname='reverse_charge', label='Reverse Charge Applicable', fieldtype='Select', insert_after='recoverable_standard_rated_expenses', print_hide=1, options='Y\nN', default='N'), @@ -55,6 +56,8 @@ def make_custom_fields(): dict(fieldname='customer_name_in_arabic', label='Customer Name in Arabic', fieldtype='Read Only', insert_after='customer_name', fetch_from='customer.customer_name_in_arabic', print_hide=1), + dict(fieldname='branch', label='Branch', options='Branch', + fieldtype='Link', insert_after='company', print_hide=1), dict(fieldname='vat_emirate', label='VAT Emirate', insert_after='permit_no', fieldtype='Select', options='\nAbu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain', fetch_from='company_address.emirate'), @@ -103,7 +106,11 @@ def make_custom_fields(): ], 'Address': [ dict(fieldname='emirate', label='Emirate', fieldtype='Select', insert_after='state', - options='Abu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain') + options='\nAbu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain') + ], + 'Branch': [ + dict(fieldname='emirate', label='Emirate', fieldtype='Select', insert_after='state', + options='\nAbu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain') ], 'Purchase Invoice': purchase_invoice_fields + invoice_fields, 'Purchase Order': purchase_invoice_fields + invoice_fields, From d2477e6cc5cd0acc9353e9dc8a0b23a729da6ff3 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Mon, 16 Nov 2020 18:47:05 +0530 Subject: [PATCH 60/60] fix(UAE VAT 201): remove branch parts --- .../doctype/sales_invoice/sales_invoice.js | 23 ------------------- .../regional/united_arab_emirates/setup.py | 6 ----- 2 files changed, 29 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 803312072c7..502e65ed8d0 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -446,29 +446,6 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte this.frm.refresh_field("outstanding_amount"); this.frm.refresh_field("paid_amount"); this.frm.refresh_field("base_paid_amount"); - }, - - branch: function(){ - const me = this - if (this.frm.doc.branch) { - frappe.call({ - async: false, - method: "frappe.client.get_value", - args: { - "doctype": "Branch", - "filters": { - 'name': this.frm.doc.branch - }, - "fieldname": ['emirate'] - }, - callback: function (res) { - if (res.message && res.message['emirate']) { - me.frm.set_value("vat_emirate", res.message['emirate']) - me.frm.refresh_field("vat_emirate") - } - } - }) - } } }); diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index 2e546deb82c..013ae5cf73c 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -56,8 +56,6 @@ def make_custom_fields(): dict(fieldname='customer_name_in_arabic', label='Customer Name in Arabic', fieldtype='Read Only', insert_after='customer_name', fetch_from='customer.customer_name_in_arabic', print_hide=1), - dict(fieldname='branch', label='Branch', options='Branch', - fieldtype='Link', insert_after='company', print_hide=1), dict(fieldname='vat_emirate', label='VAT Emirate', insert_after='permit_no', fieldtype='Select', options='\nAbu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain', fetch_from='company_address.emirate'), @@ -108,10 +106,6 @@ def make_custom_fields(): dict(fieldname='emirate', label='Emirate', fieldtype='Select', insert_after='state', options='\nAbu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain') ], - 'Branch': [ - dict(fieldname='emirate', label='Emirate', fieldtype='Select', insert_after='state', - options='\nAbu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain') - ], 'Purchase Invoice': purchase_invoice_fields + invoice_fields, 'Purchase Order': purchase_invoice_fields + invoice_fields, 'Purchase Receipt': purchase_invoice_fields + invoice_fields,
{%= report_columns[0].label %}{%= report_columns[1].label %}