refactor(region): Splitting of KSA(Saudi Arabia) Regional logic from ERPNext (#33895)
* feat: remove KSA regional code
This commit is contained in:
parent
dde5bbc9a7
commit
a06d24037b
@ -311,15 +311,10 @@ doc_events = {
|
|||||||
"on_submit": [
|
"on_submit": [
|
||||||
"erpnext.regional.create_transaction_log",
|
"erpnext.regional.create_transaction_log",
|
||||||
"erpnext.regional.italy.utils.sales_invoice_on_submit",
|
"erpnext.regional.italy.utils.sales_invoice_on_submit",
|
||||||
"erpnext.regional.saudi_arabia.utils.create_qr_code",
|
|
||||||
],
|
|
||||||
"on_cancel": [
|
|
||||||
"erpnext.regional.italy.utils.sales_invoice_on_cancel",
|
|
||||||
"erpnext.regional.saudi_arabia.utils.delete_qr_code_file",
|
|
||||||
],
|
],
|
||||||
|
"on_cancel": ["erpnext.regional.italy.utils.sales_invoice_on_cancel"],
|
||||||
"on_trash": "erpnext.regional.check_deletion_permission",
|
"on_trash": "erpnext.regional.check_deletion_permission",
|
||||||
},
|
},
|
||||||
"POS Invoice": {"on_submit": ["erpnext.regional.saudi_arabia.utils.create_qr_code"]},
|
|
||||||
"Purchase Invoice": {
|
"Purchase Invoice": {
|
||||||
"validate": [
|
"validate": [
|
||||||
"erpnext.regional.united_arab_emirates.utils.update_grand_total_for_rcm",
|
"erpnext.regional.united_arab_emirates.utils.update_grand_total_for_rcm",
|
||||||
@ -347,7 +342,6 @@ doc_events = {
|
|||||||
"Email Unsubscribe": {
|
"Email Unsubscribe": {
|
||||||
"after_insert": "erpnext.crm.doctype.email_campaign.email_campaign.unsubscribe_recipient"
|
"after_insert": "erpnext.crm.doctype.email_campaign.email_campaign.unsubscribe_recipient"
|
||||||
},
|
},
|
||||||
"Company": {"on_trash": ["erpnext.regional.saudi_arabia.utils.delete_vat_settings_for_company"]},
|
|
||||||
"Integration Request": {
|
"Integration Request": {
|
||||||
"validate": "erpnext.accounts.doctype.payment_request.payment_request.validate_payment"
|
"validate": "erpnext.accounts.doctype.payment_request.payment_request.validate_payment"
|
||||||
},
|
},
|
||||||
|
@ -250,18 +250,14 @@ erpnext.patches.v13_0.item_naming_series_not_mandatory
|
|||||||
erpnext.patches.v13_0.update_category_in_ltds_certificate
|
erpnext.patches.v13_0.update_category_in_ltds_certificate
|
||||||
erpnext.patches.v13_0.fetch_thumbnail_in_website_items
|
erpnext.patches.v13_0.fetch_thumbnail_in_website_items
|
||||||
erpnext.patches.v13_0.update_maintenance_schedule_field_in_visit
|
erpnext.patches.v13_0.update_maintenance_schedule_field_in_visit
|
||||||
erpnext.patches.v13_0.create_ksa_vat_custom_fields # 07-01-2022
|
|
||||||
erpnext.patches.v14_0.migrate_crm_settings
|
erpnext.patches.v14_0.migrate_crm_settings
|
||||||
erpnext.patches.v13_0.rename_ksa_qr_field
|
|
||||||
erpnext.patches.v13_0.wipe_serial_no_field_for_0_qty
|
erpnext.patches.v13_0.wipe_serial_no_field_for_0_qty
|
||||||
erpnext.patches.v13_0.disable_ksa_print_format_for_others # 16-12-2021
|
|
||||||
erpnext.patches.v13_0.agriculture_deprecation_warning
|
erpnext.patches.v13_0.agriculture_deprecation_warning
|
||||||
erpnext.patches.v13_0.hospitality_deprecation_warning
|
erpnext.patches.v13_0.hospitality_deprecation_warning
|
||||||
erpnext.patches.v13_0.update_asset_quantity_field
|
erpnext.patches.v13_0.update_asset_quantity_field
|
||||||
erpnext.patches.v13_0.delete_bank_reconciliation_detail
|
erpnext.patches.v13_0.delete_bank_reconciliation_detail
|
||||||
erpnext.patches.v13_0.enable_provisional_accounting
|
erpnext.patches.v13_0.enable_provisional_accounting
|
||||||
erpnext.patches.v13_0.non_profit_deprecation_warning
|
erpnext.patches.v13_0.non_profit_deprecation_warning
|
||||||
erpnext.patches.v13_0.enable_ksa_vat_docs #1
|
|
||||||
erpnext.patches.v13_0.show_india_localisation_deprecation_warning
|
erpnext.patches.v13_0.show_india_localisation_deprecation_warning
|
||||||
erpnext.patches.v13_0.show_hr_payroll_deprecation_warning
|
erpnext.patches.v13_0.show_hr_payroll_deprecation_warning
|
||||||
erpnext.patches.v13_0.reset_corrupt_defaults
|
erpnext.patches.v13_0.reset_corrupt_defaults
|
||||||
@ -269,6 +265,8 @@ erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair
|
|||||||
erpnext.patches.v15_0.delete_taxjar_doctypes
|
erpnext.patches.v15_0.delete_taxjar_doctypes
|
||||||
erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets
|
erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets
|
||||||
erpnext.patches.v14_0.update_reference_due_date_in_journal_entry
|
erpnext.patches.v14_0.update_reference_due_date_in_journal_entry
|
||||||
|
erpnext.patches.v15_0.saudi_depreciation_warning
|
||||||
|
erpnext.patches.v15_0.delete_saudi_doctypes
|
||||||
|
|
||||||
[post_model_sync]
|
[post_model_sync]
|
||||||
execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings')
|
execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings')
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
import frappe
|
|
||||||
|
|
||||||
from erpnext.regional.saudi_arabia.setup import make_custom_fields
|
|
||||||
|
|
||||||
|
|
||||||
def execute():
|
|
||||||
company = frappe.get_all("Company", filters={"country": "Saudi Arabia"})
|
|
||||||
if not company:
|
|
||||||
return
|
|
||||||
|
|
||||||
make_custom_fields()
|
|
@ -1,19 +0,0 @@
|
|||||||
# Copyright (c) 2020, Wahni Green Technologies and Contributors
|
|
||||||
# License: GNU General Public License v3. See license.txt
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
|
|
||||||
from erpnext.regional.saudi_arabia.setup import add_print_formats
|
|
||||||
|
|
||||||
|
|
||||||
def execute():
|
|
||||||
company = frappe.get_all("Company", filters={"country": "Saudi Arabia"})
|
|
||||||
if company:
|
|
||||||
add_print_formats()
|
|
||||||
return
|
|
||||||
|
|
||||||
if frappe.db.exists("DocType", "Print Format"):
|
|
||||||
frappe.reload_doc("regional", "print_format", "ksa_vat_invoice", force=True)
|
|
||||||
frappe.reload_doc("regional", "print_format", "ksa_pos_invoice", force=True)
|
|
||||||
for d in ("KSA VAT Invoice", "KSA POS Invoice"):
|
|
||||||
frappe.db.set_value("Print Format", d, "disabled", 1)
|
|
@ -1,12 +0,0 @@
|
|||||||
import frappe
|
|
||||||
|
|
||||||
from erpnext.regional.saudi_arabia.setup import add_permissions, add_print_formats
|
|
||||||
|
|
||||||
|
|
||||||
def execute():
|
|
||||||
company = frappe.get_all("Company", filters={"country": "Saudi Arabia"})
|
|
||||||
if not company:
|
|
||||||
return
|
|
||||||
|
|
||||||
add_print_formats()
|
|
||||||
add_permissions()
|
|
@ -1,36 +0,0 @@
|
|||||||
# Copyright (c) 2020, Wahni Green Technologies and Contributors
|
|
||||||
# License: GNU General Public License v3. See license.txt
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
|
|
||||||
from frappe.model.utils.rename_field import rename_field
|
|
||||||
|
|
||||||
|
|
||||||
def execute():
|
|
||||||
company = frappe.get_all("Company", filters={"country": "Saudi Arabia"})
|
|
||||||
if not company:
|
|
||||||
return
|
|
||||||
|
|
||||||
if frappe.db.exists("DocType", "Sales Invoice"):
|
|
||||||
frappe.reload_doc("accounts", "doctype", "sales_invoice", force=True)
|
|
||||||
|
|
||||||
# rename_field method assumes that the field already exists or the doc is synced
|
|
||||||
if not frappe.db.has_column("Sales Invoice", "ksa_einv_qr"):
|
|
||||||
create_custom_fields(
|
|
||||||
{
|
|
||||||
"Sales Invoice": [
|
|
||||||
dict(
|
|
||||||
fieldname="ksa_einv_qr",
|
|
||||||
label="KSA E-Invoicing QR",
|
|
||||||
fieldtype="Attach Image",
|
|
||||||
read_only=1,
|
|
||||||
no_copy=1,
|
|
||||||
hidden=1,
|
|
||||||
)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
if frappe.db.has_column("Sales Invoice", "qr_code"):
|
|
||||||
rename_field("Sales Invoice", "qr_code", "ksa_einv_qr")
|
|
||||||
frappe.delete_doc_if_exists("Custom Field", "Sales Invoice-qr_code")
|
|
25
erpnext/patches/v15_0/delete_saudi_doctypes.py
Normal file
25
erpnext/patches/v15_0/delete_saudi_doctypes.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import click
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
if "ksa" in frappe.get_installed_apps():
|
||||||
|
return
|
||||||
|
|
||||||
|
doctypes = ["KSA VAT Setting", "KSA VAT Purchase Account", "KSA VAT Sales Account"]
|
||||||
|
for doctype in doctypes:
|
||||||
|
frappe.delete_doc("DocType", doctype, ignore_missing=True)
|
||||||
|
|
||||||
|
print_formats = ["KSA POS Invoice", "KSA VAT Invoice"]
|
||||||
|
for print_format in print_formats:
|
||||||
|
frappe.delete_doc("Print Format", print_format, ignore_missing=True, force=True)
|
||||||
|
|
||||||
|
reports = ["KSA VAT"]
|
||||||
|
for report in reports:
|
||||||
|
frappe.delete_doc("Report", report, ignore_missing=True, force=True)
|
||||||
|
|
||||||
|
click.secho(
|
||||||
|
"Region Saudi Arabia(KSA) is moved to a separate app"
|
||||||
|
"Please install the app to continue using the module: https://github.com/8848digital/KSA",
|
||||||
|
fg="yellow",
|
||||||
|
)
|
12
erpnext/patches/v15_0/saudi_depreciation_warning.py
Normal file
12
erpnext/patches/v15_0/saudi_depreciation_warning.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import click
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
if "ksa" in frappe.get_installed_apps():
|
||||||
|
return
|
||||||
|
click.secho(
|
||||||
|
"Region Saudi Arabia(KSA) is moved to a separate app\n"
|
||||||
|
"Please install the app to continue using the KSA Features: https://github.com/8848digital/KSA",
|
||||||
|
fg="yellow",
|
||||||
|
)
|
@ -1,49 +0,0 @@
|
|||||||
{
|
|
||||||
"actions": [],
|
|
||||||
"creation": "2021-07-13 09:17:09.862163",
|
|
||||||
"doctype": "DocType",
|
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"field_order": [
|
|
||||||
"title",
|
|
||||||
"item_tax_template",
|
|
||||||
"account"
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldname": "account",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Account",
|
|
||||||
"options": "Account",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "title",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Title",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "item_tax_template",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Item Tax Template",
|
|
||||||
"options": "Item Tax Template",
|
|
||||||
"reqd": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"index_web_pages_for_search": 1,
|
|
||||||
"istable": 1,
|
|
||||||
"links": [],
|
|
||||||
"modified": "2021-08-04 06:42:38.205597",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Regional",
|
|
||||||
"name": "KSA VAT Purchase Account",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [],
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"track_changes": 1
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2021, Havenir Solutions and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
# import frappe
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
|
|
||||||
class KSAVATPurchaseAccount(Document):
|
|
||||||
pass
|
|
@ -1,8 +0,0 @@
|
|||||||
// Copyright (c) 2021, Havenir Solutions and contributors
|
|
||||||
// For license information, please see license.txt
|
|
||||||
|
|
||||||
frappe.ui.form.on('KSA VAT Sales Account', {
|
|
||||||
// refresh: function(frm) {
|
|
||||||
|
|
||||||
// }
|
|
||||||
});
|
|
@ -1,49 +0,0 @@
|
|||||||
{
|
|
||||||
"actions": [],
|
|
||||||
"creation": "2021-07-13 08:46:33.820968",
|
|
||||||
"doctype": "DocType",
|
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"field_order": [
|
|
||||||
"title",
|
|
||||||
"item_tax_template",
|
|
||||||
"account"
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldname": "account",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Account",
|
|
||||||
"options": "Account",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "title",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Title",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "item_tax_template",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Item Tax Template",
|
|
||||||
"options": "Item Tax Template",
|
|
||||||
"reqd": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"index_web_pages_for_search": 1,
|
|
||||||
"istable": 1,
|
|
||||||
"links": [],
|
|
||||||
"modified": "2021-08-04 06:42:00.081407",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Regional",
|
|
||||||
"name": "KSA VAT Sales Account",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [],
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"track_changes": 1
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2021, Havenir Solutions and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
# import frappe
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
|
|
||||||
class KSAVATSalesAccount(Document):
|
|
||||||
pass
|
|
@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2021, Havenir Solutions and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
# import frappe
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class TestKSAVATSalesAccount(unittest.TestCase):
|
|
||||||
pass
|
|
@ -1,8 +0,0 @@
|
|||||||
// Copyright (c) 2021, Havenir Solutions and contributors
|
|
||||||
// For license information, please see license.txt
|
|
||||||
|
|
||||||
frappe.ui.form.on('KSA VAT Setting', {
|
|
||||||
onload: function () {
|
|
||||||
frappe.breadcrumbs.add('Accounts', 'KSA VAT Setting');
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,49 +0,0 @@
|
|||||||
{
|
|
||||||
"actions": [],
|
|
||||||
"autoname": "field:company",
|
|
||||||
"creation": "2021-07-13 08:49:01.100356",
|
|
||||||
"doctype": "DocType",
|
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"field_order": [
|
|
||||||
"company",
|
|
||||||
"ksa_vat_sales_accounts",
|
|
||||||
"ksa_vat_purchase_accounts"
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldname": "company",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Company",
|
|
||||||
"options": "Company",
|
|
||||||
"reqd": 1,
|
|
||||||
"unique": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "ksa_vat_sales_accounts",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"label": "KSA VAT Sales Accounts",
|
|
||||||
"options": "KSA VAT Sales Account",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "ksa_vat_purchase_accounts",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"label": "KSA VAT Purchase Accounts",
|
|
||||||
"options": "KSA VAT Purchase Account",
|
|
||||||
"reqd": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"links": [],
|
|
||||||
"modified": "2021-08-26 04:29:06.499378",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Regional",
|
|
||||||
"name": "KSA VAT Setting",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [],
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"title_field": "company",
|
|
||||||
"track_changes": 1
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2021, Havenir Solutions and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
# import frappe
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
|
|
||||||
class KSAVATSetting(Document):
|
|
||||||
pass
|
|
@ -1,5 +0,0 @@
|
|||||||
frappe.listview_settings['KSA VAT Setting'] = {
|
|
||||||
onload () {
|
|
||||||
frappe.breadcrumbs.add('Accounts');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2021, Havenir Solutions and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
# import frappe
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class TestKSAVATSetting(unittest.TestCase):
|
|
||||||
pass
|
|
@ -1,32 +0,0 @@
|
|||||||
{
|
|
||||||
"absolute_value": 0,
|
|
||||||
"align_labels_right": 0,
|
|
||||||
"creation": "2021-12-07 13:25:05.424827",
|
|
||||||
"css": "",
|
|
||||||
"custom_format": 1,
|
|
||||||
"default_print_language": "en",
|
|
||||||
"disabled": 1,
|
|
||||||
"doc_type": "POS Invoice",
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "Print Format",
|
|
||||||
"font_size": 0,
|
|
||||||
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tline-height: 150%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n{% if letter_head %}\n {{ letter_head }}\n{% endif %}\n\n<p class=\"text-center\" style=\"margin-bottom: 1rem\">\n\t{{ doc.company }}<br>\n\t<b>{{ doc.select_print_heading or _(\"Invoice\") }}</b><br>\n\t<img src={{doc.ksa_einv_qr}}>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Cashier\") }}:</b> {{ doc.owner }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Time\") }}:</b> {{ doc.get_formatted(\"posting_time\") }}<br>\n</p>\n\n<hr>\n<table class=\"table table-condensed\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"40%\">{{ _(\"Item\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"35%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t<br><b>{{ _(\"SR.No\") }}:</b><br>\n\t\t\t\t\t{{ item.serial_no | replace(\"\\n\", \", \") }}\n\t\t\t\t{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"net_amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t {% if '%' in row.description %}\n\t\t\t\t\t {{ row.description }}\n\t\t\t\t\t{% else %}\n\t\t\t\t\t {{ row.description }}@{{ row.rate }}%\n\t\t\t\t\t{% endif %}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t{%- endfor -%}\n\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t<b>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.change_amount -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t{%- endif -%}\n\t</tbody>\n</table>\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
|
|
||||||
"idx": 0,
|
|
||||||
"line_breaks": 0,
|
|
||||||
"margin_bottom": 0.0,
|
|
||||||
"margin_left": 0.0,
|
|
||||||
"margin_right": 0.0,
|
|
||||||
"margin_top": 0.0,
|
|
||||||
"modified": "2021-12-08 10:25:01.930885",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Regional",
|
|
||||||
"name": "KSA POS Invoice",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"page_number": "Hide",
|
|
||||||
"print_format_builder": 0,
|
|
||||||
"print_format_builder_beta": 0,
|
|
||||||
"print_format_type": "Jinja",
|
|
||||||
"raw_printing": 0,
|
|
||||||
"show_section_headings": 0,
|
|
||||||
"standard": "Yes"
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
@ -1,59 +0,0 @@
|
|||||||
// Copyright (c) 2016, Havenir Solutions and contributors
|
|
||||||
// For license information, please see license.txt
|
|
||||||
/* eslint-disable */
|
|
||||||
|
|
||||||
frappe.query_reports["KSA VAT"] = {
|
|
||||||
onload() {
|
|
||||||
frappe.breadcrumbs.add('Accounts');
|
|
||||||
},
|
|
||||||
"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(), -1),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "to_date",
|
|
||||||
"label": __("To Date"),
|
|
||||||
"fieldtype": "Date",
|
|
||||||
"reqd": 1,
|
|
||||||
"default": frappe.datetime.get_today()
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"formatter": function(value, row, column, data, default_formatter) {
|
|
||||||
if (data
|
|
||||||
&& (data.title=='VAT on Sales' || data.title=='VAT on Purchases')
|
|
||||||
&& data.title==value) {
|
|
||||||
value = $(`<span>${value}</span>`);
|
|
||||||
var $value = $(value).css("font-weight", "bold");
|
|
||||||
value = $value.wrap("<p></p>").parent().html();
|
|
||||||
return value
|
|
||||||
}else if (data.title=='Grand Total'){
|
|
||||||
if (data.title==value) {
|
|
||||||
value = $(`<span>${value}</span>`);
|
|
||||||
var $value = $(value).css("font-weight", "bold");
|
|
||||||
value = $value.wrap("<p></p>").parent().html();
|
|
||||||
return value
|
|
||||||
}else{
|
|
||||||
value = default_formatter(value, row, column, data);
|
|
||||||
value = $(`<span>${value}</span>`);
|
|
||||||
var $value = $(value).css("font-weight", "bold");
|
|
||||||
value = $value.wrap("<p></p>").parent().html();
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
value = default_formatter(value, row, column, data);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,32 +0,0 @@
|
|||||||
{
|
|
||||||
"add_total_row": 0,
|
|
||||||
"columns": [],
|
|
||||||
"creation": "2021-07-13 08:54:38.000949",
|
|
||||||
"disable_prepared_report": 1,
|
|
||||||
"disabled": 1,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "Report",
|
|
||||||
"filters": [],
|
|
||||||
"idx": 0,
|
|
||||||
"is_standard": "Yes",
|
|
||||||
"modified": "2021-08-26 04:14:37.202594",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Regional",
|
|
||||||
"name": "KSA VAT",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"prepared_report": 1,
|
|
||||||
"ref_doctype": "GL Entry",
|
|
||||||
"report_name": "KSA VAT",
|
|
||||||
"report_type": "Script Report",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"role": "System Manager"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "Accounts Manager"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "Accounts User"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,231 +0,0 @@
|
|||||||
# Copyright (c) 2013, Havenir Solutions and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
from frappe import _
|
|
||||||
from frappe.utils import get_url_to_list
|
|
||||||
|
|
||||||
|
|
||||||
def execute(filters=None):
|
|
||||||
columns = columns = get_columns()
|
|
||||||
data = get_data(filters)
|
|
||||||
return columns, data
|
|
||||||
|
|
||||||
|
|
||||||
def get_columns():
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
"fieldname": "title",
|
|
||||||
"label": _("Title"),
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"width": 300,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "amount",
|
|
||||||
"label": _("Amount (SAR)"),
|
|
||||||
"fieldtype": "Currency",
|
|
||||||
"options": "currency",
|
|
||||||
"width": 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "adjustment_amount",
|
|
||||||
"label": _("Adjustment (SAR)"),
|
|
||||||
"fieldtype": "Currency",
|
|
||||||
"options": "currency",
|
|
||||||
"width": 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "vat_amount",
|
|
||||||
"label": _("VAT Amount (SAR)"),
|
|
||||||
"fieldtype": "Currency",
|
|
||||||
"options": "currency",
|
|
||||||
"width": 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "currency",
|
|
||||||
"label": _("Currency"),
|
|
||||||
"fieldtype": "Currency",
|
|
||||||
"width": 150,
|
|
||||||
"hidden": 1,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def get_data(filters):
|
|
||||||
data = []
|
|
||||||
|
|
||||||
# Validate if vat settings exist
|
|
||||||
company = filters.get("company")
|
|
||||||
company_currency = frappe.get_cached_value("Company", company, "default_currency")
|
|
||||||
|
|
||||||
if frappe.db.exists("KSA VAT Setting", company) is None:
|
|
||||||
url = get_url_to_list("KSA VAT Setting")
|
|
||||||
frappe.msgprint(_('Create <a href="{}">KSA VAT Setting</a> for this company').format(url))
|
|
||||||
return data
|
|
||||||
|
|
||||||
ksa_vat_setting = frappe.get_doc("KSA VAT Setting", company)
|
|
||||||
|
|
||||||
# Sales Heading
|
|
||||||
append_data(data, "VAT on Sales", "", "", "", company_currency)
|
|
||||||
|
|
||||||
grand_total_taxable_amount = 0
|
|
||||||
grand_total_taxable_adjustment_amount = 0
|
|
||||||
grand_total_tax = 0
|
|
||||||
|
|
||||||
for vat_setting in ksa_vat_setting.ksa_vat_sales_accounts:
|
|
||||||
(
|
|
||||||
total_taxable_amount,
|
|
||||||
total_taxable_adjustment_amount,
|
|
||||||
total_tax,
|
|
||||||
) = get_tax_data_for_each_vat_setting(vat_setting, filters, "Sales Invoice")
|
|
||||||
|
|
||||||
# Adding results to data
|
|
||||||
append_data(
|
|
||||||
data,
|
|
||||||
vat_setting.title,
|
|
||||||
total_taxable_amount,
|
|
||||||
total_taxable_adjustment_amount,
|
|
||||||
total_tax,
|
|
||||||
company_currency,
|
|
||||||
)
|
|
||||||
|
|
||||||
grand_total_taxable_amount += total_taxable_amount
|
|
||||||
grand_total_taxable_adjustment_amount += total_taxable_adjustment_amount
|
|
||||||
grand_total_tax += total_tax
|
|
||||||
|
|
||||||
# Sales Grand Total
|
|
||||||
append_data(
|
|
||||||
data,
|
|
||||||
"Grand Total",
|
|
||||||
grand_total_taxable_amount,
|
|
||||||
grand_total_taxable_adjustment_amount,
|
|
||||||
grand_total_tax,
|
|
||||||
company_currency,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Blank Line
|
|
||||||
append_data(data, "", "", "", "", company_currency)
|
|
||||||
|
|
||||||
# Purchase Heading
|
|
||||||
append_data(data, "VAT on Purchases", "", "", "", company_currency)
|
|
||||||
|
|
||||||
grand_total_taxable_amount = 0
|
|
||||||
grand_total_taxable_adjustment_amount = 0
|
|
||||||
grand_total_tax = 0
|
|
||||||
|
|
||||||
for vat_setting in ksa_vat_setting.ksa_vat_purchase_accounts:
|
|
||||||
(
|
|
||||||
total_taxable_amount,
|
|
||||||
total_taxable_adjustment_amount,
|
|
||||||
total_tax,
|
|
||||||
) = get_tax_data_for_each_vat_setting(vat_setting, filters, "Purchase Invoice")
|
|
||||||
|
|
||||||
# Adding results to data
|
|
||||||
append_data(
|
|
||||||
data,
|
|
||||||
vat_setting.title,
|
|
||||||
total_taxable_amount,
|
|
||||||
total_taxable_adjustment_amount,
|
|
||||||
total_tax,
|
|
||||||
company_currency,
|
|
||||||
)
|
|
||||||
|
|
||||||
grand_total_taxable_amount += total_taxable_amount
|
|
||||||
grand_total_taxable_adjustment_amount += total_taxable_adjustment_amount
|
|
||||||
grand_total_tax += total_tax
|
|
||||||
|
|
||||||
# Purchase Grand Total
|
|
||||||
append_data(
|
|
||||||
data,
|
|
||||||
"Grand Total",
|
|
||||||
grand_total_taxable_amount,
|
|
||||||
grand_total_taxable_adjustment_amount,
|
|
||||||
grand_total_tax,
|
|
||||||
company_currency,
|
|
||||||
)
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
def get_tax_data_for_each_vat_setting(vat_setting, filters, doctype):
|
|
||||||
"""
|
|
||||||
(KSA, {filters}, 'Sales Invoice') => 500, 153, 10 \n
|
|
||||||
calculates and returns \n
|
|
||||||
total_taxable_amount, total_taxable_adjustment_amount, total_tax"""
|
|
||||||
from_date = filters.get("from_date")
|
|
||||||
to_date = filters.get("to_date")
|
|
||||||
|
|
||||||
# Initiate variables
|
|
||||||
total_taxable_amount = 0
|
|
||||||
total_taxable_adjustment_amount = 0
|
|
||||||
total_tax = 0
|
|
||||||
# Fetch All Invoices
|
|
||||||
invoices = frappe.get_all(
|
|
||||||
doctype,
|
|
||||||
filters={"docstatus": 1, "posting_date": ["between", [from_date, to_date]]},
|
|
||||||
fields=["name", "is_return"],
|
|
||||||
)
|
|
||||||
|
|
||||||
for invoice in invoices:
|
|
||||||
invoice_items = frappe.get_all(
|
|
||||||
f"{doctype} Item",
|
|
||||||
filters={
|
|
||||||
"docstatus": 1,
|
|
||||||
"parent": invoice.name,
|
|
||||||
"item_tax_template": vat_setting.item_tax_template,
|
|
||||||
},
|
|
||||||
fields=["item_code", "net_amount"],
|
|
||||||
)
|
|
||||||
|
|
||||||
for item in invoice_items:
|
|
||||||
# Summing up total taxable amount
|
|
||||||
if invoice.is_return == 0:
|
|
||||||
total_taxable_amount += item.net_amount
|
|
||||||
|
|
||||||
if invoice.is_return == 1:
|
|
||||||
total_taxable_adjustment_amount += item.net_amount
|
|
||||||
|
|
||||||
# Summing up total tax
|
|
||||||
total_tax += get_tax_amount(item.item_code, vat_setting.account, doctype, invoice.name)
|
|
||||||
|
|
||||||
return total_taxable_amount, total_taxable_adjustment_amount, total_tax
|
|
||||||
|
|
||||||
|
|
||||||
def append_data(data, title, amount, adjustment_amount, vat_amount, company_currency):
|
|
||||||
"""Returns data with appended value."""
|
|
||||||
data.append(
|
|
||||||
{
|
|
||||||
"title": _(title),
|
|
||||||
"amount": amount,
|
|
||||||
"adjustment_amount": adjustment_amount,
|
|
||||||
"vat_amount": vat_amount,
|
|
||||||
"currency": company_currency,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_tax_amount(item_code, account_head, doctype, parent):
|
|
||||||
if doctype == "Sales Invoice":
|
|
||||||
tax_doctype = "Sales Taxes and Charges"
|
|
||||||
|
|
||||||
elif doctype == "Purchase Invoice":
|
|
||||||
tax_doctype = "Purchase Taxes and Charges"
|
|
||||||
|
|
||||||
item_wise_tax_detail = frappe.get_value(
|
|
||||||
tax_doctype,
|
|
||||||
{"docstatus": 1, "parent": parent, "account_head": account_head},
|
|
||||||
"item_wise_tax_detail",
|
|
||||||
)
|
|
||||||
|
|
||||||
tax_amount = 0
|
|
||||||
if item_wise_tax_detail and len(item_wise_tax_detail) > 0:
|
|
||||||
item_wise_tax_detail = json.loads(item_wise_tax_detail)
|
|
||||||
for key, value in item_wise_tax_detail.items():
|
|
||||||
if key == item_code:
|
|
||||||
tax_amount = value[1]
|
|
||||||
break
|
|
||||||
|
|
||||||
return tax_amount
|
|
@ -1,173 +0,0 @@
|
|||||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# License: GNU General Public License v3. See license.txt
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
from frappe.permissions import add_permission, update_permission_property
|
|
||||||
from erpnext.regional.saudi_arabia.wizard.operations.setup_ksa_vat_setting import (
|
|
||||||
create_ksa_vat_setting,
|
|
||||||
)
|
|
||||||
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
|
|
||||||
|
|
||||||
|
|
||||||
def setup(company=None, patch=True):
|
|
||||||
add_print_formats()
|
|
||||||
add_permissions()
|
|
||||||
make_custom_fields()
|
|
||||||
|
|
||||||
|
|
||||||
def add_print_formats():
|
|
||||||
frappe.reload_doc("regional", "print_format", "detailed_tax_invoice", force=True)
|
|
||||||
frappe.reload_doc("regional", "print_format", "simplified_tax_invoice", force=True)
|
|
||||||
frappe.reload_doc("regional", "print_format", "tax_invoice", force=True)
|
|
||||||
frappe.reload_doc("regional", "print_format", "ksa_vat_invoice", force=True)
|
|
||||||
frappe.reload_doc("regional", "print_format", "ksa_pos_invoice", force=True)
|
|
||||||
|
|
||||||
for d in (
|
|
||||||
"Simplified Tax Invoice",
|
|
||||||
"Detailed Tax Invoice",
|
|
||||||
"Tax Invoice",
|
|
||||||
"KSA VAT Invoice",
|
|
||||||
"KSA POS Invoice",
|
|
||||||
):
|
|
||||||
frappe.db.set_value("Print Format", d, "disabled", 0)
|
|
||||||
|
|
||||||
|
|
||||||
def add_permissions():
|
|
||||||
"""Add Permissions for KSA VAT Setting."""
|
|
||||||
add_permission("KSA VAT Setting", "All", 0)
|
|
||||||
for role in ("Accounts Manager", "Accounts User", "System Manager"):
|
|
||||||
add_permission("KSA VAT Setting", role, 0)
|
|
||||||
update_permission_property("KSA VAT Setting", role, 0, "write", 1)
|
|
||||||
update_permission_property("KSA VAT Setting", role, 0, "create", 1)
|
|
||||||
|
|
||||||
"""Enable KSA VAT Report"""
|
|
||||||
frappe.db.set_value("Report", "KSA VAT", "disabled", 0)
|
|
||||||
|
|
||||||
|
|
||||||
def make_custom_fields():
|
|
||||||
"""Create Custom fields
|
|
||||||
- QR code Image file
|
|
||||||
- Company Name in Arabic
|
|
||||||
- Address in Arabic
|
|
||||||
"""
|
|
||||||
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,
|
|
||||||
)
|
|
||||||
|
|
||||||
purchase_invoice_fields = [
|
|
||||||
dict(
|
|
||||||
fieldname="company_trn",
|
|
||||||
label="Company TRN",
|
|
||||||
fieldtype="Read Only",
|
|
||||||
insert_after="shipping_address",
|
|
||||||
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,
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
sales_invoice_fields = [
|
|
||||||
dict(
|
|
||||||
fieldname="company_trn",
|
|
||||||
label="Company TRN",
|
|
||||||
fieldtype="Read Only",
|
|
||||||
insert_after="company_address",
|
|
||||||
fetch_from="company.tax_id",
|
|
||||||
print_hide=1,
|
|
||||||
),
|
|
||||||
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="ksa_einv_qr",
|
|
||||||
label="KSA E-Invoicing QR",
|
|
||||||
fieldtype="Attach Image",
|
|
||||||
read_only=1,
|
|
||||||
no_copy=1,
|
|
||||||
hidden=1,
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
custom_fields = {
|
|
||||||
"Item": [is_zero_rated, is_exempt],
|
|
||||||
"Customer": [
|
|
||||||
dict(
|
|
||||||
fieldname="customer_name_in_arabic",
|
|
||||||
label="Customer Name in Arabic",
|
|
||||||
fieldtype="Data",
|
|
||||||
insert_after="customer_name",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
"Supplier": [
|
|
||||||
dict(
|
|
||||||
fieldname="supplier_name_in_arabic",
|
|
||||||
label="Supplier Name in Arabic",
|
|
||||||
fieldtype="Data",
|
|
||||||
insert_after="supplier_name",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
"Purchase Invoice": purchase_invoice_fields,
|
|
||||||
"Purchase Order": purchase_invoice_fields,
|
|
||||||
"Purchase Receipt": purchase_invoice_fields,
|
|
||||||
"Sales Invoice": sales_invoice_fields,
|
|
||||||
"POS Invoice": sales_invoice_fields,
|
|
||||||
"Sales Order": sales_invoice_fields,
|
|
||||||
"Delivery Note": sales_invoice_fields,
|
|
||||||
"Sales Invoice Item": [is_zero_rated, is_exempt],
|
|
||||||
"POS Invoice Item": [is_zero_rated, is_exempt],
|
|
||||||
"Purchase Invoice Item": [is_zero_rated, is_exempt],
|
|
||||||
"Sales Order Item": [is_zero_rated, is_exempt],
|
|
||||||
"Delivery Note Item": [is_zero_rated, is_exempt],
|
|
||||||
"Quotation Item": [is_zero_rated, is_exempt],
|
|
||||||
"Purchase Order Item": [is_zero_rated, is_exempt],
|
|
||||||
"Purchase Receipt Item": [is_zero_rated, is_exempt],
|
|
||||||
"Supplier Quotation Item": [is_zero_rated, is_exempt],
|
|
||||||
"Address": [
|
|
||||||
dict(
|
|
||||||
fieldname="address_in_arabic",
|
|
||||||
label="Address in Arabic",
|
|
||||||
fieldtype="Data",
|
|
||||||
insert_after="address_line2",
|
|
||||||
)
|
|
||||||
],
|
|
||||||
"Company": [
|
|
||||||
dict(
|
|
||||||
fieldname="company_name_in_arabic",
|
|
||||||
label="Company Name In Arabic",
|
|
||||||
fieldtype="Data",
|
|
||||||
insert_after="company_name",
|
|
||||||
)
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
create_custom_fields(custom_fields, ignore_validate=True, update=True)
|
|
||||||
|
|
||||||
|
|
||||||
def update_regional_tax_settings(country, company):
|
|
||||||
create_ksa_vat_setting(company)
|
|
@ -1,169 +0,0 @@
|
|||||||
import io
|
|
||||||
import os
|
|
||||||
from base64 import b64encode
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
from frappe import _
|
|
||||||
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
|
|
||||||
from frappe.utils.data import add_to_date, get_time, getdate
|
|
||||||
from pyqrcode import create as qr_create
|
|
||||||
|
|
||||||
from erpnext import get_region
|
|
||||||
|
|
||||||
|
|
||||||
def create_qr_code(doc, method=None):
|
|
||||||
region = get_region(doc.company)
|
|
||||||
if region not in ["Saudi Arabia"]:
|
|
||||||
return
|
|
||||||
|
|
||||||
# if QR Code field not present, create it. Invoices without QR are invalid as per law.
|
|
||||||
if not hasattr(doc, "ksa_einv_qr"):
|
|
||||||
create_custom_fields(
|
|
||||||
{
|
|
||||||
doc.doctype: [
|
|
||||||
dict(
|
|
||||||
fieldname="ksa_einv_qr",
|
|
||||||
label="KSA E-Invoicing QR",
|
|
||||||
fieldtype="Attach Image",
|
|
||||||
read_only=1,
|
|
||||||
no_copy=1,
|
|
||||||
hidden=1,
|
|
||||||
)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Don't create QR Code if it already exists
|
|
||||||
qr_code = doc.get("ksa_einv_qr")
|
|
||||||
if qr_code and frappe.db.exists({"doctype": "File", "file_url": qr_code}):
|
|
||||||
return
|
|
||||||
|
|
||||||
meta = frappe.get_meta(doc.doctype)
|
|
||||||
|
|
||||||
if "ksa_einv_qr" in [d.fieldname for d in meta.get_image_fields()]:
|
|
||||||
"""TLV conversion for
|
|
||||||
1. Seller's Name
|
|
||||||
2. VAT Number
|
|
||||||
3. Time Stamp
|
|
||||||
4. Invoice Amount
|
|
||||||
5. VAT Amount
|
|
||||||
"""
|
|
||||||
tlv_array = []
|
|
||||||
# Sellers Name
|
|
||||||
|
|
||||||
seller_name = frappe.db.get_value("Company", doc.company, "company_name_in_arabic")
|
|
||||||
|
|
||||||
if not seller_name:
|
|
||||||
frappe.throw(_("Arabic name missing for {} in the company document").format(doc.company))
|
|
||||||
|
|
||||||
tag = bytes([1]).hex()
|
|
||||||
length = bytes([len(seller_name.encode("utf-8"))]).hex()
|
|
||||||
value = seller_name.encode("utf-8").hex()
|
|
||||||
tlv_array.append("".join([tag, length, value]))
|
|
||||||
|
|
||||||
# VAT Number
|
|
||||||
tax_id = frappe.db.get_value("Company", doc.company, "tax_id")
|
|
||||||
if not tax_id:
|
|
||||||
frappe.throw(_("Tax ID missing for {} in the company document").format(doc.company))
|
|
||||||
|
|
||||||
tag = bytes([2]).hex()
|
|
||||||
length = bytes([len(tax_id)]).hex()
|
|
||||||
value = tax_id.encode("utf-8").hex()
|
|
||||||
tlv_array.append("".join([tag, length, value]))
|
|
||||||
|
|
||||||
# Time Stamp
|
|
||||||
posting_date = getdate(doc.posting_date)
|
|
||||||
time = get_time(doc.posting_time)
|
|
||||||
seconds = time.hour * 60 * 60 + time.minute * 60 + time.second
|
|
||||||
time_stamp = add_to_date(posting_date, seconds=seconds)
|
|
||||||
time_stamp = time_stamp.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
||||||
|
|
||||||
tag = bytes([3]).hex()
|
|
||||||
length = bytes([len(time_stamp)]).hex()
|
|
||||||
value = time_stamp.encode("utf-8").hex()
|
|
||||||
tlv_array.append("".join([tag, length, value]))
|
|
||||||
|
|
||||||
# Invoice Amount
|
|
||||||
invoice_amount = str(doc.base_grand_total)
|
|
||||||
tag = bytes([4]).hex()
|
|
||||||
length = bytes([len(invoice_amount)]).hex()
|
|
||||||
value = invoice_amount.encode("utf-8").hex()
|
|
||||||
tlv_array.append("".join([tag, length, value]))
|
|
||||||
|
|
||||||
# VAT Amount
|
|
||||||
vat_amount = str(get_vat_amount(doc))
|
|
||||||
|
|
||||||
tag = bytes([5]).hex()
|
|
||||||
length = bytes([len(vat_amount)]).hex()
|
|
||||||
value = vat_amount.encode("utf-8").hex()
|
|
||||||
tlv_array.append("".join([tag, length, value]))
|
|
||||||
|
|
||||||
# Joining bytes into one
|
|
||||||
tlv_buff = "".join(tlv_array)
|
|
||||||
|
|
||||||
# base64 conversion for QR Code
|
|
||||||
base64_string = b64encode(bytes.fromhex(tlv_buff)).decode()
|
|
||||||
|
|
||||||
qr_image = io.BytesIO()
|
|
||||||
url = qr_create(base64_string, error="L")
|
|
||||||
url.png(qr_image, scale=2, quiet_zone=1)
|
|
||||||
|
|
||||||
name = frappe.generate_hash(doc.name, 5)
|
|
||||||
|
|
||||||
# making file
|
|
||||||
filename = f"QRCode-{name}.png".replace(os.path.sep, "__")
|
|
||||||
_file = frappe.get_doc(
|
|
||||||
{
|
|
||||||
"doctype": "File",
|
|
||||||
"file_name": filename,
|
|
||||||
"is_private": 0,
|
|
||||||
"content": qr_image.getvalue(),
|
|
||||||
"attached_to_doctype": doc.get("doctype"),
|
|
||||||
"attached_to_name": doc.get("name"),
|
|
||||||
"attached_to_field": "ksa_einv_qr",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
_file.save()
|
|
||||||
|
|
||||||
# assigning to document
|
|
||||||
doc.db_set("ksa_einv_qr", _file.file_url)
|
|
||||||
doc.notify_update()
|
|
||||||
|
|
||||||
|
|
||||||
def get_vat_amount(doc):
|
|
||||||
vat_settings = frappe.db.get_value("KSA VAT Setting", {"company": doc.company})
|
|
||||||
vat_accounts = []
|
|
||||||
vat_amount = 0
|
|
||||||
|
|
||||||
if vat_settings:
|
|
||||||
vat_settings_doc = frappe.get_cached_doc("KSA VAT Setting", vat_settings)
|
|
||||||
|
|
||||||
for row in vat_settings_doc.get("ksa_vat_sales_accounts"):
|
|
||||||
vat_accounts.append(row.account)
|
|
||||||
|
|
||||||
for tax in doc.get("taxes"):
|
|
||||||
if tax.account_head in vat_accounts:
|
|
||||||
vat_amount += tax.base_tax_amount
|
|
||||||
|
|
||||||
return vat_amount
|
|
||||||
|
|
||||||
|
|
||||||
def delete_qr_code_file(doc, method=None):
|
|
||||||
region = get_region(doc.company)
|
|
||||||
if region not in ["Saudi Arabia"]:
|
|
||||||
return
|
|
||||||
|
|
||||||
if hasattr(doc, "ksa_einv_qr"):
|
|
||||||
if doc.get("ksa_einv_qr"):
|
|
||||||
file_doc = frappe.get_list("File", {"file_url": doc.get("ksa_einv_qr")})
|
|
||||||
if len(file_doc):
|
|
||||||
frappe.delete_doc("File", file_doc[0].name)
|
|
||||||
|
|
||||||
|
|
||||||
def delete_vat_settings_for_company(doc, method=None):
|
|
||||||
if doc.country != "Saudi Arabia":
|
|
||||||
return
|
|
||||||
|
|
||||||
if frappe.db.exists("KSA VAT Setting", doc.name):
|
|
||||||
frappe.delete_doc("KSA VAT Setting", doc.name)
|
|
@ -1,47 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"type": "Sales Account",
|
|
||||||
"accounts": [
|
|
||||||
{
|
|
||||||
"title": "Standard rated Sales",
|
|
||||||
"item_tax_template": "KSA VAT 5%",
|
|
||||||
"account": "VAT 5%"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Zero rated domestic sales",
|
|
||||||
"item_tax_template": "KSA VAT Zero",
|
|
||||||
"account": "VAT Zero"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Exempted sales",
|
|
||||||
"item_tax_template": "KSA VAT Exempted",
|
|
||||||
"account": "VAT Exempted"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Purchase Account",
|
|
||||||
"accounts": [
|
|
||||||
{
|
|
||||||
"title": "Standard rated domestic purchases",
|
|
||||||
"item_tax_template": "KSA VAT 5%",
|
|
||||||
"account": "VAT 5%"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Imports subject to VAT paid at customs",
|
|
||||||
"item_tax_template": "KSA Excise 50%",
|
|
||||||
"account": "Excise 50%"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Zero rated purchases",
|
|
||||||
"item_tax_template": "KSA VAT Zero",
|
|
||||||
"account": "VAT Zero"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Exempted purchases",
|
|
||||||
"item_tax_template": "KSA VAT Exempted",
|
|
||||||
"account": "VAT Exempted"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,46 +0,0 @@
|
|||||||
import json
|
|
||||||
import os
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
|
|
||||||
|
|
||||||
def create_ksa_vat_setting(company):
|
|
||||||
"""On creation of first company. Creates KSA VAT Setting"""
|
|
||||||
|
|
||||||
company = frappe.get_doc("Company", company)
|
|
||||||
|
|
||||||
file_path = os.path.join(os.path.dirname(__file__), "..", "data", "ksa_vat_settings.json")
|
|
||||||
with open(file_path, "r") as json_file:
|
|
||||||
account_data = json.load(json_file)
|
|
||||||
|
|
||||||
# Creating KSA VAT Setting
|
|
||||||
ksa_vat_setting = frappe.get_doc({"doctype": "KSA VAT Setting", "company": company.name})
|
|
||||||
|
|
||||||
for data in account_data:
|
|
||||||
if data["type"] == "Sales Account":
|
|
||||||
for row in data["accounts"]:
|
|
||||||
item_tax_template = row["item_tax_template"]
|
|
||||||
account = row["account"]
|
|
||||||
ksa_vat_setting.append(
|
|
||||||
"ksa_vat_sales_accounts",
|
|
||||||
{
|
|
||||||
"title": row["title"],
|
|
||||||
"item_tax_template": f"{item_tax_template} - {company.abbr}",
|
|
||||||
"account": f"{account} - {company.abbr}",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
elif data["type"] == "Purchase Account":
|
|
||||||
for row in data["accounts"]:
|
|
||||||
item_tax_template = row["item_tax_template"]
|
|
||||||
account = row["account"]
|
|
||||||
ksa_vat_setting.append(
|
|
||||||
"ksa_vat_purchase_accounts",
|
|
||||||
{
|
|
||||||
"title": row["title"],
|
|
||||||
"item_tax_template": f"{item_tax_template} - {company.abbr}",
|
|
||||||
"account": f"{account} - {company.abbr}",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
ksa_vat_setting.save()
|
|
@ -4015,34 +4015,6 @@
|
|||||||
"tax_rate": 18.00
|
"tax_rate": 18.00
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"Saudi Arabia": {
|
|
||||||
"KSA VAT 15%": {
|
|
||||||
"account_name": "VAT 15%",
|
|
||||||
"tax_rate": 15.00
|
|
||||||
},
|
|
||||||
"KSA VAT 5%": {
|
|
||||||
"account_name": "VAT 5%",
|
|
||||||
"tax_rate": 5.00
|
|
||||||
},
|
|
||||||
"KSA VAT Zero": {
|
|
||||||
"account_name": "VAT Zero",
|
|
||||||
"tax_rate": 0.00
|
|
||||||
},
|
|
||||||
"KSA VAT Exempted": {
|
|
||||||
"account_name": "VAT Exempted",
|
|
||||||
"tax_rate": 0.00
|
|
||||||
},
|
|
||||||
"KSA Excise 50%": {
|
|
||||||
"account_name": "Excise 50%",
|
|
||||||
"tax_rate": 50.00
|
|
||||||
},
|
|
||||||
"KSA Excise 100%": {
|
|
||||||
"account_name": "Excise 100%",
|
|
||||||
"tax_rate": 100.00
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"Serbia": {
|
"Serbia": {
|
||||||
"Serbia Tax": {
|
"Serbia Tax": {
|
||||||
"account_name": "VAT",
|
"account_name": "VAT",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user