From 08bb9f9c98352634de0effcbda3adf17f3b4716d Mon Sep 17 00:00:00 2001
From: "watcha.h"
Date: Wed, 18 Feb 2015 15:50:35 +0700
Subject: [PATCH] report labor cost
---
.../clinic_report_labor_cost_overtime.xml | 8 +
.../layouts/clinic_account_menu.xml | 1 +
.../layouts/clinic_account_setting.xml | 6 +
.../layouts/clinic_labor_cost_form.xml | 1 +
netforce_clinic/layouts/clinic_menu.xml | 2 +-
.../clinic_report_labor_cost_daily.xml | 2 +-
.../clinic_report_labor_cost_overtime.xml | 9 +
.../clinic_report_labor_cost_summary.xml | 3 +-
netforce_clinic/layouts/clinic_staff_form.xml | 3 +-
.../layouts/clinic_staff_rotate_form.xml | 1 +
netforce_clinic/models/__init__.py | 1 +
netforce_clinic/models/hd_case.py | 2 +-
netforce_clinic/models/labor_cost.py | 8 +-
netforce_clinic/models/patient.py | 2 +-
.../models/report_labor_cost_daily.py | 9 +-
.../models/report_labor_cost_detail.py | 5 +
.../models/report_labor_cost_overtime.py | 171 ++++++++++++++++++
.../models/report_labor_cost_summary.py | 34 ++--
.../models/report_medical_summary.py | 2 +-
netforce_clinic/models/setting.py | 2 +
netforce_clinic/models/staff.py | 3 +
netforce_clinic/models/staff_rotation.py | 1 +
.../reports/report_labor_cost_daily.xlsx | Bin 0 -> 6960 bytes
.../reports/report_labor_cost_detail.xlsx | Bin 6677 -> 6786 bytes
.../reports/report_labor_cost_overtime.xlsx | Bin 0 -> 7270 bytes
.../reports/report_labor_cost_summary.xlsx | Bin 6677 -> 6900 bytes
.../templates/report_labor_cost_overtime.hbs | 59 ++++++
27 files changed, 312 insertions(+), 23 deletions(-)
create mode 100644 netforce_clinic/actions/clinic_report_labor_cost_overtime.xml
create mode 100644 netforce_clinic/layouts/clinic_report_labor_cost_overtime.xml
create mode 100644 netforce_clinic/models/report_labor_cost_overtime.py
create mode 100644 netforce_clinic/reports/report_labor_cost_daily.xlsx
create mode 100644 netforce_clinic/reports/report_labor_cost_overtime.xlsx
create mode 100644 netforce_clinic/templates/report_labor_cost_overtime.hbs
diff --git a/netforce_clinic/actions/clinic_report_labor_cost_overtime.xml b/netforce_clinic/actions/clinic_report_labor_cost_overtime.xml
new file mode 100644
index 0000000..d8c79b3
--- /dev/null
+++ b/netforce_clinic/actions/clinic_report_labor_cost_overtime.xml
@@ -0,0 +1,8 @@
+
+ Report Labor Cost Overtime
+ report
+ clinic.report.labor.cost.overtime
+ report_labor_cost_overtime
+ report_labor_cost_overtime
+ account_menu
+
diff --git a/netforce_clinic/layouts/clinic_account_menu.xml b/netforce_clinic/layouts/clinic_account_menu.xml
index 7c6c8d6..5bba9fc 100644
--- a/netforce_clinic/layouts/clinic_account_menu.xml
+++ b/netforce_clinic/layouts/clinic_account_menu.xml
@@ -11,6 +11,7 @@
+
diff --git a/netforce_clinic/layouts/clinic_account_setting.xml b/netforce_clinic/layouts/clinic_account_setting.xml
index c4cb98f..2c03d64 100644
--- a/netforce_clinic/layouts/clinic_account_setting.xml
+++ b/netforce_clinic/layouts/clinic_account_setting.xml
@@ -43,5 +43,11 @@
+
+
+
+
+
+
diff --git a/netforce_clinic/layouts/clinic_labor_cost_form.xml b/netforce_clinic/layouts/clinic_labor_cost_form.xml
index 2ac8626..125fb5d 100644
--- a/netforce_clinic/layouts/clinic_labor_cost_form.xml
+++ b/netforce_clinic/layouts/clinic_labor_cost_form.xml
@@ -47,6 +47,7 @@
+
diff --git a/netforce_clinic/layouts/clinic_menu.xml b/netforce_clinic/layouts/clinic_menu.xml
index cedf990..65f59eb 100644
--- a/netforce_clinic/layouts/clinic_menu.xml
+++ b/netforce_clinic/layouts/clinic_menu.xml
@@ -1,7 +1,7 @@
diff --git a/netforce_clinic/layouts/clinic_staff_rotate_form.xml b/netforce_clinic/layouts/clinic_staff_rotate_form.xml
index d2a64ac..b42972a 100644
--- a/netforce_clinic/layouts/clinic_staff_rotate_form.xml
+++ b/netforce_clinic/layouts/clinic_staff_rotate_form.xml
@@ -7,6 +7,7 @@
+
diff --git a/netforce_clinic/models/__init__.py b/netforce_clinic/models/__init__.py
index e67173d..8b95118 100644
--- a/netforce_clinic/models/__init__.py
+++ b/netforce_clinic/models/__init__.py
@@ -78,6 +78,7 @@ from . import report_payment_matching
from . import report_labor_cost_summary
from . import report_labor_cost_detail
from . import report_labor_cost_daily
+from . import report_labor_cost_overtime
from . import branch
from . import period
from . import period_line
diff --git a/netforce_clinic/models/hd_case.py b/netforce_clinic/models/hd_case.py
index 933b077..4918e66 100644
--- a/netforce_clinic/models/hd_case.py
+++ b/netforce_clinic/models/hd_case.py
@@ -1020,7 +1020,7 @@ class HDCase(Model):
"membrane_type": pop.membrane_type,
}
else:
- dlz_vals=get_model("clinic.dialyzer").default_get()
+ dlz_vals=get_model("clinic.dialyzer").default_get(context=context)
dlz_vals['patient_id']=obj.patient_id.id
dlz_vals['company_id']=dlz_vals['company_id'][0]
product_name=dlz_vals['product_id'][1]
diff --git a/netforce_clinic/models/labor_cost.py b/netforce_clinic/models/labor_cost.py
index 371a037..2ccb51d 100644
--- a/netforce_clinic/models/labor_cost.py
+++ b/netforce_clinic/models/labor_cost.py
@@ -90,10 +90,16 @@ class LaborCost(Model):
'cycle_id': fields.Many2One('clinic.cycle',"Cycle", function="_get_store",function_multi=True,store=True,search=True),
'department_id': fields.Many2One('clinic.department',"Department", function="_get_store",function_multi=True,store=True,search=True),
'branch_id': fields.Many2One('clinic.branch',"Branch", function="_get_store",function_multi=True,store=True,search=True),
+ 'cost_per_case': fields.Float("Cost Per Case"), # for doctor
}
+
+ def _get_cost_per_case(self,context={}):
+ st=get_model("clinic.setting").browse(1)
+ return st.cost_per_case or 0
_defaults={
'company_id': lambda *a: get_active_company(),
+ 'cost_per_case': _get_cost_per_case,
}
def compute(self,ids,context={}):
@@ -279,7 +285,7 @@ class LaborCost(Model):
# cost's doctor
st=get_model('clinic.setting').browse(1)
- cost_per_case=st.cost_per_case or 0
+ cost_per_case=obj.cost_per_case or st.cost_per_case or 0
staff_total={}
for hd_case in item.hd_cases:
staffs=hd_case.staffs
diff --git a/netforce_clinic/models/patient.py b/netforce_clinic/models/patient.py
index d220bf4..695d28a 100644
--- a/netforce_clinic/models/patient.py
+++ b/netforce_clinic/models/patient.py
@@ -312,7 +312,7 @@ class Patient(Model):
def new_dialyzer(self,ids,context={}):
dlz_id=None
for obj in self.browse(ids):
- dlz_vals=get_model("clinic.dialyzer").default_get()
+ dlz_vals=get_model("clinic.dialyzer").default_get(context=context)
dlz_vals['patient_id']=obj.id
dlz_vals['company_id']=dlz_vals['company_id'][0]
dlz_vals['product_id']=dlz_vals['product_id'][0]
diff --git a/netforce_clinic/models/report_labor_cost_daily.py b/netforce_clinic/models/report_labor_cost_daily.py
index d8d76d6..06ace9e 100644
--- a/netforce_clinic/models/report_labor_cost_daily.py
+++ b/netforce_clinic/models/report_labor_cost_daily.py
@@ -11,7 +11,7 @@ class ReportLaborCostDaily(Model):
_fields={
"date": fields.Date("Date"),
- "type": fields.Selection([["doctor","Doctor"],["nurse","Nurse"],["staff","Staff"]],"Type"),
+ "staff_type": fields.Selection([["doctor","Doctor"],["nurse","Nurse"],["staff","Staff"]],"Type"),
'staff_id': fields.Many2One("clinic.staff","Staff"),
'department_id': fields.Many2One("clinic.department",'Department'),
}
@@ -26,7 +26,7 @@ class ReportLaborCostDaily(Model):
department_id=int(defaults.get('department_id', "0"))
res={
'date': date,
- 'type': staff_type,
+ 'staff_type': staff_type,
'staff_id': staff_id and staff_id or None,
'department_id': department_id and department_id or None,
}
@@ -36,7 +36,7 @@ class ReportLaborCostDaily(Model):
def get_report_data(self,ids,context={}):
company_id=get_active_company()
comp=get_model("company").browse(company_id)
- defaults=context.get("defaults")
+ defaults=self.default_get(context=context)
date=defaults.get("date")
staff_id=defaults.get("staff_id")
staff_type=defaults.get("staff_type")
@@ -52,6 +52,7 @@ class ReportLaborCostDaily(Model):
dom.append(['date','<=',date])
# prevent to load more
if not staff_id:
+ print("not staff_id")
return {}
if staff_id:
dom.append(['staff_id','=',staff_id])
@@ -59,6 +60,7 @@ class ReportLaborCostDaily(Model):
dom.append(['type','=',staff_type])
if dpt_id:
dom.append(['labor_cost_id.cycle_item_id.department_id','=',dpt_id])
+ print('dom ', dom)
lines=[]
no=1
for line in get_model("clinic.labor.cost.line").search_browse(dom):
@@ -90,6 +92,7 @@ class ReportLaborCostDaily(Model):
})
no+=1
elif staff_type=='nurse':
+ print("nurse ")
for hdcase in citem.hd_cases:
doctor=hdcase.doctor_id
pt_type=hdcase.patient_type_id
diff --git a/netforce_clinic/models/report_labor_cost_detail.py b/netforce_clinic/models/report_labor_cost_detail.py
index 1b714f5..157505a 100644
--- a/netforce_clinic/models/report_labor_cost_detail.py
+++ b/netforce_clinic/models/report_labor_cost_detail.py
@@ -179,7 +179,12 @@ class ReportLaborCostDetail(Model):
'amt_text': 'จำนวนเงิน',
})
comp_span=(len(dpts)*2)+1
+ staff_name=''
+ if staff_id:
+ staff=get_model("clinic.staff").browse(staff_id)
+ staff_name=staff.name or ''
data={
+ 'staff_name': staff_name,
'date_from': date_from,
'date_to': date_to,
'dpts': dpts,
diff --git a/netforce_clinic/models/report_labor_cost_overtime.py b/netforce_clinic/models/report_labor_cost_overtime.py
new file mode 100644
index 0000000..d7c7c39
--- /dev/null
+++ b/netforce_clinic/models/report_labor_cost_overtime.py
@@ -0,0 +1,171 @@
+import time
+from calendar import monthrange
+
+from netforce.model import Model,fields,get_model
+from netforce.access import get_active_company
+
+class ReportLaborCostOverTime(Model):
+ _name="clinic.report.labor.cost.overtime"
+ _string="Report Labor Cost Overtime"
+ _transient=True
+
+ _fields={
+ "date": fields.Date("Month"),
+ "date_from": fields.Date("From", required=True),
+ "date_to": fields.Date("To", required=True),
+ 'staff_id': fields.Many2One("clinic.staff","Staff"),
+ "type": fields.Selection([["nurse","Nurse"]],"Type"),
+ 'department_id': fields.Many2One("clinic.department","Department"),
+ 'level_id': fields.Many2One("clinic.staff.level","Level"),
+ 'categ_id': fields.Many2One("clinic.staff.categ","Category"),
+ }
+
+ def _get_date_from(self,context={}):
+ year,month=time.strftime("%Y-%m").split("-")
+ return '%s-%s-01'%(year,month)
+
+ def _get_date_to(self,context={}):
+ year,month,day=time.strftime("%Y-%m-%d").split("-")
+ weekday, total_day=monthrange(int(year), int(month))
+ return "%s-%s-%s"%(year,month,total_day)
+
+ def _get_helper_categ(self,ids,context={}):
+ st=get_model("clinic.setting").browse(1)
+ return st.helper_categ_id.id
+
+ _defaults={
+ 'date': lambda *a: time.strftime("%Y-%m-%d"),
+ 'date_from': _get_date_from,
+ 'date_to': _get_date_to,
+ 'type': 'nurse',
+ 'categ_id': _get_helper_categ,
+ }
+
+ def get_report_data(self,ids,context={}):
+ setting=get_model("clinic.setting").browse(1)
+ base_salary_day=setting.base_salary_day or 1
+ res=get_model("clinic.report.labor.cost.overtime").default_get(context=context)
+ date_from=res['date_from']
+ date_to=res['date_to']
+ if res.get("categ_id"):
+ categ_id=res['categ_id'][0]
+ staff_id=None
+ level_id=None
+ dom=[]
+ if ids:
+ obj=self.browse(ids)[0]
+ date_from=obj.date_from
+ date_to=obj.date_to
+ staff_id=obj.staff_id.id
+ level_id=obj.level_id.id
+ categ_id=obj.categ_id.id
+ dom.append(['date','>=',date_from])
+ dom.append(['date','<=',date_to])
+ dom.append(['staff_id.type','=','nurse'])
+ if staff_id:
+ dom.append(['staff_id','=',staff_id])
+ if categ_id:
+ dom.append(['staff_id.categ_id','=',categ_id])
+ print("dom ", dom)
+ staffs={}
+ for line in get_model("clinic.labor.cost.line").search_browse(dom):
+ #lcost=line.labor_cost_id
+ #citem=lcost.cycle_item_id
+ amt=line.amount or 0
+ staff=line.staff_id
+ categ_name=''
+ categ_id=None
+ categ=staff.categ_id
+ if level_id and staff.level_id.id!=level_id:
+ continue
+ if categ:
+ categ_id=categ.id
+ categ_name=categ.name or ""
+ wage=staff.wage or 0
+ #wage_per_day=wage/base_salary_day
+ if not staffs.get(staff.name):
+ staffs[staff.name]={
+ 'number': staff.number or '',
+ 'staff_id': staff.id,
+ 'staff_type': staff.type,
+ 'staff_name': staff.name or '',
+ 'staff_level': staff.level_id.name,
+ 'staff_wage': wage or 0,
+ 'categ_name': categ_name,
+ 'categ_id': categ_id,
+ 'max_cycle': staff.max_cycle or 0,
+ 'ot_per_cycle': staff.ot_per_cycle or 0,
+ 'cycle_qty':0,
+ 'amount': 0,
+ }
+ staffs[staff.name]['amount']+=amt # amount from formular
+ staffs[staff.name]['cycle_qty']+=1 # number of cycle
+ lines=[]
+ snames=sorted(staffs.keys()) #sort by staff name
+ no=1
+ for sname in snames:
+ vals=staffs[sname]
+ cycle_qty=vals.get("cycle_qty",0)
+ max_cycle=vals.get("max_cycle",0)
+ ot_qty=cycle_qty-max_cycle
+ #prevent to show
+ if ot_qty < 1:
+ ot_qty=0
+ ot_per_cycle=vals.get("ot_per_cycle",0)
+ ot_amount=ot_per_cycle*ot_qty
+ net_pay=(vals['staff_wage'] or 0)+ot_amount
+ net_diff=(vals['amount'] or 0)-net_pay
+ vals.update({
+ 'no': no,
+ 'ot_qty': ot_qty,
+ 'ot_amount': ot_amount,
+ 'net_pay': net_pay,
+ 'net_diff': net_diff,
+ })
+ lines.append(vals)
+ no+=1
+
+ company_id=get_active_company()
+ comp=get_model("company").browse(company_id)
+ data={
+ 'date_from': date_from,
+ 'date_to': date_to,
+ 'comp_name': comp.name or 0,
+ 'lines': lines,
+ 'total_amount':0,
+ 'total_max_cycle':0,
+ 'total_cycle_qty':0,
+ 'total_ot_qty':0,
+ 'total_ot_per_cycle':0,
+ 'total_ot_amount':0,
+ 'total_wage': 0,
+ 'total_net_pay': 0,
+ 'total_net_diff': 0,
+ }
+ for line in lines:
+ data['total_amount']+=line['amount'] or 0
+ data['total_max_cycle']+=line['max_cycle'] or 0
+ data['total_cycle_qty']+=line['cycle_qty'] or 0
+ data['total_ot_qty']+=line['ot_qty'] or 0
+ data['total_ot_per_cycle']+=line['ot_per_cycle'] or 0
+ data['total_ot_amount']+=line['ot_amount'] or 0
+ data['total_wage']+=line['staff_wage'] or 0
+ data['total_net_pay']+=line['net_pay'] or 0
+ data['total_net_diff']+=line['net_diff'] or 0
+ return data
+
+ def onchange_date(self,context={}):
+ data=context['data']
+ date=data['date']
+ year,month,day=date.split("-")
+ weekday, total_day=monthrange(int(year), int(month))
+ data['date_from']="%s-%s-01"%(year,month)
+ data['date_to']="%s-%s-%s"%(year,month,total_day)
+ return data
+
+ def onchange_type(self,context={}):
+ data=context['data']
+ data['staff_id']=None
+ return data
+
+ReportLaborCostOverTime.register()
diff --git a/netforce_clinic/models/report_labor_cost_summary.py b/netforce_clinic/models/report_labor_cost_summary.py
index 8d01395..c2c4a82 100644
--- a/netforce_clinic/models/report_labor_cost_summary.py
+++ b/netforce_clinic/models/report_labor_cost_summary.py
@@ -14,11 +14,10 @@ class ReportLaborCostSummary(Model):
"date_from": fields.Date("From", required=True),
"date_to": fields.Date("To", required=True),
'staff_id': fields.Many2One("clinic.staff","Staff"),
- "type": fields.Selection([["doctor","Doctor"],["nurse","Nurse"],["staff","Staff"]],"Type"),
+ "staff_type": fields.Selection([["doctor","Doctor"],["nurse","Nurse"],["staff","Staff"]],"Type"),
'department_id': fields.Many2One("clinic.department","Department"),
'level_id': fields.Many2One("clinic.staff.level","Level"),
'categ_id': fields.Many2One("clinic.staff.categ","Category"),
- 'branch_id': fields.Many2One("clinic.branch","Branch"),
'only_value': fields.Boolean("Only Amount"),
}
@@ -31,20 +30,29 @@ class ReportLaborCostSummary(Model):
weekday, total_day=monthrange(int(year), int(month))
return "%s-%s-%s"%(year,month,total_day)
- _defaults={
- 'date': lambda *a: time.strftime("%Y-%m-%d"),
- 'date_from': _get_date_from,
- 'date_to': _get_date_to,
- 'only_value': True,
- 'type': 'nurse',
- }
+ def default_get(self,field_names=None,context={},**kw):
+ defaults=context.get("defaults",{})
+ date_from=defaults.get("date", self._get_date_from())
+ date_to=defaults.get("date", self._get_date_to())
+ staff_type=defaults.get("staff_type","doctor")
+ staff_id=int(defaults.get('staff_id', "0"))
+ print('defaults ', defaults)
+ res={
+ 'date': time.strftime("%Y-%m-%d"),
+ 'date_from': date_from,
+ 'date_to': date_to,
+ 'staff_type': staff_type,
+ 'staff_id': staff_id and staff_id or None,
+ 'only_value': True,
+ }
+ return res
def get_report_data(self,ids,context={}):
- res=get_model("clinic.report.labor.cost.summary").default_get()
+ res=get_model("clinic.report.labor.cost.summary").default_get(context=context)
date_from=res['date_from']
date_to=res['date_to']
- staff_id=None
- staff_type=res['type']
+ staff_id=res['staff_id']
+ staff_type=res['staff_type']
only_value=res['only_value']
level_id=None
categ_id=None
@@ -78,6 +86,8 @@ class ReportLaborCostSummary(Model):
categ_name=''
categ_id=None
categ=staff.categ_id
+ if level_id and staff.level_id.id!=level_id:
+ continue
if categ:
categ_id=categ.id
categ_name=categ.name or ""
diff --git a/netforce_clinic/models/report_medical_summary.py b/netforce_clinic/models/report_medical_summary.py
index 25f2303..e90af73 100644
--- a/netforce_clinic/models/report_medical_summary.py
+++ b/netforce_clinic/models/report_medical_summary.py
@@ -72,7 +72,7 @@ class ReportMedicalSummary(Model):
prod_categ_id=None
branch_id=None
department_id=None
- res=get_model("clinic.report.medical.summary").default_get()
+ res=get_model("clinic.report.medical.summary").default_get(context=context)
if res:
if res.get("prod_categ_id"):
prod_categ_id=res.get("prod_categ_id")[0]
diff --git a/netforce_clinic/models/setting.py b/netforce_clinic/models/setting.py
index fb502e5..16c3dbd 100644
--- a/netforce_clinic/models/setting.py
+++ b/netforce_clinic/models/setting.py
@@ -34,6 +34,8 @@ class ClinicSetting(Model):
"cash_account_id": fields.Many2One("account.account","Cash Account",multi_company=True),
"income_account_id": fields.Many2One("account.account","Income Account",multi_company=True),
"import_account_id": fields.Many2One("account.account","Import Account",multi_company=True),
+ 'helper_categ_id': fields.Many2One("clinic.staff.categ","Helper Category"),
+ 'base_salary_day': fields.Float("Base Salary Day"),
}
_defaults={
diff --git a/netforce_clinic/models/staff.py b/netforce_clinic/models/staff.py
index b7664c0..e5deb04 100644
--- a/netforce_clinic/models/staff.py
+++ b/netforce_clinic/models/staff.py
@@ -47,9 +47,11 @@ class Staff(Model):
for rotate in obj.rotations:
wage=rotate.wage
max_cycle=rotate.max_cycle
+ ot_per_cycle=rotate.ot_per_cycle or 0
res[obj.id]={
'wage': wage,
'max_cycle': max_cycle,
+ 'ot_per_cycle': ot_per_cycle,
}
return res
@@ -113,6 +115,7 @@ class Staff(Model):
'date': fields.Date("Register Date"),
'wage': fields.Float("Wage", function="_get_base",function_multi=True),
'max_cycle': fields.Integer("Max Cycle", function="_get_base",function_multi=True),
+ 'ot_per_cycle': fields.Integer("OT Per Cycle", function="_get_base",function_multi=True),
'check_max_cycle': fields.Boolean("Check Max Cycle"),
'hire_date': fields.Date("Hire Date"),
'resign_date': fields.Date("Resign Date"),
diff --git a/netforce_clinic/models/staff_rotation.py b/netforce_clinic/models/staff_rotation.py
index 555728e..aba30e0 100644
--- a/netforce_clinic/models/staff_rotation.py
+++ b/netforce_clinic/models/staff_rotation.py
@@ -15,6 +15,7 @@ class StaffRotation(Model):
"resign_date": fields.Date("Resign Date", search=True),
"wage": fields.Float("Wage"),
"max_cycle": fields.Integer("Max Cycle"),
+ "ot_per_cycle": fields.Float("OT Per Cycle"),
"note": fields.Text("Note"),
'company_id': fields.Many2One("company","Company"),
}
diff --git a/netforce_clinic/reports/report_labor_cost_daily.xlsx b/netforce_clinic/reports/report_labor_cost_daily.xlsx
new file mode 100644
index 0000000000000000000000000000000000000000..c5d0fc0e54afa9bd027dc6170257588b4d7fd0c5
GIT binary patch
literal 6960
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
B=Ewj5
diff --git a/netforce_clinic/reports/report_labor_cost_overtime.xlsx b/netforce_clinic/reports/report_labor_cost_overtime.xlsx
new file mode 100644
index 0000000000000000000000000000000000000000..7b7211ea5f8bcbb0ccc98daea03833eaff29dc62
GIT binary patch
literal 7270
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
+
+
+
+ ลำดับ |
+ รหัส |
+ ชื่อ-สกุล |
+ ระดับ |
+ รวมยอด |
+ ฐานวันที่ทำงาน (รอบ) |
+ ทำงานจริง (รอบ) |
+ OT ทั้งหมด |
+ OT ต่อรอบ |
+ รวม OT |
+ เงินเดือน |
+ จ่ายจริง |
+ ผลต่าง |
+
+
+
+ {{#each lines }}
+
+ {{no}}
+ | {{number}}
+ |
+ {{view "link" string=staff_name action="clinic_staff" action_options="mode=form" active_id=staff_id}}
+ |
+ {{staff_level}} |
+
+ {{currency amount zero=""}}
+ |
+ {{max_cycle}}
+ | {{cycle_qty}}
+ | {{ot_qty}}
+ | {{currency ot_per_cycle zero=""}}
+ | {{currency ot_amount zero=""}}
+ | {{currency staff_wage zero=""}}
+ | {{currency net_pay zero=""}}
+ | {{currency net_diff zero=""}}
+ |
+ {{/each}}
+
+
+ |
+ |
+ |
+ รวม |
+ {{currency total_amount zero=""}} |
+ {{total_max_cycle}} |
+ {{total_cycle_qty}} |
+ {{total_ot_qty}} |
+ {{currency total_ot_per_cycle zero=""}} |
+ {{currency total_ot_amount zero=""}} |
+ {{currency total_wage zero=""}} |
+ {{currency total_net_pay zero=""}} |
+ {{currency total_net_diff zero=""}} |
+ |
+
+