From c8d1256ce6e6efadcfb1bde2d55806a484de5251 Mon Sep 17 00:00:00 2001 From: Kitti U Date: Mon, 26 Jun 2023 11:36:31 +0700 Subject: [PATCH] Add pre-commit check --- .editorconfig | 15 + .eslintrc | 155 ++++ .flake8 | 75 ++ .pre-commit-config.yaml | 65 ++ setup.py | 4 +- thai_tax/__init__.py | 4 +- thai_tax/config/desktop.py | 9 +- thai_tax/config/docs.py | 1 + thai_tax/custom/custom_api.py | 711 +++++++++--------- thai_tax/custom/dashboard_overrides.py | 27 +- thai_tax/custom/employee_advance.py | 100 +-- thai_tax/custom/queries.py | 6 +- thai_tax/hooks.py | 290 +++---- thai_tax/public/js/address.js | 66 +- thai_tax/public/js/expense_claim.js | 18 +- thai_tax/public/js/journal_entry.js | 18 +- thai_tax/public/js/payment_entry.js | 161 ++-- thai_tax/public/js/purchase_tax_invoice.js | 18 +- thai_tax/public/js/sales_tax_invoice.js | 18 +- thai_tax/public/js/withholding_tax_cert.js | 69 +- .../purchase_tax_invoice.js | 3 +- .../purchase_tax_invoice.py | 4 +- .../sales_tax_invoice/sales_tax_invoice.js | 3 +- .../sales_tax_invoice/sales_tax_invoice.py | 2 +- .../tax_invoice_settings.js | 34 +- .../tax_invoice_settings.py | 1 + .../withholding_tax_cert.js | 20 +- .../withholding_tax_cert.py | 1 + .../withholding_tax_items.py | 1 + .../withholding_tax_setting.js | 3 +- .../withholding_tax_setting.py | 1 + .../withholding_tax_type.js | 3 +- .../withholding_tax_type.py | 1 + thai_tax/thai_tax/report/pnd3/pnd3.js | 35 +- thai_tax/thai_tax/report/pnd3/pnd3.py | 28 +- thai_tax/thai_tax/report/pnd53/pnd53.js | 35 +- thai_tax/thai_tax/report/pnd53/pnd53.py | 17 +- .../purchase_tax_report.js | 35 +- .../purchase_tax_report.py | 11 +- .../sales_tax_report/sales_tax_report.js | 34 +- .../sales_tax_report/sales_tax_report.py | 11 +- thai_tax/utils.py | 151 ++-- 42 files changed, 1315 insertions(+), 949 deletions(-) create mode 100644 .editorconfig create mode 100644 .eslintrc create mode 100644 .flake8 create mode 100644 .pre-commit-config.yaml diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a3b1ef0 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +# Root editor config file +root = true + +# Common settings +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +charset = utf-8 + +# python, js indentation settings +[{*.py,*.js,*.vue,*.css,*.scss,*.html}] +indent_style = tab +indent_size = 4 +max_line_length = 99 diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..3271ca3 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,155 @@ +{ + "env": { + "browser": true, + "node": true, + "es6": true + }, + "parserOptions": { + "ecmaVersion": 11, + "sourceType": "module" + }, + "extends": "eslint:recommended", + "rules": { + "indent": [ + "error", + "tab", + { "SwitchCase": 1 } + ], + "brace-style": [ + "error", + "1tbs" + ], + "space-unary-ops": [ + "error", + { "words": true } + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "off" + ], + "semi": [ + "warn", + "always" + ], + "camelcase": [ + "off" + ], + "no-unused-vars": [ + "warn" + ], + "no-redeclare": [ + "warn" + ], + "no-console": [ + "warn" + ], + "no-extra-boolean-cast": [ + "off" + ], + "no-control-regex": [ + "off" + ], + "space-before-blocks": "warn", + "keyword-spacing": "warn", + "comma-spacing": "warn", + "key-spacing": "warn", + }, + "root": true, + "globals": { + "frappe": true, + "Vue": true, + "__": true, + "repl": true, + "Class": true, + "locals": true, + "cint": true, + "cstr": true, + "cur_frm": true, + "cur_dialog": true, + "cur_page": true, + "cur_list": true, + "cur_tree": true, + "msg_dialog": true, + "is_null": true, + "in_list": true, + "has_common": true, + "has_words": true, + "validate_email": true, + "validate_name": true, + "validate_phone": true, + "validate_url": true, + "get_number_format": true, + "format_number": true, + "format_currency": true, + "comment_when": true, + "open_url_post": true, + "toTitle": true, + "lstrip": true, + "rstrip": true, + "strip": true, + "strip_html": true, + "replace_all": true, + "flt": true, + "precision": true, + "CREATE": true, + "AMEND": true, + "CANCEL": true, + "copy_dict": true, + "get_number_format_info": true, + "strip_number_groups": true, + "print_table": true, + "Layout": true, + "web_form_settings": true, + "$c": true, + "$a": true, + "$i": true, + "$bg": true, + "$y": true, + "$c_obj": true, + "refresh_many": true, + "refresh_field": true, + "toggle_field": true, + "get_field_obj": true, + "get_query_params": true, + "unhide_field": true, + "hide_field": true, + "set_field_options": true, + "getCookie": true, + "getCookies": true, + "get_url_arg": true, + "md5": true, + "$": true, + "jQuery": true, + "moment": true, + "hljs": true, + "Awesomplete": true, + "Sortable": true, + "Showdown": true, + "Taggle": true, + "Gantt": true, + "Slick": true, + "Webcam": true, + "PhotoSwipe": true, + "PhotoSwipeUI_Default": true, + "io": true, + "JsBarcode": true, + "L": true, + "Chart": true, + "DataTable": true, + "Cypress": true, + "cy": true, + "it": true, + "describe": true, + "expect": true, + "context": true, + "before": true, + "beforeEach": true, + "after": true, + "qz": true, + "localforage": true, + "extend_cscript": true + } +} diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..f80be64 --- /dev/null +++ b/.flake8 @@ -0,0 +1,75 @@ +[flake8] +ignore = + B001, + B007, + B009, + B010, + B950, + E101, + E111, + E114, + E116, + E117, + E121, + E122, + E123, + E124, + E125, + E126, + E127, + E128, + E131, + E201, + E202, + E203, + E211, + E221, + E222, + E223, + E224, + E225, + E226, + E228, + E231, + E241, + E242, + E251, + E261, + E262, + E265, + E266, + E271, + E272, + E273, + E274, + E301, + E302, + E303, + E305, + E306, + E402, + E501, + E502, + E701, + E702, + E703, + E741, + F401, + F403, + F405, + W191, + W291, + W292, + W293, + W391, + W503, + W504, + E711, + E129, + F841, + E713, + E712, + B028, + +max-line-length = 200 +exclude=,test_*.py \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..0c6bbe8 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,65 @@ +exclude: 'node_modules|.git' +default_stages: [commit] +fail_fast: false + + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.3.0 + hooks: + - id: trailing-whitespace + files: "frappe.*" + exclude: ".*json$|.*txt$|.*csv|.*md|.*svg" + - id: check-yaml + - id: no-commit-to-branch + args: ['--branch', 'develop'] + - id: check-merge-conflict + - id: check-ast + - id: check-json + - id: check-toml + - id: check-yaml + - id: debug-statements + + - repo: https://github.com/asottile/pyupgrade + rev: v2.34.0 + hooks: + - id: pyupgrade + args: ['--py310-plus'] + + - repo: https://github.com/frappe/black + rev: 951ccf4d5bb0d692b457a5ebc4215d755618eb68 + hooks: + - id: black + + - repo: https://github.com/pre-commit/mirrors-prettier + rev: v2.7.1 + hooks: + - id: prettier + types_or: [javascript] + # Ignore any files that might contain jinja / bundles + exclude: | + (?x)^( + frappe/public/dist/.*| + .*node_modules.*| + .*boilerplate.*| + frappe/www/website_script.js| + frappe/templates/includes/.*| + frappe/public/js/lib/.* + )$ + + + - repo: https://github.com/PyCQA/isort + rev: 5.12.0 + hooks: + - id: isort + + - repo: https://github.com/PyCQA/flake8 + rev: 5.0.4 + hooks: + - id: flake8 + additional_dependencies: ['flake8-bugbear',] + +ci: + autoupdate_schedule: weekly + skip: [] + submodules: false diff --git a/setup.py b/setup.py index 6e2a67a..3996092 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -from setuptools import setup, find_packages +from setuptools import find_packages, setup with open("requirements.txt") as f: install_requires = f.read().strip().split("\n") @@ -15,5 +15,5 @@ packages=find_packages(), zip_safe=False, include_package_data=True, - install_requires=install_requires + install_requires=install_requires, ) diff --git a/thai_tax/__init__.py b/thai_tax/__init__.py index 7a0660b..f102a9c 100644 --- a/thai_tax/__init__.py +++ b/thai_tax/__init__.py @@ -1,3 +1 @@ - -__version__ = '0.0.1' - +__version__ = "0.0.1" diff --git a/thai_tax/config/desktop.py b/thai_tax/config/desktop.py index a5cf729..2f99f1a 100644 --- a/thai_tax/config/desktop.py +++ b/thai_tax/config/desktop.py @@ -1,10 +1,5 @@ from frappe import _ + def get_data(): - return [ - { - "module_name": "Thai Tax", - "type": "module", - "label": _("Thai Tax") - } - ] + return [{"module_name": "Thai Tax", "type": "module", "label": _("Thai Tax")}] diff --git a/thai_tax/config/docs.py b/thai_tax/config/docs.py index f471862..3ed6dca 100644 --- a/thai_tax/config/docs.py +++ b/thai_tax/config/docs.py @@ -6,5 +6,6 @@ # headline = "App that does everything" # sub_heading = "Yes, you got that right the first time, everything" + def get_context(context): context.brand_html = "Thai Tax" diff --git a/thai_tax/custom/custom_api.py b/thai_tax/custom/custom_api.py index 8fd2e0b..83375fb 100644 --- a/thai_tax/custom/custom_api.py +++ b/thai_tax/custom/custom_api.py @@ -1,373 +1,412 @@ import json -import urllib3 from ast import literal_eval + import frappe +import urllib3 from frappe import _ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) def create_tax_invoice_on_gl_tax(doc, method): + def create_tax_invoice(doc, doctype, base_amount, tax_amount, voucher): + tinv_dict = {} + # For sales invoice / purchase invoice / payment and journal entry, we can get the party from GL + gl = frappe.db.get_all( + "GL Entry", + filters={ + "voucher_type": doc.voucher_type, + "voucher_no": doc.voucher_no, + "party": ["!=", ""], + }, + fields=["party"], + ) + party = gl and gl[0].get("party") + # Case use Journal Entry + if not party and doc.voucher_type == "Journal Entry": + je = frappe.get_doc(doc.voucher_type, doc.voucher_no) + party = je.supplier + if je.for_payment: + tinv_dict.update( + { + "against_voucher_type": "Payment Entry", + "against_voucher": je.for_payment, + } + ) + # Case Payment Entry, party must be of type customer/supplier only + if doc.voucher_type == "Payment Entry" and doc.party_type == "Employee": + party = voucher.supplier + # Case expense claim, partner should be supplier, not employee + if doc.voucher_type == "Expense Claim": + party = voucher.supplier + if not party: + frappe.throw(_("Please fill in Supplier for Purchase Tax Invoice")) + # Create Tax Invoice + tinv_dict.update( + { + "doctype": doctype, + "gl_entry": doc.name, + "tax_amount": tax_amount, + "tax_base": base_amount, + "party": party, + } + ) + tinv = frappe.get_doc(tinv_dict) + tinv.insert(ignore_permissions=True) + return tinv + + def update_voucher_tinv(doctype, voucher, tinv): + # Set company tax address + def update_company_tax_address(voucher, tinv): + # From Sales Invoice and Purchase Invoice, use voucher address + if tinv.voucher_type == "Sales Invoice": + tinv.company_tax_address = voucher.company_address + elif tinv.voucher_type == "Purchase Invoice": + tinv.company_tax_address = voucher.billing_address + else: # From Payment Entry, Expense Claim and Journal Entry + tinv.company_tax_address = voucher.company_tax_address + if not tinv.company_tax_address: + frappe.throw(_("No Company Billing/Tax Address")) - def create_tax_invoice(doc, doctype, base_amount, tax_amount, voucher): - tinv_dict = {} - # For sales invoice / purchase invoice / payment and journal entry, we can get the party from GL - gl = frappe.db.get_all( - 'GL Entry', - filters={'voucher_type': doc.voucher_type, 'voucher_no': doc.voucher_no, 'party': ['!=', '']}, - fields=['party'], - ) - party = gl and gl[0].get('party') - # Case use Journal Entry - if not party and doc.voucher_type == 'Journal Entry': - je = frappe.get_doc(doc.voucher_type, doc.voucher_no) - party = je.supplier - if je.for_payment: - tinv_dict.update({ - 'against_voucher_type': 'Payment Entry', - 'against_voucher': je.for_payment, - }) - # Case Payment Entry, party must be of type customer/supplier only - if doc.voucher_type == 'Payment Entry' and doc.party_type == 'Employee': - party = voucher.supplier - # Case expense claim, partner should be supplier, not employee - if doc.voucher_type == 'Expense Claim': - party = voucher.supplier - if not party: - frappe.throw(_('Please fill in Supplier for Purchase Tax Invoice')) - # Create Tax Invoice - tinv_dict.update({ - 'doctype': doctype, - 'gl_entry': doc.name, - 'tax_amount': tax_amount, - 'tax_base': base_amount, - 'party': party, - }) - tinv = frappe.get_doc(tinv_dict) - tinv.insert(ignore_permissions=True) - return tinv - - def update_voucher_tinv(doctype, voucher, tinv): - # Set company tax address - def update_company_tax_address(voucher, tinv): - # From Sales Invoice and Purchase Invoice, use voucher address - if tinv.voucher_type == 'Sales Invoice': - tinv.company_tax_address = voucher.company_address - elif tinv.voucher_type == 'Purchase Invoice': - tinv.company_tax_address = voucher.billing_address - else: # From Payment Entry, Expense Claim and Journal Entry - tinv.company_tax_address = voucher.company_tax_address - if not tinv.company_tax_address: - frappe.throw(_('No Company Billing/Tax Address')) + update_company_tax_address(voucher, tinv) - update_company_tax_address(voucher, tinv) + # Sales Invoice - use Sales Tax Invoice as Tax Invoice + # Purchase Invoice - use Bill No as Tax Invoice + if doctype == "Sales Tax Invoice": + voucher.tax_invoice_number = tinv.name + voucher.tax_invoice_date = tinv.date + tinv.report_date = tinv.date + if doctype == "Purchase Tax Invoice": + if not (voucher.tax_invoice_number and voucher.tax_invoice_date): + frappe.throw(_("Please enter Tax Invoice Number / Tax Invoice Date")) + voucher.save() + tinv.number = voucher.tax_invoice_number + tinv.report_date = tinv.date = voucher.tax_invoice_date + voucher.save() + tinv.save() + return tinv - # Sales Invoice - use Sales Tax Invoice as Tax Invoice - # Purchase Invoice - use Bill No as Tax Invoice - if doctype == 'Sales Tax Invoice': - voucher.tax_invoice_number = tinv.name - voucher.tax_invoice_date = tinv.date - tinv.report_date = tinv.date - if doctype == 'Purchase Tax Invoice': - if not (voucher.tax_invoice_number and voucher.tax_invoice_date): - frappe.throw(_('Please enter Tax Invoice Number / Tax Invoice Date')) - voucher.save() - tinv.number = voucher.tax_invoice_number - tinv.report_date = tinv.date = voucher.tax_invoice_date - voucher.save() - tinv.save() - return tinv + # Auto create Tax Invoice only when account equal to tax account. + setting = frappe.get_doc("Tax Invoice Settings") + doctype = False + tax_amount = 0.0 + voucher = frappe.get_doc(doc.voucher_type, doc.voucher_no) + is_return = False + if doc.voucher_type in ["Sales Invoice", "Purchase Invoice"]: + is_return = voucher.is_return # Case Debit/Credit Note + sign = is_return and -1 or 1 + # Tax amount, use Dr/Cr to ensure it support every case + if doc.account in [setting.sales_tax_account, setting.purchase_tax_account]: + tax_amount = doc.credit - doc.debit + if (tax_amount > 0 and not is_return) or (tax_amount < 0 and is_return): + doctype = "Sales Tax Invoice" + if (tax_amount < 0 and not is_return) or (tax_amount > 0 and is_return): + doctype = "Purchase Tax Invoice" + tax_amount = abs(tax_amount) * sign + if doctype: + voucher = frappe.get_doc(doc.voucher_type, doc.voucher_no) + if voucher.docstatus == 2: + tax_amount = 0 + if tax_amount != 0: + # Base amount, use base amount from origin document + if voucher.doctype == "Expense Claim": + base_amount = voucher.base_amount_overwrite or voucher.total_sanctioned_amount + elif voucher.doctype in ["Purchase Invoice", "Sales Invoice"]: + base_amount = voucher.base_net_total + elif voucher.doctype == "Payment Entry": + base_amount = voucher.tax_base_amount + elif voucher.doctype == "Journal Entry": + base_amount = voucher.tax_base_amount + base_amount = abs(base_amount) * sign + # Validate base amount + tax_rate = frappe.get_cached_value("Account", doc.account, "tax_rate") + if abs((base_amount * tax_rate / 100) - tax_amount) > 0.1: + frappe.throw( + _( + "Tax should be {}% of the base amount
" + "Note: To correct base amount, fill in Base Amount Overwrite.".format( + tax_rate + ) + ) + ) + tinv = create_tax_invoice(doc, doctype, base_amount, tax_amount, voucher) + tinv = update_voucher_tinv(doctype, voucher, tinv) + tinv.submit() - # Auto create Tax Invoice only when account equal to tax account. - setting = frappe.get_doc('Tax Invoice Settings') - doctype = False - tax_amount = 0.0 - voucher = frappe.get_doc(doc.voucher_type, doc.voucher_no) - is_return = False - if doc.voucher_type in ['Sales Invoice', 'Purchase Invoice']: - is_return = voucher.is_return # Case Debit/Credit Note - sign = is_return and -1 or 1 - # Tax amount, use Dr/Cr to ensure it support every case - if doc.account in [setting.sales_tax_account, setting.purchase_tax_account]: - tax_amount = doc.credit - doc.debit - if (tax_amount > 0 and not is_return) or (tax_amount < 0 and is_return): - doctype = 'Sales Tax Invoice' - if (tax_amount < 0 and not is_return) or (tax_amount > 0 and is_return): - doctype = 'Purchase Tax Invoice' - tax_amount = abs(tax_amount) * sign - if doctype: - voucher = frappe.get_doc(doc.voucher_type, doc.voucher_no) - if voucher.docstatus == 2: - tax_amount = 0 - if tax_amount != 0: - # Base amount, use base amount from origin document - if voucher.doctype == 'Expense Claim': - base_amount = voucher.base_amount_overwrite or voucher.total_sanctioned_amount - elif voucher.doctype in ['Purchase Invoice', 'Sales Invoice']: - base_amount = voucher.base_net_total - elif voucher.doctype == 'Payment Entry': - base_amount = voucher.tax_base_amount - elif voucher.doctype == 'Journal Entry': - base_amount = voucher.tax_base_amount - base_amount = abs(base_amount) * sign - # Validate base amount - tax_rate = frappe.get_cached_value('Account', doc.account, 'tax_rate') - if abs((base_amount * tax_rate/100) - tax_amount) > 0.1: - frappe.throw(_( - 'Tax should be {0}% of the base amount
' - 'Note: To correct base amount, fill in Base Amount Overwrite.'.format(tax_rate) - )) - tinv = create_tax_invoice(doc, doctype, base_amount, tax_amount, voucher) - tinv = update_voucher_tinv(doctype, voucher, tinv) - tinv.submit() def validate_company_address(doc, method): - if not doc.company_tax_address: - addresses = frappe.db.get_all( - 'Address', - filters={'is_your_company_address': 1, 'address_type': 'Billing'}, - fields=['name', 'address_type'], - ) - if len(addresses) == 1: - doc.company_tax_address = addresses[0]['name'] + if not doc.company_tax_address: + addresses = frappe.db.get_all( + "Address", + filters={"is_your_company_address": 1, "address_type": "Billing"}, + fields=["name", "address_type"], + ) + if len(addresses) == 1: + doc.company_tax_address = addresses[0]["name"] + def validate_tax_invoice(doc, method): - # If taxes contain tax account, tax invoice is required. - tax_account = frappe.db.get_single_value('Tax Invoice Settings', 'purchase_tax_account') - voucher = frappe.get_doc(doc.doctype, doc.name) - has_vat = False - for tax in voucher.taxes: - if tax.account_head == tax_account: - has_vat = True - break - if has_vat and not doc.tax_invoice_number: - frappe.throw(_('This document require Tax Invoice Number')) - if not has_vat and doc.tax_invoice_number: - frappe.throw(_('This document has no due VAT, please remove Tax Invoice Number')) + # If taxes contain tax account, tax invoice is required. + tax_account = frappe.db.get_single_value( + "Tax Invoice Settings", "purchase_tax_account" + ) + voucher = frappe.get_doc(doc.doctype, doc.name) + has_vat = False + for tax in voucher.taxes: + if tax.account_head == tax_account: + has_vat = True + break + if has_vat and not doc.tax_invoice_number: + frappe.throw(_("This document require Tax Invoice Number")) + if not has_vat and doc.tax_invoice_number: + frappe.throw(_("This document has no due VAT, please remove Tax Invoice Number")) + @frappe.whitelist() def to_clear_undue_tax(dt, dn): - to_clear = True - if not make_clear_vat_journal_entry(dt, dn): - to_clear = False - return to_clear + to_clear = True + if not make_clear_vat_journal_entry(dt, dn): + to_clear = False + return to_clear + @frappe.whitelist() def make_clear_vat_journal_entry(dt, dn): - tax = frappe.get_single('Tax Invoice Settings') - doc = frappe.get_doc(dt, dn) - je = frappe.new_doc('Journal Entry') - je.entry_type = 'Journal Entry' - je.supplier = doc.party_type == 'Supplier' and doc.party or False - je.company_tax_address = doc.company_tax_address - je.for_payment = doc.name - je.user_remark = _('Clear Undue Tax on %s' % doc.name) - # Loop through all paid doc, pick only ones with Undue Tax - base_total = 0 - tax_total = 0 - references = filter( - lambda x: x.reference_doctype in ('Purchase Invoice', 'Expense Claim'), - doc.references - ) - for ref in references: - if not ref.allocated_amount or not ref.total_amount: - continue - # Find gl entry of ref doc that has undue amount - gl_entries = frappe.db.get_all( - 'GL Entry', - filters={ - 'voucher_type': ref.reference_doctype, - 'voucher_no': ref.reference_name, - }, - fields=["*"]) - for gl in gl_entries: - (undue_tax, base_amount, account_undue, account) = get_undue_tax(doc, ref, gl, tax) - if ref.reference_doctype in ('Purchase Invoice', 'Expense Claim'): - undue_tax = -undue_tax - base_amount = -base_amount - base_total += base_amount - if undue_tax: - je.append('accounts', - { - 'account': account_undue, - 'credit_in_account_currency': undue_tax > 0 and undue_tax, - 'debit_in_account_currency': undue_tax < 0 and abs(undue_tax), - }, - ) - tax_total += undue_tax - if not tax_total: - return False - # To due tax - je.append('accounts', - { - 'account': account, - 'credit_in_account_currency': tax_total < 0 and abs(tax_total), - 'debit_in_account_currency': tax_total > 0 and tax_total, - } + tax = frappe.get_single("Tax Invoice Settings") + doc = frappe.get_doc(dt, dn) + je = frappe.new_doc("Journal Entry") + je.entry_type = "Journal Entry" + je.supplier = doc.party_type == "Supplier" and doc.party or False + je.company_tax_address = doc.company_tax_address + je.for_payment = doc.name + je.user_remark = _("Clear Undue Tax on %s" % doc.name) + # Loop through all paid doc, pick only ones with Undue Tax + base_total = 0 + tax_total = 0 + references = filter( + lambda x: x.reference_doctype in ("Purchase Invoice", "Expense Claim"), doc.references ) - # Base amount - je.tax_base_amount = base_total - return je + for ref in references: + if not ref.allocated_amount or not ref.total_amount: + continue + # Find gl entry of ref doc that has undue amount + gl_entries = frappe.db.get_all( + "GL Entry", + filters={ + "voucher_type": ref.reference_doctype, + "voucher_no": ref.reference_name, + }, + fields=["*"], + ) + for gl in gl_entries: + (undue_tax, base_amount, account_undue, account) = get_undue_tax(doc, ref, gl, tax) + if ref.reference_doctype in ("Purchase Invoice", "Expense Claim"): + undue_tax = -undue_tax + base_amount = -base_amount + base_total += base_amount + if undue_tax: + je.append( + "accounts", + { + "account": account_undue, + "credit_in_account_currency": undue_tax > 0 and undue_tax, + "debit_in_account_currency": undue_tax < 0 and abs(undue_tax), + }, + ) + tax_total += undue_tax + if not tax_total: + return False + # To due tax + je.append( + "accounts", + { + "account": account, + "credit_in_account_currency": tax_total < 0 and abs(tax_total), + "debit_in_account_currency": tax_total > 0 and tax_total, + }, + ) + # Base amount + je.tax_base_amount = base_total + return je + def clear_invoice_undue_tax(doc, method): - old_doc = doc.get_doc_before_save() - if ( - old_doc - and old_doc.total_allocated_amount == doc.total_allocated_amount - and old_doc.has_purchase_tax_invoice == doc.has_purchase_tax_invoice - ): - return - doc.taxes = [] - tax = frappe.get_single('Tax Invoice Settings') - base_total = 0 - tax_total = 0 - references = filter( - lambda x: x.reference_doctype in ('Sales Invoice', 'Purchase Invoice', 'Expense Claim'), - doc.references - ) - for ref in references: - if ref.reference_doctype in ('Purchase Invoice', 'Expense Claim') and not doc.has_purchase_tax_invoice: - return - if not ref.allocated_amount or not ref.total_amount: - continue - # Find gl entry of ref doc that has undue amount - gl_entries = frappe.db.get_all( - 'GL Entry', - filters={ - 'voucher_type': ref.reference_doctype, - 'voucher_no': ref.reference_name, - }, - fields=["*"]) - for gl in gl_entries: - (undue_tax, base_amount, account_undue, account) = get_undue_tax(doc, ref, gl, tax) - if ref.reference_doctype in ('Purchase Invoice', 'Expense Claim'): - undue_tax = -undue_tax - base_amount = -base_amount - base_total += base_amount - if undue_tax: - doc.append('taxes', - { - # 'add_deduct_tax': undue_tax > 0 and 'Deduct' or 'Add', - 'add_deduct_tax': 'Add', - 'description': 'Clear Undue Tax', - 'charge_type': 'Actual', - 'account_head': account_undue, - 'tax_amount': -undue_tax, - }, - ) - tax_total += undue_tax - if not tax_total: - if doc.has_purchase_tax_invoice: - frappe.throw(_("No undue tax amount to clear. Please uncheck 'Has Purchase Tax Invoice'")) - return - # To due tax - doc.append('taxes', - { - # 'add_deduct_tax': tax_total > 0 and 'Add' or 'Deduct', - 'add_deduct_tax': 'Add', - 'description': 'Clear Undue Tax', - 'charge_type': 'Actual', - 'account_head': account, - 'tax_amount': tax_total, - }, + old_doc = doc.get_doc_before_save() + if ( + old_doc + and old_doc.total_allocated_amount == doc.total_allocated_amount + and old_doc.has_purchase_tax_invoice == doc.has_purchase_tax_invoice + ): + return + doc.taxes = [] + tax = frappe.get_single("Tax Invoice Settings") + base_total = 0 + tax_total = 0 + references = filter( + lambda x: x.reference_doctype + in ("Sales Invoice", "Purchase Invoice", "Expense Claim"), + doc.references, ) - doc.tax_base_amount = base_total - doc.calculate_taxes() + for ref in references: + if ( + ref.reference_doctype in ("Purchase Invoice", "Expense Claim") + and not doc.has_purchase_tax_invoice + ): + return + if not ref.allocated_amount or not ref.total_amount: + continue + # Find gl entry of ref doc that has undue amount + gl_entries = frappe.db.get_all( + "GL Entry", + filters={ + "voucher_type": ref.reference_doctype, + "voucher_no": ref.reference_name, + }, + fields=["*"], + ) + for gl in gl_entries: + (undue_tax, base_amount, account_undue, account) = get_undue_tax(doc, ref, gl, tax) + if ref.reference_doctype in ("Purchase Invoice", "Expense Claim"): + undue_tax = -undue_tax + base_amount = -base_amount + base_total += base_amount + if undue_tax: + doc.append( + "taxes", + { + # 'add_deduct_tax': undue_tax > 0 and 'Deduct' or 'Add', + "add_deduct_tax": "Add", + "description": "Clear Undue Tax", + "charge_type": "Actual", + "account_head": account_undue, + "tax_amount": -undue_tax, + }, + ) + tax_total += undue_tax + if not tax_total: + if doc.has_purchase_tax_invoice: + frappe.throw( + _("No undue tax amount to clear. Please uncheck 'Has Purchase Tax Invoice'") + ) + return + # To due tax + doc.append( + "taxes", + { + # 'add_deduct_tax': tax_total > 0 and 'Add' or 'Deduct', + "add_deduct_tax": "Add", + "description": "Clear Undue Tax", + "charge_type": "Actual", + "account_head": account, + "tax_amount": tax_total, + }, + ) + doc.tax_base_amount = base_total + doc.calculate_taxes() + def get_undue_tax(doc, ref, gl, tax): - # Prepration - undue_tax = 0 - base_amount = 0 - tax_account_undue = tax.sales_tax_account_undue - tax_account = tax.sales_tax_account - if ref.reference_doctype in ('Purchase Invoice', 'Expense Claim'): - tax_account_undue = tax.purchase_tax_account_undue - tax_account = tax.purchase_tax_account - credit = gl['credit'] - debit = gl['debit'] - alloc_percent = ref.allocated_amount / ref.total_amount - # Find Base - report_type = frappe.get_cached_value('Account', gl['account'], 'report_type') - if report_type == 'Profit and Loss': - base_amount = alloc_percent * (credit-debit) - # Find Tax - if gl['account'] == tax_account_undue: - undue_tax = alloc_percent * (credit-debit) - undue_remain = get_uncleared_tax_amount(gl, doc.payment_type) - if not undue_remain: - undue_tax = 0 - else: - undue_tax = undue_tax if undue_tax < undue_remain else undue_remain - return (undue_tax, base_amount, tax_account_undue, tax_account) + # Prepration + undue_tax = 0 + base_amount = 0 + tax_account_undue = tax.sales_tax_account_undue + tax_account = tax.sales_tax_account + if ref.reference_doctype in ("Purchase Invoice", "Expense Claim"): + tax_account_undue = tax.purchase_tax_account_undue + tax_account = tax.purchase_tax_account + credit = gl["credit"] + debit = gl["debit"] + alloc_percent = ref.allocated_amount / ref.total_amount + # Find Base + report_type = frappe.get_cached_value("Account", gl["account"], "report_type") + if report_type == "Profit and Loss": + base_amount = alloc_percent * (credit - debit) + # Find Tax + if gl["account"] == tax_account_undue: + undue_tax = alloc_percent * (credit - debit) + undue_remain = get_uncleared_tax_amount(gl, doc.payment_type) + if not undue_remain: + undue_tax = 0 + else: + undue_tax = undue_tax if undue_tax < undue_remain else undue_remain + return (undue_tax, base_amount, tax_account_undue, tax_account) + def get_uncleared_tax_amount(gl, payment_type): - # If module bs_reconcile is installed, uncleared_tax = residual amount - # else uncleared_tax is the debit - credit amount - uncleared_tax = gl.debit - gl.credit - if gl.get("is_reconcile"): - uncleared_tax = gl.get("residual") - if payment_type == 'Receive': - uncleared_tax = -uncleared_tax - return uncleared_tax + # If module bs_reconcile is installed, uncleared_tax = residual amount + # else uncleared_tax is the debit - credit amount + uncleared_tax = gl.debit - gl.credit + if gl.get("is_reconcile"): + uncleared_tax = gl.get("residual") + if payment_type == "Receive": + uncleared_tax = -uncleared_tax + return uncleared_tax + @frappe.whitelist() def make_withholding_tax_cert(filters, doc): - wht = get_withholding_tax(filters, doc) - filters = literal_eval(filters) - pay = json.loads(doc) - cert = frappe.new_doc('Withholding Tax Cert') - cert.supplier = pay.get('party_type') == 'Supplier' and pay.get('party') or '' - if cert.supplier != '': - supplier = frappe.get_doc('Supplier', cert.supplier) - cert.supplier_name = supplier and supplier.supplier_name or '' - cert.supplier_address = supplier and supplier.supplier_primary_address or '' - cert.voucher_type = 'Payment Entry' - cert.voucher_no = pay.get('name') - cert.company_address = filters.get('company_address') - cert.income_tax_form = filters.get('income_tax_form') - cert.date = filters.get('date') - cert.append('withholding_tax_items', { - 'tax_base': -wht['base'], - 'tax_rate': wht['rate'], - 'tax_amount': -wht['amount'], - }) - return cert + wht = get_withholding_tax(filters, doc) + filters = literal_eval(filters) + pay = json.loads(doc) + cert = frappe.new_doc("Withholding Tax Cert") + cert.supplier = pay.get("party_type") == "Supplier" and pay.get("party") or "" + if cert.supplier != "": + supplier = frappe.get_doc("Supplier", cert.supplier) + cert.supplier_name = supplier and supplier.supplier_name or "" + cert.supplier_address = supplier and supplier.supplier_primary_address or "" + cert.voucher_type = "Payment Entry" + cert.voucher_no = pay.get("name") + cert.company_address = filters.get("company_address") + cert.income_tax_form = filters.get("income_tax_form") + cert.date = filters.get("date") + cert.append( + "withholding_tax_items", + { + "tax_base": -wht["base"], + "tax_rate": wht["rate"], + "tax_amount": -wht["amount"], + }, + ) + return cert + @frappe.whitelist() def get_withholding_tax(filters, doc): - filters = literal_eval(filters) - pay = json.loads(doc) - wht = frappe.get_doc('Withholding Tax Type', filters['wht_type']) - company = frappe.get_doc('Company', pay['company']) - for ref in pay.get('references'): - if ref.get('reference_doctype') not in ['Purchase Invoice', 'Expense Claim']: - return - if not ref.get('allocated_amount') or not ref.get('total_amount'): - continue - # Find gl entry of ref doc that has undue amount - gl_entries = frappe.db.get_all( - 'GL Entry', - filters={ - 'voucher_type': ref['reference_doctype'], - 'voucher_no': ref['reference_name'], - }, - fields=[ - 'name', 'account', - 'debit', - 'credit', - ]) - base_amount = 0 - for gl in gl_entries: - credit = gl['credit'] - debit = gl['debit'] - alloc_percent = ref['allocated_amount'] / ref['total_amount'] - report_type = frappe.get_cached_value('Account', gl['account'], 'report_type') - if report_type == 'Profit and Loss': - base_amount += alloc_percent * (credit-debit) - return { - 'account': wht.account, - 'cost_center': company.cost_center, - 'base': base_amount, - 'rate': wht.percent, - 'amount': wht.percent/100 * base_amount - } + filters = literal_eval(filters) + pay = json.loads(doc) + wht = frappe.get_doc("Withholding Tax Type", filters["wht_type"]) + company = frappe.get_doc("Company", pay["company"]) + for ref in pay.get("references"): + if ref.get("reference_doctype") not in ["Purchase Invoice", "Expense Claim"]: + return + if not ref.get("allocated_amount") or not ref.get("total_amount"): + continue + # Find gl entry of ref doc that has undue amount + gl_entries = frappe.db.get_all( + "GL Entry", + filters={ + "voucher_type": ref["reference_doctype"], + "voucher_no": ref["reference_name"], + }, + fields=[ + "name", + "account", + "debit", + "credit", + ], + ) + base_amount = 0 + for gl in gl_entries: + credit = gl["credit"] + debit = gl["debit"] + alloc_percent = ref["allocated_amount"] / ref["total_amount"] + report_type = frappe.get_cached_value("Account", gl["account"], "report_type") + if report_type == "Profit and Loss": + base_amount += alloc_percent * (credit - debit) + return { + "account": wht.account, + "cost_center": company.cost_center, + "base": base_amount, + "rate": wht.percent, + "amount": wht.percent / 100 * base_amount, + } diff --git a/thai_tax/custom/dashboard_overrides.py b/thai_tax/custom/dashboard_overrides.py index 7343b33..b3db625 100644 --- a/thai_tax/custom/dashboard_overrides.py +++ b/thai_tax/custom/dashboard_overrides.py @@ -1,16 +1,25 @@ from frappe import _ + def get_dashboard_data_for_purchase_invoice(data): - data["non_standard_fieldnames"].update({"Purchase Tax Invoice": "voucher_no"}) - data["transactions"].append({"label": _("Tax Invoice"), "items": ["Purchase Tax Invoice"]}) - return data + data["non_standard_fieldnames"].update({"Purchase Tax Invoice": "voucher_no"}) + data["transactions"].append( + {"label": _("Tax Invoice"), "items": ["Purchase Tax Invoice"]} + ) + return data + def get_dashboard_data_for_sales_invoice(data): - data["non_standard_fieldnames"].update({"Sales Tax Invoice": "voucher_no"}) - data["transactions"].append({"label": _("Tax Invoice"), "items": ["Sales Tax Invoice"]}) - return data + data["non_standard_fieldnames"].update({"Sales Tax Invoice": "voucher_no"}) + data["transactions"].append( + {"label": _("Tax Invoice"), "items": ["Sales Tax Invoice"]} + ) + return data + def get_dashboard_data_for_expense_claim(data): - data["non_standard_fieldnames"].update({"Purchase Tax Invoice": "voucher_no"}) - data["transactions"].append({"label": _("Tax Invoice"), "items": ["Purchase Tax Invoice"]}) - return data \ No newline at end of file + data["non_standard_fieldnames"].update({"Purchase Tax Invoice": "voucher_no"}) + data["transactions"].append( + {"label": _("Tax Invoice"), "items": ["Purchase Tax Invoice"]} + ) + return data diff --git a/thai_tax/custom/employee_advance.py b/thai_tax/custom/employee_advance.py index 9f859cc..fdf0282 100644 --- a/thai_tax/custom/employee_advance.py +++ b/thai_tax/custom/employee_advance.py @@ -11,53 +11,53 @@ class EmployeeAdvanceOverPayment(frappe.ValidationError): class ThaiTaxEmployeeAdvance(EmployeeAdvance): - # For python bug fix only, to be removed if fixed in the core - def set_total_advance_paid(self): - gle = frappe.qb.DocType("GL Entry") - - paid_amount = ( - frappe.qb.from_(gle) - .select(Sum(gle.debit).as_("paid_amount")) - .where( - (gle.against_voucher_type == "Employee Advance") - & (gle.against_voucher == self.name) - & (gle.party_type == "Employee") - & (gle.party == self.employee) - & (gle.docstatus == 1) - & (gle.is_cancelled == 0) - ) - ).run(as_dict=True)[0].paid_amount or 0 - - return_amount = ( - frappe.qb.from_(gle) - .select(Sum(gle.credit).as_("return_amount")) - .where( - (gle.against_voucher_type == "Employee Advance") - & (gle.voucher_type != "Expense Claim") - & (gle.against_voucher == self.name) - & (gle.party_type == "Employee") - & (gle.party == self.employee) - & (gle.docstatus == 1) - & (gle.is_cancelled == 0) - ) - ).run(as_dict=True)[0].return_amount or 0 - - if paid_amount != 0: - paid_amount = flt(paid_amount) / flt(self.exchange_rate) - if return_amount != 0: - return_amount = flt(return_amount) / flt(self.exchange_rate) - - if flt(paid_amount) > self.advance_amount: - frappe.throw( - _("Row {0}# Paid Amount cannot be greater than requested advance amount"), - EmployeeAdvanceOverPayment, - ) - - # FIX: because python result in 2000.0-1780.2 = 219.79999999999995 - # if flt(return_amount) > self.paid_amount - self.claimed_amount: - if flt(return_amount) > flt(self.paid_amount - self.claimed_amount, 4): - frappe.throw(_("Return amount cannot be greater unclaimed amount")) - - self.db_set("paid_amount", paid_amount) - self.db_set("return_amount", return_amount) - self.set_status(update=True) + # For python bug fix only, to be removed if fixed in the core + def set_total_advance_paid(self): + gle = frappe.qb.DocType("GL Entry") + + paid_amount = ( + frappe.qb.from_(gle) + .select(Sum(gle.debit).as_("paid_amount")) + .where( + (gle.against_voucher_type == "Employee Advance") + & (gle.against_voucher == self.name) + & (gle.party_type == "Employee") + & (gle.party == self.employee) + & (gle.docstatus == 1) + & (gle.is_cancelled == 0) + ) + ).run(as_dict=True)[0].paid_amount or 0 + + return_amount = ( + frappe.qb.from_(gle) + .select(Sum(gle.credit).as_("return_amount")) + .where( + (gle.against_voucher_type == "Employee Advance") + & (gle.voucher_type != "Expense Claim") + & (gle.against_voucher == self.name) + & (gle.party_type == "Employee") + & (gle.party == self.employee) + & (gle.docstatus == 1) + & (gle.is_cancelled == 0) + ) + ).run(as_dict=True)[0].return_amount or 0 + + if paid_amount != 0: + paid_amount = flt(paid_amount) / flt(self.exchange_rate) + if return_amount != 0: + return_amount = flt(return_amount) / flt(self.exchange_rate) + + if flt(paid_amount) > self.advance_amount: + frappe.throw( + _("Row {0}# Paid Amount cannot be greater than requested advance amount"), + EmployeeAdvanceOverPayment, + ) + + # FIX: because python result in 2000.0-1780.2 = 219.79999999999995 + # if flt(return_amount) > self.paid_amount - self.claimed_amount: + if flt(return_amount) > flt(self.paid_amount - self.claimed_amount, 4): + frappe.throw(_("Return amount cannot be greater unclaimed amount")) + + self.db_set("paid_amount", paid_amount) + self.db_set("return_amount", return_amount) + self.set_status(update=True) diff --git a/thai_tax/custom/queries.py b/thai_tax/custom/queries.py index a9e9c8b..9ceb0a5 100644 --- a/thai_tax/custom/queries.py +++ b/thai_tax/custom/queries.py @@ -4,6 +4,6 @@ @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs def undue_tax_query(doctype, txt, searchfield, start, page_len, filters): - setting = frappe.get_doc('Tax Invoice Settings') - res = list(set([setting.purchase_tax_account_undue, setting.sales_tax_account_undue])) - return [[x] for x in res] \ No newline at end of file + setting = frappe.get_doc("Tax Invoice Settings") + res = list({setting.purchase_tax_account_undue, setting.sales_tax_account_undue}) + return [[x] for x in res] diff --git a/thai_tax/hooks.py b/thai_tax/hooks.py index 90e8a2f..9e90a6a 100644 --- a/thai_tax/hooks.py +++ b/thai_tax/hooks.py @@ -9,78 +9,78 @@ required_apps = ["erpnext", "hrms"] fixtures = [ - { - "doctype": "Custom Field", - "filters": [ - [ - "name", - "in", - ( - "Payment Entry-column_break_yio5c", - "Payment Entry-section_break_owjbn", - "Supplier-branch_code", - "Customer-branch_code", - "Expense Claim-tax_invoice_date", - "Expense Claim-supplier_name", - "Expense Claim-column_break_6atpw", - "Expense Claim-supplier", - "Expense Claim-tax_invoice_number", - "Expense Claim-section_break_uodhb", - "Expense Claim-company_tax_address", - "Expense Claim-tax_invoice", - "Journal Entry-tax_invoice_date", - "Journal Entry-column_break_1ds9m", - "Journal Entry-tax_invoice_number", - "Journal Entry-section_break_hjndu", - "Journal Entry-company_tax_address", - "Journal Entry-tax_invoice", - "Payment Entry-tax_invoice_date", - "Payment Entry-tax_invoice_number", - "Payment Entry-company_tax_address", - "Payment Entry-tax_invoice", - "Payment Entry-deduct_withholding_tax", - "Sales Invoice-tax_invoice_number", - "Sales Invoice-column_break_cijbv", - "Sales Invoice-tax_invoice_date", - "Sales Invoice-tax_invoice", - "Purchase Invoice-tax_invoice_date", - "Purchase Invoice-column_break_t0qgt", - "Purchase Invoice-tax_invoice_number", - "Purchase Invoice-tax_invoice", - "Advance Taxes and Charges-rate-precision", - "Purchase Taxes and Charges-rate-precision", - "Sales Taxes and Charges-rate-precision", - "Journal Entry-column_break_3djv9", - "Journal Entry-for_payment", - "Journal Entry-supplier_name", - "Journal Entry-supplier", - "Journal Entry-tax_base_amount", - "Expense Claim-column_break_rqacr", - "Expense Claim-base_amount_overwrite", - "Payment Entry-column_break_bqyze", - "Payment Entry-tax_base_amount", - "Payment Entry-has_purchase_tax_invoice", - "Payment Entry-supplier", - "Payment Entry-supplier_name", - ) - ] - ], - }, - { - "doctype": "Property Setter", - "filters": [ - [ - "name", - "in", - ( - "Purchase Invoice-tax_invoice", - "Advance Taxes and Charges-rate-precision", - "Purchase Taxes and Charges-rate-precision", - "Sales Taxes and Charges-rate-precision" - ) - ] - ] - }, + { + "doctype": "Custom Field", + "filters": [ + [ + "name", + "in", + ( + "Payment Entry-column_break_yio5c", + "Payment Entry-section_break_owjbn", + "Supplier-branch_code", + "Customer-branch_code", + "Expense Claim-tax_invoice_date", + "Expense Claim-supplier_name", + "Expense Claim-column_break_6atpw", + "Expense Claim-supplier", + "Expense Claim-tax_invoice_number", + "Expense Claim-section_break_uodhb", + "Expense Claim-company_tax_address", + "Expense Claim-tax_invoice", + "Journal Entry-tax_invoice_date", + "Journal Entry-column_break_1ds9m", + "Journal Entry-tax_invoice_number", + "Journal Entry-section_break_hjndu", + "Journal Entry-company_tax_address", + "Journal Entry-tax_invoice", + "Payment Entry-tax_invoice_date", + "Payment Entry-tax_invoice_number", + "Payment Entry-company_tax_address", + "Payment Entry-tax_invoice", + "Payment Entry-deduct_withholding_tax", + "Sales Invoice-tax_invoice_number", + "Sales Invoice-column_break_cijbv", + "Sales Invoice-tax_invoice_date", + "Sales Invoice-tax_invoice", + "Purchase Invoice-tax_invoice_date", + "Purchase Invoice-column_break_t0qgt", + "Purchase Invoice-tax_invoice_number", + "Purchase Invoice-tax_invoice", + "Advance Taxes and Charges-rate-precision", + "Purchase Taxes and Charges-rate-precision", + "Sales Taxes and Charges-rate-precision", + "Journal Entry-column_break_3djv9", + "Journal Entry-for_payment", + "Journal Entry-supplier_name", + "Journal Entry-supplier", + "Journal Entry-tax_base_amount", + "Expense Claim-column_break_rqacr", + "Expense Claim-base_amount_overwrite", + "Payment Entry-column_break_bqyze", + "Payment Entry-tax_base_amount", + "Payment Entry-has_purchase_tax_invoice", + "Payment Entry-supplier", + "Payment Entry-supplier_name", + ), + ] + ], + }, + { + "doctype": "Property Setter", + "filters": [ + [ + "name", + "in", + ( + "Purchase Invoice-tax_invoice", + "Advance Taxes and Charges-rate-precision", + "Purchase Taxes and Charges-rate-precision", + "Sales Taxes and Charges-rate-precision", + ), + ] + ], + }, ] @@ -109,13 +109,13 @@ # doctype_js = {"doctype" : "public/js/doctype.js"} doctype_js = { - "Journal Entry" : "public/js/journal_entry.js", - "Payment Entry" : "public/js/payment_entry.js", - "Expense Claim" : "public/js/expense_claim.js", - "Purchase Tax Invoice" : "public/js/purchase_tax_invoice.js", - "Sales Tax Invoice" : "public/js/sales_tax_invoice.js", - "Withholding Tax Cert" : "public/js/withholding_tax_cert.js", - "Address" : "public/js/address.js", + "Journal Entry": "public/js/journal_entry.js", + "Payment Entry": "public/js/payment_entry.js", + "Expense Claim": "public/js/expense_claim.js", + "Purchase Tax Invoice": "public/js/purchase_tax_invoice.js", + "Sales Tax Invoice": "public/js/sales_tax_invoice.js", + "Withholding Tax Cert": "public/js/withholding_tax_cert.js", + "Address": "public/js/address.js", } @@ -131,7 +131,7 @@ # website user home page (by Role) # role_home_page = { -# "Role": "home_page" +# "Role": "home_page" # } # Generators @@ -145,14 +145,14 @@ # add methods and filters to jinja environment # jinja = { -# "methods": "thai_tax.utils.jinja_methods", -# "filters": "thai_tax.utils.jinja_filters" +# "methods": "thai_tax.utils.jinja_methods", +# "filters": "thai_tax.utils.jinja_filters" # } jinja = { - "methods": [ - "thai_tax.utils.amount_in_bahttext", - ], + "methods": [ + "thai_tax.utils.amount_in_bahttext", + ], } # Installation @@ -178,18 +178,18 @@ # Permissions evaluated in scripted ways # permission_query_conditions = { -# "Event": "frappe.desk.doctype.event.event.get_permission_query_conditions", +# "Event": "frappe.desk.doctype.event.event.get_permission_query_conditions", # } # # has_permission = { -# "Event": "frappe.desk.doctype.event.event.has_permission", +# "Event": "frappe.desk.doctype.event.event.has_permission", # } # DocType Class # --------------- # Override standard doctype classes override_doctype_class = { - "Employee Advance": "thai_tax.custom.employee_advance.ThaiTaxEmployeeAdvance", + "Employee Advance": "thai_tax.custom.employee_advance.ThaiTaxEmployeeAdvance", } # Document Events @@ -197,50 +197,50 @@ # Hook on document methods and events # doc_events = { -# "*": { -# "on_update": "method", -# "on_cancel": "method", -# "on_trash": "method" -# } +# "*": { +# "on_update": "method", +# "on_cancel": "method", +# "on_trash": "method" +# } # } doc_events = { - "GL Entry": { - "after_insert": "thai_tax.custom.custom_api.create_tax_invoice_on_gl_tax", - }, - "Payment Entry": { - "validate": "thai_tax.custom.custom_api.validate_company_address", - "on_update": "thai_tax.custom.custom_api.clear_invoice_undue_tax", - }, - "Purchase Invoice": { - "after_insert": "thai_tax.custom.custom_api.validate_tax_invoice", - "on_update": "thai_tax.custom.custom_api.validate_tax_invoice", - }, - "Expense Claim": { - "after_insert": "thai_tax.custom.custom_api.validate_tax_invoice", - "on_update": "thai_tax.custom.custom_api.validate_tax_invoice", - }, + "GL Entry": { + "after_insert": "thai_tax.custom.custom_api.create_tax_invoice_on_gl_tax", + }, + "Payment Entry": { + "validate": "thai_tax.custom.custom_api.validate_company_address", + "on_update": "thai_tax.custom.custom_api.clear_invoice_undue_tax", + }, + "Purchase Invoice": { + "after_insert": "thai_tax.custom.custom_api.validate_tax_invoice", + "on_update": "thai_tax.custom.custom_api.validate_tax_invoice", + }, + "Expense Claim": { + "after_insert": "thai_tax.custom.custom_api.validate_tax_invoice", + "on_update": "thai_tax.custom.custom_api.validate_tax_invoice", + }, } # Scheduled Tasks # --------------- # scheduler_events = { -# "all": [ -# "thai_tax.tasks.all" -# ], -# "daily": [ -# "thai_tax.tasks.daily" -# ], -# "hourly": [ -# "thai_tax.tasks.hourly" -# ], -# "weekly": [ -# "thai_tax.tasks.weekly" -# ], -# "monthly": [ -# "thai_tax.tasks.monthly" -# ], +# "all": [ +# "thai_tax.tasks.all" +# ], +# "daily": [ +# "thai_tax.tasks.daily" +# ], +# "hourly": [ +# "thai_tax.tasks.hourly" +# ], +# "weekly": [ +# "thai_tax.tasks.weekly" +# ], +# "monthly": [ +# "thai_tax.tasks.monthly" +# ], # } # Testing @@ -252,7 +252,7 @@ # ------------------------------ # # override_whitelisted_methods = { -# "frappe.desk.doctype.event.event.get_events": "thai_tax.event.get_events" +# "frappe.desk.doctype.event.event.get_events": "thai_tax.event.get_events" # } # # each overriding function accepts a `data` argument; @@ -262,11 +262,11 @@ override_doctype_dashboards = { "Purchase Invoice": "thai_tax.custom.dashboard_overrides.get_dashboard_data_for_purchase_invoice", "Sales Invoice": "thai_tax.custom.dashboard_overrides.get_dashboard_data_for_sales_invoice", - "Expense Claim": "thai_tax.custom.dashboard_overrides.get_dashboard_data_for_expense_claim" + "Expense Claim": "thai_tax.custom.dashboard_overrides.get_dashboard_data_for_expense_claim", } # override_doctype_dashboards = { -# "Task": "thai_tax.task.get_dashboard_data" +# "Task": "thai_tax.task.get_dashboard_data" # } # exempt linked doctypes from being automatically cancelled # @@ -291,29 +291,29 @@ # -------------------- # user_data_fields = [ -# { -# "doctype": "{doctype_1}", -# "filter_by": "{filter_by}", -# "redact_fields": ["{field_1}", "{field_2}"], -# "partial": 1, -# }, -# { -# "doctype": "{doctype_2}", -# "filter_by": "{filter_by}", -# "partial": 1, -# }, -# { -# "doctype": "{doctype_3}", -# "strict": False, -# }, -# { -# "doctype": "{doctype_4}" -# } +# { +# "doctype": "{doctype_1}", +# "filter_by": "{filter_by}", +# "redact_fields": ["{field_1}", "{field_2}"], +# "partial": 1, +# }, +# { +# "doctype": "{doctype_2}", +# "filter_by": "{filter_by}", +# "partial": 1, +# }, +# { +# "doctype": "{doctype_3}", +# "strict": False, +# }, +# { +# "doctype": "{doctype_4}" +# } # ] # Authentication and authorization # -------------------------------- # auth_hooks = [ -# "thai_tax.auth.validate" +# "thai_tax.auth.validate" # ] diff --git a/thai_tax/public/js/address.js b/thai_tax/public/js/address.js index 312bab5..ccba552 100644 --- a/thai_tax/public/js/address.js +++ b/thai_tax/public/js/address.js @@ -1,46 +1,48 @@ -frappe.ui.form.on('Address', { - +frappe.ui.form.on("Address", { refresh(frm) { - - // Add button to use VAT Service - frm.add_custom_button(__('Get Address by Tax ID'), function () { + // Add button to use VAT Service + frm.add_custom_button(__("Get Address by Tax ID"), function () { const fields = [ { - fieldtype: 'Data', - label: __('Tax ID'), - fieldname: 'tax_id', - reqd: 1 + fieldtype: "Data", + label: __("Tax ID"), + fieldname: "tax_id", + reqd: 1, }, { - fieldtype: 'Data', - label: __('Branch'), - fieldname: 'branch', - default: '00000', - reqd: 1 + fieldtype: "Data", + label: __("Branch"), + fieldname: "branch", + default: "00000", + reqd: 1, }, ]; - frappe.prompt(fields, function(filters){ - frm.events.get_address_by_tax_id(frm, filters); - }, __('RD VAT Service'), __('Get Address')); - }) + frappe.prompt( + fields, + function (filters) { + frm.events.get_address_by_tax_id(frm, filters); + }, + __("RD VAT Service"), + __("Get Address") + ); + }); }, - get_address_by_tax_id: function(frm, filters) { + get_address_by_tax_id: function (frm, filters) { return frappe.call({ - method: 'thai_tax.utils.get_address_by_tax_id', + method: "thai_tax.utils.get_address_by_tax_id", args: { tax_id: filters.tax_id, - branch: filters.branch + branch: filters.branch, + }, + callback: function (r) { + cur_frm.set_value("address_title", r.message["name"]); + cur_frm.set_value("address_line1", r.message["address_line1"]); + cur_frm.set_value("city", r.message["city"]); + cur_frm.set_value("county", r.message["county"]); + cur_frm.set_value("state", r.message["state"]); + cur_frm.set_value("pincode", r.message["pincode"]); }, - callback: function(r) { - cur_frm.set_value('address_title', r.message['name']); - cur_frm.set_value('address_line1', r.message['address_line1']); - cur_frm.set_value('city', r.message['city']); - cur_frm.set_value('county', r.message['county']); - cur_frm.set_value('state', r.message['state']); - cur_frm.set_value('pincode', r.message['pincode']); - } }); - } - -}) + }, +}); diff --git a/thai_tax/public/js/expense_claim.js b/thai_tax/public/js/expense_claim.js index 4291198..a961ac4 100644 --- a/thai_tax/public/js/expense_claim.js +++ b/thai_tax/public/js/expense_claim.js @@ -1,11 +1,11 @@ -frappe.ui.form.on('Expense Claim', { +frappe.ui.form.on("Expense Claim", { refresh(frm) { - frm.set_query('company_tax_address', function() { - return { + frm.set_query("company_tax_address", function () { + return { filters: { - is_your_company_address: true - } - } - }) - } -}) + is_your_company_address: true, + }, + }; + }); + }, +}); diff --git a/thai_tax/public/js/journal_entry.js b/thai_tax/public/js/journal_entry.js index cdadc4e..784170c 100644 --- a/thai_tax/public/js/journal_entry.js +++ b/thai_tax/public/js/journal_entry.js @@ -1,11 +1,11 @@ -frappe.ui.form.on('Journal Entry', { +frappe.ui.form.on("Journal Entry", { refresh(frm) { - frm.set_query('company_tax_address', function() { - return { + frm.set_query("company_tax_address", function () { + return { filters: { - is_your_company_address: true - } - } - }) - } -}) + is_your_company_address: true, + }, + }; + }); + }, +}); diff --git a/thai_tax/public/js/payment_entry.js b/thai_tax/public/js/payment_entry.js index 0d16768..5d133c8 100644 --- a/thai_tax/public/js/payment_entry.js +++ b/thai_tax/public/js/payment_entry.js @@ -1,137 +1,150 @@ -frappe.ui.form.on('Payment Entry', { +frappe.ui.form.on("Payment Entry", { refresh(frm) { - // Filter company tax address - frm.set_query('company_tax_address', function() { - return { + // Filter company tax address + frm.set_query("company_tax_address", function () { + return { filters: { - is_your_company_address: true - } - } - }) + is_your_company_address: true, + }, + }; + }); - // Add button to create withholding tax cert - if(frm.doc.docstatus == 1 && frm.doc.payment_type == 'Pay' && frm.doc.deductions.length > 0) { - frm.add_custom_button(__('Create Withholding Tax Cert'), function () { + // Add button to create withholding tax cert + if ( + frm.doc.docstatus == 1 && + frm.doc.payment_type == "Pay" && + frm.doc.deductions.length > 0 + ) { + frm.add_custom_button(__("Create Withholding Tax Cert"), function () { const fields = [ { - fieldtype: 'Link', - label: __('WHT Type'), - fieldname: 'wht_type', - options: 'Withholding Tax Type', - reqd: 1 + fieldtype: "Link", + label: __("WHT Type"), + fieldname: "wht_type", + options: "Withholding Tax Type", + reqd: 1, }, { - fieldtype: 'Date', - label: __('Date'), - fieldname: 'date', - reqd: 1 + fieldtype: "Date", + label: __("Date"), + fieldname: "date", + reqd: 1, }, { - fieldtype: 'Select', - label: __('Income Tax Form'), - fieldname: 'income_tax_form', - options: 'PND3\nPND53', + fieldtype: "Select", + label: __("Income Tax Form"), + fieldname: "income_tax_form", + options: "PND3\nPND53", }, { - fieldtype: 'Link', - label: __('Company Address'), - fieldname: 'company_address', - options: 'Address', + fieldtype: "Link", + label: __("Company Address"), + fieldname: "company_address", + options: "Address", get_query: () => { return { filters: { - 'is_your_company_address': 1 - } - } - } + is_your_company_address: 1, + }, + }; + }, }, ]; - frappe.prompt(fields, function(filters){ - frm.events.make_withholding_tax_cert(frm, filters); - }, __('Withholding Tax Cert'), __('Create Withholding Tax Cert')); + frappe.prompt( + fields, + function (filters) { + frm.events.make_withholding_tax_cert(frm, filters); + }, + __("Withholding Tax Cert"), + __("Create Withholding Tax Cert") + ); }); } // Create Clear Undue VAT Journal Entry - if(frm.doc.docstatus == 1) { + if (frm.doc.docstatus == 1) { // Check first whether all tax has been cleared, to add button frappe.call({ - method: 'thai_tax.custom.custom_api.to_clear_undue_tax', + method: "thai_tax.custom.custom_api.to_clear_undue_tax", args: { - "dt": cur_frm.doc.doctype, - "dn": cur_frm.doc.name + dt: cur_frm.doc.doctype, + dn: cur_frm.doc.name, }, - callback: function(r) { + callback: function (r) { if (r.message == true) { // Add button - frm.add_custom_button(__('Clear Undue Tax'), function () { + frm.add_custom_button(__("Clear Undue Tax"), function () { frm.trigger("make_clear_vat_journal_entry"); }); } - } + }, }); } }, // Called from button Duduct Withholding Tax - deduct_withholding_tax: function(frm) { + deduct_withholding_tax: function (frm) { const fields = [ { - fieldtype: 'Link', - label: __('WHT Type'), - fieldname: 'wht_type', - options: 'Withholding Tax Type', - reqd: 1 + fieldtype: "Link", + label: __("WHT Type"), + fieldname: "wht_type", + options: "Withholding Tax Type", + reqd: 1, }, ]; - frappe.prompt(fields, function(filters){ - frm.events.add_withholding_tax_deduction(frm, filters); - }, __('Deduct Withholding Tax'), __('Add Withholding Tax Deduction')); + frappe.prompt( + fields, + function (filters) { + frm.events.add_withholding_tax_deduction(frm, filters); + }, + __("Deduct Withholding Tax"), + __("Add Withholding Tax Deduction") + ); }, - add_withholding_tax_deduction: function(frm, filters) { + add_withholding_tax_deduction: function (frm, filters) { return frappe.call({ - method: 'thai_tax.custom.custom_api.get_withholding_tax', + method: "thai_tax.custom.custom_api.get_withholding_tax", args: { filters: filters, - doc: frm.doc + doc: frm.doc, + }, + callback: function (r) { + var d = frm.add_child("deductions"); + d.account = r.message["account"]; + d.cost_center = r.message["cost_center"]; + d.amount = r.message["amount"]; + frm.refresh(); }, - callback: function(r) { - var d = frm.add_child('deductions'); - d.account = r.message['account'] - d.cost_center = r.message['cost_center'] - d.amount = r.message['amount'] - frm.refresh(); - } }); }, - make_withholding_tax_cert: function(frm, filters) { + make_withholding_tax_cert: function (frm, filters) { return frappe.call({ - method: 'thai_tax.custom.custom_api.make_withholding_tax_cert', + method: "thai_tax.custom.custom_api.make_withholding_tax_cert", args: { filters: filters, - doc: frm.doc + doc: frm.doc, }, - callback: function(r) { + callback: function (r) { var doclist = frappe.model.sync(r.message); frappe.set_route("Form", doclist[0].doctype, doclist[0].name); - } + }, }); }, make_clear_vat_journal_entry() { return frappe.call({ - method: 'thai_tax.custom.custom_api.make_clear_vat_journal_entry', + method: "thai_tax.custom.custom_api.make_clear_vat_journal_entry", args: { - "dt": cur_frm.doc.doctype, - "dn": cur_frm.doc.name + dt: cur_frm.doc.doctype, + dn: cur_frm.doc.name, }, - callback: function(r) { + callback: function (r) { var doclist = frappe.model.sync(r.message); frappe.set_route("Form", doclist[0].doctype, doclist[0].name); - } + }, }); - } - -}) \ No newline at end of file + }, +}); diff --git a/thai_tax/public/js/purchase_tax_invoice.js b/thai_tax/public/js/purchase_tax_invoice.js index 44672aa..af772c7 100644 --- a/thai_tax/public/js/purchase_tax_invoice.js +++ b/thai_tax/public/js/purchase_tax_invoice.js @@ -1,11 +1,11 @@ -frappe.ui.form.on('Purchase Tax Invoice', { +frappe.ui.form.on("Purchase Tax Invoice", { refresh(frm) { - frm.set_query('company_tax_address', function() { - return { + frm.set_query("company_tax_address", function () { + return { filters: { - is_your_company_address: true - } - } - }) - } -}) + is_your_company_address: true, + }, + }; + }); + }, +}); diff --git a/thai_tax/public/js/sales_tax_invoice.js b/thai_tax/public/js/sales_tax_invoice.js index b7b445c..201e59e 100644 --- a/thai_tax/public/js/sales_tax_invoice.js +++ b/thai_tax/public/js/sales_tax_invoice.js @@ -1,11 +1,11 @@ -frappe.ui.form.on('Sales Tax Invoice', { +frappe.ui.form.on("Sales Tax Invoice", { refresh(frm) { - frm.set_query('company_tax_address', function() { - return { + frm.set_query("company_tax_address", function () { + return { filters: { - is_your_company_address: true - } - } - }) - } -}) + is_your_company_address: true, + }, + }; + }); + }, +}); diff --git a/thai_tax/public/js/withholding_tax_cert.js b/thai_tax/public/js/withholding_tax_cert.js index 2f57ab7..97c0e26 100644 --- a/thai_tax/public/js/withholding_tax_cert.js +++ b/thai_tax/public/js/withholding_tax_cert.js @@ -1,49 +1,56 @@ -frappe.ui.form.on('Withholding Tax Cert', { +frappe.ui.form.on("Withholding Tax Cert", { refresh(frm) { - frm.set_query('company_address', function() { - return { + frm.set_query("company_address", function () { + return { filters: { - is_your_company_address: 1 - } - } - }); - frm.set_query("voucher_type", function() { + is_your_company_address: 1, + }, + }; + }); + frm.set_query("voucher_type", function () { return { filters: { - "name": ["in", ["Payment Entry", "Journal Entry"]] - } - } + name: ["in", ["Payment Entry", "Journal Entry"]], + }, + }; }); - - } + }, }); frappe.ui.form.on("Withholding Tax Items", { // Helper to calculate tax amount from given rate - tax_rate: function(frm, cdt, cdn) { + tax_rate: function (frm, cdt, cdn) { var row = locals[cdt][cdn]; - frappe.model.set_value(cdt, cdn, "tax_amount", row.tax_base * row.tax_rate / 100); + frappe.model.set_value(cdt, cdn, "tax_amount", (row.tax_base * row.tax_rate) / 100); }, // Auto assign income type description - type_of_income: function(frm, cdt, cdn) { + type_of_income: function (frm, cdt, cdn) { var row = locals[cdt][cdn]; var vals = { - "1": "เงินเดือน ค่าจ้าง ฯลฯ 40(1)", - "2": "ค่าธรรมเนียม ค่านายหน้า ฯลฯ 40(2)", - "3": "ค่าแห่งลิขสิทธิ์ ฯลฯ 40(3)", - "4": "ดอกเบี้ย ฯลฯ 40(4)ก", - "4.1.1": "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (1.1) กิจการที่ต้องเสียภาษีเงินได้นิติบุคคลร้อยละ 30 ของกำไรสุทธิ", - "4.1.2": "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (1.2) กิจการที่ต้องเสียภาษีเงินได้นิติบุคคลร้อยละ 25 ของกำไรสุทธิ", - "4.1.3": "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (1.3) กิจการที่ต้องเสียภาษีเงินได้นิติบุคคลร้อยละ 20 ของกำไรสุทธิ", - "4.1.4": "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (1.4) กิจการที่ต้องเสียภาษีเงินได้นิติบุคคลร้อยละ อื่นๆ (ระบุ) ของกำไรสุทธิ", - "4.2.1": "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (2.1) กำไรสุทธิกิจการที่ได้รับยกเว้นภาษีเงินได้นิติบุคคล", - "4.2.2": "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (2.2) ได้รับยกเว้นไม่ต้องนำมารวมคำนวณเป็นรายได้", - "4.2.3": "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (2.3) กำไรสุทธิส่วนที่หักผลขาดทุนสุทธิยกมาไม่เกิน 5 ปี", - "4.2.4": "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (2.4) กำไรที่รับรู้ทางบัญชีโดยวิธีส่วนได้เสีย", + 1: "เงินเดือน ค่าจ้าง ฯลฯ 40(1)", + 2: "ค่าธรรมเนียม ค่านายหน้า ฯลฯ 40(2)", + 3: "ค่าแห่งลิขสิทธิ์ ฯลฯ 40(3)", + 4: "ดอกเบี้ย ฯลฯ 40(4)ก", + "4.1.1": + "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (1.1) กิจการที่ต้องเสียภาษีเงินได้นิติบุคคลร้อยละ 30 ของกำไรสุทธิ", + "4.1.2": + "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (1.2) กิจการที่ต้องเสียภาษีเงินได้นิติบุคคลร้อยละ 25 ของกำไรสุทธิ", + "4.1.3": + "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (1.3) กิจการที่ต้องเสียภาษีเงินได้นิติบุคคลร้อยละ 20 ของกำไรสุทธิ", + "4.1.4": + "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (1.4) กิจการที่ต้องเสียภาษีเงินได้นิติบุคคลร้อยละ อื่นๆ (ระบุ) ของกำไรสุทธิ", + "4.2.1": + "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (2.1) กำไรสุทธิกิจการที่ได้รับยกเว้นภาษีเงินได้นิติบุคคล", + "4.2.2": + "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (2.2) ได้รับยกเว้นไม่ต้องนำมารวมคำนวณเป็นรายได้", + "4.2.3": + "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (2.3) กำไรสุทธิส่วนที่หักผลขาดทุนสุทธิยกมาไม่เกิน 5 ปี", + "4.2.4": + "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (2.4) กำไรที่รับรู้ทางบัญชีโดยวิธีส่วนได้เสีย", "4.2.5": "เงินปันผล เงินส่วนแบ่งกำไร ฯลฯ 40(4)ข (2.5) อื่นๆ (ระบุ)", - "5": "ค่าจ้างทำของ ค่าบริการ ค่าเช่า ค่าขนส่ง ฯลฯ 3 เตรส", - "6": "อื่นๆ (ระบุ)" - } + 5: "ค่าจ้างทำของ ค่าบริการ ค่าเช่า ค่าขนส่ง ฯลฯ 3 เตรส", + 6: "อื่นๆ (ระบุ)", + }; frappe.model.set_value(cdt, cdn, "description", vals[row.type_of_income]); }, }); diff --git a/thai_tax/thai_tax/doctype/purchase_tax_invoice/purchase_tax_invoice.js b/thai_tax/thai_tax/doctype/purchase_tax_invoice/purchase_tax_invoice.js index 05c9031..c7825af 100644 --- a/thai_tax/thai_tax/doctype/purchase_tax_invoice/purchase_tax_invoice.js +++ b/thai_tax/thai_tax/doctype/purchase_tax_invoice/purchase_tax_invoice.js @@ -1,8 +1,7 @@ // Copyright (c) 2023, Kitti U. and contributors // For license information, please see license.txt -frappe.ui.form.on('Purchase Tax Invoice', { +frappe.ui.form.on("Purchase Tax Invoice", { // refresh: function(frm) { - // } }); diff --git a/thai_tax/thai_tax/doctype/purchase_tax_invoice/purchase_tax_invoice.py b/thai_tax/thai_tax/doctype/purchase_tax_invoice/purchase_tax_invoice.py index 842f5c1..f310469 100644 --- a/thai_tax/thai_tax/doctype/purchase_tax_invoice/purchase_tax_invoice.py +++ b/thai_tax/thai_tax/doctype/purchase_tax_invoice/purchase_tax_invoice.py @@ -4,8 +4,8 @@ from frappe.model.document import Document from frappe.utils import add_months -class PurchaseTaxInvoice(Document): +class PurchaseTaxInvoice(Document): def validate(self): self.compute_report_date() @@ -22,4 +22,4 @@ def compute_report_date(self): if int(self.months_delayed) == 0: self.db_set("report_date", self.date) else: - self.db_set("report_date",add_months(self.date, int(self.months_delayed))) + self.db_set("report_date", add_months(self.date, int(self.months_delayed))) diff --git a/thai_tax/thai_tax/doctype/sales_tax_invoice/sales_tax_invoice.js b/thai_tax/thai_tax/doctype/sales_tax_invoice/sales_tax_invoice.js index 74e8b63..699aa29 100644 --- a/thai_tax/thai_tax/doctype/sales_tax_invoice/sales_tax_invoice.js +++ b/thai_tax/thai_tax/doctype/sales_tax_invoice/sales_tax_invoice.js @@ -1,8 +1,7 @@ // Copyright (c) 2023, Kitti U. and contributors // For license information, please see license.txt -frappe.ui.form.on('Sales Tax Invoice', { +frappe.ui.form.on("Sales Tax Invoice", { // refresh: function(frm) { - // } }); diff --git a/thai_tax/thai_tax/doctype/sales_tax_invoice/sales_tax_invoice.py b/thai_tax/thai_tax/doctype/sales_tax_invoice/sales_tax_invoice.py index a7d0f5b..6ece80a 100644 --- a/thai_tax/thai_tax/doctype/sales_tax_invoice/sales_tax_invoice.py +++ b/thai_tax/thai_tax/doctype/sales_tax_invoice/sales_tax_invoice.py @@ -4,8 +4,8 @@ from frappe.model.document import Document from frappe.utils import add_months -class SalesTaxInvoice(Document): +class SalesTaxInvoice(Document): def validate(self): self.compute_report_date() diff --git a/thai_tax/thai_tax/doctype/tax_invoice_settings/tax_invoice_settings.js b/thai_tax/thai_tax/doctype/tax_invoice_settings/tax_invoice_settings.js index 1337a64..e0fbb85 100644 --- a/thai_tax/thai_tax/doctype/tax_invoice_settings/tax_invoice_settings.js +++ b/thai_tax/thai_tax/doctype/tax_invoice_settings/tax_invoice_settings.js @@ -1,27 +1,29 @@ // Copyright (c) 2023, Kitti U. and contributors // For license information, please see license.txt -frappe.ui.form.on('Tax Invoice Settings', { - onload: function(frm) { - for (let field of ['sales_tax_account', - 'sales_tax_account_undue', - 'purchase_tax_account', - 'purchase_tax_account_undue']) { - frm.set_query(field, function(doc) { +frappe.ui.form.on("Tax Invoice Settings", { + onload: function (frm) { + for (let field of [ + "sales_tax_account", + "sales_tax_account_undue", + "purchase_tax_account", + "purchase_tax_account_undue", + ]) { + frm.set_query(field, function (doc) { return { filters: { - "account_type": "Tax", - "company": doc.company - } + account_type: "Tax", + company: doc.company, + }, }; }); } }, - company: function(frm) { - frm.set_value("sales_tax_account", null) - frm.set_value("sales_tax_account_undue", null) - frm.set_value("purchase_tax_account", null) - frm.set_value("purchase_tax_account_undue", null) - } + company: function (frm) { + frm.set_value("sales_tax_account", null); + frm.set_value("sales_tax_account_undue", null); + frm.set_value("purchase_tax_account", null); + frm.set_value("purchase_tax_account_undue", null); + }, }); diff --git a/thai_tax/thai_tax/doctype/tax_invoice_settings/tax_invoice_settings.py b/thai_tax/thai_tax/doctype/tax_invoice_settings/tax_invoice_settings.py index d849e16..0373b71 100644 --- a/thai_tax/thai_tax/doctype/tax_invoice_settings/tax_invoice_settings.py +++ b/thai_tax/thai_tax/doctype/tax_invoice_settings/tax_invoice_settings.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class TaxInvoiceSettings(Document): pass diff --git a/thai_tax/thai_tax/doctype/withholding_tax_cert/withholding_tax_cert.js b/thai_tax/thai_tax/doctype/withholding_tax_cert/withholding_tax_cert.js index 4c4a36b..38581dc 100644 --- a/thai_tax/thai_tax/doctype/withholding_tax_cert/withholding_tax_cert.js +++ b/thai_tax/thai_tax/doctype/withholding_tax_cert/withholding_tax_cert.js @@ -1,15 +1,15 @@ // Copyright (c) 2023, Kitti U. and contributors // For license information, please see license.txt -frappe.ui.form.on('Withholding Tax Cert', { +frappe.ui.form.on("Withholding Tax Cert", { refresh(frm) { - frm.set_query('supplier_address', function() { - return { + frm.set_query("supplier_address", function () { + return { filters: { - link_doctype: 'Supplier', - link_name: frm.doc.supplier, - } - } - }) - } -}) + link_doctype: "Supplier", + link_name: frm.doc.supplier, + }, + }; + }); + }, +}); diff --git a/thai_tax/thai_tax/doctype/withholding_tax_cert/withholding_tax_cert.py b/thai_tax/thai_tax/doctype/withholding_tax_cert/withholding_tax_cert.py index eb1ac02..6143773 100644 --- a/thai_tax/thai_tax/doctype/withholding_tax_cert/withholding_tax_cert.py +++ b/thai_tax/thai_tax/doctype/withholding_tax_cert/withholding_tax_cert.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class WithholdingTaxCert(Document): pass diff --git a/thai_tax/thai_tax/doctype/withholding_tax_items/withholding_tax_items.py b/thai_tax/thai_tax/doctype/withholding_tax_items/withholding_tax_items.py index 12e41b6..f644073 100644 --- a/thai_tax/thai_tax/doctype/withholding_tax_items/withholding_tax_items.py +++ b/thai_tax/thai_tax/doctype/withholding_tax_items/withholding_tax_items.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class WithholdingTaxItems(Document): pass diff --git a/thai_tax/thai_tax/doctype/withholding_tax_setting/withholding_tax_setting.js b/thai_tax/thai_tax/doctype/withholding_tax_setting/withholding_tax_setting.js index 19f8db1..f9b6f37 100644 --- a/thai_tax/thai_tax/doctype/withholding_tax_setting/withholding_tax_setting.js +++ b/thai_tax/thai_tax/doctype/withholding_tax_setting/withholding_tax_setting.js @@ -1,8 +1,7 @@ // Copyright (c) 2023, Kitti U. and contributors // For license information, please see license.txt -frappe.ui.form.on('Withholding Tax Setting', { +frappe.ui.form.on("Withholding Tax Setting", { // refresh: function(frm) { - // } }); diff --git a/thai_tax/thai_tax/doctype/withholding_tax_setting/withholding_tax_setting.py b/thai_tax/thai_tax/doctype/withholding_tax_setting/withholding_tax_setting.py index 8efb4ce..2249f3f 100644 --- a/thai_tax/thai_tax/doctype/withholding_tax_setting/withholding_tax_setting.py +++ b/thai_tax/thai_tax/doctype/withholding_tax_setting/withholding_tax_setting.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class WithholdingTaxSetting(Document): pass diff --git a/thai_tax/thai_tax/doctype/withholding_tax_type/withholding_tax_type.js b/thai_tax/thai_tax/doctype/withholding_tax_type/withholding_tax_type.js index 1d3ae22..52e9d3c 100644 --- a/thai_tax/thai_tax/doctype/withholding_tax_type/withholding_tax_type.js +++ b/thai_tax/thai_tax/doctype/withholding_tax_type/withholding_tax_type.js @@ -1,8 +1,7 @@ // Copyright (c) 2023, Kitti U. and contributors // For license information, please see license.txt -frappe.ui.form.on('Withholding Tax Type', { +frappe.ui.form.on("Withholding Tax Type", { // refresh: function(frm) { - // } }); diff --git a/thai_tax/thai_tax/doctype/withholding_tax_type/withholding_tax_type.py b/thai_tax/thai_tax/doctype/withholding_tax_type/withholding_tax_type.py index f8ae701..511636e 100644 --- a/thai_tax/thai_tax/doctype/withholding_tax_type/withholding_tax_type.py +++ b/thai_tax/thai_tax/doctype/withholding_tax_type/withholding_tax_type.py @@ -4,5 +4,6 @@ # import frappe from frappe.model.document import Document + class WithholdingTaxType(Document): pass diff --git a/thai_tax/thai_tax/report/pnd3/pnd3.js b/thai_tax/thai_tax/report/pnd3/pnd3.js index 88f9660..cd01eff 100644 --- a/thai_tax/thai_tax/report/pnd3/pnd3.js +++ b/thai_tax/thai_tax/report/pnd3/pnd3.js @@ -2,33 +2,32 @@ // For license information, please see license.txt /* eslint-disable */ - frappe.query_reports["PND3"] = { filters: [ { - "fieldname": "year", - "label": __("Year"), - "fieldtype": "Link", - "options": "Fiscal Year", + fieldname: "year", + label: __("Year"), + fieldtype: "Link", + options: "Fiscal Year", }, { - "fieldname": "month", - "label": __("Month"), - "fieldtype": "Select", - "options": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"], + fieldname: "month", + label: __("Month"), + fieldtype: "Select", + options: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"], }, { - "fieldname": "company_address", - "label": __("Company Address"), - "fieldtype": "Link", - "options": "Address", + fieldname: "company_address", + label: __("Company Address"), + fieldtype: "Link", + options: "Address", get_query: () => { return { filters: { - 'is_your_company_address': 1 - } + is_your_company_address: 1, + }, }; - } - } - ] + }, + }, + ], }; diff --git a/thai_tax/thai_tax/report/pnd3/pnd3.py b/thai_tax/thai_tax/report/pnd3/pnd3.py index 3c92820..7c6d612 100644 --- a/thai_tax/thai_tax/report/pnd3/pnd3.py +++ b/thai_tax/thai_tax/report/pnd3/pnd3.py @@ -144,8 +144,8 @@ def get_columns(): def get_data(filters): -# SUBSTRING(s.supplier_name, 1, CHAR_LENGTH(s.supplier_name) - LOCATE(' ', REVERSE(s.supplier_name))+1) as firstname, -# SUBSTRING_INDEX(s.supplier_name, " ", -1) as lastname, + # SUBSTRING(s.supplier_name, 1, CHAR_LENGTH(s.supplier_name) - LOCATE(' ', REVERSE(s.supplier_name))+1) as firstname, + # SUBSTRING_INDEX(s.supplier_name, " ", -1) as lastname, wht_cert = frappe.qb.DocType("Withholding Tax Cert") wht_items = frappe.qb.DocType("Withholding Tax Items") @@ -173,8 +173,11 @@ def get_data(filters): supplier.branch_code.as_("branch"), ConstantColumn("").as_("title"), substring( - supplier.supplier_name, 1, - char_length(supplier.supplier_name) - locate(' ', reverse(supplier.supplier_name)) + 1 + supplier.supplier_name, + 1, + char_length(supplier.supplier_name) + - locate(" ", reverse(supplier.supplier_name)) + + 1, ).as_("firstname"), substring_index(supplier.supplier_name, " ", -1).as_("lastname"), address.address_line1.as_("address_line1"), @@ -188,25 +191,22 @@ def get_data(filters): wht_items.tax_rate.as_("tax_rate"), round(wht_items.tax_amount, 2).as_("tax_amount"), Case() - .when(wht_cert.tax_payer == 'Withholding', '1') - .when(wht_cert.tax_payer == 'Paid One Time', '3') + .when(wht_cert.tax_payer == "Withholding", "1") + .when(wht_cert.tax_payer == "Paid One Time", "3") .else_(wht_cert.tax_payer) .as_("tax_payer"), wht_cert.name.as_("name"), wht_cert.voucher_type.as_("voucher_type"), - wht_cert.voucher_no.as_("voucher_no") + wht_cert.voucher_no.as_("voucher_no"), ) .distinct() .where( - (wht_cert.docstatus == 1) - & (wht_cert.income_tax_form == 'PND3') + (wht_cert.docstatus == 1) + & (wht_cert.income_tax_form == "PND3") & (month(wht_cert.date) == filters.get("month")) & (year(wht_cert.date) == filters.get("year")) - - ) - .orderby( - wht_cert.date, wht_cert.name ) + .orderby(wht_cert.date, wht_cert.name) ) if filters.get("company_address"): @@ -217,6 +217,6 @@ def get_data(filters): # Add row number column i = 0 for r in result: - r['no'] = i = i+1 + r["no"] = i = i + 1 return result diff --git a/thai_tax/thai_tax/report/pnd53/pnd53.js b/thai_tax/thai_tax/report/pnd53/pnd53.js index 6c03009..e7b6402 100644 --- a/thai_tax/thai_tax/report/pnd53/pnd53.js +++ b/thai_tax/thai_tax/report/pnd53/pnd53.js @@ -2,33 +2,32 @@ // For license information, please see license.txt /* eslint-disable */ - frappe.query_reports["PND53"] = { filters: [ { - "fieldname": "year", - "label": __("Year"), - "fieldtype": "Link", - "options": "Fiscal Year", + fieldname: "year", + label: __("Year"), + fieldtype: "Link", + options: "Fiscal Year", }, { - "fieldname": "month", - "label": __("Month"), - "fieldtype": "Select", - "options": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"], + fieldname: "month", + label: __("Month"), + fieldtype: "Select", + options: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"], }, { - "fieldname": "company_address", - "label": __("Company Address"), - "fieldtype": "Link", - "options": "Address", + fieldname: "company_address", + label: __("Company Address"), + fieldtype: "Link", + options: "Address", get_query: () => { return { filters: { - 'is_your_company_address': 1 - } + is_your_company_address: 1, + }, }; - } - } - ] + }, + }, + ], }; diff --git a/thai_tax/thai_tax/report/pnd53/pnd53.py b/thai_tax/thai_tax/report/pnd53/pnd53.py index 4f8e308..7d5eb64 100644 --- a/thai_tax/thai_tax/report/pnd53/pnd53.py +++ b/thai_tax/thai_tax/report/pnd53/pnd53.py @@ -162,25 +162,22 @@ def get_data(filters): wht_items.tax_rate.as_("tax_rate"), round(wht_items.tax_amount, 2).as_("tax_amount"), Case() - .when(wht_cert.tax_payer == 'Withholding', '1') - .when(wht_cert.tax_payer == 'Paid One Time', '3') + .when(wht_cert.tax_payer == "Withholding", "1") + .when(wht_cert.tax_payer == "Paid One Time", "3") .else_(wht_cert.tax_payer) .as_("tax_payer"), wht_cert.name.as_("name"), wht_cert.voucher_type.as_("voucher_type"), - wht_cert.voucher_no.as_("voucher_no") + wht_cert.voucher_no.as_("voucher_no"), ) .distinct() .where( - (wht_cert.docstatus == 1) - & (wht_cert.income_tax_form == 'PND53') + (wht_cert.docstatus == 1) + & (wht_cert.income_tax_form == "PND53") & (month(wht_cert.date) == filters.get("month")) & (year(wht_cert.date) == filters.get("year")) - - ) - .orderby( - wht_cert.date, wht_cert.name ) + .orderby(wht_cert.date, wht_cert.name) ) if filters.get("company_address"): @@ -191,6 +188,6 @@ def get_data(filters): # Add row number column i = 0 for r in result: - r['no'] = i = i+1 + r["no"] = i = i + 1 return result diff --git a/thai_tax/thai_tax/report/purchase_tax_report/purchase_tax_report.js b/thai_tax/thai_tax/report/purchase_tax_report/purchase_tax_report.js index ecd7c18..98af5d7 100644 --- a/thai_tax/thai_tax/report/purchase_tax_report/purchase_tax_report.js +++ b/thai_tax/thai_tax/report/purchase_tax_report/purchase_tax_report.js @@ -2,33 +2,32 @@ // For license information, please see license.txt /* eslint-disable */ - frappe.query_reports["Purchase Tax Report"] = { filters: [ { - "fieldname": "year", - "label": __("Year"), - "fieldtype": "Link", - "options": "Fiscal Year", + fieldname: "year", + label: __("Year"), + fieldtype: "Link", + options: "Fiscal Year", }, { - "fieldname": "month", - "label": __("Month"), - "fieldtype": "Select", - "options": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"], + fieldname: "month", + label: __("Month"), + fieldtype: "Select", + options: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"], }, { - "fieldname": "company_tax_address", - "label": __("Company Address"), - "fieldtype": "Link", - "options": "Address", + fieldname: "company_tax_address", + label: __("Company Address"), + fieldtype: "Link", + options: "Address", get_query: () => { return { filters: { - 'is_your_company_address': 1 - } + is_your_company_address: 1, + }, }; - } - } - ] + }, + }, + ], }; diff --git a/thai_tax/thai_tax/report/purchase_tax_report/purchase_tax_report.py b/thai_tax/thai_tax/report/purchase_tax_report/purchase_tax_report.py index 6b84dbe..8aa1ef2 100644 --- a/thai_tax/thai_tax/report/purchase_tax_report/purchase_tax_report.py +++ b/thai_tax/thai_tax/report/purchase_tax_report/purchase_tax_report.py @@ -125,23 +125,20 @@ def get_data(filters): addr.city, addr.county, addr.state, - addr.pincode + addr.pincode, ).as_("supplier_address"), round(tinv.tax_base, 2).as_("tax_base"), round(tinv.tax_amount, 2).as_("tax_amount"), tinv.voucher_type.as_("voucher_type"), tinv.voucher_no.as_("voucher_no"), - tinv.name.as_("tax_invoice") + tinv.name.as_("tax_invoice"), ) .where( - (tinv.docstatus == 1) + (tinv.docstatus == 1) & (month(tinv.report_date) == filters.get("month")) & (year(tinv.report_date) == filters.get("year")) - - ) - .orderby( - tinv.report_date ) + .orderby(tinv.report_date) ) if filters.get("company_tax_address"): diff --git a/thai_tax/thai_tax/report/sales_tax_report/sales_tax_report.js b/thai_tax/thai_tax/report/sales_tax_report/sales_tax_report.js index 42be43f..c4e79a3 100644 --- a/thai_tax/thai_tax/report/sales_tax_report/sales_tax_report.js +++ b/thai_tax/thai_tax/report/sales_tax_report/sales_tax_report.js @@ -5,29 +5,29 @@ frappe.query_reports["Sales Tax Report"] = { filters: [ { - "fieldname": "year", - "label": __("Year"), - "fieldtype": "Link", - "options": "Fiscal Year", + fieldname: "year", + label: __("Year"), + fieldtype: "Link", + options: "Fiscal Year", }, { - "fieldname": "month", - "label": __("Month"), - "fieldtype": "Select", - "options": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"], + fieldname: "month", + label: __("Month"), + fieldtype: "Select", + options: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"], }, { - "fieldname": "company_tax_address", - "label": __("Company Address"), - "fieldtype": "Link", - "options": "Address", + fieldname: "company_tax_address", + label: __("Company Address"), + fieldtype: "Link", + options: "Address", get_query: () => { return { filters: { - 'is_your_company_address': 1 - } + is_your_company_address: 1, + }, }; - } - } - ] + }, + }, + ], }; diff --git a/thai_tax/thai_tax/report/sales_tax_report/sales_tax_report.py b/thai_tax/thai_tax/report/sales_tax_report/sales_tax_report.py index 0e3261f..d229474 100644 --- a/thai_tax/thai_tax/report/sales_tax_report/sales_tax_report.py +++ b/thai_tax/thai_tax/report/sales_tax_report/sales_tax_report.py @@ -97,10 +97,7 @@ def get_data(filters): .as_("name"), tinv.party_name.as_("party_name"), cust.tax_id.as_("tax_id"), - Case() - .when(tinv.docstatus == 1, round(tinv.tax_base, 2)) - .else_(0) - .as_("tax_base"), + Case().when(tinv.docstatus == 1, round(tinv.tax_base, 2)).else_(0).as_("tax_base"), Case() .when(tinv.docstatus == 1, round(tinv.tax_amount, 2)) .else_(0) @@ -109,13 +106,11 @@ def get_data(filters): tinv.voucher_no.as_("voucher_no"), ) .where( - (tinv.docstatus.isin([1, 2])) + (tinv.docstatus.isin([1, 2])) & (month(tinv.report_date) == filters.get("month")) & (year(tinv.report_date) == filters.get("year")) ) - .orderby( - tinv.name - ) + .orderby(tinv.name) ) if filters.get("company_tax_address"): diff --git a/thai_tax/utils.py b/thai_tax/utils.py index 615625c..e81952b 100644 --- a/thai_tax/utils.py +++ b/thai_tax/utils.py @@ -1,88 +1,91 @@ -from num2words import num2words +import frappe import zeep +from frappe import _ +from num2words import num2words from requests import Session from zeep import Client from zeep.transports import Transport -import frappe -from frappe import _ def amount_in_bahttext(amount): - return num2words(amount, to="currency", lang="th") + return num2words(amount, to="currency", lang="th") + @frappe.whitelist() def get_address_by_tax_id(tax_id=False, branch=False): - if not (tax_id and branch): - frappe.throw(_('Please provide Tax ID and Branch')) - session = Session() - session.verify = False - transport = Transport(session=session) - client = Client('https://rdws.rd.go.th/serviceRD3/vatserviceRD3.asmx?wsdl', - transport=transport) - result = client.service.Service( - username='anonymous', - password='anonymous', - TIN=tax_id, - ProvinceCode=0, - BranchNumber=int(branch.isnumeric() and branch or '0'), - AmphurCode=0 - ) - result = zeep.helpers.serialize_object(result) - data = {} - for k in result.keys(): - if k == 'vmsgerr' and result[k] is not None: - frappe.throw(result[k].get('anyType', None)[0]) - if result[k] is not None: - v = result[k].get('anyType', None)[0] - data.update({k: v}) - return finalize_address_dict(data) + if not (tax_id and branch): + frappe.throw(_("Please provide Tax ID and Branch")) + session = Session() + session.verify = False + transport = Transport(session=session) + client = Client( + "https://rdws.rd.go.th/serviceRD3/vatserviceRD3.asmx?wsdl", transport=transport + ) + result = client.service.Service( + username="anonymous", + password="anonymous", + TIN=tax_id, + ProvinceCode=0, + BranchNumber=int(branch.isnumeric() and branch or "0"), + AmphurCode=0, + ) + result = zeep.helpers.serialize_object(result) + data = {} + for k in result.keys(): + if k == "vmsgerr" and result[k] is not None: + frappe.throw(result[k].get("anyType", None)[0]) + if result[k] is not None: + v = result[k].get("anyType", None)[0] + data.update({k: v}) + return finalize_address_dict(data) + def finalize_address_dict(data): - def get_part(data, key, value): - return data.get(key, '-') != '-' and value % (map[key], data.get(key)) or '' - map = { - "vBuildingName": "อาคาร", - "vFloorNumber": "ชั้น", - "vVillageName": "หมู่บ้าน", - "vRoomNumber": "ห้อง", - # "vHouseNumber": "เลขที่", - "vMooNumber": "หมู่ที่", - "vSoiName": "ซอย", - "vStreetName": "ถนน", - "vThambol": "ต.", - "vAmphur": "อ.", - "vProvince": "จ.", - } - name = '%s %s' % (data.get('vtitleName'), data.get('vName')) - if data.get('vSurname', '-') != '-': - name = '%s %s' % (name, data['vSurname']) - house = data.get('vHouseNumber', '') - village = get_part(data, 'vVillageName', '%s %s') - soi = get_part(data, 'vSoiName', '%s %s') - moo = get_part(data, 'vMooNumber', '%s %s') - building = get_part(data, 'vBuildingName', '%s %s') - floor = get_part(data, 'vFloorNumber', '%s %s') - room = get_part(data, 'vRoomNumber', '%s %s') - street = get_part(data, 'vStreetName', '%s%s') - thambon = get_part(data, 'vThambol', '%s%s') - amphur = get_part(data, 'vAmphur', '%s%s') - province = get_part(data, 'vProvince', '%s%s') - postal = data.get('vPostCode', '') + def get_part(data, key, value): + return data.get(key, "-") != "-" and value % (map[key], data.get(key)) or "" + + map = { + "vBuildingName": "อาคาร", + "vFloorNumber": "ชั้น", + "vVillageName": "หมู่บ้าน", + "vRoomNumber": "ห้อง", + # "vHouseNumber": "เลขที่", + "vMooNumber": "หมู่ที่", + "vSoiName": "ซอย", + "vStreetName": "ถนน", + "vThambol": "ต.", + "vAmphur": "อ.", + "vProvince": "จ.", + } + name = "{} {}".format(data.get("vtitleName"), data.get("vName")) + if data.get("vSurname", "-") != "-": + name = "{} {}".format(name, data["vSurname"]) + house = data.get("vHouseNumber", "") + village = get_part(data, "vVillageName", "%s %s") + soi = get_part(data, "vSoiName", "%s %s") + moo = get_part(data, "vMooNumber", "%s %s") + building = get_part(data, "vBuildingName", "%s %s") + floor = get_part(data, "vFloorNumber", "%s %s") + room = get_part(data, "vRoomNumber", "%s %s") + street = get_part(data, "vStreetName", "%s%s") + thambon = get_part(data, "vThambol", "%s%s") + amphur = get_part(data, "vAmphur", "%s%s") + province = get_part(data, "vProvince", "%s%s") + postal = data.get("vPostCode", "") - if province == 'จ.กรุงเทพมหานคร': - thambon = data.get('vThambol') and 'แขวง%s' % data['vAmphur'] or '' - amphur = data.get('vAmphur') and 'เขต%s' % data['vAmphur'] or '' - province = data.get('vProvince') and '%s' % data['vProvince'] or '' + if province == "จ.กรุงเทพมหานคร": + thambon = data.get("vThambol") and "แขวง%s" % data["vAmphur"] or "" + amphur = data.get("vAmphur") and "เขต%s" % data["vAmphur"] or "" + province = data.get("vProvince") and "%s" % data["vProvince"] or "" - address_parts = filter( - lambda x: x != '', - [house, village, soi, moo, building, floor, room, street] - ) - return { - 'name': name, - 'address_line1': ' '.join(address_parts), - 'city': thambon, - 'county': amphur, - 'state': province, - 'pincode': postal, - } + address_parts = filter( + lambda x: x != "", [house, village, soi, moo, building, floor, room, street] + ) + return { + "name": name, + "address_line1": " ".join(address_parts), + "city": thambon, + "county": amphur, + "state": province, + "pincode": postal, + }