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_report_labor_cost_daily.xml b/netforce_clinic/layouts/clinic_report_labor_cost_daily.xml index b046b3f..6647b90 100644 --- a/netforce_clinic/layouts/clinic_report_labor_cost_daily.xml +++ b/netforce_clinic/layouts/clinic_report_labor_cost_daily.xml @@ -1,6 +1,6 @@
- + diff --git a/netforce_clinic/layouts/clinic_report_labor_cost_overtime.xml b/netforce_clinic/layouts/clinic_report_labor_cost_overtime.xml new file mode 100644 index 0000000..5edf1b6 --- /dev/null +++ b/netforce_clinic/layouts/clinic_report_labor_cost_overtime.xml @@ -0,0 +1,9 @@ +
+ + + + + + + + diff --git a/netforce_clinic/layouts/clinic_report_labor_cost_summary.xml b/netforce_clinic/layouts/clinic_report_labor_cost_summary.xml index c6227b7..70f16a2 100644 --- a/netforce_clinic/layouts/clinic_report_labor_cost_summary.xml +++ b/netforce_clinic/layouts/clinic_report_labor_cost_summary.xml @@ -2,8 +2,9 @@ - + + diff --git a/netforce_clinic/layouts/clinic_staff_form.xml b/netforce_clinic/layouts/clinic_staff_form.xml index 787eaa3..23c0b8c 100644 --- a/netforce_clinic/layouts/clinic_staff_form.xml +++ b/netforce_clinic/layouts/clinic_staff_form.xml @@ -42,7 +42,8 @@ - + + 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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

+ + + + + + + + + + + + + + + + + + + + {{#each lines }} + + + + + + {{/each}} + + + + + + + + + + + + + + + + + +
ลำดับรหัสชื่อ-สกุลระดับรวมยอดฐานวันที่ทำงาน (รอบ)ทำงานจริง (รอบ)OT ทั้งหมดOT ต่อรอบรวม OTเงินเดือนจ่ายจริงผลต่าง
{{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=""}} +
รวม{{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=""}}