├── license.txt
├── thai_tax
├── config
│ ├── __init__.py
│ ├── desktop.py
│ └── docs.py
├── modules.txt
├── public
│ ├── .gitkeep
│ ├── images
│ │ └── wht
│ │ │ └── WithholdingTaxCert.png
│ └── js
│ │ ├── expense_claim.js
│ │ ├── sales_tax_invoice.js
│ │ ├── purchase_tax_invoice.js
│ │ ├── address.js
│ │ ├── journal_entry.js
│ │ ├── withholding_tax_cert.js
│ │ └── payment_entry.js
├── templates
│ ├── __init__.py
│ └── pages
│ │ └── __init__.py
├── thai_tax
│ ├── __init__.py
│ ├── doctype
│ │ ├── __init__.py
│ │ ├── purchase_tax_invoice
│ │ │ ├── __init__.py
│ │ │ ├── purchase_tax_invoice.js
│ │ │ ├── test_purchase_tax_invoice.py
│ │ │ ├── purchase_tax_invoice.py
│ │ │ └── purchase_tax_invoice.json
│ │ ├── sales_tax_invoice
│ │ │ ├── __init__.py
│ │ │ ├── sales_tax_invoice.js
│ │ │ ├── test_sales_tax_invoice.py
│ │ │ ├── sales_tax_invoice.py
│ │ │ └── sales_tax_invoice.json
│ │ ├── tax_invoice_settings
│ │ │ ├── __init__.py
│ │ │ ├── test_tax_invoice_settings.py
│ │ │ ├── tax_invoice_settings.py
│ │ │ ├── tax_invoice_settings.js
│ │ │ └── tax_invoice_settings.json
│ │ ├── withholding_tax_cert
│ │ │ ├── __init__.py
│ │ │ ├── test_withholding_tax_cert.py
│ │ │ ├── withholding_tax_cert.py
│ │ │ ├── withholding_tax_cert.js
│ │ │ └── withholding_tax_cert.json
│ │ ├── withholding_tax_type
│ │ │ ├── __init__.py
│ │ │ ├── test_withholding_tax_type.py
│ │ │ ├── withholding_tax_type.js
│ │ │ ├── withholding_tax_type.py
│ │ │ └── withholding_tax_type.json
│ │ ├── withholding_tax_items
│ │ │ ├── __init__.py
│ │ │ ├── withholding_tax_items.py
│ │ │ └── withholding_tax_items.json
│ │ ├── withholding_tax_setting
│ │ │ ├── __init__.py
│ │ │ ├── withholding_tax_setting.js
│ │ │ ├── test_withholding_tax_setting.py
│ │ │ ├── withholding_tax_setting.py
│ │ │ └── withholding_tax_setting.json
│ │ └── journal_entry_tax_invoice_detail
│ │ │ ├── __init__.py
│ │ │ ├── journal_entry_tax_invoice_detail.py
│ │ │ └── journal_entry_tax_invoice_detail.json
│ ├── report
│ │ ├── __init__.py
│ │ ├── pnd3
│ │ │ ├── __init__.py
│ │ │ ├── pnd3.json
│ │ │ ├── pnd3.js
│ │ │ └── pnd3.py
│ │ ├── pnd53
│ │ │ ├── __init__.py
│ │ │ ├── pnd53.json
│ │ │ ├── pnd53.js
│ │ │ └── pnd53.py
│ │ ├── sales_tax_report
│ │ │ ├── __init__.py
│ │ │ ├── sales_tax_report.json
│ │ │ ├── sales_tax_report.js
│ │ │ └── sales_tax_report.py
│ │ └── purchase_tax_report
│ │ │ ├── __init__.py
│ │ │ ├── purchase_tax_report.json
│ │ │ ├── purchase_tax_report.js
│ │ │ └── purchase_tax_report.py
│ ├── print_format
│ │ ├── __init__.py
│ │ └── withholding_tax_cert
│ │ │ ├── __init__.py
│ │ │ └── withholding_tax_cert.json
│ ├── onboarding_step
│ │ ├── add_taxes_to_chart_of_account
│ │ │ └── add_taxes_to_chart_of_account.json
│ │ ├── add_withholding_tax_type
│ │ │ └── add_withholding_tax_type.json
│ │ ├── tax_invoice_setting
│ │ │ └── tax_invoice_setting.json
│ │ ├── tax_report
│ │ │ └── tax_report.json
│ │ ├── browse_withholding_tax_cert
│ │ │ └── browse_withholding_tax_cert.json
│ │ ├── asset_item
│ │ │ └── asset_item.json
│ │ ├── browse_sales_tax_invoices
│ │ │ └── browse_sales_tax_invoices.json
│ │ ├── browse_purchase_tax_invoices
│ │ │ └── browse_purchase_tax_invoices.json
│ │ ├── withholding_tax_report_(pnd)
│ │ │ └── withholding_tax_report_(pnd).json
│ │ ├── company_set_up
│ │ │ └── company_set_up.json
│ │ └── add_thai_tax_accounts
│ │ │ └── add_thai_tax_accounts.json
│ ├── module_onboarding
│ │ └── thai_tax
│ │ │ └── thai_tax.json
│ ├── form_tour
│ │ └── tax_invoice_settings
│ │ │ └── tax_invoice_settings.json
│ └── workspace
│ │ └── thai_tax
│ │ └── thai_tax.json
├── __init__.py
├── patches.txt
├── custom
│ ├── gl_entry.py
│ ├── unreconcile_payment.py
│ ├── queries.py
│ ├── journal_entry.py
│ ├── dashboard_overrides.py
│ ├── employee_advance.py
│ ├── payment_entry.py
│ └── custom_api.py
├── uninstall.py
├── install.py
├── utils.py
├── hooks.py
└── constants.py
├── requirements.txt
├── .gitignore
├── .editorconfig
├── MANIFEST.in
├── setup.py
├── .flake8
├── .pre-commit-config.yaml
├── README.md
└── .eslintrc
/license.txt:
--------------------------------------------------------------------------------
1 | License: MIT
--------------------------------------------------------------------------------
/thai_tax/config/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/modules.txt:
--------------------------------------------------------------------------------
1 | Thai Tax
--------------------------------------------------------------------------------
/thai_tax/public/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | zeep
2 | pandas
--------------------------------------------------------------------------------
/thai_tax/templates/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/templates/pages/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/report/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/print_format/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/report/pnd3/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/report/pnd53/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/__init__.py:
--------------------------------------------------------------------------------
1 | __version__ = "0.0.1"
2 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/report/sales_tax_report/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/purchase_tax_invoice/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/sales_tax_invoice/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/tax_invoice_settings/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/withholding_tax_cert/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/withholding_tax_type/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/report/purchase_tax_report/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/withholding_tax_items/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/withholding_tax_setting/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/print_format/withholding_tax_cert/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/journal_entry_tax_invoice_detail/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.pyc
3 | *.egg-info
4 | *.swp
5 | tags
6 | thai_tax/docs/current
7 | node_modules/
--------------------------------------------------------------------------------
/thai_tax/patches.txt:
--------------------------------------------------------------------------------
1 | [pre_model_sync]
2 |
3 | [post_model_sync]
4 | execute:from thai_tax.install import after_install; after_install()
5 |
--------------------------------------------------------------------------------
/thai_tax/public/images/wht/WithholdingTaxCert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kittiu/thai_tax/HEAD/thai_tax/public/images/wht/WithholdingTaxCert.png
--------------------------------------------------------------------------------
/thai_tax/config/desktop.py:
--------------------------------------------------------------------------------
1 | from frappe import _
2 |
3 |
4 | def get_data():
5 | return [{"module_name": "Thai Tax", "type": "module", "label": _("Thai Tax")}]
6 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/sales_tax_invoice/sales_tax_invoice.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2023, Kitti U. and contributors
2 | // For license information, please see license.txt
3 |
4 | frappe.ui.form.on("Sales Tax Invoice", {
5 | // refresh: function(frm) {
6 | // }
7 | });
8 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/purchase_tax_invoice/purchase_tax_invoice.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2023, Kitti U. and contributors
2 | // For license information, please see license.txt
3 |
4 | frappe.ui.form.on("Purchase Tax Invoice", {
5 | // refresh: function(frm) {
6 | // }
7 | });
8 |
--------------------------------------------------------------------------------
/thai_tax/public/js/expense_claim.js:
--------------------------------------------------------------------------------
1 | frappe.ui.form.on("Expense Claim", {
2 | refresh(frm) {
3 | frm.set_query("company_tax_address", function () {
4 | return {
5 | filters: {
6 | is_your_company_address: true,
7 | },
8 | };
9 | });
10 | },
11 | });
12 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/withholding_tax_setting/withholding_tax_setting.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2023, Kitti U. and contributors
2 | // For license information, please see license.txt
3 |
4 | frappe.ui.form.on("Withholding Tax Setting", {
5 | // refresh: function(frm) {
6 | // }
7 | });
8 |
--------------------------------------------------------------------------------
/thai_tax/public/js/sales_tax_invoice.js:
--------------------------------------------------------------------------------
1 | frappe.ui.form.on("Sales Tax Invoice", {
2 | refresh(frm) {
3 | frm.set_query("company_tax_address", function () {
4 | return {
5 | filters: {
6 | is_your_company_address: true,
7 | },
8 | };
9 | });
10 | },
11 | });
12 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/sales_tax_invoice/test_sales_tax_invoice.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023, Kitti U. and Contributors
2 | # See license.txt
3 |
4 | # import frappe
5 | from frappe.tests.utils import FrappeTestCase
6 |
7 |
8 | class TestSalesTaxInvoice(FrappeTestCase):
9 | pass
10 |
--------------------------------------------------------------------------------
/thai_tax/public/js/purchase_tax_invoice.js:
--------------------------------------------------------------------------------
1 | frappe.ui.form.on("Purchase Tax Invoice", {
2 | refresh(frm) {
3 | frm.set_query("company_tax_address", function () {
4 | return {
5 | filters: {
6 | is_your_company_address: true,
7 | },
8 | };
9 | });
10 | },
11 | });
12 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/purchase_tax_invoice/test_purchase_tax_invoice.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023, Kitti U. and Contributors
2 | # See license.txt
3 |
4 | # import frappe
5 | from frappe.tests.utils import FrappeTestCase
6 |
7 |
8 | class TestPurchaseTaxInvoice(FrappeTestCase):
9 | pass
10 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/tax_invoice_settings/test_tax_invoice_settings.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023, Kitti U. and Contributors
2 | # See license.txt
3 |
4 | # import frappe
5 | from frappe.tests.utils import FrappeTestCase
6 |
7 |
8 | class TestTaxInvoiceSettings(FrappeTestCase):
9 | pass
10 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/withholding_tax_cert/test_withholding_tax_cert.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023, Kitti U. and Contributors
2 | # See license.txt
3 |
4 | # import frappe
5 | from frappe.tests.utils import FrappeTestCase
6 |
7 |
8 | class TestWithholdingTaxCert(FrappeTestCase):
9 | pass
10 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/withholding_tax_type/test_withholding_tax_type.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023, Kitti U. and Contributors
2 | # See license.txt
3 |
4 | # import frappe
5 | from frappe.tests.utils import FrappeTestCase
6 |
7 |
8 | class TestWithholdingTaxType(FrappeTestCase):
9 | pass
10 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/withholding_tax_setting/test_withholding_tax_setting.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023, Kitti U. and Contributors
2 | # See license.txt
3 |
4 | # import frappe
5 | from frappe.tests.utils import FrappeTestCase
6 |
7 |
8 | class TestWithholdingTaxSetting(FrappeTestCase):
9 | pass
10 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/tax_invoice_settings/tax_invoice_settings.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023, Kitti U. and contributors
2 | # For license information, please see license.txt
3 |
4 | # import frappe
5 | from frappe.model.document import Document
6 |
7 |
8 | class TaxInvoiceSettings(Document):
9 | pass
10 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/withholding_tax_cert/withholding_tax_cert.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023, Kitti U. and contributors
2 | # For license information, please see license.txt
3 |
4 | # import frappe
5 | from frappe.model.document import Document
6 |
7 |
8 | class WithholdingTaxCert(Document):
9 | pass
10 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/withholding_tax_items/withholding_tax_items.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023, Kitti U. and contributors
2 | # For license information, please see license.txt
3 |
4 | # import frappe
5 | from frappe.model.document import Document
6 |
7 |
8 | class WithholdingTaxItems(Document):
9 | pass
10 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/withholding_tax_setting/withholding_tax_setting.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023, Kitti U. and contributors
2 | # For license information, please see license.txt
3 |
4 | # import frappe
5 | from frappe.model.document import Document
6 |
7 |
8 | class WithholdingTaxSetting(Document):
9 | pass
10 |
--------------------------------------------------------------------------------
/thai_tax/custom/gl_entry.py:
--------------------------------------------------------------------------------
1 | import frappe
2 |
3 |
4 | def rename_gl_entry_in_tax_invoice(newname, oldname):
5 | for tax_invoice in ["Sales Tax Invoice", "Purchase Tax Invoice"]:
6 | frappe.db.sql(
7 | f"UPDATE `tab{tax_invoice}` SET gl_entry = %s where gl_entry = %s",
8 | (newname, oldname)
9 | )
10 |
--------------------------------------------------------------------------------
/thai_tax/config/docs.py:
--------------------------------------------------------------------------------
1 | """
2 | Configuration for docs
3 | """
4 |
5 | # source_link = "https://github.com/[org_name]/thai_tax"
6 | # headline = "App that does everything"
7 | # sub_heading = "Yes, you got that right the first time, everything"
8 |
9 |
10 | def get_context(context):
11 | context.brand_html = "Thai Tax"
12 |
--------------------------------------------------------------------------------
/thai_tax/custom/unreconcile_payment.py:
--------------------------------------------------------------------------------
1 | from .payment_entry import reconcile_undue_tax_gls
2 |
3 |
4 | def unreconcile_undue_tax(doc, method):
5 | """ If bs_reconcile is installed, unreconcile undue tax gls """
6 | vouchers = [doc.voucher_no] + [r.reference_name for r in doc.allocations]
7 | reconcile_undue_tax_gls(vouchers, unreconcile=True)
8 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/journal_entry_tax_invoice_detail/journal_entry_tax_invoice_detail.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023, Kitti U. and contributors
2 | # For license information, please see license.txt
3 |
4 | # import frappe
5 | from frappe.model.document import Document
6 |
7 |
8 | class JournalEntryTaxInvoiceDetail(Document):
9 | pass
10 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Root editor config file
2 | root = true
3 |
4 | # Common settings
5 | [*]
6 | end_of_line = lf
7 | insert_final_newline = true
8 | trim_trailing_whitespace = true
9 | charset = utf-8
10 |
11 | # python, js indentation settings
12 | [{*.py,*.js,*.vue,*.css,*.scss,*.html}]
13 | indent_style = tab
14 | indent_size = 4
15 | max_line_length = 99
16 |
--------------------------------------------------------------------------------
/thai_tax/custom/queries.py:
--------------------------------------------------------------------------------
1 | import frappe
2 |
3 |
4 | @frappe.whitelist()
5 | @frappe.validate_and_sanitize_search_inputs
6 | def undue_tax_query(doctype, txt, searchfield, start, page_len, filters):
7 | setting = frappe.get_doc("Tax Invoice Settings")
8 | res = list({setting.purchase_tax_account_undue, setting.sales_tax_account_undue})
9 | return [[x] for x in res if x]
10 |
--------------------------------------------------------------------------------
/thai_tax/custom/journal_entry.py:
--------------------------------------------------------------------------------
1 | import frappe
2 | from .payment_entry import reconcile_undue_tax_gls
3 |
4 |
5 | def reconcile_undue_tax(jv, method):
6 | """ If bs_reconcile is installed, reconcile undue tax gls """
7 | if jv.for_payment:
8 | pay = frappe.get_doc("Payment Entry", jv.for_payment)
9 | vouchers = [jv.name, pay.name] + [r.reference_name for r in pay.references]
10 | reconcile_undue_tax_gls(vouchers)
11 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/withholding_tax_cert/withholding_tax_cert.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2023, Kitti U. and contributors
2 | // For license information, please see license.txt
3 |
4 | frappe.ui.form.on("Withholding Tax Cert", {
5 | refresh(frm) {
6 | frm.set_query("supplier_address", function () {
7 | return {
8 | filters: {
9 | link_doctype: "Supplier",
10 | link_name: frm.doc.supplier,
11 | },
12 | };
13 | });
14 | },
15 | });
16 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/withholding_tax_type/withholding_tax_type.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2023, Kitti U. and contributors
2 | // For license information, please see license.txt
3 |
4 | frappe.ui.form.on("Withholding Tax Type", {
5 | refresh: function (frm) {
6 | if (frm.doc.name === "Auto" && !frappe.boot.developer_mode) {
7 | // make the document read-only
8 | frm.disable_form();
9 | } else {
10 | frm.enable_save();
11 | }
12 | },
13 | });
14 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include MANIFEST.in
2 | include requirements.txt
3 | include *.json
4 | include *.md
5 | include *.py
6 | include *.txt
7 | recursive-include thai_tax *.css
8 | recursive-include thai_tax *.csv
9 | recursive-include thai_tax *.html
10 | recursive-include thai_tax *.ico
11 | recursive-include thai_tax *.js
12 | recursive-include thai_tax *.json
13 | recursive-include thai_tax *.md
14 | recursive-include thai_tax *.png
15 | recursive-include thai_tax *.py
16 | recursive-include thai_tax *.svg
17 | recursive-include thai_tax *.txt
18 | recursive-exclude thai_tax *.pyc
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import find_packages, setup
2 |
3 | with open("requirements.txt") as f:
4 | install_requires = f.read().strip().split("\n")
5 |
6 | # get version from __version__ variable in thai_tax/__init__.py
7 | from thai_tax import __version__ as version
8 |
9 | setup(
10 | name="thai_tax",
11 | version=version,
12 | description="Thailand Taxation - VAT, WHT",
13 | author="Kitti U.",
14 | author_email="kittiu@gmail.com",
15 | packages=find_packages(),
16 | zip_safe=False,
17 | include_package_data=True,
18 | install_requires=install_requires,
19 | )
20 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/withholding_tax_type/withholding_tax_type.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023, Kitti U. and contributors
2 | # For license information, please see license.txt
3 |
4 | import frappe
5 | from frappe import _
6 | from frappe.model.document import Document
7 | from frappe.utils import cint, cstr
8 |
9 |
10 | class WithholdingTaxType(Document):
11 | def on_trash(self):
12 | if (
13 | self.name == "Auto"
14 | and not cint(getattr(frappe.local.conf, "developer_mode", 0))
15 | and not (frappe.flags.in_migrate or frappe.flags.in_patch)
16 | ):
17 | frappe.throw(_("You are not allowed to delete Auto"))
18 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/onboarding_step/add_taxes_to_chart_of_account/add_taxes_to_chart_of_account.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "Create Entry",
3 | "creation": "2023-06-22 12:02:29.107120",
4 | "description": "YYY",
5 | "docstatus": 0,
6 | "doctype": "Onboarding Step",
7 | "idx": 0,
8 | "is_complete": 0,
9 | "is_single": 0,
10 | "is_skipped": 0,
11 | "modified": "2023-06-22 12:02:29.107120",
12 | "modified_by": "Administrator",
13 | "name": "Add Taxes to Chart of Account",
14 | "owner": "Administrator",
15 | "reference_document": "Account",
16 | "show_form_tour": 0,
17 | "show_full_form": 0,
18 | "title": "XXX",
19 | "validate_action": 1
20 | }
--------------------------------------------------------------------------------
/thai_tax/thai_tax/onboarding_step/add_withholding_tax_type/add_withholding_tax_type.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "Create Entry",
3 | "creation": "2023-06-23 10:43:23.606425",
4 | "description": "To withhold tax, you need to create Withholding Tyes, i.e., 1%, 2%, 3% and 5%",
5 | "docstatus": 0,
6 | "doctype": "Onboarding Step",
7 | "idx": 0,
8 | "is_complete": 0,
9 | "is_single": 0,
10 | "is_skipped": 0,
11 | "modified": "2023-06-23 11:59:02.378631",
12 | "modified_by": "Administrator",
13 | "name": "Add Withholding Tax Type",
14 | "owner": "Administrator",
15 | "reference_document": "Withholding Tax Type",
16 | "show_form_tour": 0,
17 | "show_full_form": 0,
18 | "title": "Add Withholding Tax Type",
19 | "validate_action": 1
20 | }
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/sales_tax_invoice/sales_tax_invoice.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023, Kitti U. and contributors
2 | # For license information, please see license.txt
3 | import frappe
4 | from frappe.model.document import Document
5 | from frappe.utils import add_months
6 |
7 |
8 | class SalesTaxInvoice(Document):
9 | def validate(self):
10 | self.compute_report_date()
11 |
12 | def on_update_after_submit(self):
13 | if self.get_doc_before_save(): # Some change is made
14 | self.compute_report_date()
15 |
16 | def compute_report_date(self):
17 | if int(self.months_delayed) == 0:
18 | self.db_set("report_date", self.date)
19 | else:
20 | self.db_set("report_date", add_months(self.date, int(self.months_delayed)))
21 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/report/pnd3/pnd3.json:
--------------------------------------------------------------------------------
1 | {
2 | "add_total_row": 1,
3 | "columns": [],
4 | "creation": "2023-03-14 14:33:48.576965",
5 | "disable_prepared_report": 0,
6 | "disabled": 0,
7 | "docstatus": 0,
8 | "doctype": "Report",
9 | "filters": [],
10 | "idx": 0,
11 | "is_standard": "Yes",
12 | "modified": "2023-03-14 14:33:48.576965",
13 | "modified_by": "Administrator",
14 | "module": "Thai Tax",
15 | "name": "PND3",
16 | "owner": "Administrator",
17 | "prepared_report": 0,
18 | "query": "",
19 | "ref_doctype": "Withholding Tax Cert",
20 | "report_name": "PND3",
21 | "report_type": "Script Report",
22 | "roles": [
23 | {
24 | "role": "Accounts Manager"
25 | },
26 | {
27 | "role": "Accounts User"
28 | }
29 | ]
30 | }
--------------------------------------------------------------------------------
/thai_tax/thai_tax/report/pnd53/pnd53.json:
--------------------------------------------------------------------------------
1 | {
2 | "add_total_row": 1,
3 | "columns": [],
4 | "creation": "2023-03-07 10:38:13.525376",
5 | "disable_prepared_report": 0,
6 | "disabled": 0,
7 | "docstatus": 0,
8 | "doctype": "Report",
9 | "filters": [],
10 | "idx": 0,
11 | "is_standard": "Yes",
12 | "modified": "2023-03-14 13:49:42.818372",
13 | "modified_by": "Administrator",
14 | "module": "Thai Tax",
15 | "name": "PND53",
16 | "owner": "Administrator",
17 | "prepared_report": 0,
18 | "query": "",
19 | "ref_doctype": "Withholding Tax Cert",
20 | "report_name": "PND53",
21 | "report_type": "Script Report",
22 | "roles": [
23 | {
24 | "role": "Accounts Manager"
25 | },
26 | {
27 | "role": "Accounts User"
28 | }
29 | ]
30 | }
--------------------------------------------------------------------------------
/thai_tax/uninstall.py:
--------------------------------------------------------------------------------
1 | import frappe
2 |
3 | from thai_tax.constants import HRMS_CUSTOM_FIELDS
4 |
5 |
6 | def before_app_uninstall(app_name):
7 | if app_name == "hrms":
8 | delete_custom_fields(HRMS_CUSTOM_FIELDS)
9 |
10 |
11 | def delete_custom_fields(custom_fields):
12 | """Helper function to delete custom fields"""
13 | for doctypes, fields in custom_fields.items():
14 | if isinstance(fields, dict):
15 | fields = [fields]
16 | if isinstance(doctypes, str):
17 | doctypes = (doctypes,)
18 | for doctype in doctypes:
19 | frappe.db.delete(
20 | "Custom Field",
21 | {
22 | "fieldname": ("in", [field["fieldname"] for field in fields]),
23 | "dt": doctype,
24 | },
25 | )
26 | frappe.clear_cache(doctype=doctype)
27 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/report/sales_tax_report/sales_tax_report.json:
--------------------------------------------------------------------------------
1 | {
2 | "add_total_row": 1,
3 | "columns": [],
4 | "creation": "2023-03-22 16:47:28.702077",
5 | "disable_prepared_report": 0,
6 | "disabled": 0,
7 | "docstatus": 0,
8 | "doctype": "Report",
9 | "filters": [],
10 | "idx": 0,
11 | "is_standard": "Yes",
12 | "modified": "2023-03-22 21:44:23.331658",
13 | "modified_by": "Administrator",
14 | "module": "Thai Tax",
15 | "name": "Sales Tax Report",
16 | "owner": "Administrator",
17 | "prepared_report": 0,
18 | "query": "",
19 | "ref_doctype": "Sales Tax Invoice",
20 | "report_name": "Sales Tax Report",
21 | "report_type": "Script Report",
22 | "roles": [
23 | {
24 | "role": "Accounts Manager"
25 | },
26 | {
27 | "role": "Accounts User"
28 | }
29 | ]
30 | }
--------------------------------------------------------------------------------
/thai_tax/thai_tax/report/purchase_tax_report/purchase_tax_report.json:
--------------------------------------------------------------------------------
1 | {
2 | "add_total_row": 1,
3 | "columns": [],
4 | "creation": "2023-03-20 16:44:27.862127",
5 | "disable_prepared_report": 0,
6 | "disabled": 0,
7 | "docstatus": 0,
8 | "doctype": "Report",
9 | "filters": [],
10 | "idx": 0,
11 | "is_standard": "Yes",
12 | "modified": "2023-03-20 16:44:27.862127",
13 | "modified_by": "Administrator",
14 | "module": "Thai Tax",
15 | "name": "Purchase Tax Report",
16 | "owner": "Administrator",
17 | "prepared_report": 0,
18 | "query": "",
19 | "ref_doctype": "Purchase Tax Invoice",
20 | "report_name": "Purchase Tax Report",
21 | "report_type": "Script Report",
22 | "roles": [
23 | {
24 | "role": "Accounts Manager"
25 | },
26 | {
27 | "role": "Accounts User"
28 | }
29 | ]
30 | }
--------------------------------------------------------------------------------
/thai_tax/thai_tax/onboarding_step/tax_invoice_setting/tax_invoice_setting.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "Show Form Tour",
3 | "creation": "2023-06-22 12:59:15.255686",
4 | "description": "#Tax Invoice Settings\n\nAfter you have created all required tax account, please map them in the settings.",
5 | "docstatus": 0,
6 | "doctype": "Onboarding Step",
7 | "field": "sales_tax_account",
8 | "idx": 0,
9 | "is_complete": 0,
10 | "is_single": 1,
11 | "is_skipped": 0,
12 | "modified": "2023-06-22 14:00:33.605362",
13 | "modified_by": "Administrator",
14 | "name": "Tax Invoice Setting",
15 | "owner": "Administrator",
16 | "reference_document": "Tax Invoice Settings",
17 | "show_form_tour": 0,
18 | "show_full_form": 0,
19 | "title": "Tax Invoice Setting",
20 | "validate_action": 1,
21 | "value_to_validate": "%"
22 | }
--------------------------------------------------------------------------------
/thai_tax/thai_tax/report/pnd3/pnd3.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2023, Kitti U. and contributors
2 | // For license information, please see license.txt
3 | /* eslint-disable */
4 |
5 | frappe.query_reports["PND3"] = {
6 | filters: [
7 | {
8 | fieldname: "year",
9 | label: __("Year"),
10 | fieldtype: "Link",
11 | options: "Fiscal Year",
12 | },
13 | {
14 | fieldname: "month",
15 | label: __("Month"),
16 | fieldtype: "Select",
17 | options: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
18 | },
19 | {
20 | fieldname: "company_address",
21 | label: __("Company Address"),
22 | fieldtype: "Link",
23 | options: "Address",
24 | get_query: () => {
25 | return {
26 | filters: {
27 | is_your_company_address: 1,
28 | },
29 | };
30 | },
31 | },
32 | ],
33 | };
34 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/report/pnd53/pnd53.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2023, Kitti U. and contributors
2 | // For license information, please see license.txt
3 | /* eslint-disable */
4 |
5 | frappe.query_reports["PND53"] = {
6 | filters: [
7 | {
8 | fieldname: "year",
9 | label: __("Year"),
10 | fieldtype: "Link",
11 | options: "Fiscal Year",
12 | },
13 | {
14 | fieldname: "month",
15 | label: __("Month"),
16 | fieldtype: "Select",
17 | options: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
18 | },
19 | {
20 | fieldname: "company_address",
21 | label: __("Company Address"),
22 | fieldtype: "Link",
23 | options: "Address",
24 | get_query: () => {
25 | return {
26 | filters: {
27 | is_your_company_address: 1,
28 | },
29 | };
30 | },
31 | },
32 | ],
33 | };
34 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/onboarding_step/tax_report/tax_report.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "View Report",
3 | "creation": "2023-06-23 11:18:50.186869",
4 | "description": "Sales Tax Report and Purchase Tax Repot can be found in separated menu.",
5 | "docstatus": 0,
6 | "doctype": "Onboarding Step",
7 | "idx": 0,
8 | "is_complete": 0,
9 | "is_single": 0,
10 | "is_skipped": 0,
11 | "modified": "2023-06-23 11:32:45.317640",
12 | "modified_by": "Administrator",
13 | "name": "Tax Report",
14 | "owner": "Administrator",
15 | "reference_report": "Sales Tax Report",
16 | "report_description": "You can also go to Purchase Tax Report for the same",
17 | "report_reference_doctype": "Sales Tax Invoice",
18 | "report_type": "Script Report",
19 | "show_form_tour": 0,
20 | "show_full_form": 0,
21 | "title": "Sales / Purchase Tax Report",
22 | "validate_action": 1
23 | }
--------------------------------------------------------------------------------
/thai_tax/thai_tax/onboarding_step/browse_withholding_tax_cert/browse_withholding_tax_cert.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "Go to Page",
3 | "action_label": "Browse Withholding Tax Certs",
4 | "creation": "2023-06-23 11:22:48.027326",
5 | "description": "On Payment Entry with withholding tax deduction, button Create Withholing Tax Cert will be visible.\nThese are all Withholding Tax Certs created during payments.",
6 | "docstatus": 0,
7 | "doctype": "Onboarding Step",
8 | "idx": 0,
9 | "is_complete": 0,
10 | "is_single": 0,
11 | "is_skipped": 0,
12 | "modified": "2023-06-23 11:26:09.219232",
13 | "modified_by": "Administrator",
14 | "name": "Browse Withholding Tax Cert",
15 | "owner": "Administrator",
16 | "path": "List/Withholding Tax Cert",
17 | "show_form_tour": 0,
18 | "show_full_form": 0,
19 | "title": "Browse Withholding Tax Cert",
20 | "validate_action": 1
21 | }
--------------------------------------------------------------------------------
/thai_tax/thai_tax/onboarding_step/asset_item/asset_item.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "Create Entry",
3 | "action_label": "Let's create a new Asset item",
4 | "creation": "2021-08-13 14:27:07.277167",
5 | "description": "# Asset Item\n\nAsset items are created based on Asset Category. You can create one or multiple items against once Asset Category. The sales and purchase transaction for Asset is done via Asset Item. ",
6 | "docstatus": 0,
7 | "doctype": "Onboarding Step",
8 | "form_tour": "Item",
9 | "idx": 0,
10 | "is_complete": 0,
11 | "is_single": 0,
12 | "is_skipped": 0,
13 | "modified": "2021-12-02 11:23:48.158504",
14 | "modified_by": "Administrator",
15 | "name": "Asset Item",
16 | "owner": "Administrator",
17 | "reference_document": "Item",
18 | "show_form_tour": 1,
19 | "show_full_form": 1,
20 | "title": "Create an Asset Item",
21 | "validate_action": 1
22 | }
--------------------------------------------------------------------------------
/thai_tax/custom/dashboard_overrides.py:
--------------------------------------------------------------------------------
1 | from frappe import _
2 |
3 |
4 | def get_dashboard_data_for_purchase_invoice(data):
5 | data["non_standard_fieldnames"].update({"Purchase Tax Invoice": "voucher_no"})
6 | data["transactions"].append(
7 | {"label": _("Tax Invoice"), "items": ["Purchase Tax Invoice"]}
8 | )
9 | return data
10 |
11 |
12 | def get_dashboard_data_for_sales_invoice(data):
13 | data["non_standard_fieldnames"].update({"Sales Tax Invoice": "voucher_no"})
14 | data["transactions"].append(
15 | {"label": _("Tax Invoice"), "items": ["Sales Tax Invoice"]}
16 | )
17 | return data
18 |
19 |
20 | def get_dashboard_data_for_expense_claim(data):
21 | data["non_standard_fieldnames"].update({"Purchase Tax Invoice": "voucher_no"})
22 | data["transactions"].append(
23 | {"label": _("Tax Invoice"), "items": ["Purchase Tax Invoice"]}
24 | )
25 | return data
26 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/tax_invoice_settings/tax_invoice_settings.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2023, Kitti U. and contributors
2 | // For license information, please see license.txt
3 |
4 | frappe.ui.form.on("Tax Invoice Settings", {
5 | onload: function (frm) {
6 | for (let field of [
7 | "sales_tax_account",
8 | "sales_tax_account_undue",
9 | "purchase_tax_account",
10 | "purchase_tax_account_undue",
11 | ]) {
12 | frm.set_query(field, function (doc) {
13 | return {
14 | filters: {
15 | account_type: "Tax",
16 | company: doc.company,
17 | },
18 | };
19 | });
20 | }
21 | },
22 |
23 | company: function (frm) {
24 | frm.set_value("sales_tax_account", null);
25 | frm.set_value("sales_tax_account_undue", null);
26 | frm.set_value("purchase_tax_account", null);
27 | frm.set_value("purchase_tax_account_undue", null);
28 | },
29 | });
30 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/onboarding_step/browse_sales_tax_invoices/browse_sales_tax_invoices.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "Go to Page",
3 | "callback_message": "",
4 | "callback_title": "Sales Tax Invoices are created after you have record tax.",
5 | "creation": "2023-06-23 11:11:48.094053",
6 | "description": "Sales Tax Invoice is created when tax ledger is recorded, which could be,\n1. On Sales Invoice for case selling product\n2. On Payment for case selling service",
7 | "docstatus": 0,
8 | "doctype": "Onboarding Step",
9 | "idx": 0,
10 | "is_complete": 0,
11 | "is_single": 0,
12 | "is_skipped": 0,
13 | "modified": "2023-06-23 11:17:45.307520",
14 | "modified_by": "Administrator",
15 | "name": "Browse Sales Tax Invoices",
16 | "owner": "Administrator",
17 | "path": "List/Sales Tax Invoice",
18 | "show_form_tour": 0,
19 | "show_full_form": 0,
20 | "title": "Browse Sales Tax Invoices",
21 | "validate_action": 1
22 | }
--------------------------------------------------------------------------------
/thai_tax/thai_tax/onboarding_step/browse_purchase_tax_invoices/browse_purchase_tax_invoices.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "Go to Page",
3 | "callback_message": "",
4 | "callback_title": "Purchase Tax Invoices are created after you have record tax.",
5 | "creation": "2023-06-23 11:16:19.993908",
6 | "description": "Purchase Tax Invoice is created when tax ledger is recorded, which could be,\n1. On Purchase Invoice for case buying product\n2. On Payment for case buying service and can record tax on payment\n3. On Journal Entry for case buying service and record tax afterward",
7 | "docstatus": 0,
8 | "doctype": "Onboarding Step",
9 | "idx": 0,
10 | "is_complete": 0,
11 | "is_single": 0,
12 | "is_skipped": 0,
13 | "modified": "2023-06-23 11:17:34.911128",
14 | "modified_by": "Administrator",
15 | "name": "Browse Purchase Tax Invoices",
16 | "owner": "Administrator",
17 | "path": "List/Purchase Tax Invoice",
18 | "show_form_tour": 0,
19 | "show_full_form": 0,
20 | "title": "Browse Purchase Tax Invoices",
21 | "validate_action": 1
22 | }
--------------------------------------------------------------------------------
/thai_tax/thai_tax/onboarding_step/withholding_tax_report_(pnd)/withholding_tax_report_(pnd).json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "Go to Page",
3 | "action_label": "View PND Report",
4 | "callback_message": "PND53 can be found in separated menu.",
5 | "callback_title": "PND3 Report",
6 | "creation": "2023-06-23 11:27:09.437734",
7 | "description": "PND3 and PND53 reports are summay of Withholding Ta Certs",
8 | "docstatus": 0,
9 | "doctype": "Onboarding Step",
10 | "idx": 0,
11 | "is_complete": 0,
12 | "is_single": 0,
13 | "is_skipped": 0,
14 | "modified": "2023-06-23 11:32:29.566442",
15 | "modified_by": "Administrator",
16 | "name": "Withholding Tax Report (PND)",
17 | "owner": "Administrator",
18 | "path": "query-report/PND3",
19 | "reference_report": "PND3",
20 | "report_description": "PND53 can also be found in separated menu.",
21 | "report_reference_doctype": "Withholding Tax Cert",
22 | "report_type": "Script Report",
23 | "show_form_tour": 0,
24 | "show_full_form": 0,
25 | "title": "Withholding Tax Report (PND)",
26 | "validate_action": 1
27 | }
--------------------------------------------------------------------------------
/thai_tax/thai_tax/onboarding_step/company_set_up/company_set_up.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "Create Entry",
3 | "action_label": "Let's review your Company",
4 | "creation": "2021-11-22 11:55:48.931427",
5 | "description": "# Set Up a Company\n\nA company is a legal entity for which you will set up your books of account and create accounting transactions. In ERPNext, you can create multiple companies, and establish relationships (group/subsidiary) among them.\n\nWithin the company master, you can capture various default accounts for that Company and set crucial settings related to the accounting methodology followed for a company.\n",
6 | "docstatus": 0,
7 | "doctype": "Onboarding Step",
8 | "idx": 1,
9 | "is_complete": 0,
10 | "is_single": 0,
11 | "is_skipped": 0,
12 | "modified": "2023-05-15 09:18:42.895537",
13 | "modified_by": "Administrator",
14 | "name": "Company Set Up",
15 | "owner": "Administrator",
16 | "reference_document": "Company",
17 | "show_form_tour": 1,
18 | "show_full_form": 1,
19 | "title": "Set Up a Company",
20 | "validate_action": 1
21 | }
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/withholding_tax_setting/withholding_tax_setting.json:
--------------------------------------------------------------------------------
1 | {
2 | "actions": [],
3 | "allow_rename": 1,
4 | "creation": "2023-03-04 12:09:31.842524",
5 | "default_view": "List",
6 | "doctype": "DocType",
7 | "editable_grid": 1,
8 | "engine": "InnoDB",
9 | "field_order": [
10 | "wht_cert_image"
11 | ],
12 | "fields": [
13 | {
14 | "fieldname": "wht_cert_image",
15 | "fieldtype": "Attach Image",
16 | "label": "WHT Cert Image"
17 | }
18 | ],
19 | "image_field": "wht_cert_image",
20 | "index_web_pages_for_search": 1,
21 | "issingle": 1,
22 | "links": [],
23 | "modified": "2023-03-04 12:14:13.207499",
24 | "modified_by": "Administrator",
25 | "module": "Thai Tax",
26 | "name": "Withholding Tax Setting",
27 | "owner": "Administrator",
28 | "permissions": [
29 | {
30 | "create": 1,
31 | "delete": 1,
32 | "email": 1,
33 | "print": 1,
34 | "read": 1,
35 | "role": "System Manager",
36 | "share": 1,
37 | "write": 1
38 | }
39 | ],
40 | "sort_field": "modified",
41 | "sort_order": "DESC",
42 | "states": []
43 | }
--------------------------------------------------------------------------------
/.flake8:
--------------------------------------------------------------------------------
1 | [flake8]
2 | ignore =
3 | B001,
4 | B007,
5 | B009,
6 | B010,
7 | B950,
8 | E101,
9 | E111,
10 | E114,
11 | E116,
12 | E117,
13 | E121,
14 | E122,
15 | E123,
16 | E124,
17 | E125,
18 | E126,
19 | E127,
20 | E128,
21 | E131,
22 | E201,
23 | E202,
24 | E203,
25 | E211,
26 | E221,
27 | E222,
28 | E223,
29 | E224,
30 | E225,
31 | E226,
32 | E228,
33 | E231,
34 | E241,
35 | E242,
36 | E251,
37 | E261,
38 | E262,
39 | E265,
40 | E266,
41 | E271,
42 | E272,
43 | E273,
44 | E274,
45 | E301,
46 | E302,
47 | E303,
48 | E305,
49 | E306,
50 | E402,
51 | E501,
52 | E502,
53 | E701,
54 | E702,
55 | E703,
56 | E741,
57 | F401,
58 | F403,
59 | F405,
60 | W191,
61 | W291,
62 | W292,
63 | W293,
64 | W391,
65 | W503,
66 | W504,
67 | E711,
68 | E129,
69 | F841,
70 | E713,
71 | E712,
72 | B028,
73 |
74 | max-line-length = 200
75 | exclude=,test_*.py
--------------------------------------------------------------------------------
/thai_tax/thai_tax/onboarding_step/add_thai_tax_accounts/add_thai_tax_accounts.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "Go to Page",
3 | "action_label": "Let's create tax accounts",
4 | "callback_message": "",
5 | "callback_title": "",
6 | "creation": "2023-06-22 12:36:13.122910",
7 | "description": "# Add Thai Tax Accounts\n\nPlease make sure you have all required Tax Accounts, you can name it as you want.\n1. Purchase Tax -- Current Asset, Rate = 7\n2. Undue Purchase Tax -- Currency Asset, Rate = 7\n3. Sales Tax -- Current Liability, Rate = 7\n4. Undue Sales Tax -- Current Liability, Rate = 7\n5. Withholding Tax -- Current Liability\n\n",
8 | "docstatus": 0,
9 | "doctype": "Onboarding Step",
10 | "idx": 0,
11 | "is_complete": 0,
12 | "is_single": 0,
13 | "is_skipped": 0,
14 | "modified": "2023-06-23 11:20:25.502674",
15 | "modified_by": "Administrator",
16 | "name": "Add Thai Tax Accounts",
17 | "owner": "Administrator",
18 | "path": "account/view/tree",
19 | "reference_document": "Account",
20 | "show_form_tour": 0,
21 | "show_full_form": 1,
22 | "title": "Add Thai Tax Accounts",
23 | "validate_action": 1
24 | }
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/purchase_tax_invoice/purchase_tax_invoice.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023, Kitti U. and contributors
2 | # For license information, please see license.txt
3 | import frappe
4 | from frappe.model.document import Document
5 | from frappe.utils import add_months
6 |
7 |
8 | class PurchaseTaxInvoice(Document):
9 | def validate(self):
10 | self.compute_report_date()
11 |
12 | def on_update_after_submit(self):
13 | if self.get_doc_before_save(): # Some change is made
14 | self.compute_report_date()
15 | if self.voucher_type and self.voucher_no:
16 | origin_doc = frappe.get_doc(self.voucher_type, self.voucher_no)
17 | if self.voucher_type == "Journal Entry":
18 | gl = frappe.get_doc("GL Entry", self.gl_entry)
19 | origin_doc = frappe.get_doc(
20 | "Journal Entry Tax Invoice Detail", gl.voucher_detail_no
21 | )
22 | origin_doc.tax_invoice_number = self.number
23 | origin_doc.tax_invoice_date = self.date
24 | origin_doc.save(ignore_permissions=True)
25 |
26 | def compute_report_date(self):
27 | if int(self.months_delayed) == 0:
28 | self.db_set("report_date", self.date)
29 | else:
30 | self.db_set("report_date", add_months(self.date, int(self.months_delayed)))
31 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/module_onboarding/thai_tax/thai_tax.json:
--------------------------------------------------------------------------------
1 | {
2 | "allow_roles": [
3 | {
4 | "role": "Accounts Manager"
5 | },
6 | {
7 | "role": "Accounts User"
8 | }
9 | ],
10 | "creation": "2023-06-22 11:58:50.650153",
11 | "docstatus": 0,
12 | "doctype": "Module Onboarding",
13 | "documentation_url": "https://github.com/kittiu/thai_tax/blob/main/README.md",
14 | "idx": 0,
15 | "is_complete": 0,
16 | "modified": "2023-06-23 11:59:08.144024",
17 | "modified_by": "Administrator",
18 | "module": "Thai Tax",
19 | "name": "Thai Tax",
20 | "owner": "Administrator",
21 | "steps": [
22 | {
23 | "step": "Add Thai Tax Accounts"
24 | },
25 | {
26 | "step": "Tax Invoice Setting"
27 | },
28 | {
29 | "step": "Add Withholding Tax Type"
30 | },
31 | {
32 | "step": "Browse Sales Tax Invoices"
33 | },
34 | {
35 | "step": "Browse Purchase Tax Invoices"
36 | },
37 | {
38 | "step": "Tax Report"
39 | },
40 | {
41 | "step": "Browse Withholding Tax Cert"
42 | },
43 | {
44 | "step": "Withholding Tax Report (PND)"
45 | }
46 | ],
47 | "subtitle": "Tax Account Setup, Withholding Tax Type",
48 | "success_message": "The Thai Tax Module is all set up!",
49 | "title": "Setup Thai Tax"
50 | }
--------------------------------------------------------------------------------
/thai_tax/public/js/address.js:
--------------------------------------------------------------------------------
1 | frappe.ui.form.on("Address", {
2 | refresh(frm) {
3 | // Add button to use VAT Service
4 | frm.add_custom_button(__("Get Address by Tax ID"), function () {
5 | const fields = [
6 | {
7 | fieldtype: "Data",
8 | label: __("Tax ID"),
9 | fieldname: "tax_id",
10 | reqd: 1,
11 | },
12 | {
13 | fieldtype: "Data",
14 | label: __("Branch"),
15 | fieldname: "branch",
16 | default: "00000",
17 | reqd: 1,
18 | },
19 | ];
20 | frappe.prompt(
21 | fields,
22 | function (filters) {
23 | frm.events.get_address_by_tax_id(frm, filters);
24 | },
25 | __("RD VAT Service"),
26 | __("Get Address")
27 | );
28 | });
29 | },
30 |
31 | get_address_by_tax_id: function (frm, filters) {
32 | return frappe.call({
33 | method: "thai_tax.utils.get_address_by_tax_id",
34 | args: {
35 | tax_id: filters.tax_id,
36 | branch: filters.branch,
37 | },
38 | callback: function (r) {
39 | cur_frm.set_value("address_title", r.message["name"]);
40 | cur_frm.set_value("address_line1", r.message["address_line1"]);
41 | cur_frm.set_value("city", r.message["city"]);
42 | cur_frm.set_value("county", r.message["county"]);
43 | cur_frm.set_value("state", r.message["state"]);
44 | cur_frm.set_value("pincode", r.message["pincode"]);
45 | },
46 | });
47 | },
48 | });
49 |
--------------------------------------------------------------------------------
/thai_tax/public/js/journal_entry.js:
--------------------------------------------------------------------------------
1 | frappe.ui.form.on("Journal Entry", {
2 | setup(frm) {
3 | frm.add_fetch("customer", "customer_name", "party_name");
4 | frm.add_fetch("supplier", "supplier_name", "party_name");
5 | },
6 | refresh(frm) {
7 | frm.set_query("company_tax_address", function () {
8 | return {
9 | filters: {
10 | is_your_company_address: true,
11 | },
12 | };
13 | });
14 | frm.set_query("company_tax_address", "tax_invoice_details", () => {
15 | return {
16 | filters: {
17 | is_your_company_address: true,
18 | },
19 | };
20 | });
21 | },
22 | });
23 |
24 | frappe.ui.form.on("Journal Entry Tax Invoice Detail", {
25 | customer(frm, cdt, cdn) {
26 | let row = locals[cdt][cdn];
27 | if (row.customer) {
28 | frappe.model.set_value(cdt, cdn, "supplier", "");
29 | }
30 | },
31 | supplier(frm, cdt, cdn) {
32 | let row = locals[cdt][cdn];
33 | if (row.supplier) {
34 | frappe.model.set_value(cdt, cdn, "customer", "");
35 | }
36 | },
37 | });
38 |
39 | frappe.ui.form.on("Journal Entry Account", {
40 | customer(frm, cdt, cdn) {
41 | let row = locals[cdt][cdn];
42 | if (row.customer) {
43 | frappe.model.set_value(cdt, cdn, "supplier", "");
44 | }
45 | },
46 | supplier(frm, cdt, cdn) {
47 | let row = locals[cdt][cdn];
48 | if (row.supplier) {
49 | frappe.model.set_value(cdt, cdn, "customer", "");
50 | }
51 | },
52 | });
53 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/withholding_tax_type/withholding_tax_type.json:
--------------------------------------------------------------------------------
1 | {
2 | "actions": [],
3 | "allow_rename": 1,
4 | "autoname": "field:title",
5 | "creation": "2023-03-04 12:08:38.271210",
6 | "default_view": "List",
7 | "doctype": "DocType",
8 | "editable_grid": 1,
9 | "engine": "InnoDB",
10 | "field_order": [
11 | "title",
12 | "percent",
13 | "account"
14 | ],
15 | "fields": [
16 | {
17 | "fieldname": "title",
18 | "fieldtype": "Data",
19 | "in_list_view": 1,
20 | "label": "Title",
21 | "mandatory_depends_on": "eval:doc.title == 'Auto'",
22 | "reqd": 1,
23 | "unique": 1
24 | },
25 | {
26 | "description": "% of withholding tax",
27 | "fieldname": "percent",
28 | "fieldtype": "Int",
29 | "in_list_view": 1,
30 | "label": "Percent",
31 | "reqd": 1
32 | },
33 | {
34 | "fieldname": "account",
35 | "fieldtype": "Link",
36 | "in_list_view": 1,
37 | "label": "Account",
38 | "options": "Account",
39 | "reqd": 1
40 | }
41 | ],
42 | "index_web_pages_for_search": 1,
43 | "links": [],
44 | "modified": "2024-10-10 15:27:17.778852",
45 | "modified_by": "Administrator",
46 | "module": "Thai Tax",
47 | "name": "Withholding Tax Type",
48 | "naming_rule": "By fieldname",
49 | "owner": "Administrator",
50 | "permissions": [
51 | {
52 | "create": 1,
53 | "delete": 1,
54 | "email": 1,
55 | "export": 1,
56 | "print": 1,
57 | "read": 1,
58 | "report": 1,
59 | "role": "System Manager",
60 | "share": 1,
61 | "write": 1
62 | },
63 | {
64 | "email": 1,
65 | "export": 1,
66 | "print": 1,
67 | "read": 1,
68 | "report": 1,
69 | "role": "Accounts User",
70 | "share": 1
71 | }
72 | ],
73 | "sort_field": "title",
74 | "sort_order": "DESC",
75 | "states": [],
76 | "title_field": "title"
77 | }
--------------------------------------------------------------------------------
/thai_tax/install.py:
--------------------------------------------------------------------------------
1 | import click
2 | import frappe
3 | from frappe.custom.doctype.custom_field.custom_field import \
4 | create_custom_fields
5 | from frappe.custom.doctype.property_setter.property_setter import \
6 | make_property_setter
7 |
8 | from thai_tax.constants import (ERP_CUSTOM_FIELDS, ERP_PROPERTY_SETTERS,
9 | HRMS_CUSTOM_FIELDS)
10 |
11 |
12 | def after_install():
13 | try:
14 | print("Setting up Thai Tax...")
15 | make_custom_fields()
16 | make_property_setters()
17 | click.secho("Thank you for installing Thai Tax!", fg="green")
18 | except Exception as e:
19 | BUG_REPORT_URL = "https://github.com/kittiu/thai_tax/issues/new"
20 | click.secho(
21 | "Installation for Thai Tax app failed due to an error."
22 | " Please try re-installing the app or"
23 | f" report the issue on {BUG_REPORT_URL} if not resolved.",
24 | fg="bright_red",
25 | )
26 | raise e
27 |
28 |
29 | def make_custom_fields():
30 | print("Setup custom fields for erpnext...")
31 | create_custom_fields(ERP_CUSTOM_FIELDS, ignore_validate=True)
32 | if "hrms" in frappe.get_installed_apps():
33 | print("Setup custom fields for hrms...")
34 | create_custom_fields(HRMS_CUSTOM_FIELDS, ignore_validate=True)
35 |
36 |
37 | def make_property_setters():
38 | print("Setup property setters for erpnext...")
39 | for doctypes, property_setters in ERP_PROPERTY_SETTERS.items():
40 | if isinstance(doctypes, str):
41 | doctypes = (doctypes,)
42 | for doctype in doctypes:
43 | for property_setter in property_setters:
44 | for_doctype = not property_setter[0]
45 | make_property_setter(doctype, *property_setter, for_doctype)
46 |
47 |
48 | def after_app_install(app_name):
49 | if app_name == "hrms":
50 | create_custom_fields(HRMS_CUSTOM_FIELDS, ignore_validate=True)
51 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | exclude: 'node_modules|.git'
2 | default_stages: [commit]
3 | fail_fast: false
4 |
5 |
6 | repos:
7 | - repo: https://github.com/pre-commit/pre-commit-hooks
8 | rev: v4.3.0
9 | hooks:
10 | - id: trailing-whitespace
11 | files: "frappe.*"
12 | exclude: ".*json$|.*txt$|.*csv|.*md|.*svg"
13 | - id: check-yaml
14 | - id: no-commit-to-branch
15 | args: ['--branch', 'develop']
16 | - id: check-merge-conflict
17 | - id: check-ast
18 | - id: check-json
19 | - id: check-toml
20 | - id: check-yaml
21 | - id: debug-statements
22 |
23 | - repo: https://github.com/asottile/pyupgrade
24 | rev: v2.34.0
25 | hooks:
26 | - id: pyupgrade
27 | args: ['--py310-plus']
28 |
29 | - repo: https://github.com/frappe/black
30 | rev: 951ccf4d5bb0d692b457a5ebc4215d755618eb68
31 | hooks:
32 | - id: black
33 |
34 | - repo: https://github.com/pre-commit/mirrors-prettier
35 | rev: v2.7.1
36 | hooks:
37 | - id: prettier
38 | types_or: [javascript]
39 | # Ignore any files that might contain jinja / bundles
40 | exclude: |
41 | (?x)^(
42 | frappe/public/dist/.*|
43 | .*node_modules.*|
44 | .*boilerplate.*|
45 | frappe/www/website_script.js|
46 | frappe/templates/includes/.*|
47 | frappe/public/js/lib/.*
48 | )$
49 |
50 |
51 | - repo: https://github.com/PyCQA/isort
52 | rev: 5.12.0
53 | hooks:
54 | - id: isort
55 |
56 | - repo: https://github.com/PyCQA/flake8
57 | rev: 5.0.4
58 | hooks:
59 | - id: flake8
60 | additional_dependencies: ['flake8-bugbear',]
61 |
62 | ci:
63 | autoupdate_schedule: weekly
64 | skip: []
65 | submodules: false
66 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/report/sales_tax_report/sales_tax_report.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2023, Kitti U. and contributors
2 | // For license information, please see license.txt
3 | /* eslint-disable */
4 |
5 | frappe.query_reports["Sales Tax Report"] = {
6 | filters: [
7 | {
8 | fieldname: "filter_based_on",
9 | label: __("Filter Based On"),
10 | fieldtype: "Select",
11 | options: ["Fiscal Year", "Date Range"],
12 | default: ["Fiscal Year"],
13 | reqd: 1,
14 | on_change: function () {
15 | let filter_based_on = frappe.query_report.get_filter_value("filter_based_on");
16 | frappe.query_report.toggle_filter_display(
17 | "year",
18 | filter_based_on === "Date Range"
19 | );
20 | frappe.query_report.toggle_filter_display(
21 | "month",
22 | filter_based_on === "Date Range"
23 | );
24 | frappe.query_report.toggle_filter_display(
25 | "start_date",
26 | filter_based_on === "Fiscal Year"
27 | );
28 | frappe.query_report.toggle_filter_display(
29 | "end_date",
30 | filter_based_on === "Fiscal Year"
31 | );
32 |
33 | frappe.query_report.refresh();
34 | },
35 | },
36 | {
37 | fieldname: "year",
38 | label: __("Year"),
39 | fieldtype: "Link",
40 | options: "Fiscal Year",
41 | },
42 | {
43 | fieldname: "month",
44 | label: __("Month"),
45 | fieldtype: "Select",
46 | options: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
47 | },
48 | {
49 | fieldname: "start_date",
50 | label: __("Start Date"),
51 | fieldtype: "Date",
52 | },
53 | {
54 | fieldname: "end_date",
55 | label: __("End Date"),
56 | fieldtype: "Date",
57 | },
58 | {
59 | fieldname: "company_tax_address",
60 | label: __("Company Address"),
61 | fieldtype: "Link",
62 | options: "Address",
63 | get_query: () => {
64 | return {
65 | filters: {
66 | is_your_company_address: 1,
67 | },
68 | };
69 | },
70 | },
71 | ],
72 | };
73 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/report/purchase_tax_report/purchase_tax_report.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2023, Kitti U. and contributors
2 | // For license information, please see license.txt
3 | /* eslint-disable */
4 |
5 | frappe.query_reports["Purchase Tax Report"] = {
6 | filters: [
7 | {
8 | fieldname: "filter_based_on",
9 | label: __("Filter Based On"),
10 | fieldtype: "Select",
11 | options: ["Fiscal Year", "Date Range"],
12 | default: ["Fiscal Year"],
13 | reqd: 1,
14 | on_change: function () {
15 | let filter_based_on = frappe.query_report.get_filter_value("filter_based_on");
16 | frappe.query_report.toggle_filter_display(
17 | "year",
18 | filter_based_on === "Date Range"
19 | );
20 | frappe.query_report.toggle_filter_display(
21 | "month",
22 | filter_based_on === "Date Range"
23 | );
24 | frappe.query_report.toggle_filter_display(
25 | "start_date",
26 | filter_based_on === "Fiscal Year"
27 | );
28 | frappe.query_report.toggle_filter_display(
29 | "end_date",
30 | filter_based_on === "Fiscal Year"
31 | );
32 |
33 | frappe.query_report.refresh();
34 | },
35 | },
36 | {
37 | fieldname: "year",
38 | label: __("Year"),
39 | fieldtype: "Link",
40 | options: "Fiscal Year",
41 | },
42 | {
43 | fieldname: "month",
44 | label: __("Month"),
45 | fieldtype: "Select",
46 | options: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
47 | },
48 | {
49 | fieldname: "start_date",
50 | label: __("Start Date"),
51 | fieldtype: "Date",
52 | },
53 | {
54 | fieldname: "end_date",
55 | label: __("End Date"),
56 | fieldtype: "Date",
57 | },
58 | {
59 | fieldname: "company_tax_address",
60 | label: __("Company Address"),
61 | fieldtype: "Link",
62 | options: "Address",
63 | get_query: () => {
64 | return {
65 | filters: {
66 | is_your_company_address: 1,
67 | },
68 | };
69 | },
70 | },
71 | ],
72 | };
73 |
--------------------------------------------------------------------------------
/thai_tax/custom/employee_advance.py:
--------------------------------------------------------------------------------
1 | import frappe
2 | from frappe import _
3 | from frappe.query_builder.functions import Sum
4 | from frappe.utils import flt
5 | from hrms.hr.doctype.employee_advance.employee_advance import EmployeeAdvance
6 |
7 |
8 | class EmployeeAdvanceOverPayment(frappe.ValidationError):
9 | pass
10 |
11 |
12 | class ThaiTaxEmployeeAdvance(EmployeeAdvance):
13 |
14 | # For python bug fix only, to be removed if fixed in the core
15 | def set_total_advance_paid(self):
16 | gle = frappe.qb.DocType("GL Entry")
17 |
18 | paid_amount = (
19 | frappe.qb.from_(gle)
20 | .select(Sum(gle.debit).as_("paid_amount"))
21 | .where(
22 | (gle.against_voucher_type == "Employee Advance")
23 | & (gle.against_voucher == self.name)
24 | & (gle.party_type == "Employee")
25 | & (gle.party == self.employee)
26 | & (gle.docstatus == 1)
27 | & (gle.is_cancelled == 0)
28 | )
29 | ).run(as_dict=True)[0].paid_amount or 0
30 |
31 | return_amount = (
32 | frappe.qb.from_(gle)
33 | .select(Sum(gle.credit).as_("return_amount"))
34 | .where(
35 | (gle.against_voucher_type == "Employee Advance")
36 | & (gle.voucher_type != "Expense Claim")
37 | & (gle.against_voucher == self.name)
38 | & (gle.party_type == "Employee")
39 | & (gle.party == self.employee)
40 | & (gle.docstatus == 1)
41 | & (gle.is_cancelled == 0)
42 | )
43 | ).run(as_dict=True)[0].return_amount or 0
44 |
45 | if paid_amount != 0:
46 | paid_amount = flt(paid_amount) / flt(self.exchange_rate)
47 | if return_amount != 0:
48 | return_amount = flt(return_amount) / flt(self.exchange_rate)
49 |
50 | if flt(paid_amount) > self.advance_amount:
51 | frappe.throw(
52 | _("Row {0}# Paid Amount cannot be greater than requested advance amount"),
53 | EmployeeAdvanceOverPayment,
54 | )
55 |
56 | # FIX: because python result in 2000.0-1780.2 = 219.79999999999995
57 | # if flt(return_amount) > self.paid_amount - self.claimed_amount:
58 | if flt(return_amount) > flt(self.paid_amount - self.claimed_amount, 2):
59 | frappe.throw(_("Return amount cannot be greater unclaimed amount"))
60 |
61 | self.db_set("paid_amount", paid_amount)
62 | self.db_set("return_amount", return_amount)
63 | self.set_status(update=True)
64 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/tax_invoice_settings/tax_invoice_settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "actions": [],
3 | "allow_rename": 1,
4 | "creation": "2023-03-04 12:11:10.337895",
5 | "default_view": "List",
6 | "doctype": "DocType",
7 | "editable_grid": 1,
8 | "engine": "InnoDB",
9 | "field_order": [
10 | "company",
11 | "section_break_2",
12 | "sales_tax_account",
13 | "sales_tax_account_undue",
14 | "column_break_5",
15 | "purchase_tax_account",
16 | "purchase_tax_account_undue"
17 | ],
18 | "fields": [
19 | {
20 | "fieldname": "company",
21 | "fieldtype": "Link",
22 | "in_list_view": 1,
23 | "label": "Company",
24 | "options": "Company",
25 | "reqd": 1
26 | },
27 | {
28 | "fieldname": "section_break_2",
29 | "fieldtype": "Section Break",
30 | "label": "Tax Invoice Account"
31 | },
32 | {
33 | "fieldname": "sales_tax_account",
34 | "fieldtype": "Link",
35 | "in_list_view": 1,
36 | "label": "Sales Tax Account",
37 | "options": "Account",
38 | "reqd": 1
39 | },
40 | {
41 | "fieldname": "column_break_5",
42 | "fieldtype": "Column Break"
43 | },
44 | {
45 | "fieldname": "purchase_tax_account",
46 | "fieldtype": "Link",
47 | "in_list_view": 1,
48 | "label": "Purchase Tax Account",
49 | "options": "Account",
50 | "reqd": 1
51 | },
52 | {
53 | "fieldname": "sales_tax_account_undue",
54 | "fieldtype": "Link",
55 | "label": "Sales Tax Account Undue",
56 | "options": "Account"
57 | },
58 | {
59 | "fieldname": "purchase_tax_account_undue",
60 | "fieldtype": "Link",
61 | "label": "Purchase Tax Account Undue",
62 | "options": "Account"
63 | }
64 | ],
65 | "index_web_pages_for_search": 1,
66 | "issingle": 1,
67 | "links": [],
68 | "modified": "2023-06-22 09:27:29.366931",
69 | "modified_by": "Administrator",
70 | "module": "Thai Tax",
71 | "name": "Tax Invoice Settings",
72 | "owner": "Administrator",
73 | "permissions": [
74 | {
75 | "create": 1,
76 | "read": 1,
77 | "role": "Accounts Manager",
78 | "write": 1
79 | },
80 | {
81 | "read": 1,
82 | "role": "Sales User"
83 | },
84 | {
85 | "read": 1,
86 | "role": "Purchase User"
87 | }
88 | ],
89 | "sort_field": "modified",
90 | "sort_order": "DESC",
91 | "states": [],
92 | "track_changes": 1
93 | }
--------------------------------------------------------------------------------
/thai_tax/public/js/withholding_tax_cert.js:
--------------------------------------------------------------------------------
1 | frappe.ui.form.on("Withholding Tax Cert", {
2 | refresh(frm) {
3 | frm.set_query("company_address", function (doc) {
4 | return {
5 | query: "frappe.contacts.doctype.address.address.address_query",
6 | filters: {
7 | link_doctype: "Company",
8 | link_name: doc.company,
9 | },
10 | };
11 | });
12 | frm.set_query("voucher_type", function () {
13 | return {
14 | filters: {
15 | name: ["in", ["Payment Entry", "Journal Entry"]],
16 | },
17 | };
18 | });
19 | },
20 | });
21 |
22 | frappe.ui.form.on("Withholding Tax Items", {
23 | // Helper to calculate tax amount from given rate
24 | tax_rate: function (frm, cdt, cdn) {
25 | var row = locals[cdt][cdn];
26 | frappe.model.set_value(cdt, cdn, "tax_amount", (row.tax_base * row.tax_rate) / 100);
27 | },
28 | // Auto assign income type description
29 | type_of_income: function (frm, cdt, cdn) {
30 | var row = locals[cdt][cdn];
31 | var vals = {
32 | 1: "เงินเดือน ค่าจ้าง ฯลฯ 40(1)",
33 | 2: "ค่าธรรมเนียม ค่านายหน้า ฯลฯ 40(2)",
34 | 3: "ค่าแห่งลิขสิทธิ์ ฯลฯ 40(3)",
35 | 4: "ดอกเบี้ย ฯลฯ 40(4)ก",
36 | "4.1.1":
37 | "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (1.1) กิจการที่ต้องเสียภาษีเงินได้นิติบุคคลร้อยละ 30 ของกำไรสุทธิ",
38 | "4.1.2":
39 | "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (1.2) กิจการที่ต้องเสียภาษีเงินได้นิติบุคคลร้อยละ 25 ของกำไรสุทธิ",
40 | "4.1.3":
41 | "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (1.3) กิจการที่ต้องเสียภาษีเงินได้นิติบุคคลร้อยละ 20 ของกำไรสุทธิ",
42 | "4.1.4":
43 | "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (1.4) กิจการที่ต้องเสียภาษีเงินได้นิติบุคคลร้อยละ อื่นๆ (ระบุ) ของกำไรสุทธิ",
44 | "4.2.1":
45 | "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (2.1) กำไรสุทธิกิจการที่ได้รับยกเว้นภาษีเงินได้นิติบุคคล",
46 | "4.2.2":
47 | "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (2.2) ได้รับยกเว้นไม่ต้องนำมารวมคำนวณเป็นรายได้",
48 | "4.2.3":
49 | "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (2.3) กำไรสุทธิส่วนที่หักผลขาดทุนสุทธิยกมาไม่เกิน 5 ปี",
50 | "4.2.4":
51 | "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (2.4) กำไรที่รับรู้ทางบัญชีโดยวิธีส่วนได้เสีย",
52 | "4.2.5": "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (2.5) อื่นๆ (ระบุ)",
53 | 5: "ค่าจ้างทำของ ค่าบริการ ค่าเช่า ค่าขนส่ง ฯลฯ 3 เตรส",
54 | 6: "อื่นๆ (ระบุ)",
55 | };
56 | frappe.model.set_value(cdt, cdn, "description", vals[row.type_of_income]);
57 | },
58 | });
59 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/doctype/journal_entry_tax_invoice_detail/journal_entry_tax_invoice_detail.json:
--------------------------------------------------------------------------------
1 | {
2 | "actions": [],
3 | "allow_rename": 1,
4 | "creation": "2023-07-30 10:00:38.519032",
5 | "doctype": "DocType",
6 | "editable_grid": 1,
7 | "engine": "InnoDB",
8 | "field_order": [
9 | "company_tax_address",
10 | "column_break_gg3aa",
11 | "party_name",
12 | "section_break_gh6bu",
13 | "supplier",
14 | "column_break_b7ziy",
15 | "customer",
16 | "section_break_rpmxt",
17 | "tax_invoice_number",
18 | "tax_invoice_date",
19 | "column_break_bxvza",
20 | "tax_base_amount",
21 | "tax_amount"
22 | ],
23 | "fields": [
24 | {
25 | "fieldname": "company_tax_address",
26 | "fieldtype": "Link",
27 | "label": "Company Tax Address",
28 | "options": "Address"
29 | },
30 | {
31 | "fieldname": "supplier",
32 | "fieldtype": "Link",
33 | "label": "Supplier",
34 | "options": "Supplier"
35 | },
36 | {
37 | "allow_on_submit": 1,
38 | "fieldname": "tax_invoice_number",
39 | "fieldtype": "Data",
40 | "in_list_view": 1,
41 | "in_standard_filter": 1,
42 | "label": "Tax Invoice Number"
43 | },
44 | {
45 | "allow_on_submit": 1,
46 | "fieldname": "tax_invoice_date",
47 | "fieldtype": "Date",
48 | "in_list_view": 1,
49 | "label": "Tax Invoice Date"
50 | },
51 | {
52 | "fieldname": "tax_base_amount",
53 | "fieldtype": "Float",
54 | "in_list_view": 1,
55 | "label": "Tax Base Amount",
56 | "precision": "2",
57 | "read_only": 1
58 | },
59 | {
60 | "fieldname": "tax_amount",
61 | "fieldtype": "Float",
62 | "in_list_view": 1,
63 | "label": "Tax Amount",
64 | "precision": "2",
65 | "read_only": 1
66 | },
67 | {
68 | "fieldname": "customer",
69 | "fieldtype": "Link",
70 | "label": "Customer",
71 | "options": "Customer"
72 | },
73 | {
74 | "fieldname": "party_name",
75 | "fieldtype": "Data",
76 | "in_list_view": 1,
77 | "label": "Party Name",
78 | "read_only": 1
79 | },
80 | {
81 | "fieldname": "column_break_gg3aa",
82 | "fieldtype": "Column Break"
83 | },
84 | {
85 | "fieldname": "section_break_gh6bu",
86 | "fieldtype": "Section Break"
87 | },
88 | {
89 | "fieldname": "column_break_b7ziy",
90 | "fieldtype": "Column Break"
91 | },
92 | {
93 | "fieldname": "section_break_rpmxt",
94 | "fieldtype": "Section Break"
95 | },
96 | {
97 | "fieldname": "column_break_bxvza",
98 | "fieldtype": "Column Break"
99 | }
100 | ],
101 | "index_web_pages_for_search": 1,
102 | "istable": 1,
103 | "links": [],
104 | "modified": "2023-07-30 15:33:54.967313",
105 | "modified_by": "Administrator",
106 | "module": "Thai Tax",
107 | "name": "Journal Entry Tax Invoice Detail",
108 | "owner": "Administrator",
109 | "permissions": [],
110 | "sort_field": "modified",
111 | "sort_order": "DESC",
112 | "states": []
113 | }
--------------------------------------------------------------------------------
/thai_tax/thai_tax/form_tour/tax_invoice_settings/tax_invoice_settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "creation": "2023-06-22 13:05:27.078306",
3 | "docstatus": 0,
4 | "doctype": "Form Tour",
5 | "first_document": 0,
6 | "idx": 0,
7 | "include_name_field": 0,
8 | "is_standard": 1,
9 | "list_name": "List",
10 | "modified": "2023-06-22 13:35:18.914103",
11 | "modified_by": "Administrator",
12 | "module": "Thai Tax",
13 | "name": "Tax Invoice Settings",
14 | "new_document_form": 0,
15 | "owner": "Administrator",
16 | "reference_doctype": "Tax Invoice Settings",
17 | "report_name": "",
18 | "save_on_complete": 0,
19 | "steps": [
20 | {
21 | "description": "Select your current company",
22 | "fieldname": "company",
23 | "fieldtype": "Link",
24 | "has_next_condition": 0,
25 | "hide_buttons": 0,
26 | "is_table_field": 0,
27 | "label": "Company",
28 | "modal_trigger": 0,
29 | "next_on_click": 0,
30 | "offset_x": 0,
31 | "offset_y": 0,
32 | "popover_element": 0,
33 | "position": "Bottom",
34 | "title": "Company",
35 | "ui_tour": 0
36 | },
37 | {
38 | "description": "Select Sales Tax Account",
39 | "fieldname": "sales_tax_account",
40 | "fieldtype": "Link",
41 | "has_next_condition": 0,
42 | "hide_buttons": 0,
43 | "is_table_field": 0,
44 | "label": "Sales Tax Account",
45 | "modal_trigger": 0,
46 | "next_on_click": 0,
47 | "offset_x": 0,
48 | "offset_y": 0,
49 | "popover_element": 0,
50 | "position": "Bottom",
51 | "title": "Sales Tax Account",
52 | "ui_tour": 0
53 | },
54 | {
55 | "description": "Select Undue Sales Tax Account",
56 | "fieldname": "sales_tax_account_undue",
57 | "fieldtype": "Link",
58 | "has_next_condition": 0,
59 | "hide_buttons": 0,
60 | "is_table_field": 0,
61 | "label": "Sales Tax Account Undue",
62 | "modal_trigger": 0,
63 | "next_on_click": 0,
64 | "offset_x": 0,
65 | "offset_y": 0,
66 | "popover_element": 0,
67 | "position": "Bottom",
68 | "title": "Select Undue Sales Tax Account",
69 | "ui_tour": 0
70 | },
71 | {
72 | "description": "Select Purchase Tax Account",
73 | "fieldname": "purchase_tax_account",
74 | "fieldtype": "Link",
75 | "has_next_condition": 0,
76 | "hide_buttons": 0,
77 | "is_table_field": 0,
78 | "label": "Purchase Tax Account",
79 | "modal_trigger": 0,
80 | "next_on_click": 0,
81 | "offset_x": 0,
82 | "offset_y": 0,
83 | "popover_element": 0,
84 | "position": "Bottom",
85 | "title": "Select Purchase Tax Account",
86 | "ui_tour": 0
87 | },
88 | {
89 | "description": "Select Undue Purchase Tax Account",
90 | "fieldname": "purchase_tax_account_undue",
91 | "fieldtype": "Link",
92 | "has_next_condition": 0,
93 | "hide_buttons": 0,
94 | "is_table_field": 0,
95 | "label": "Purchase Tax Account Undue",
96 | "modal_trigger": 0,
97 | "next_on_click": 0,
98 | "offset_x": 0,
99 | "offset_y": 0,
100 | "popover_element": 0,
101 | "position": "Bottom",
102 | "title": "Select Undue Purchase Tax Account",
103 | "ui_tour": 0
104 | }
105 | ],
106 | "title": "Tax Invoice Settings",
107 | "track_steps": 0,
108 | "ui_tour": 0,
109 | "view_name": "Workspaces"
110 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # !IMPORTANT! This repo is not longer improved (only bug fix), we moved to https://github.com/ecosoft-frappe/erpnext_thailand
2 |
3 | ## Thai Tax
4 |
5 | Additional tax functionality to comply with Thailand Tax regulation.
6 |
7 | ### 1. Tax Point on both Invoice and Payment
8 |
9 | Tax Point determine when tax is recorded in general ledger. And on tax point, with Sales Tax Invoice or Purchase Tax Invoice will be created.
10 |
11 | Trading of stockable product, tax point occur when deliver product and invoice is issued. The selling party will issue out document called "Delivery Note / Tax Invoice". And so Tax Invoice doctype got created when submit sales/purchase invoice.
12 |
13 | For service, tax point occur when service is done and payment is made. When submit sales/purchase invoice, account ledger will record Undue Tax. Until when the seller get paid, it will then create Tax Invoice doctype on payment submission, in which account ledger will clear Undue Tax into Tax. The document issued from seller is called "Receipt / Tax Invoice"
14 |
15 | ### 2. Withholding Tax and Certificate
16 |
17 | When a company purchase service from a supplier, when making payment, it is responsible to withhold (deduct) a tax amount (i.e., 3%) of invoice amount and issue out the Withholding Tax Certificate (pdf) to supplier.
18 |
19 | ### 3. Reports that require for submission to RD,
20 |
21 | - Purchase Tax Report, Sales Tax Report
22 | - Withholding Tax Report (PND or ภงด)
23 |
24 | ### TODO:
25 |
26 | - Thailand e-Tax Invoice, e-Withholding Tax
27 |
28 | ## Features
29 |
30 | - Sales Tax and Undue Sales Tax
31 | - Purchase Tax and Undue Purchase Tax
32 | - Sales and Purchase Tax Report
33 | - Withholding Tax on Payment (based on invoice amount before tax) and Withholding Tax Cert (pdf)
34 | - Withholding Tax Report (PND3, PND53)
35 | - Get Address by Tax ID
36 |
37 | ## Setup
38 |
39 | ### Installation
40 |
41 | ```
42 | $ cd frappe-bench
43 | $ bench get-app https://github.com/kittiu/thai_tax
44 | $ bench install-app thai_tax
45 | ```
46 |
47 | ### Configurations
48 |
49 | #### For Tax Invoice setup
50 |
51 | 1. In chart of account, make sure to have with Rate, i.e, 7% for Thailand Tax (Tax)
52 | - Sales Tax, Undue Sales Tax
53 | - Purchase Tax, Undue Purchase Tax
54 | 2. Open Tax Invoice Settings, and setup above taxes
55 | 3. Setup Sales / Purchase Taxes and Charges Template, we just want to make sure that,
56 | - When buy/sell product, Sales/Purchase Tax is record on invoice
57 | - When buy/sell service, Undue Sales/Purchase Tax is record on invoice, then on payment, clear Undue Tax and record Tax
58 | 4. Make sure you have setup Company's Billing Address, as it will be used for Tax Invoice
59 | 5. Make sure all Supplier/Customer have setup Billing Address, they will be used for Tax Invoice
60 |
61 | Whenever Tax is recorded (with Tax Invoice and Tax Date), Sales/Purchase Tax Invoice will be created.
62 |
63 | #### For Withholding Tax setup
64 |
65 | 1. In chart of account, make sure to have Withholding Tax Account
66 | 2. Create Withholding Tax Types (1%, 2%, 3% and 5%)
67 |
68 | During payment, user will manually choose to deduct with one of these Withholding Tax Type, and then click button Create Withholding Tax cert with the deducted amount plus some additional deduction information.
69 |
70 | -----------------------
71 | #### License
72 |
73 | MIT
74 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/report/sales_tax_report/sales_tax_report.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023, Kitti U. and contributors
2 | # For license information, please see license.txt
3 |
4 | import frappe
5 | from frappe import _
6 | from frappe.query_builder import Case, CustomFunction
7 |
8 |
9 | def execute(filters=None):
10 | columns = get_columns()
11 | data = get_data(filters)
12 | return columns, data, None, None, None
13 |
14 |
15 | def get_columns():
16 | return [
17 | {
18 | "label": _("Tax Address"),
19 | "fieldname": "company_tax_address",
20 | "fieldtype": "Link",
21 | "options": "Address",
22 | "width": 0,
23 | },
24 | {
25 | "label": _("Report Date"),
26 | "fieldname": "report_date",
27 | "fieldtype": "Date",
28 | "width": 0,
29 | },
30 | {
31 | "label": _("Number"),
32 | "fieldname": "name",
33 | "fieldtype": "Data",
34 | "width": 150,
35 | },
36 | {
37 | "label": _("Customer"),
38 | "fieldname": "party_name",
39 | "fieldtype": "Data",
40 | "width": 200,
41 | },
42 | {
43 | "label": _("Tax ID"),
44 | "fieldname": "tax_id",
45 | "fieldtype": "Data",
46 | "width": 120,
47 | },
48 | {
49 | "label": _("Tax Base"),
50 | "fieldname": "tax_base",
51 | "fieldtype": "Currency",
52 | "options": "Company:company:default_currency",
53 | "width": 0,
54 | },
55 | {
56 | "label": _("Tax Amount"),
57 | "fieldname": "tax_amount",
58 | "fieldtype": "Currency",
59 | "options": "Company:company:default_currency",
60 | "width": 0,
61 | },
62 | {
63 | "label": _("Ref Voucher Type"),
64 | "fieldname": "voucher_type",
65 | "fieldtype": "Data",
66 | "width": 0,
67 | },
68 | {
69 | "label": _("Ref Voucher No"),
70 | "fieldname": "voucher_no",
71 | "fieldtype": "Dynamic Link",
72 | "options": "voucher_type",
73 | "width": 200,
74 | },
75 | ]
76 |
77 |
78 | def get_data(filters):
79 |
80 | tinv = frappe.qb.DocType("Sales Tax Invoice")
81 | cust = frappe.qb.DocType("Customer")
82 | round = CustomFunction("round", ["value", "digit"])
83 | month = CustomFunction("month", ["date"])
84 | year = CustomFunction("year", ["date"])
85 | concat = CustomFunction("concat", ["1", "2"])
86 |
87 | query = (
88 | frappe.qb.from_(tinv)
89 | .left_join(cust)
90 | .on(cust.name == tinv.party)
91 | .select(
92 | tinv.company_tax_address.as_("company_tax_address"),
93 | tinv.report_date.as_("report_date"),
94 | Case()
95 | .when(tinv.docstatus == 1, tinv.name)
96 | .else_(concat(tinv.name, " (CANCEL)"))
97 | .as_("name"),
98 | tinv.party_name.as_("party_name"),
99 | cust.tax_id.as_("tax_id"),
100 | Case().when(tinv.docstatus == 1, round(tinv.tax_base, 2)).else_(0).as_("tax_base"),
101 | Case()
102 | .when(tinv.docstatus == 1, round(tinv.tax_amount, 2))
103 | .else_(0)
104 | .as_("tax_amount"),
105 | tinv.voucher_type.as_("voucher_type"),
106 | tinv.voucher_no.as_("voucher_no"),
107 | )
108 | .where(tinv.docstatus.isin([1, 2]))
109 | .orderby(tinv.name)
110 | )
111 |
112 | if filters.get("filter_based_on") == "Fiscal Year":
113 | query = query.where(month(tinv.report_date) == filters.get("month"))
114 | query = query.where(year(tinv.report_date) == filters.get("year"))
115 |
116 | if filters.get("filter_based_on") == "Date Range":
117 | query = query.where(tinv.report_date >= filters.get("start_date"))
118 | query = query.where(tinv.report_date <= filters.get("end_date"))
119 |
120 | if filters.get("company_tax_address"):
121 | query = query.where(tinv.company_tax_address == filters.get("company_tax_address"))
122 |
123 | result = query.run(as_dict=True)
124 |
125 | return result
126 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/workspace/thai_tax/thai_tax.json:
--------------------------------------------------------------------------------
1 | {
2 | "charts": [],
3 | "content": "[{\"id\":\"Uty0KUCJZZ\",\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Thai Tax\",\"col\":12}},{\"id\":\"0xFTodMRF1\",\"type\":\"card\",\"data\":{\"card_name\":\"Tax Invoices\",\"col\":4}},{\"id\":\"MOY2MzVVaE\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"id\":\"NLSyjJJigj\",\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]",
4 | "creation": "2023-06-22 11:35:38.341907",
5 | "custom_blocks": [],
6 | "docstatus": 0,
7 | "doctype": "Workspace",
8 | "for_user": "",
9 | "hide_custom": 0,
10 | "icon": "milestone",
11 | "idx": 0,
12 | "is_hidden": 0,
13 | "label": "Thai Tax",
14 | "links": [
15 | {
16 | "hidden": 0,
17 | "is_query_report": 0,
18 | "label": "Settings",
19 | "link_count": 2,
20 | "onboard": 0,
21 | "type": "Card Break"
22 | },
23 | {
24 | "hidden": 0,
25 | "is_query_report": 0,
26 | "label": "Tax Invoice Setting",
27 | "link_count": 0,
28 | "link_to": "Tax Invoice Settings",
29 | "link_type": "DocType",
30 | "onboard": 0,
31 | "type": "Link"
32 | },
33 | {
34 | "hidden": 0,
35 | "is_query_report": 0,
36 | "label": "Withholding Tax Type",
37 | "link_count": 0,
38 | "link_to": "Withholding Tax Type",
39 | "link_type": "DocType",
40 | "onboard": 0,
41 | "type": "Link"
42 | },
43 | {
44 | "hidden": 0,
45 | "is_query_report": 0,
46 | "label": "Tax Invoices",
47 | "link_count": 2,
48 | "onboard": 0,
49 | "type": "Card Break"
50 | },
51 | {
52 | "hidden": 0,
53 | "is_query_report": 0,
54 | "label": "Sales Tax Invoice",
55 | "link_count": 0,
56 | "link_to": "Sales Tax Invoice",
57 | "link_type": "DocType",
58 | "onboard": 0,
59 | "type": "Link"
60 | },
61 | {
62 | "hidden": 0,
63 | "is_query_report": 0,
64 | "label": "Purchase Tax Invoice",
65 | "link_count": 0,
66 | "link_to": "Purchase Tax Invoice",
67 | "link_type": "DocType",
68 | "onboard": 0,
69 | "type": "Link"
70 | },
71 | {
72 | "hidden": 0,
73 | "is_query_report": 0,
74 | "label": "Reports",
75 | "link_count": 4,
76 | "onboard": 0,
77 | "type": "Card Break"
78 | },
79 | {
80 | "hidden": 0,
81 | "is_query_report": 0,
82 | "label": "Sales Tax Report",
83 | "link_count": 0,
84 | "link_to": "Sales Tax Report",
85 | "link_type": "Report",
86 | "onboard": 0,
87 | "type": "Link"
88 | },
89 | {
90 | "hidden": 0,
91 | "is_query_report": 0,
92 | "label": "Purchase Tax Report",
93 | "link_count": 0,
94 | "link_to": "Purchase Tax Report",
95 | "link_type": "Report",
96 | "onboard": 0,
97 | "type": "Link"
98 | },
99 | {
100 | "hidden": 0,
101 | "is_query_report": 0,
102 | "label": "PND3",
103 | "link_count": 0,
104 | "link_to": "PND3",
105 | "link_type": "Report",
106 | "onboard": 0,
107 | "type": "Link"
108 | },
109 | {
110 | "hidden": 0,
111 | "is_query_report": 0,
112 | "label": "PND53",
113 | "link_count": 0,
114 | "link_to": "PND53",
115 | "link_type": "Report",
116 | "onboard": 0,
117 | "type": "Link"
118 | }
119 | ],
120 | "modified": "2024-05-03 10:25:42.626039",
121 | "modified_by": "Administrator",
122 | "module": "Thai Tax",
123 | "name": "Thai Tax",
124 | "number_cards": [],
125 | "owner": "Administrator",
126 | "parent_page": "Accounting",
127 | "public": 1,
128 | "quick_lists": [],
129 | "roles": [
130 | {
131 | "role": "Accounts User"
132 | },
133 | {
134 | "role": "Accounts Manager"
135 | }
136 | ],
137 | "sequence_id": 7.0,
138 | "shortcuts": [],
139 | "title": "Thai Tax"
140 | }
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "node": true,
5 | "es6": true
6 | },
7 | "parserOptions": {
8 | "ecmaVersion": 11,
9 | "sourceType": "module"
10 | },
11 | "extends": "eslint:recommended",
12 | "rules": {
13 | "indent": [
14 | "error",
15 | "tab",
16 | { "SwitchCase": 1 }
17 | ],
18 | "brace-style": [
19 | "error",
20 | "1tbs"
21 | ],
22 | "space-unary-ops": [
23 | "error",
24 | { "words": true }
25 | ],
26 | "linebreak-style": [
27 | "error",
28 | "unix"
29 | ],
30 | "quotes": [
31 | "off"
32 | ],
33 | "semi": [
34 | "warn",
35 | "always"
36 | ],
37 | "camelcase": [
38 | "off"
39 | ],
40 | "no-unused-vars": [
41 | "warn"
42 | ],
43 | "no-redeclare": [
44 | "warn"
45 | ],
46 | "no-console": [
47 | "warn"
48 | ],
49 | "no-extra-boolean-cast": [
50 | "off"
51 | ],
52 | "no-control-regex": [
53 | "off"
54 | ],
55 | "space-before-blocks": "warn",
56 | "keyword-spacing": "warn",
57 | "comma-spacing": "warn",
58 | "key-spacing": "warn",
59 | },
60 | "root": true,
61 | "globals": {
62 | "frappe": true,
63 | "Vue": true,
64 | "__": true,
65 | "repl": true,
66 | "Class": true,
67 | "locals": true,
68 | "cint": true,
69 | "cstr": true,
70 | "cur_frm": true,
71 | "cur_dialog": true,
72 | "cur_page": true,
73 | "cur_list": true,
74 | "cur_tree": true,
75 | "msg_dialog": true,
76 | "is_null": true,
77 | "in_list": true,
78 | "has_common": true,
79 | "has_words": true,
80 | "validate_email": true,
81 | "validate_name": true,
82 | "validate_phone": true,
83 | "validate_url": true,
84 | "get_number_format": true,
85 | "format_number": true,
86 | "format_currency": true,
87 | "comment_when": true,
88 | "open_url_post": true,
89 | "toTitle": true,
90 | "lstrip": true,
91 | "rstrip": true,
92 | "strip": true,
93 | "strip_html": true,
94 | "replace_all": true,
95 | "flt": true,
96 | "precision": true,
97 | "CREATE": true,
98 | "AMEND": true,
99 | "CANCEL": true,
100 | "copy_dict": true,
101 | "get_number_format_info": true,
102 | "strip_number_groups": true,
103 | "print_table": true,
104 | "Layout": true,
105 | "web_form_settings": true,
106 | "$c": true,
107 | "$a": true,
108 | "$i": true,
109 | "$bg": true,
110 | "$y": true,
111 | "$c_obj": true,
112 | "refresh_many": true,
113 | "refresh_field": true,
114 | "toggle_field": true,
115 | "get_field_obj": true,
116 | "get_query_params": true,
117 | "unhide_field": true,
118 | "hide_field": true,
119 | "set_field_options": true,
120 | "getCookie": true,
121 | "getCookies": true,
122 | "get_url_arg": true,
123 | "md5": true,
124 | "$": true,
125 | "jQuery": true,
126 | "moment": true,
127 | "hljs": true,
128 | "Awesomplete": true,
129 | "Sortable": true,
130 | "Showdown": true,
131 | "Taggle": true,
132 | "Gantt": true,
133 | "Slick": true,
134 | "Webcam": true,
135 | "PhotoSwipe": true,
136 | "PhotoSwipeUI_Default": true,
137 | "io": true,
138 | "JsBarcode": true,
139 | "L": true,
140 | "Chart": true,
141 | "DataTable": true,
142 | "Cypress": true,
143 | "cy": true,
144 | "it": true,
145 | "describe": true,
146 | "expect": true,
147 | "context": true,
148 | "before": true,
149 | "beforeEach": true,
150 | "after": true,
151 | "qz": true,
152 | "localforage": true,
153 | "extend_cscript": true
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/thai_tax/thai_tax/report/purchase_tax_report/purchase_tax_report.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023, Kitti U. and contributors
2 | # For license information, please see license.txt
3 |
4 | import frappe
5 | from frappe import _
6 | from frappe.query_builder import CustomFunction
7 |
8 |
9 | def execute(filters=None):
10 | columns = get_columns()
11 | data = get_data(filters)
12 | return columns, data, None, None, None
13 |
14 |
15 | def get_columns():
16 | return [
17 | {
18 | "label": _("Tax Address"),
19 | "fieldname": "company_tax_address",
20 | "fieldtype": "Link",
21 | "options": "Address",
22 | "width": 0,
23 | },
24 | {
25 | "label": _("Report Date"),
26 | "fieldname": "report_date",
27 | "fieldtype": "Date",
28 | "width": 0,
29 | },
30 | {
31 | "label": _("Number"),
32 | "fieldname": "name",
33 | "fieldtype": "Data",
34 | "width": 0,
35 | },
36 | {
37 | "label": _("Supplier"),
38 | "fieldname": "party_name",
39 | "fieldtype": "Data",
40 | "width": 0,
41 | },
42 | {
43 | "label": _("Tax ID"),
44 | "fieldname": "tax_id",
45 | "fieldtype": "Data",
46 | "width": 0,
47 | },
48 | {
49 | "label": _("Branch"),
50 | "fieldname": "branch_code",
51 | "fieldtype": "Data",
52 | "width": 0,
53 | },
54 | {
55 | "label": _("Supplier Address"),
56 | "fieldname": "supplier_address",
57 | "fieldtype": "Data",
58 | "width": 0,
59 | },
60 | {
61 | "label": _("Tax Base"),
62 | "fieldname": "tax_base",
63 | "fieldtype": "Currency",
64 | "options": "Company:company:default_currency",
65 | "width": 0,
66 | },
67 | {
68 | "label": _("Tax Amount"),
69 | "fieldname": "tax_amount",
70 | "fieldtype": "Currency",
71 | "options": "Company:company:default_currency",
72 | "width": 0,
73 | },
74 | {
75 | "label": _("Ref Voucher Type"),
76 | "fieldname": "voucher_type",
77 | "fieldtype": "Data",
78 | "width": 0,
79 | },
80 | {
81 | "label": _("Ref Voucher No"),
82 | "fieldname": "voucher_no",
83 | "fieldtype": "Dynamic Link",
84 | "options": "voucher_type",
85 | "width": 0,
86 | },
87 | {
88 | "label": _("Ref Tax Invoice"),
89 | "fieldname": "tax_invoice",
90 | "fieldtype": "Link",
91 | "options": "Purchase Tax Invoice",
92 | "width": 0,
93 | },
94 | ]
95 |
96 |
97 | def get_data(filters):
98 |
99 | tinv = frappe.qb.DocType("Purchase Tax Invoice")
100 | sup = frappe.qb.DocType("Supplier")
101 | addr = frappe.qb.DocType("Address")
102 | round = CustomFunction("round", ["value", "digit"])
103 | coalesce = CustomFunction("coalesce", ["value1", "value2"])
104 | month = CustomFunction("month", ["date"])
105 | year = CustomFunction("year", ["date"])
106 | concat_ws = CustomFunction("concat_ws", ["separator", "1", "2", "3", "4", "5", "6"])
107 |
108 | query = (
109 | frappe.qb.from_(tinv)
110 | .left_join(sup)
111 | .on(sup.name == tinv.party)
112 | .left_join(addr)
113 | .on(addr.name == sup.supplier_primary_address)
114 | .select(
115 | tinv.company_tax_address.as_("company_tax_address"),
116 | tinv.report_date.as_("report_date"),
117 | coalesce(tinv.number, tinv.name).as_("name"),
118 | sup.supplier_name.as_("party_name"),
119 | sup.tax_id.as_("tax_id"),
120 | sup.branch_code.as_("branch_code"),
121 | concat_ws(
122 | " ",
123 | addr.address_line1,
124 | addr.address_line2,
125 | addr.city,
126 | addr.county,
127 | addr.state,
128 | addr.pincode,
129 | ).as_("supplier_address"),
130 | round(tinv.tax_base, 2).as_("tax_base"),
131 | round(tinv.tax_amount, 2).as_("tax_amount"),
132 | tinv.voucher_type.as_("voucher_type"),
133 | tinv.voucher_no.as_("voucher_no"),
134 | tinv.name.as_("tax_invoice"),
135 | )
136 | .where(tinv.docstatus == 1)
137 | .orderby(tinv.report_date)
138 | )
139 |
140 | if filters.get("filter_based_on") == "Fiscal Year":
141 | query = query.where(month(tinv.report_date) == filters.get("month"))
142 | query = query.where(year(tinv.report_date) == filters.get("year"))
143 |
144 | if filters.get("filter_based_on") == "Date Range":
145 | query = query.where(tinv.report_date >= filters.get("start_date"))
146 | query = query.where(tinv.report_date <= filters.get("end_date"))
147 |
148 | if filters.get("company_tax_address"):
149 | query = query.where(tinv.company_tax_address == filters.get("company_tax_address"))
150 |
151 | result = query.run(as_dict=True)
152 |
153 | return result
154 |
--------------------------------------------------------------------------------
/thai_tax/utils.py:
--------------------------------------------------------------------------------
1 | import datetime
2 |
3 | import frappe
4 | from frappe import _
5 | from num2words import num2words
6 | import requests
7 | from lxml import etree
8 |
9 | def amount_in_bahttext(amount):
10 | return num2words(amount, to="currency", lang="th")
11 |
12 |
13 | def full_thai_date(date_str):
14 | if not date_str:
15 | return ""
16 | date = datetime.datetime.strptime(str(date_str), "%Y-%m-%d")
17 | month_name = "x มกราคม กุมภาพันธ์ มีนาคม เมษายน พฤษภาคม มิถุนายน กรกฎาคม สิงหาคม กันยายน ตุลาคม พฤศจิกายน ธันวาคม".split()[
18 | date.month
19 | ]
20 | thai_year = date.year + 543
21 | return "%d %s %d" % (date.day, month_name, thai_year) # 30 ตุลาคม 2560
22 |
23 |
24 | @frappe.whitelist()
25 | def get_address_by_tax_id(tax_id=False, branch=False):
26 | """Get address information from Revenue Department Web Service by Tax ID and Branch number.
27 |
28 | Args:
29 | tax_id (str): Tax ID of the company
30 | branch (str): Branch number of the company
31 |
32 | Returns:
33 | dict: Dictionary containing address information
34 | Empty dict if there's an error
35 |
36 | Raises:
37 | frappe.ValidationError: If tax_id or branch is not provided
38 | """
39 | if not (tax_id and branch):
40 | frappe.throw(_('Please provide both Tax ID and Branch number'))
41 |
42 | # API Configuration
43 | url = "https://rdws.rd.go.th/serviceRD3/vatserviceRD3.asmx"
44 | querystring = {"wsdl": ""}
45 | headers = {"content-type": "application/soap+xml; charset=utf-8"}
46 |
47 | # Convert branch number, default to "0" if not numeric
48 | branch_number = int(branch if branch.isnumeric() else "0")
49 |
50 | # Prepare SOAP payload
51 | payload = (
52 | '
\n {{ doc.company }}\n
\n\n {{ sup.supplier_name }}\n
\n