diff --git a/netforce_clinic/layouts/clinic_tax_rate_form.xml b/netforce_clinic/layouts/clinic_tax_rate_form.xml
new file mode 100644
index 0000000..74483a9
--- /dev/null
+++ b/netforce_clinic/layouts/clinic_tax_rate_form.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/netforce_clinic/models/__init__.py b/netforce_clinic/models/__init__.py
index d4e1fa4..cdbc078 100644
--- a/netforce_clinic/models/__init__.py
+++ b/netforce_clinic/models/__init__.py
@@ -128,3 +128,6 @@ from . import compute_labor_cost
from . import login
from . import sequence
from . import report_shop
+from . import account_tax_component
+from . import report_thai_wht_certif
+from . import num2word
diff --git a/netforce_clinic/models/account_tax_component.py b/netforce_clinic/models/account_tax_component.py
new file mode 100644
index 0000000..3350c00
--- /dev/null
+++ b/netforce_clinic/models/account_tax_component.py
@@ -0,0 +1,29 @@
+from netforce.model import Model, fields
+
+class TaxComponent(Model):
+ _inherit="account.tax.component"
+ _fields={
+ "sequence": fields.Selection([
+ ["1","1"],
+ ["2","2"],
+ ["3","3"],
+ ["4","4"],
+ ["4.1.1","4.1.1"],
+ ["4.1.2","4.1.2"],
+ ["4.1.3","4.1.3"],
+ ["4.1.4","4.1.4"],
+ ["4.2.1","4.2.1"],
+ ["4.2.2","4.2.2"],
+ ["4.2.3","4.2.3"],
+ ["4.2.4","4.2.4"],
+ ["4.2.5","4.2.5"],
+ ["5","5"],
+ ["6","6"],
+ ],"Sequence"), #report sequence
+ }
+
+ _defaults={
+ 'sequence': 5,
+ }
+
+TaxComponent.register()
diff --git a/netforce_clinic/models/num2word.py b/netforce_clinic/models/num2word.py
new file mode 100644
index 0000000..28a51aa
--- /dev/null
+++ b/netforce_clinic/models/num2word.py
@@ -0,0 +1,85 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+sym={
+ "en": {
+ "sep": " ",
+ "0": "zero",
+ "x": ["one","two","three","four","five" ,"six","seven","eight","nine"],
+ "1x": ["ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"],
+ "x0": ["twenty","thirty","fourty","fifty","sixty","seventy","eighty","ninety"],
+ "100": "hundred",
+ "1K": "thousand",
+ "1M": "million",
+ },
+ "th": {
+ "sep": "",
+ "0": "ศูนย์",
+ "x": ["หนึ่ง","สอง","สาม","สี่","ห้า" ,"หก","เจ็ด","แปด","เก้า"],
+ "x0": ["สิบ","ยี่สิบ","สามสิบ","สี่สิบ","ห้าสิบ","หกสิบ","เจ็ดสิบ","แปดสิบ","เก้าสิบ"],
+ "x1": "เอ็ด",
+ "100": "ร้อย",
+ "1K": "พัน",
+ "10K": "หมื่น",
+ "100K": "แสน",
+ "1M":"ล้าน",
+ }
+}
+
+def num2word(n,l="en"):
+ #TODO:Support Thai Stang
+ if n==0:
+ return sym[l]["0"] + " "
+ elif n<10:
+ return sym[l]["x"][n-1]
+ elif n<100:
+ if l=="en":
+ if n<20:
+ return sym[l]["1x"][n-10]
+ else:
+ return sym[l]["x0"][n//10-2]+(n%10 and sym[l]["sep"]+num2word(n%10,l) or "")
+ elif l=="th":
+ return sym[l]["x0"][n//10-1]+(n%10 and (n%10==1 and sym[l]["x1"] or sym[l]["x"][n%10-1]) or "")
+ elif n<1000:
+ return sym[l]["x"][n//100-1]+sym[l]["sep"]+sym[l]["100"]+(n%100 and sym[l]["sep"]+num2word(n%100,l) or "")
+
+ elif n<1000000:
+ if l=="en":
+ return num2word(n/1000,l)+sym[l]["sep"]+sym[l]["1K"]+(n%1000 and sym[l]["sep"]+num2word(n%1000,l) or "")
+ elif l=="th":
+ if n<10000:
+ return sym[l]["x"][n//1000-1]+sym[l]["1K"]+(n%1000 and num2word(n%1000,l) or "")
+ elif n<100000:
+ print(">>>>>",n)
+ return sym[l]["x"][n//10000-1]+sym[l]["10K"]+(n%10000 and num2word(n%10000,l) or "")
+ else:
+ return sym[l]["x"][n//100000-1]+sym[l]["100K"]+(n%100000 and num2word(n%100000,l) or "")
+ elif n<1000000000:
+ return num2word(n//1000000,l)+sym[l]["sep"]+sym[l]["1M"]+sym[l]["sep"]+(n%1000000 and num2word(n%1000000,l) or "")
+ else:
+ return "N/A"
+
+def num2word_th(n,l="th"):
+ base=0
+ end=0
+ number = n
+ if type(n) == type(''):
+ number=float(n)
+ word = ''
+ if type(number) in (type(0),type(0.0)):
+ number = ('%.2f'%number).split('.')
+ base = num2word(int(number[0]),l=l)
+ if int(number[1])!=0:
+ end = num2word(int(number[1]),l=l)
+ if base==0 and end==0:
+ word='ศุนย์บาทถ้วน'
+ if base!=0 and end==0:
+ word=base+'บาทถ้วน'
+ if base!=0 and end!=0:
+ word=base+'บาท'+end+'สตางค์'
+ return word
+
+if __name__ == '__main__':
+ import sys
+ n=sys.stdin.readline()
+ #print num2word_th(n)
diff --git a/netforce_clinic/models/report_thai_wht_certif.py b/netforce_clinic/models/report_thai_wht_certif.py
new file mode 100644
index 0000000..8f6ceb7
--- /dev/null
+++ b/netforce_clinic/models/report_thai_wht_certif.py
@@ -0,0 +1,97 @@
+from netforce.model import Model, fields, get_model
+from datetime import *
+from dateutil.relativedelta import *
+from netforce.access import get_active_company
+from . import num2word
+
+def fmt_thai_tax_no(tax_no):
+ s=tax_no or ""
+ s.replace("-","")
+ if len(s)<13:
+ s+=" "*(13-len(s))
+ return s
+
+class ReportThaiWHTCertif(Model):
+ _inherit="report.thai.wht.certif"
+
+ def get_report_data(self,ids,context={}):
+ if not ids:
+ return {}
+ obj=self.browse(ids)[0]
+ company_id=get_active_company()
+ comp=get_model("company").browse(company_id)
+ settings=get_model("settings").browse(1)
+ pmt=obj.payment_id
+ contact=pmt.partner_id
+ data={
+ "company_tax_no": fmt_thai_tax_no(settings.tax_no),
+ "company_name": comp.name,
+ "dept_addr": settings.default_address_id.address_text.replace("\n",", "), # XXX
+ "tax_no": fmt_thai_tax_no(contact.tax_no),
+ "partner_name": contact.name,
+ "partner_addr": contact.default_address_id.address_text.replace("\n",", ") if contact.default_address_id else None, # XXX
+ "date": datetime.strptime(pmt.date,"%Y-%m-%d").strftime("%d/%m/%Y"),
+ "lines": [{}], # XXX
+ }
+ move=pmt.move_id
+ if not move:
+ raise Exception("Journal entry not found")
+ base={}
+ tax={}
+ contact_type=None
+ wht_no=None
+ for line in move.lines:
+ comp=line.tax_comp_id
+ if not comp:
+ continue
+ if comp.type!="wht" or comp.trans_type!="in":
+ continue
+ if not wht_no:
+ wht_no=line.tax_no
+ else:
+ if wht_no!=line.tax_no:
+ raise Exception("Multiple WHT numbers for same payment")
+ if not contact_type:
+ contact_type=comp.contact_type
+ else:
+ if contact_type!=comp.contact_type:
+ raise Exception("Different WHT contact types for same payment")
+ print('sequence ', comp.sequence)
+ exp_code=comp.sequence or "5"
+ #if comp.exp_type=="salary":
+ #exp_code="1"
+ #elif comp.exp_type=="commission":
+ #exp_code="2"
+ #elif comp.exp_type=="royalty":
+ #exp_code="3"
+ #elif comp.exp_type=="interest":
+ #exp_code="4"
+ #elif comp.exp_type in ("rental","service","transport","advert"):
+ #exp_code="5"
+ #else:
+ #exp_code="6"
+ if exp_code=="6":
+ data["desc"]=comp.description
+ base.setdefault(exp_code,0)
+ tax.setdefault(exp_code,0)
+ base[exp_code]+=line.tax_base
+ tax[exp_code]+=line.credit-line.debit
+ if not wht_no:
+ raise Exception("WHT number not found")
+ data["number"]=wht_no
+ if contact_type=="individual":
+ data["num_user1"]="x"
+ data["num_user2"]=""
+ elif contact_type=="company":
+ data["num_user1"]=""
+ data["num_user2"]="x"
+ for exp_code,amt in base.items():
+ data["amt_"+exp_code]=amt
+ for exp_code,amt in tax.items():
+ data["tax_"+exp_code]=amt
+ data["sum_amt"]=sum(base.values())
+ data["sum_tax"]=sum(tax.values())
+ data["total_word"]=num2word.num2word_th(data["sum_tax"],l='th')
+ return data
+
+ReportThaiWHTCertif.register()
diff --git a/netforce_clinic/reports/report_labor_cost.xlsx b/netforce_clinic/reports/report_labor_cost.xlsx
new file mode 100644
index 0000000..87e827a
Binary files /dev/null and b/netforce_clinic/reports/report_labor_cost.xlsx differ
diff --git a/netforce_clinic/templates/report_labor_cost.hbs b/netforce_clinic/templates/report_labor_cost.hbs
index 84ffe7e..75c337d 100644
--- a/netforce_clinic/templates/report_labor_cost.hbs
+++ b/netforce_clinic/templates/report_labor_cost.hbs
@@ -1,6 +1,7 @@
จาก {{date_from}} ถึง {{date_to}}
+
{{#ifeq report_type "detail"}}