labor cost
parent
c02a2b4a98
commit
2aa67e0271
|
@ -3,6 +3,9 @@
|
||||||
<button string="Options" dropdown="1">
|
<button string="Options" dropdown="1">
|
||||||
</button>
|
</button>
|
||||||
</head>
|
</head>
|
||||||
|
<group form_layout="stacked">
|
||||||
|
<field name="cycle_item_id" span="3"/>
|
||||||
|
</group>
|
||||||
<tabs>
|
<tabs>
|
||||||
<tab string="Computation">
|
<tab string="Computation">
|
||||||
<group form_layout="stacked">
|
<group form_layout="stacked">
|
||||||
|
@ -10,7 +13,6 @@
|
||||||
<field name="var_pt" span="3"/>
|
<field name="var_pt" span="3"/>
|
||||||
<field name="var_ptx" span="3"/>
|
<field name="var_ptx" span="3"/>
|
||||||
<field name="manual" span="3" help="Help"/>
|
<field name="manual" span="3" help="Help"/>
|
||||||
<field name="cycle_item_id" span="3"/>
|
|
||||||
<field name="formulars" nolabel="1">
|
<field name="formulars" nolabel="1">
|
||||||
<list colors='{"red":[["state","=","fail"]]}'>
|
<list colors='{"red":[["state","=","fail"]]}'>
|
||||||
<field name="level_id"/>
|
<field name="level_id"/>
|
||||||
|
@ -34,18 +36,23 @@
|
||||||
<tab string="Cost">
|
<tab string="Cost">
|
||||||
<field name="lines" nolabel="1">
|
<field name="lines" nolabel="1">
|
||||||
<list>
|
<list>
|
||||||
|
<field name="cycle_id"/>
|
||||||
<field name="staff_id"/>
|
<field name="staff_id"/>
|
||||||
<field name="level_id"/>
|
<field name="level_id"/>
|
||||||
<field name="qty"/>
|
<field name="qty" onchange="onchange_cost_line"/>
|
||||||
|
<field name="rate" onchange="onchange_cost_line"/>
|
||||||
<field name="amount"/>
|
<field name="amount"/>
|
||||||
</list>
|
</list>
|
||||||
<form>
|
<form>
|
||||||
|
<field name="cycle_id"/>
|
||||||
<field name="staff_id"/>
|
<field name="staff_id"/>
|
||||||
<field name="level_id"/>
|
<field name="level_id"/>
|
||||||
<field name="qty"/>
|
<field name="qty"/>
|
||||||
|
<field name="rate"/>
|
||||||
<field name="amount"/>
|
<field name="amount"/>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
|
<field name="total_cost" span="3" offset="9"/>
|
||||||
</tab>
|
</tab>
|
||||||
</tabs>
|
</tabs>
|
||||||
<foot>
|
<foot>
|
||||||
|
|
|
@ -103,140 +103,16 @@ class CycleItem(Model):
|
||||||
if lc:
|
if lc:
|
||||||
lc.compute()
|
lc.compute()
|
||||||
obj.write({
|
obj.write({
|
||||||
'state': 'validate',
|
'state': 'validated',
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
levels={}
|
|
||||||
for line in obj.lines:
|
|
||||||
level=line.level_id
|
|
||||||
levels[level.id]={
|
|
||||||
'amount': line.amount or 0,
|
|
||||||
'qty': line.qty,
|
|
||||||
'level_id': level.id,
|
|
||||||
}
|
|
||||||
|
|
||||||
lines=[]
|
|
||||||
# cost's nurses
|
|
||||||
for nr in obj.nurses:
|
|
||||||
nurse=nr.nurse_id
|
|
||||||
level=nr.level_id
|
|
||||||
vals=levels.get(level.id)
|
|
||||||
rate,amt,qty=0.0,0.0,0
|
|
||||||
level_id=level.id
|
|
||||||
if vals:
|
|
||||||
level_id=vals['level_id']
|
|
||||||
amt=vals['amount']
|
|
||||||
qty=vals['qty']
|
|
||||||
if qty:
|
|
||||||
rate=amt/qty
|
|
||||||
lines.append(('create',{
|
|
||||||
'cycle_id': obj.cycle_id.id,
|
|
||||||
'staff_id': nurse.id,
|
|
||||||
'level_id': level_id,
|
|
||||||
'rate': rate,
|
|
||||||
'type': 'nurse',
|
|
||||||
'qty': 1,
|
|
||||||
}))
|
|
||||||
|
|
||||||
# cost's doctor
|
|
||||||
st=get_model('clinic.setting').browse(1)
|
|
||||||
cost_per_case=st.cost_per_case or 0
|
|
||||||
staff_total={}
|
|
||||||
for hd_case in obj.hd_cases:
|
|
||||||
staffs=hd_case.staffs
|
|
||||||
for ps in staffs:
|
|
||||||
staff=ps.staff_id
|
|
||||||
if not staff:
|
|
||||||
continue
|
|
||||||
base=staff.base
|
|
||||||
if not base:
|
|
||||||
base=cost_per_case
|
|
||||||
if not staff_total.get(staff.id):
|
|
||||||
staff_total[staff.id]={
|
|
||||||
'base': 0,
|
|
||||||
'level_id': staff.level_id.id,
|
|
||||||
'type': ps.type,
|
|
||||||
'qty': 0,
|
|
||||||
}
|
|
||||||
staff_total[staff.id]['base']=base
|
|
||||||
staff_total[staff.id]['qty']+=1
|
|
||||||
|
|
||||||
for doctor_id, value in staff_total.items():
|
|
||||||
base=value['base']
|
|
||||||
type=value['type']
|
|
||||||
qty=value['qty']
|
|
||||||
level_id=value['level_id']
|
|
||||||
lines.append(('create',{
|
|
||||||
'cycle_id': obj.cycle_id.id,
|
|
||||||
'staff_id': doctor_id,
|
|
||||||
'level_id': level_id,
|
|
||||||
'rate': base,
|
|
||||||
'qty': qty,
|
|
||||||
'type': type,
|
|
||||||
}))
|
|
||||||
|
|
||||||
cycle_daily=obj.cycle_daily_id
|
|
||||||
# clear cost line
|
|
||||||
for line in cycle_daily.lines:
|
|
||||||
cycle=line.cycle_id
|
|
||||||
if obj.cycle_id.id==cycle.id: # only own cycle
|
|
||||||
line.delete()
|
|
||||||
|
|
||||||
# group staff and cycle date
|
|
||||||
glines={}
|
|
||||||
for line in lines:
|
|
||||||
mode,vals=line
|
|
||||||
cycle_id=vals['cycle_id']
|
|
||||||
staff_id=vals['staff_id']
|
|
||||||
#amount=vals['amount'] or 0
|
|
||||||
rate=vals['rate'] or 0
|
|
||||||
qty=vals['qty'] or 0
|
|
||||||
amount=qty*rate
|
|
||||||
key=(cycle_id,staff_id)
|
|
||||||
if not key in glines.keys():
|
|
||||||
glines[key]={
|
|
||||||
'amount': amount,
|
|
||||||
'type': vals['type'],
|
|
||||||
'level_id': vals['level_id'],
|
|
||||||
'rate': rate,
|
|
||||||
'qty': qty,
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
glines[key]['amount']+=amount
|
|
||||||
glines[key]['qty']+=qty
|
|
||||||
|
|
||||||
lines=[]
|
|
||||||
for key,vals in glines.items():
|
|
||||||
cycle_id,staff_id=key
|
|
||||||
line={
|
|
||||||
'cycle_id': cycle_id,
|
|
||||||
'staff_id': staff_id,
|
|
||||||
'date': obj.date,
|
|
||||||
}
|
|
||||||
line.update(vals)
|
|
||||||
lines.append(('create',line))
|
|
||||||
|
|
||||||
# call from outside
|
|
||||||
if context.get('called'):
|
|
||||||
return lines
|
|
||||||
|
|
||||||
cycle_daily.write({
|
|
||||||
'lines': lines,
|
|
||||||
})
|
|
||||||
|
|
||||||
obj.write({
|
|
||||||
'state': 'done',
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'next': {
|
'next': {
|
||||||
'name': 'clinic_cycle_daily',
|
'name': 'clinic_cycle_item',
|
||||||
'mode': 'form',
|
'mode': 'form',
|
||||||
'active_id': cycle_daily.id,
|
'active_id': obj.id,
|
||||||
},
|
},
|
||||||
'flash': 'Cycle Item has been validated, please see the detail of cost below.',
|
'flash': 'Cycle Item has been validated.',
|
||||||
}
|
}
|
||||||
|
|
||||||
def to_draft(self,ids,context={}):
|
def to_draft(self,ids,context={}):
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from netforce.model import Model, fields, get_model
|
from netforce.model import Model, fields, get_model
|
||||||
|
from netforce.utils import get_data_path
|
||||||
|
|
||||||
class LaborCost(Model):
|
class LaborCost(Model):
|
||||||
_name="clinic.labor.cost"
|
_name="clinic.labor.cost"
|
||||||
|
@ -13,16 +14,21 @@ class LaborCost(Model):
|
||||||
total_case=len(hd_cases)
|
total_case=len(hd_cases)
|
||||||
total_a,total_b=0,0
|
total_a,total_b=0,0
|
||||||
total=0.0
|
total=0.0
|
||||||
for line in obj.lines:
|
for fline in obj.formulars:
|
||||||
total+=line.amount or 0
|
total+=fline.amount or 0
|
||||||
total_a+=line.var_a or 0
|
total_a+=fline.var_a or 0
|
||||||
total_b+=line.var_b or 0
|
total_b+=fline.var_b or 0
|
||||||
var_ptx=total_case*(obj.var_k or 0)
|
var_ptx=total_case*(obj.var_k or 0)
|
||||||
var_fml1='PTxK=%sX%s'%(total_a,total_b)
|
var_fml1='PTxK=%sX%s'%(total_a,total_b)
|
||||||
total_bstr=total_b < 0 and "+%s"%(abs(total_b)) or "-%s"%total_b
|
total_bstr=total_b < 0 and "+%s"%(abs(total_b)) or "-%s"%total_b
|
||||||
var_x=0.0
|
var_x=0.0
|
||||||
if total_a:
|
if total_a:
|
||||||
var_x=eval('(%s%s)/%s'%(var_ptx,total_bstr,total_a))
|
var_x=eval('(%s%s)/%s'%(var_ptx,total_bstr,total_a))
|
||||||
|
|
||||||
|
total_cost=0.0
|
||||||
|
for line in obj.lines:
|
||||||
|
total_cost+=line.amount or 0.0
|
||||||
|
|
||||||
res[obj.id]={
|
res[obj.id]={
|
||||||
'var_pt': total_case,
|
'var_pt': total_case,
|
||||||
'var_ptx': total_case*(obj.var_k or 0),
|
'var_ptx': total_case*(obj.var_k or 0),
|
||||||
|
@ -31,7 +37,9 @@ class LaborCost(Model):
|
||||||
'var_fml3': '(%s%s)/%s'%(var_ptx,total_bstr,total_a),
|
'var_fml3': '(%s%s)/%s'%(var_ptx,total_bstr,total_a),
|
||||||
'var_x': round(var_x,2),
|
'var_x': round(var_x,2),
|
||||||
'total': total,
|
'total': total,
|
||||||
|
'total_cost': total_cost,
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
_fields={
|
_fields={
|
||||||
|
@ -44,6 +52,7 @@ class LaborCost(Model):
|
||||||
'var_fml3': fields.Char("X:",function="_get_all",function_multi=True),
|
'var_fml3': fields.Char("X:",function="_get_all",function_multi=True),
|
||||||
'var_x': fields.Char("X:",function="_get_all",function_multi=True),
|
'var_x': fields.Char("X:",function="_get_all",function_multi=True),
|
||||||
'total': fields.Float("Total",function="_get_all",function_multi=True),
|
'total': fields.Float("Total",function="_get_all",function_multi=True),
|
||||||
|
'total_cost': fields.Float("Total",function="_get_all",function_multi=True),
|
||||||
'manual': fields.Boolean("Manual"),
|
'manual': fields.Boolean("Manual"),
|
||||||
"formulars": fields.One2Many("clinic.labor.cost.formular", "labor_cost_id", "Formulars"),
|
"formulars": fields.One2Many("clinic.labor.cost.formular", "labor_cost_id", "Formulars"),
|
||||||
"staffs": fields.One2Many("clinic.labor.cost.staff", "labor_cost_id", "Staffs"),
|
"staffs": fields.One2Many("clinic.labor.cost.staff", "labor_cost_id", "Staffs"),
|
||||||
|
@ -174,6 +183,7 @@ class LaborCost(Model):
|
||||||
'formulars': formulars,
|
'formulars': formulars,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
levels={}
|
||||||
if obj.manual:
|
if obj.manual:
|
||||||
for fline in obj.formulars:
|
for fline in obj.formulars:
|
||||||
fml=(fline.formular or "").replace("X","*%s")
|
fml=(fline.formular or "").replace("X","*%s")
|
||||||
|
@ -185,6 +195,125 @@ class LaborCost(Model):
|
||||||
'amount': amt,
|
'amount': amt,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
level=fline.level_id
|
||||||
|
levels[level.id]={
|
||||||
|
'amount': amt or 0.0,
|
||||||
|
'qty': fline.qty or 0,
|
||||||
|
'level_id': level.id,
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
for fline in formulars:
|
||||||
|
vals=fline[1]
|
||||||
|
level_id=vals['level_id']
|
||||||
|
levels[level_id]={
|
||||||
|
'amount': vals['amount'] or 0.0,
|
||||||
|
'qty': vals['qty'] or 0,
|
||||||
|
'level_id': level_id,
|
||||||
|
}
|
||||||
|
|
||||||
|
#TODO UPDATE COST : like cycle daily
|
||||||
|
item=obj.cycle_item_id
|
||||||
|
lines=[]
|
||||||
|
# cost's nurses
|
||||||
|
for nr in item.nurses:
|
||||||
|
nurse=nr.nurse_id
|
||||||
|
level=nr.level_id
|
||||||
|
vals=levels.get(level.id)
|
||||||
|
rate,amt,qty=0.0,0.0,0
|
||||||
|
level_id=level.id
|
||||||
|
if vals:
|
||||||
|
level_id=vals['level_id']
|
||||||
|
amt=vals['amount']
|
||||||
|
qty=vals['qty']
|
||||||
|
if qty:
|
||||||
|
rate=amt/qty
|
||||||
|
lines.append(('create',{
|
||||||
|
'cycle_id': item.cycle_id.id,
|
||||||
|
'staff_id': nurse.id,
|
||||||
|
'level_id': level_id,
|
||||||
|
'rate': rate,
|
||||||
|
'type': 'nurse',
|
||||||
|
'qty': 1,
|
||||||
|
}))
|
||||||
|
|
||||||
|
# cost's doctor
|
||||||
|
st=get_model('clinic.setting').browse(1)
|
||||||
|
cost_per_case=st.cost_per_case or 0
|
||||||
|
staff_total={}
|
||||||
|
for hd_case in item.hd_cases:
|
||||||
|
staffs=hd_case.staffs
|
||||||
|
for ps in staffs:
|
||||||
|
staff=ps.staff_id
|
||||||
|
if not staff:
|
||||||
|
continue
|
||||||
|
base=staff.base
|
||||||
|
if not base:
|
||||||
|
base=cost_per_case
|
||||||
|
if not staff_total.get(staff.id):
|
||||||
|
staff_total[staff.id]={
|
||||||
|
'base': 0,
|
||||||
|
'level_id': staff.level_id.id,
|
||||||
|
'type': ps.type,
|
||||||
|
'qty': 0,
|
||||||
|
}
|
||||||
|
staff_total[staff.id]['base']=base
|
||||||
|
staff_total[staff.id]['qty']+=1
|
||||||
|
|
||||||
|
for doctor_id, value in staff_total.items():
|
||||||
|
base=value['base']
|
||||||
|
type=value['type']
|
||||||
|
qty=value['qty']
|
||||||
|
level_id=value['level_id']
|
||||||
|
lines.append(('create',{
|
||||||
|
'cycle_id': item.cycle_id.id,
|
||||||
|
'staff_id': doctor_id,
|
||||||
|
'level_id': level_id,
|
||||||
|
'rate': base,
|
||||||
|
'qty': qty,
|
||||||
|
'type': type,
|
||||||
|
}))
|
||||||
|
|
||||||
|
# clear cost line
|
||||||
|
for line in obj.lines:
|
||||||
|
line.delete()
|
||||||
|
|
||||||
|
# group staff and cycle date
|
||||||
|
glines={}
|
||||||
|
for line in lines:
|
||||||
|
mode,vals=line
|
||||||
|
cycle_id=vals['cycle_id']
|
||||||
|
staff_id=vals['staff_id']
|
||||||
|
rate=vals['rate'] or 0
|
||||||
|
qty=vals['qty'] or 0
|
||||||
|
amount=qty*rate
|
||||||
|
key=(cycle_id,staff_id)
|
||||||
|
if not key in glines.keys():
|
||||||
|
glines[key]={
|
||||||
|
'amount': amount,
|
||||||
|
'type': vals['type'],
|
||||||
|
'level_id': vals['level_id'],
|
||||||
|
'rate': rate,
|
||||||
|
'qty': qty,
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
glines[key]['amount']+=amount
|
||||||
|
glines[key]['qty']+=qty
|
||||||
|
|
||||||
|
lines=[]
|
||||||
|
for key,vals in glines.items():
|
||||||
|
cycle_id,staff_id=key
|
||||||
|
line={
|
||||||
|
'cycle_id': cycle_id,
|
||||||
|
'staff_id': staff_id,
|
||||||
|
'date': item.date,
|
||||||
|
}
|
||||||
|
line.update(vals)
|
||||||
|
lines.append(('create',line))
|
||||||
|
|
||||||
|
obj.write({
|
||||||
|
'lines': lines,
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'next': {
|
'next': {
|
||||||
'name': 'clinic_labor_cost',
|
'name': 'clinic_labor_cost',
|
||||||
|
@ -194,5 +323,26 @@ class LaborCost(Model):
|
||||||
'flash':'Compute successfully',
|
'flash':'Compute successfully',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def onchange_cost_line(self,context={}):
|
||||||
|
data=context['data']
|
||||||
|
path=context['path']
|
||||||
|
line=get_data_path(data,path,parent=True)
|
||||||
|
qty=line.get("qty",0)
|
||||||
|
rate=line.get("rate",0.0)
|
||||||
|
amt=qty*rate
|
||||||
|
line['amount']=amt
|
||||||
|
data=self.update_amt(context)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def update_amt(self,context):
|
||||||
|
total=0.0
|
||||||
|
data=context['data']
|
||||||
|
for line in data['lines']:
|
||||||
|
qty=line['qty'] or 0
|
||||||
|
rate=line['rate'] or 0.0
|
||||||
|
amt=qty*rate
|
||||||
|
total+=amt
|
||||||
|
data['total_cost']=total
|
||||||
|
return data
|
||||||
|
|
||||||
LaborCost.register()
|
LaborCost.register()
|
||||||
|
|
|
@ -10,13 +10,19 @@ class LaborCostLine(Model):
|
||||||
"labor_cost_id": fields.Many2One("clinic.labor.cost","Cycle Item",required=True),
|
"labor_cost_id": fields.Many2One("clinic.labor.cost","Cycle Item",required=True),
|
||||||
'staff_id': fields.Many2One("clinic.staff", "Staff"),
|
'staff_id': fields.Many2One("clinic.staff", "Staff"),
|
||||||
'level_id': fields.Many2One("clinic.staff.level", "Level"),
|
'level_id': fields.Many2One("clinic.staff.level", "Level"),
|
||||||
|
'cycle_id': fields.Many2One("clinic.cycle", "Cycle"),
|
||||||
'qty': fields.Integer("Qty"),
|
'qty': fields.Integer("Qty"),
|
||||||
|
'rate': fields.Float("Rate",scale=2),
|
||||||
'amount': fields.Float("Amount",scale=2),
|
'amount': fields.Float("Amount",scale=2),
|
||||||
|
'date': fields.Date("Date"),
|
||||||
|
"type": fields.Selection([('staff','Staff'),("doctor","Doctor"),('nurse','Nurse')],"Type",required=True),
|
||||||
'company_id': fields.Many2One('company','Company'),
|
'company_id': fields.Many2One('company','Company'),
|
||||||
}
|
}
|
||||||
|
|
||||||
_defaults={
|
_defaults={
|
||||||
"company_id": lambda *a: get_active_company(),
|
"company_id": lambda *a: get_active_company(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_order="cycle_id,level_id"
|
||||||
|
|
||||||
LaborCostLine.register()
|
LaborCostLine.register()
|
||||||
|
|
|
@ -171,4 +171,25 @@ class Staff(Model):
|
||||||
vals['employee_id']=emp_id
|
vals['employee_id']=emp_id
|
||||||
super().write(ids,vals,**kw)
|
super().write(ids,vals,**kw)
|
||||||
|
|
||||||
|
def name_get(self,ids,context={}):
|
||||||
|
vals=[]
|
||||||
|
for obj in self.browse(ids):
|
||||||
|
level=obj.level_id
|
||||||
|
name="%s (%s)"%(obj.name,level.name)
|
||||||
|
vals.append((obj.id,name))
|
||||||
|
return vals
|
||||||
|
|
||||||
|
def name_search(self,name,domain=None,context={},**kw):
|
||||||
|
dom=[["name","ilike","%"+name+"%"]]
|
||||||
|
if domain:
|
||||||
|
dom=[dom,domain]
|
||||||
|
ids1=self.search(dom)
|
||||||
|
# XXX need to store db
|
||||||
|
dom=[["level_id.name","ilike","%"+name+"%"]]
|
||||||
|
if domain:
|
||||||
|
dom=[dom,domain]
|
||||||
|
ids2=self.search_read(dom)
|
||||||
|
ids=list(set(ids1+ids2))
|
||||||
|
return self.name_get(ids,context=context)
|
||||||
|
|
||||||
Staff.register()
|
Staff.register()
|
||||||
|
|
Loading…
Reference in New Issue