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 0000000..c5d0fc0 Binary files /dev/null and b/netforce_clinic/reports/report_labor_cost_daily.xlsx differ diff --git a/netforce_clinic/reports/report_labor_cost_detail.xlsx b/netforce_clinic/reports/report_labor_cost_detail.xlsx index ce8adc3..fccee4c 100644 Binary files a/netforce_clinic/reports/report_labor_cost_detail.xlsx and b/netforce_clinic/reports/report_labor_cost_detail.xlsx differ 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 0000000..7b7211e Binary files /dev/null and b/netforce_clinic/reports/report_labor_cost_overtime.xlsx differ diff --git a/netforce_clinic/reports/report_labor_cost_summary.xlsx b/netforce_clinic/reports/report_labor_cost_summary.xlsx index ce8adc3..238b52a 100644 Binary files a/netforce_clinic/reports/report_labor_cost_summary.xlsx and b/netforce_clinic/reports/report_labor_cost_summary.xlsx differ diff --git a/netforce_clinic/templates/report_labor_cost_overtime.hbs b/netforce_clinic/templates/report_labor_cost_overtime.hbs new file mode 100644 index 0000000..6e9ba0f --- /dev/null +++ b/netforce_clinic/templates/report_labor_cost_overtime.hbs @@ -0,0 +1,59 @@ +

+ + + + + + + + + + + + + + + + + + + + {{#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=""}}