Skip to content

Commit

Permalink
Code reviews
Browse files Browse the repository at this point in the history
  • Loading branch information
kittiu committed Jun 25, 2023
1 parent 60de460 commit c6ac3fb
Show file tree
Hide file tree
Showing 33 changed files with 778 additions and 741 deletions.
66 changes: 65 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,71 @@
## Thai Tax

Thailand Taxation - VAT, WHT
Additional tax functionality to comply with Thailand Tax regulation.

### 1. Tax Point on both Invoice and Payment

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.

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.

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"

### 2. Withholding Tax and Certificate

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.

### 3. Reports that require for submission to RD, i.e.,

- Purchase Tax Report, Sales Tax Report
- Withholding Tax Report (PND or ภงด)

### TODO:

- Thailand e-Tax Invoice, e-Withholding Tax

## Features

- Sales Tax and Undue Sales Tax
- Purchase Tax and Undue Purchase Tax
- Sales and Purchase Tax Report
- Withholding Tax on Payment (based on invoice amount before tax) and Withholding Tax Cert (pdf)
- Withholding Tax Report (PND3, PND53)
- Get Address by Tax ID

## Setup

### Installation

```
$ cd frappe-bench
$ bench get-app https://github.com/kittiu/thai_tax
$ bench install-app thai_tax
```

### Configurations

#### For Tax Invoice setup

1. In chart of account, make sure to have with Rate, i.e, 7% for Thailand Tax (Tax)
- Sales Tax, Undue Sales Tax
- Purchase Tax, Undue Purchase Tax
2. Open Tax Invoice Settings, and setup above taxes
3. Setup Sales / Purchase Taxes and Charges Template, we just want to make sure that,
- When buy/sell product, Sales/Purchase Tax is record on invoice
- When buy/sell service, Undue Sales/Purchase Tax is record on invoice, then on payment, clear Undue Tax and record Tax
4. Make sure you have setup Company's Billing Address, as it will be used for Tax Invoice
5. Make sure all Supplier/Customer have setup Billing Address, they will be used for Tax Invoice

Whenever Tax is recorded (with Tax Invoice and Tax Date), Sales/Purchase Tax Invoice will be created.

#### For Withholding Tax setup

1. In chart of account, make sure to have Withholding Tax Account
2. Create Withholding Tax Types (1%, 2%, 3% and 5%)

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.

-----------------------
#### License

MIT
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
# frappe -- https://github.com/frappe/frappe is installed via 'bench init'
zeep
63 changes: 20 additions & 43 deletions thai_tax/custom/custom_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,7 @@ def make_clear_vat_journal_entry(dt, dn):
'voucher_type': ref.reference_doctype,
'voucher_no': ref.reference_name,
},
fields=[
'name', 'account',
'debit_in_account_currency',
'credit_in_account_currency',
])
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'):
Expand All @@ -196,7 +192,6 @@ def make_clear_vat_journal_entry(dt, dn):
'account': account_undue,
'credit_in_account_currency': undue_tax > 0 and undue_tax,
'debit_in_account_currency': undue_tax < 0 and abs(undue_tax),
'against_gl_entry': gl['name'],
},
)
tax_total += undue_tax
Expand Down Expand Up @@ -242,11 +237,7 @@ def clear_invoice_undue_tax(doc, method):
'voucher_type': ref.reference_doctype,
'voucher_no': ref.reference_name,
},
fields=[
'name', 'account',
'debit_in_account_currency',
'credit_in_account_currency',
])
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'):
Expand All @@ -256,21 +247,24 @@ def clear_invoice_undue_tax(doc, method):
if undue_tax:
doc.append('taxes',
{
'add_deduct_tax': undue_tax > 0 and 'Deduct' or 'Add',
# '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,
'against_gl_entry': gl['name'],
'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': tax_total > 0 and 'Add' or 'Deduct',
'add_deduct_tax': 'Add',
'description': 'Clear Undue Tax',
'charge_type': 'Actual',
'account_head': account,
Expand All @@ -289,8 +283,8 @@ def get_undue_tax(doc, ref, gl, tax):
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_in_account_currency']
debit = gl['debit_in_account_currency']
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')
Expand All @@ -306,29 +300,12 @@ def get_undue_tax(doc, ref, gl, tax):
undue_tax = undue_tax if undue_tax < undue_remain else undue_remain
return (undue_tax, base_amount, tax_account_undue, tax_account)

def update_against_gl_entry_on_invoice_return(doc, method):
# For return invoice with undue tax, mark against_gl_entry to origin
if doc.voucher_type in ['Sales Invoice', 'Purchase Invoice']:
tax = frappe.get_single('Tax Invoice Settings')
if doc.account in [tax.purchase_tax_account_undue, tax.sales_tax_account_undue]:
invoice = frappe.get_doc(doc.voucher_type, doc.voucher_no)
if not invoice.is_return or not invoice.return_against:
return
gl = frappe.db.get_all(
'GL Entry',
filters={'voucher_type': invoice.doctype, 'voucher_no': invoice.return_against, 'account': doc.account},
fields=['name'],
)
doc.against_gl_entry = gl[0]['name']

def get_uncleared_tax_amount(gl, payment_type):
uncleared_gl = frappe.db.get_all(
'GL Entry',
filters={'account': gl['account']},
or_filters={'name': gl['name'], 'against_gl_entry': gl['name']},
fields=['debit_in_account_currency', 'credit_in_account_currency'],
)
uncleared_tax = sum([x.debit_in_account_currency - x.credit_in_account_currency for x in uncleared_gl])
# 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
Expand Down Expand Up @@ -376,13 +353,13 @@ def get_withholding_tax(filters, doc):
},
fields=[
'name', 'account',
'debit_in_account_currency',
'credit_in_account_currency',
'debit',
'credit',
])
base_amount = 0
for gl in gl_entries:
credit = gl['credit_in_account_currency']
debit = gl['debit_in_account_currency']
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':
Expand Down
33 changes: 0 additions & 33 deletions thai_tax/custom/general_ledger.py

This file was deleted.

46 changes: 0 additions & 46 deletions thai_tax/custom/journal_entry.py

This file was deleted.

74 changes: 0 additions & 74 deletions thai_tax/custom/payment_entry.py

This file was deleted.

Loading

0 comments on commit c6ac3fb

Please sign in to comment.