labor cost
							parent
							
								
									c02a2b4a98
								
							
						
					
					
						commit
						2aa67e0271
					
				| 
						 | 
				
			
			@ -3,6 +3,9 @@
 | 
			
		|||
        <button string="Options" dropdown="1">
 | 
			
		||||
        </button>
 | 
			
		||||
    </head>
 | 
			
		||||
    <group form_layout="stacked">
 | 
			
		||||
        <field name="cycle_item_id" span="3"/>
 | 
			
		||||
    </group>
 | 
			
		||||
    <tabs>
 | 
			
		||||
        <tab string="Computation">
 | 
			
		||||
             <group form_layout="stacked">
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +13,6 @@
 | 
			
		|||
                <field name="var_pt" span="3"/>
 | 
			
		||||
                <field name="var_ptx" span="3"/>
 | 
			
		||||
                <field name="manual" span="3" help="Help"/>
 | 
			
		||||
                <field name="cycle_item_id" span="3"/>
 | 
			
		||||
                <field name="formulars" nolabel="1">
 | 
			
		||||
                    <list colors='{"red":[["state","=","fail"]]}'>
 | 
			
		||||
                        <field name="level_id"/>
 | 
			
		||||
| 
						 | 
				
			
			@ -34,18 +36,23 @@
 | 
			
		|||
        <tab string="Cost">
 | 
			
		||||
            <field name="lines" nolabel="1">
 | 
			
		||||
                <list>
 | 
			
		||||
                    <field name="cycle_id"/>
 | 
			
		||||
                    <field name="staff_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"/>
 | 
			
		||||
                </list>
 | 
			
		||||
                <form>
 | 
			
		||||
                    <field name="cycle_id"/>
 | 
			
		||||
                    <field name="staff_id"/>
 | 
			
		||||
                    <field name="level_id"/>
 | 
			
		||||
                    <field name="qty"/>
 | 
			
		||||
                    <field name="rate"/>
 | 
			
		||||
                    <field name="amount"/>
 | 
			
		||||
                </form>
 | 
			
		||||
            </field>
 | 
			
		||||
            <field name="total_cost" span="3" offset="9"/>
 | 
			
		||||
        </tab>
 | 
			
		||||
    </tabs>
 | 
			
		||||
    <foot>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -103,140 +103,16 @@ class CycleItem(Model):
 | 
			
		|||
                if lc:
 | 
			
		||||
                    lc.compute()
 | 
			
		||||
        obj.write({
 | 
			
		||||
            'state': 'validate',
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        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',
 | 
			
		||||
            'state': 'validated',
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
            'next': {
 | 
			
		||||
                'name': 'clinic_cycle_daily',
 | 
			
		||||
                'name': 'clinic_cycle_item',
 | 
			
		||||
                '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={}):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
from netforce.model import Model, fields, get_model
 | 
			
		||||
from netforce.utils import get_data_path
 | 
			
		||||
 | 
			
		||||
class LaborCost(Model):
 | 
			
		||||
    _name="clinic.labor.cost"
 | 
			
		||||
| 
						 | 
				
			
			@ -13,16 +14,21 @@ class LaborCost(Model):
 | 
			
		|||
            total_case=len(hd_cases)
 | 
			
		||||
            total_a,total_b=0,0
 | 
			
		||||
            total=0.0
 | 
			
		||||
            for line in obj.lines:
 | 
			
		||||
                total+=line.amount or 0
 | 
			
		||||
                total_a+=line.var_a or 0
 | 
			
		||||
                total_b+=line.var_b or 0
 | 
			
		||||
            for fline in obj.formulars:
 | 
			
		||||
                total+=fline.amount or 0
 | 
			
		||||
                total_a+=fline.var_a or 0
 | 
			
		||||
                total_b+=fline.var_b or 0
 | 
			
		||||
            var_ptx=total_case*(obj.var_k or 0)
 | 
			
		||||
            var_fml1='PTxK=%sX%s'%(total_a,total_b)
 | 
			
		||||
            total_bstr=total_b < 0 and "+%s"%(abs(total_b)) or "-%s"%total_b
 | 
			
		||||
            var_x=0.0
 | 
			
		||||
            if 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]={
 | 
			
		||||
                'var_pt': total_case,
 | 
			
		||||
                '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_x': round(var_x,2),
 | 
			
		||||
                'total': total,
 | 
			
		||||
                'total_cost': total_cost,
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        return res
 | 
			
		||||
 | 
			
		||||
    _fields={
 | 
			
		||||
| 
						 | 
				
			
			@ -44,6 +52,7 @@ class LaborCost(Model):
 | 
			
		|||
        'var_fml3': 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_cost': fields.Float("Total",function="_get_all",function_multi=True),
 | 
			
		||||
        'manual': fields.Boolean("Manual"),
 | 
			
		||||
        "formulars": fields.One2Many("clinic.labor.cost.formular", "labor_cost_id", "Formulars"),
 | 
			
		||||
        "staffs": fields.One2Many("clinic.labor.cost.staff", "labor_cost_id", "Staffs"),
 | 
			
		||||
| 
						 | 
				
			
			@ -174,6 +183,7 @@ class LaborCost(Model):
 | 
			
		|||
            'formulars': formulars,
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        levels={}
 | 
			
		||||
        if obj.manual:
 | 
			
		||||
            for fline in obj.formulars:
 | 
			
		||||
                fml=(fline.formular or "").replace("X","*%s")
 | 
			
		||||
| 
						 | 
				
			
			@ -185,6 +195,125 @@ class LaborCost(Model):
 | 
			
		|||
                    '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 {
 | 
			
		||||
            'next': {
 | 
			
		||||
                'name': 'clinic_labor_cost',
 | 
			
		||||
| 
						 | 
				
			
			@ -194,5 +323,26 @@ class LaborCost(Model):
 | 
			
		|||
            '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()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,13 +10,19 @@ class LaborCostLine(Model):
 | 
			
		|||
        "labor_cost_id": fields.Many2One("clinic.labor.cost","Cycle Item",required=True),
 | 
			
		||||
        'staff_id': fields.Many2One("clinic.staff", "Staff"),
 | 
			
		||||
        'level_id': fields.Many2One("clinic.staff.level", "Level"),
 | 
			
		||||
        'cycle_id': fields.Many2One("clinic.cycle", "Cycle"),
 | 
			
		||||
        'qty': fields.Integer("Qty"),
 | 
			
		||||
        'rate': fields.Float("Rate",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'),
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _defaults={
 | 
			
		||||
        "company_id": lambda *a: get_active_company(),
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    _order="cycle_id,level_id"
 | 
			
		||||
 | 
			
		||||
LaborCostLine.register()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -171,4 +171,25 @@ class Staff(Model):
 | 
			
		|||
            vals['employee_id']=emp_id
 | 
			
		||||
        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()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue