2010-06-05 06:39:12 +00:00
#-*- coding:utf-8 -*-
##############################################################################
#
2010-07-01 07:31:46 +00:00
# OpenERP, Open Source Management Solution
2010-06-05 06:39:12 +00:00
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# d$
#
# This program is free software: you can redistribute it and/or modify
2010-10-28 06:54:18 +00:00
# it under the terms of the GNU Affero General Public License as published by
2010-06-05 06:39:12 +00:00
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2010-10-28 06:54:18 +00:00
# GNU Affero General Public License for more details.
2010-06-05 06:39:12 +00:00
#
2010-10-28 06:54:18 +00:00
# You should have received a copy of the GNU Affero General Public License
2010-06-05 06:39:12 +00:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
2010-06-05 07:32:16 +00:00
import time
2010-10-06 12:44:54 +00:00
from datetime import date
from datetime import datetime
from datetime import timedelta
2010-07-27 07:11:45 +00:00
2010-10-06 12:44:54 +00:00
import netsvc
2010-07-27 07:11:45 +00:00
from osv import fields , osv
2010-12-24 12:05:44 +00:00
import tools
2010-06-05 07:32:16 +00:00
from tools . translate import _
2010-11-03 08:04:42 +00:00
import decimal_precision as dp
2010-06-05 07:32:16 +00:00
2010-06-18 03:11:40 +00:00
def prev_bounds ( cdate = False ) :
when = date . fromtimestamp ( time . mktime ( time . strptime ( cdate , " % Y- % m- %d " ) ) )
this_first = date ( when . year , when . month , 1 )
month = when . month + 1
year = when . year
if month > 12 :
month = 1
year + = 1
next_month = date ( year , month , 1 )
prev_end = next_month - timedelta ( days = 1 )
return this_first , prev_end
2010-06-06 18:26:08 +00:00
class hr_contract_wage_type ( osv . osv ) :
"""
2010-06-07 13:26:59 +00:00
Wage types
2010-06-06 18:26:08 +00:00
Basic = Basic Salary
Grows = Basic + Allowances
New = Grows - Deductions
"""
2010-07-01 07:31:46 +00:00
2010-06-06 18:26:08 +00:00
_inherit = ' hr.contract.wage.type '
_columns = {
2010-10-27 12:49:59 +00:00
' type ' : fields . selection ( [ ( ' basic ' , ' Basic ' ) , ( ' gross ' , ' Gross ' ) , ( ' net ' , ' Net ' ) ] , ' Type ' , required = True ) ,
2010-06-06 18:26:08 +00:00
}
2010-10-27 13:10:19 +00:00
2010-06-06 18:26:08 +00:00
hr_contract_wage_type ( )
2010-06-05 07:32:16 +00:00
class hr_passport ( osv . osv ) :
2010-06-06 18:26:08 +00:00
"""
Employee Passport
Passport based Contratacts for Employees
"""
2010-07-01 07:31:46 +00:00
2010-06-05 07:32:16 +00:00
_name = ' hr.passport '
_description = ' Passport Detail '
_columns = {
' employee_id ' : fields . many2one ( ' hr.employee ' , ' Employee ' , required = True ) ,
' name ' : fields . char ( ' Passport No ' , size = 64 , required = True , readonly = False ) ,
' country_id ' : fields . many2one ( ' res.country ' , ' Country of Issue ' , required = True ) ,
2010-06-06 18:26:08 +00:00
' address_id ' : fields . many2one ( ' res.partner.address ' , ' Address ' , required = False ) ,
' date_issue ' : fields . date ( ' Passport Issue Date ' , required = True ) ,
' date_expire ' : fields . date ( ' Passport Expire Date ' , required = True ) ,
2010-06-05 07:32:16 +00:00
' contracts_ids ' : fields . one2many ( ' hr.contract ' , ' passport_id ' , ' Contracts ' , required = False , readonly = True ) ,
2010-06-06 18:26:08 +00:00
' note ' : fields . text ( ' Description ' ) ,
2010-06-05 07:32:16 +00:00
}
2010-10-06 12:44:54 +00:00
_sql_constraints = [
( ' passport_no_uniq ' , ' unique (employee_id, name) ' , ' The Passport No must be unique ! ' ) ,
]
2010-06-05 07:32:16 +00:00
hr_passport ( )
2010-06-06 18:26:08 +00:00
class hr_payroll_structure ( osv . osv ) :
"""
Salary structure used to defined
2010-06-09 14:38:22 +00:00
- Basic
- Allowlance
- Deductions
2010-06-06 18:26:08 +00:00
"""
2010-10-26 12:23:32 +00:00
2010-06-06 18:26:08 +00:00
_name = ' hr.payroll.structure '
_description = ' Salary Structure '
2010-06-05 07:32:16 +00:00
_columns = {
2010-06-06 18:26:08 +00:00
' name ' : fields . char ( ' Name ' , size = 256 , required = True , readonly = False ) ,
' code ' : fields . char ( ' Code ' , size = 64 , required = True , readonly = False ) ,
2011-03-02 07:12:38 +00:00
# 'line_ids':fields.one2many('hr.payslip.line', 'function_id', 'Salary Structure', required=False),
2010-06-05 07:32:16 +00:00
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' , required = False ) ,
2010-06-06 16:29:11 +00:00
' note ' : fields . text ( ' Description ' ) ,
2011-02-28 09:56:43 +00:00
' parent_id ' : fields . many2one ( ' hr.payroll.structure ' , ' Parent Structure ' ) ,
2010-06-05 07:32:16 +00:00
}
_defaults = {
' company_id ' : lambda self , cr , uid , context : \
self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid ,
context = context ) . company_id . id ,
}
2010-07-01 07:31:46 +00:00
2010-06-05 07:32:16 +00:00
def copy ( self , cr , uid , id , default = None , context = None ) :
2010-06-06 18:26:08 +00:00
"""
Create a new record in hr_payroll_structure model from existing one
@param cr : cursor to database
@param user : id of current user
@param id : list of record ids on which copy method executes
@param default : dict type contains the values to be override during copy of object
@param context : context arguments , like lang , time zone
2010-07-01 07:31:46 +00:00
2010-06-06 18:26:08 +00:00
@return : returns a id of newly created record
"""
2010-07-27 07:11:45 +00:00
code = self . browse ( cr , uid , id , context = context ) . code
2010-06-05 07:32:16 +00:00
default = {
' code ' : code + " (copy) " ,
' company_id ' : self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context = context ) . company_id . id
}
2010-10-27 13:10:19 +00:00
return super ( hr_payroll_structure , self ) . copy ( cr , uid , id , default , context = context )
2010-07-01 07:31:46 +00:00
2010-06-06 18:26:08 +00:00
hr_payroll_structure ( )
2010-06-05 07:32:16 +00:00
class hr_contract ( osv . osv ) :
2010-06-06 19:09:53 +00:00
"""
Employee contract based on the visa , work permits
allowas to configure different Salary structure
"""
2010-10-26 12:23:32 +00:00
2010-11-19 13:48:01 +00:00
def compute_basic ( self , cr , uid , ids , context = None ) :
2010-10-07 14:00:56 +00:00
res = { }
2010-11-23 07:05:05 +00:00
if context is None :
2010-11-19 13:48:01 +00:00
context = { }
2010-10-07 14:00:56 +00:00
ids + = context . get ( ' employee_structure ' , [ ] )
2010-10-26 12:23:32 +00:00
2010-10-08 09:05:55 +00:00
slip_line_pool = self . pool . get ( ' hr.payslip.line ' )
2010-10-26 12:23:32 +00:00
2010-11-19 13:48:01 +00:00
for contract in self . browse ( cr , uid , ids , context = context ) :
2010-10-07 14:00:56 +00:00
all_per = 0.0
ded_per = 0.0
all_fix = 0.0
ded_fix = 0.0
obj = { ' basic ' : 0.0 }
update = { }
if contract . wage_type_id . type == ' gross ' :
obj [ ' gross ' ] = contract . wage
update [ ' gross ' ] = contract . wage
if contract . wage_type_id . type == ' net ' :
obj [ ' net ' ] = contract . wage
update [ ' net ' ] = contract . wage
if contract . wage_type_id . type == ' basic ' :
obj [ ' basic ' ] = contract . wage
update [ ' basic ' ] = contract . wage
2010-10-26 12:23:32 +00:00
2010-10-07 14:00:56 +00:00
sal_type = contract . wage_type_id . type
2010-10-28 04:27:05 +00:00
# function = contract.struct_id.id
2011-02-24 13:12:20 +00:00
lines = contract . struct_id . rule_ids
2010-10-07 14:00:56 +00:00
if not contract . struct_id :
res [ contract . id ] = obj [ ' basic ' ]
2010-10-26 12:23:32 +00:00
continue
2010-10-07 14:00:56 +00:00
ad = [ ]
for line in lines :
cd = line . code . lower ( )
obj [ cd ] = line . amount or 0.0
2010-10-26 12:23:32 +00:00
2010-10-07 14:00:56 +00:00
for line in lines :
if line . category_id . code in ad :
continue
ad . append ( line . category_id . code )
cd = line . category_id . code . lower ( )
calculate = False
try :
exp = line . category_id . condition
calculate = eval ( exp , obj )
except Exception , e :
2010-11-19 12:20:03 +00:00
raise osv . except_osv ( _ ( ' Variable Error ! ' ) , _ ( ' Variable Error: %s ' ) % ( e ) )
2010-10-07 14:00:56 +00:00
if not calculate :
continue
percent = 0.0
value = 0.0
base = False
2010-10-28 04:27:05 +00:00
# company_contrib = 0.0
2010-10-07 14:00:56 +00:00
base = line . category_id . base
try :
#Please have a look at the configuration guide.
amt = eval ( base , obj )
except Exception , e :
2010-11-19 12:20:03 +00:00
raise osv . except_osv ( _ ( ' Variable Error ! ' ) , _ ( ' Variable Error: %s ' ) % ( e ) )
2010-10-07 14:00:56 +00:00
if sal_type in ( ' gross ' , ' net ' ) :
if line . amount_type == ' per ' :
percent = line . amount
if amt > 1 :
value = percent * amt
elif amt > 0 and amt < = 1 :
percent = percent * amt
if value > 0 :
percent = 0.0
elif line . amount_type == ' fix ' :
value = line . amount
elif line . amount_type == ' func ' :
value = slip_line_pool . execute_function ( cr , uid , line . id , amt , context )
line . amount = value
else :
if line . amount_type in ( ' fix ' , ' per ' ) :
value = line . amount
elif line . amount_type == ' func ' :
value = slip_line_pool . execute_function ( cr , uid , line . id , amt , context )
line . amount = value
2011-02-28 10:55:24 +00:00
if line . type . name == ' allowance ' : #FIXME: not good. We don't have to compute the gross or net on hr.contract nor hr.employee. We jsut need to define the basic; So the fields gross and net can be removed from view and object.
2010-10-07 14:00:56 +00:00
all_per + = percent
all_fix + = value
2011-02-28 10:55:24 +00:00
elif line . type . name == ' deduction ' : #FIXME: not good
2010-10-07 14:00:56 +00:00
ded_per + = percent
ded_fix + = value
if sal_type in ( ' gross ' , ' net ' ) :
sal = contract . wage
if sal_type == ' net ' :
sal + = ded_fix
sal - = all_fix
per = 0.0
if sal_type == ' net ' :
per = ( all_per - ded_per )
else :
per = all_per
2010-10-27 12:49:59 +00:00
if per < = 0 :
2010-10-07 14:00:56 +00:00
per * = - 1
final = ( per * 100 ) + 100
basic = ( sal * 100 ) / final
else :
basic = contract . wage
2010-10-26 12:23:32 +00:00
2010-10-07 14:00:56 +00:00
res [ contract . id ] = basic
return res
2010-10-26 12:23:32 +00:00
2010-10-08 09:05:55 +00:00
def check_vals ( self , val1 , val2 ) :
if val1 == val2 and val1 == 0 :
return True
return False
2010-10-26 12:23:32 +00:00
2010-10-07 14:00:56 +00:00
def _calculate_salary ( self , cr , uid , ids , field_names , arg , context = None ) :
2010-11-19 13:48:01 +00:00
res = self . compute_basic ( cr , uid , ids , context = context )
2010-10-07 14:00:56 +00:00
vals = { }
for rs in self . browse ( cr , uid , ids , context = context ) :
allow = 0.0
deduct = 0.0
others = 0.0
obj = { ' basic ' : res [ rs . id ] , ' gross ' : 0.0 , ' net ' : 0.0 }
if rs . wage_type_id . type == ' gross ' :
obj [ ' gross ' ] = rs . wage
if rs . wage_type_id . type == ' net ' :
obj [ ' net ' ] = rs . net
2010-10-26 12:23:32 +00:00
2010-10-07 14:00:56 +00:00
if not rs . struct_id :
2010-10-08 09:05:55 +00:00
if self . check_vals ( obj [ ' basic ' ] , obj [ ' gross ' ] ) :
obj [ ' gross ' ] = obj [ ' basic ' ] = obj [ ' net ' ]
elif self . check_vals ( obj [ ' gross ' ] , obj [ ' net ' ] ) :
obj [ ' gross ' ] = obj [ ' net ' ] = obj [ ' basic ' ]
elif self . check_vals ( obj [ ' net ' ] , obj [ ' basic ' ] ) :
obj [ ' net ' ] = obj [ ' basic ' ] = obj [ ' gross ' ]
2010-10-07 14:00:56 +00:00
record = {
' advantages_gross ' : 0.0 ,
' advantages_net ' : 0.0 ,
' basic ' : obj [ ' basic ' ] ,
' gross ' : obj [ ' gross ' ] ,
' net ' : obj [ ' net ' ]
}
vals [ rs . id ] = record
continue
2011-02-28 10:55:24 +00:00
for line in rs . struct_id . rule_ids :
2010-10-07 14:00:56 +00:00
amount = 0.0
if line . amount_type == ' per ' :
try :
amount = line . amount * eval ( str ( line . category_id . base ) , obj )
except Exception , e :
2010-11-19 12:20:03 +00:00
raise osv . except_osv ( _ ( ' Variable Error ! ' ) , _ ( ' Variable Error: %s ' ) % ( e ) )
2010-10-07 14:00:56 +00:00
elif line . amount_type in ( ' fix ' , ' func ' ) :
amount = line . amount
cd = line . category_id . code . lower ( )
obj [ cd ] = amount
2010-10-26 12:23:32 +00:00
2011-02-25 13:07:26 +00:00
if line . type . name == ' allowance ' :
2010-10-07 14:00:56 +00:00
allow + = amount
2011-02-25 13:07:26 +00:00
elif line . type . name == ' deduction ' :
2010-10-07 14:00:56 +00:00
deduct + = amount
record = {
' advantages_gross ' : round ( allow ) ,
' advantages_net ' : round ( deduct ) ,
2010-10-08 09:05:55 +00:00
' basic ' : obj [ ' basic ' ] ,
' gross ' : round ( obj [ ' basic ' ] + allow ) ,
' net ' : round ( obj [ ' basic ' ] + allow - deduct )
2010-10-07 14:00:56 +00:00
}
vals [ rs . id ] = record
return vals
2010-07-01 07:31:46 +00:00
2010-06-05 07:32:16 +00:00
_inherit = ' hr.contract '
_description = ' Employee Contract '
_columns = {
2010-10-27 12:49:59 +00:00
' permit_no ' : fields . char ( ' Work Permit No ' , size = 256 , required = False , readonly = False ) ,
2010-12-13 08:21:34 +00:00
' passport_id ' : fields . many2one ( ' hr.passport ' , ' Passport No ' , required = False ) ,
2010-10-27 12:49:59 +00:00
' visa_no ' : fields . char ( ' Visa No ' , size = 64 , required = False , readonly = False ) ,
2010-06-05 07:32:16 +00:00
' visa_expire ' : fields . date ( ' Visa Expire Date ' ) ,
2010-10-27 12:49:59 +00:00
' struct_id ' : fields . many2one ( ' hr.payroll.structure ' , ' Salary Structure ' ) ,
2010-10-07 14:00:56 +00:00
' working_days_per_week ' : fields . integer ( ' Working Days ' , help = " No of Working days / week for an employee " ) ,
2010-10-07 14:44:56 +00:00
' basic ' : fields . function ( _calculate_salary , method = True , store = True , multi = ' dc ' , type = ' float ' , string = ' Basic Salary ' , digits = ( 14 , 2 ) ) ,
' gross ' : fields . function ( _calculate_salary , method = True , store = True , multi = ' dc ' , type = ' float ' , string = ' Gross Salary ' , digits = ( 14 , 2 ) ) ,
' net ' : fields . function ( _calculate_salary , method = True , store = True , multi = ' dc ' , type = ' float ' , string = ' Net Salary ' , digits = ( 14 , 2 ) ) ,
' advantages_net ' : fields . function ( _calculate_salary , method = True , store = True , multi = ' dc ' , type = ' float ' , string = ' Deductions ' , digits = ( 14 , 2 ) ) ,
' advantages_gross ' : fields . function ( _calculate_salary , method = True , store = True , multi = ' dc ' , type = ' float ' , string = ' Allowances ' , digits = ( 14 , 2 ) ) ,
2010-06-18 03:11:40 +00:00
}
_defaults = {
' working_days_per_week ' : lambda * a : 5 ,
2010-06-05 07:32:16 +00:00
}
hr_contract ( )
2010-06-06 16:29:11 +00:00
class payroll_register ( osv . osv ) :
2010-06-09 14:38:22 +00:00
"""
2010-06-06 16:29:11 +00:00
Payroll Register
2010-06-09 14:38:22 +00:00
"""
2010-10-26 12:23:32 +00:00
2010-06-06 16:29:11 +00:00
_name = ' hr.payroll.register '
_description = ' Payroll Register '
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
def _calculate ( self , cr , uid , ids , field_names , arg , context = None ) :
2010-06-06 16:29:11 +00:00
res = { }
allounce = 0.0
deduction = 0.0
net = 0.0
grows = 0.0
2010-07-27 07:11:45 +00:00
for register in self . browse ( cr , uid , ids , context = context ) :
2010-06-06 16:29:11 +00:00
for slip in register . line_ids :
allounce + = slip . allounce
deduction + = slip . deduction
net + = slip . net
grows + = slip . grows
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
res [ register . id ] = {
' allounce ' : allounce ,
' deduction ' : deduction ,
' net ' : net ,
' grows ' : grows
}
return res
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
_columns = {
' name ' : fields . char ( ' Name ' , size = 64 , required = True , readonly = False ) ,
' date ' : fields . date ( ' Date ' , required = True ) ,
' number ' : fields . char ( ' Number ' , size = 64 , required = False , readonly = True ) ,
' line_ids ' : fields . one2many ( ' hr.payslip ' , ' register_id ' , ' Payslips ' , required = False ) ,
' state ' : fields . selection ( [
( ' new ' , ' New Slip ' ) ,
( ' draft ' , ' Wating for Verification ' ) ,
( ' hr_check ' , ' Wating for HR Verification ' ) ,
( ' accont_check ' , ' Wating for Account Verification ' ) ,
( ' confirm ' , ' Confirm Sheet ' ) ,
( ' done ' , ' Paid Salary ' ) ,
( ' cancel ' , ' Reject ' ) ,
] , ' State ' , select = True , readonly = True ) ,
' active ' : fields . boolean ( ' Active ' , required = False ) ,
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' , required = False ) ,
2010-07-07 06:21:07 +00:00
' grows ' : fields . function ( _calculate , method = True , store = True , multi = ' dc ' , string = ' Gross Salary ' , type = ' float ' , digits = ( 16 , 4 ) ) ,
' net ' : fields . function ( _calculate , method = True , store = True , multi = ' dc ' , string = ' Net Salary ' , digits = ( 16 , 4 ) ) ,
' allounce ' : fields . function ( _calculate , method = True , store = True , multi = ' dc ' , string = ' Allowance ' , digits = ( 16 , 4 ) ) ,
' deduction ' : fields . function ( _calculate , method = True , store = True , multi = ' dc ' , string = ' Deduction ' , digits = ( 16 , 4 ) ) ,
2010-06-06 16:29:11 +00:00
' note ' : fields . text ( ' Description ' ) ,
2010-10-06 12:44:54 +00:00
' bank_id ' : fields . many2one ( ' res.bank ' , ' Bank ' , required = False , help = " Select the Bank Address from whcih the salary is going to be paid " ) ,
2010-06-06 16:29:11 +00:00
}
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
_defaults = {
' date ' : lambda * a : time . strftime ( ' % Y- % m- %d ' ) ,
' state ' : lambda * a : ' new ' ,
' active ' : lambda * a : True ,
' company_id ' : lambda self , cr , uid , context : \
self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid ,
context = context ) . company_id . id ,
}
2010-07-27 07:11:45 +00:00
def compute_sheet ( self , cr , uid , ids , context = None ) :
2010-06-06 16:29:11 +00:00
emp_pool = self . pool . get ( ' hr.employee ' )
slip_pool = self . pool . get ( ' hr.payslip ' )
wf_service = netsvc . LocalService ( " workflow " )
2010-07-27 07:11:45 +00:00
if context is None :
context = { }
2010-07-01 07:31:46 +00:00
2010-10-06 12:44:54 +00:00
vals = self . browse ( cr , uid , ids [ 0 ] , context = context )
2010-07-27 07:11:45 +00:00
emp_ids = emp_pool . search ( cr , uid , [ ] , context = context )
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
for emp in emp_pool . browse ( cr , uid , emp_ids , context = context ) :
old_slips = slip_pool . search ( cr , uid , [ ( ' employee_id ' , ' = ' , emp . id ) , ( ' date ' , ' = ' , vals . date ) ] , context = context )
2010-06-06 16:29:11 +00:00
if old_slips :
2010-07-27 07:11:45 +00:00
slip_pool . write ( cr , uid , old_slips , { ' register_id ' : ids [ 0 ] } , context = context )
2010-06-06 16:29:11 +00:00
for sid in old_slips :
wf_service . trg_validate ( uid , ' hr.payslip ' , sid , ' compute_sheet ' , cr )
2010-07-02 10:37:15 +00:00
else :
res = {
' employee_id ' : emp . id ,
' basic ' : 0.0 ,
' register_id ' : ids [ 0 ] ,
' name ' : vals . name ,
' date ' : vals . date ,
}
2010-07-27 07:11:45 +00:00
slip_id = slip_pool . create ( cr , uid , res , context = context )
2010-07-02 10:37:15 +00:00
wf_service . trg_validate ( uid , ' hr.payslip ' , slip_id , ' compute_sheet ' , cr )
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
number = self . pool . get ( ' ir.sequence ' ) . get ( cr , uid , ' salary.register ' )
2010-07-27 07:11:45 +00:00
self . write ( cr , uid , ids , { ' state ' : ' draft ' , ' number ' : number } , context = context )
2010-06-06 16:29:11 +00:00
return True
2010-10-26 12:23:32 +00:00
def set_to_draft ( self , cr , uid , ids , context = None ) :
self . write ( cr , uid , ids , { ' state ' : ' draft ' } , context = context )
return True
def cancel_sheet ( self , cr , uid , ids , context = None ) :
self . write ( cr , uid , ids , { ' state ' : ' cancel ' } , context = context )
return True
2010-07-27 07:11:45 +00:00
def verify_sheet ( self , cr , uid , ids , context = None ) :
2010-06-06 16:29:11 +00:00
slip_pool = self . pool . get ( ' hr.payslip ' )
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
for id in ids :
2010-07-27 07:11:45 +00:00
sids = slip_pool . search ( cr , uid , [ ( ' register_id ' , ' = ' , id ) ] , context = context )
2010-06-06 16:29:11 +00:00
wf_service = netsvc . LocalService ( " workflow " )
for sid in sids :
wf_service . trg_validate ( uid , ' hr.payslip ' , sid , ' verify_sheet ' , cr )
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
self . write ( cr , uid , ids , { ' state ' : ' hr_check ' } , context = context )
2010-06-06 16:29:11 +00:00
return True
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
def final_verify_sheet ( self , cr , uid , ids , context = None ) :
2010-06-06 16:29:11 +00:00
slip_pool = self . pool . get ( ' hr.payslip ' )
advice_pool = self . pool . get ( ' hr.payroll.advice ' )
advice_line_pool = self . pool . get ( ' hr.payroll.advice.line ' )
2010-07-27 07:11:45 +00:00
sequence_pool = self . pool . get ( ' ir.sequence ' )
users_pool = self . pool . get ( ' res.users ' )
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
for id in ids :
2010-07-27 07:11:45 +00:00
sids = slip_pool . search ( cr , uid , [ ( ' register_id ' , ' = ' , id ) , ( ' state ' , ' = ' , ' hr_check ' ) ] , context = context )
2010-06-06 16:29:11 +00:00
wf_service = netsvc . LocalService ( " workflow " )
for sid in sids :
wf_service . trg_validate ( uid , ' hr.payslip ' , sid , ' final_verify_sheet ' , cr )
2010-10-26 12:23:32 +00:00
2010-10-06 12:44:54 +00:00
company_name = users_pool . browse ( cr , uid , uid , context = context ) . company_id . name
2010-07-27 07:11:45 +00:00
for reg in self . browse ( cr , uid , ids , context = context ) :
2010-10-06 12:44:54 +00:00
advice = {
' name ' : ' Payment Advice from %s ' % ( company_name ) ,
' number ' : sequence_pool . get ( cr , uid , ' payment.advice ' ) ,
' register_id ' : reg . id
}
pid = advice_pool . create ( cr , uid , advice , context = context )
2010-10-26 12:23:32 +00:00
2010-06-06 16:29:11 +00:00
for slip in reg . line_ids :
2010-10-06 12:44:54 +00:00
if not slip . employee_id . bank_account_id :
2010-11-18 16:21:31 +00:00
raise osv . except_osv ( _ ( ' Error ! ' ) , _ ( ' Please define bank account for the %s employee ' ) % ( slip . employee_id . name ) )
2010-06-06 16:29:11 +00:00
pline = {
' advice_id ' : pid ,
2010-10-06 12:44:54 +00:00
' name ' : slip . employee_id . bank_account_id . acc_number ,
2010-06-06 16:29:11 +00:00
' employee_id ' : slip . employee_id . id ,
2011-02-25 13:07:26 +00:00
' amount ' : slip . net ,
2010-06-06 16:29:11 +00:00
' bysal ' : slip . net
}
2010-07-27 07:11:45 +00:00
id = advice_line_pool . create ( cr , uid , pline , context = context )
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
self . write ( cr , uid , ids , { ' state ' : ' confirm ' } , context = context )
2010-06-06 16:29:11 +00:00
return True
2010-07-27 07:11:45 +00:00
def process_sheet ( self , cr , uid , ids , context = None ) :
2010-06-06 16:29:11 +00:00
slip_pool = self . pool . get ( ' hr.payslip ' )
for id in ids :
2010-07-27 07:11:45 +00:00
sids = slip_pool . search ( cr , uid , [ ( ' register_id ' , ' = ' , id ) , ( ' state ' , ' = ' , ' confirm ' ) ] , context = context )
2010-06-06 16:29:11 +00:00
wf_service = netsvc . LocalService ( " workflow " )
for sid in sids :
wf_service . trg_validate ( uid , ' hr.payslip ' , sid , ' process_sheet ' , cr )
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
self . write ( cr , uid , ids , { ' state ' : ' done ' } , context = context )
2010-06-06 16:29:11 +00:00
return True
payroll_register ( )
class payroll_advice ( osv . osv ) :
'''
Bank Advice Note
'''
2010-10-26 12:23:32 +00:00
2010-06-06 16:29:11 +00:00
_name = ' hr.payroll.advice '
_description = ' Bank Advice Note '
_columns = {
' register_id ' : fields . many2one ( ' hr.payroll.register ' , ' Payroll Register ' , required = False ) ,
' name ' : fields . char ( ' Name ' , size = 2048 , required = True , readonly = False ) ,
' note ' : fields . text ( ' Description ' ) ,
' date ' : fields . date ( ' Date ' ) ,
' state ' : fields . selection ( [
( ' draft ' , ' Draft Sheet ' ) ,
( ' confirm ' , ' Confirm Sheet ' ) ,
( ' cancel ' , ' Reject ' ) ,
] , ' State ' , select = True , readonly = True ) ,
' number ' : fields . char ( ' Number ' , size = 64 , required = False , readonly = True ) ,
' line_ids ' : fields . one2many ( ' hr.payroll.advice.line ' , ' advice_id ' , ' Employee Salary ' , required = False ) ,
' chaque_nos ' : fields . char ( ' Chaque Nos ' , size = 256 , required = False , readonly = False ) ,
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' , required = False ) ,
2010-10-06 12:44:54 +00:00
' bank_id ' : fields . related ( ' register_id ' , ' bank_id ' , type = ' many2one ' , relation = ' res.bank ' , string = ' Bank ' , help = " Select the Bank Address from whcih the salary is going to be paid " ) ,
2010-06-06 16:29:11 +00:00
}
_defaults = {
' date ' : lambda * a : time . strftime ( ' % Y- % m- %d ' ) ,
' state ' : lambda * a : ' draft ' ,
' company_id ' : lambda self , cr , uid , context : \
self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid ,
context = context ) . company_id . id ,
}
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
def confirm_sheet ( self , cr , uid , ids , context = None ) :
self . write ( cr , uid , ids , { ' state ' : ' confirm ' } , context = context )
2010-06-06 16:29:11 +00:00
return True
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
def set_to_draft ( self , cr , uid , ids , context = None ) :
self . write ( cr , uid , ids , { ' state ' : ' draft ' } , context = context )
2010-06-06 16:29:11 +00:00
return True
2010-07-27 07:11:45 +00:00
def cancel_sheet ( self , cr , uid , ids , context = None ) :
self . write ( cr , uid , ids , { ' state ' : ' cancel ' } , context = context )
2010-06-06 16:29:11 +00:00
return True
2010-08-05 13:41:55 +00:00
def onchange_company_id ( self , cr , uid , ids , company_id = False , context = None ) :
2010-08-05 04:41:04 +00:00
res = { }
if company_id :
company = self . pool . get ( ' res.company ' ) . browse ( cr , uid , company_id , context = context )
2010-08-05 13:41:55 +00:00
if company . partner_id . bank_ids :
res . update ( { ' bank ' : company . partner_id . bank_ids [ 0 ] . bank . name } )
2010-08-05 04:41:04 +00:00
return {
' value ' : res
}
2010-06-06 16:29:11 +00:00
payroll_advice ( )
class payroll_advice_line ( osv . osv ) :
'''
Bank Advice Lines
'''
2010-10-26 12:23:32 +00:00
2010-06-06 16:29:11 +00:00
_name = ' hr.payroll.advice.line '
_description = ' Bank Advice Lines '
_columns = {
' advice_id ' : fields . many2one ( ' hr.payroll.advice ' , ' Bank Advice ' , required = False ) ,
' name ' : fields . char ( ' Bank Account A/C ' , size = 64 , required = True , readonly = False ) ,
' employee_id ' : fields . many2one ( ' hr.employee ' , ' Employee ' , required = True ) ,
2010-07-07 06:21:07 +00:00
' amount ' : fields . float ( ' Amount ' , digits = ( 16 , 4 ) ) ,
' bysal ' : fields . float ( ' By Salary ' , digits = ( 16 , 4 ) ) ,
2010-06-06 16:29:11 +00:00
' flag ' : fields . char ( ' D/C ' , size = 8 , required = True , readonly = False ) ,
}
_defaults = {
' flag ' : lambda * a : ' C ' ,
}
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
def onchange_employee_id ( self , cr , uid , ids , ddate , employee_id , context = None ) :
2010-06-06 16:29:11 +00:00
vals = { }
2010-07-01 07:31:46 +00:00
slip_pool = self . pool . get ( ' hr.payslip ' )
2010-06-06 16:29:11 +00:00
if employee_id :
dates = prev_bounds ( ddate )
sids = False
2010-07-27 07:11:45 +00:00
sids = slip_pool . search ( cr , uid , [ ( ' paid ' , ' = ' , False ) , ( ' state ' , ' = ' , ' confirm ' ) , ( ' date ' , ' >= ' , dates [ 0 ] ) , ( ' employee_id ' , ' = ' , employee_id ) , ( ' date ' , ' <= ' , dates [ 1 ] ) ] , context = context )
2010-06-06 16:29:11 +00:00
if sids :
2010-07-27 07:11:45 +00:00
slip = slip_pool . browse ( cr , uid , sids [ 0 ] , context = context )
2010-09-11 13:29:00 +00:00
vals [ ' name ' ] = slip . employee_id . identification_id
2011-02-25 13:07:26 +00:00
vals [ ' amount ' ] = slip . net
2010-06-06 16:29:11 +00:00
vals [ ' bysal ' ] = slip . net
return {
' value ' : vals
}
payroll_advice_line ( )
class contrib_register ( osv . osv ) :
'''
Contribution Register
'''
2010-10-26 12:23:32 +00:00
2010-06-06 16:29:11 +00:00
_name = ' hr.contibution.register '
_description = ' Contribution Register '
2010-07-01 07:31:46 +00:00
2010-11-19 13:48:01 +00:00
def _total_contrib ( self , cr , uid , ids , field_names , arg , context = None ) :
2010-06-06 16:29:11 +00:00
line_pool = self . pool . get ( ' hr.contibution.register.line ' )
2010-10-06 12:44:54 +00:00
2010-06-06 16:29:11 +00:00
res = { }
2010-07-27 07:11:45 +00:00
for cur in self . browse ( cr , uid , ids , context = context ) :
2010-10-06 12:44:54 +00:00
current = line_pool . search ( cr , uid , [ ( ' register_id ' , ' = ' , cur . id ) ] , context = context )
2010-06-06 16:29:11 +00:00
e_month = 0.0
c_month = 0.0
2010-07-27 07:11:45 +00:00
for i in line_pool . browse ( cr , uid , current , context = context ) :
2010-06-06 16:29:11 +00:00
e_month + = i . emp_deduction
c_month + = i . comp_deduction
res [ cur . id ] = {
' monthly_total_by_emp ' : e_month ,
' monthly_total_by_comp ' : c_month ,
}
return res
_columns = {
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' , required = False ) ,
' name ' : fields . char ( ' Name ' , size = 256 , required = True , readonly = False ) ,
' register_line_ids ' : fields . one2many ( ' hr.contibution.register.line ' , ' register_id ' , ' Register Line ' , readonly = True ) ,
2010-10-06 12:44:54 +00:00
' monthly_total_by_emp ' : fields . function ( _total_contrib , method = True , multi = ' dc ' , string = ' Total By Employee ' , digits = ( 16 , 4 ) ) ,
' monthly_total_by_comp ' : fields . function ( _total_contrib , method = True , multi = ' dc ' , string = ' Total By Company ' , digits = ( 16 , 4 ) ) ,
2010-06-06 16:29:11 +00:00
' note ' : fields . text ( ' Description ' ) ,
}
_defaults = {
' company_id ' : lambda self , cr , uid , context : \
self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid ,
context = context ) . company_id . id ,
}
contrib_register ( )
class contrib_register_line ( osv . osv ) :
'''
Contribution Register Line
'''
2010-10-26 12:23:32 +00:00
2010-06-06 16:29:11 +00:00
_name = ' hr.contibution.register.line '
_description = ' Contribution Register Line '
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
def _total ( self , cr , uid , ids , field_names , arg , context = None ) :
2010-06-06 16:29:11 +00:00
res = { }
2010-07-27 07:11:45 +00:00
for line in self . browse ( cr , uid , ids , context = context ) :
2010-06-06 16:29:11 +00:00
res [ line . id ] = line . emp_deduction + line . comp_deduction
return res
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
_columns = {
' name ' : fields . char ( ' Name ' , size = 256 , required = True , readonly = False ) ,
' register_id ' : fields . many2one ( ' hr.contibution.register ' , ' Register ' , required = False ) ,
' code ' : fields . char ( ' Code ' , size = 64 , required = False , readonly = False ) ,
' employee_id ' : fields . many2one ( ' hr.employee ' , ' Employee ' , required = True ) ,
2010-10-06 12:44:54 +00:00
' date ' : fields . date ( ' Date ' ) ,
2010-07-07 06:21:07 +00:00
' emp_deduction ' : fields . float ( ' Employee Deduction ' , digits = ( 16 , 4 ) ) ,
' comp_deduction ' : fields . float ( ' Company Deduction ' , digits = ( 16 , 4 ) ) ,
' total ' : fields . function ( _total , method = True , store = True , string = ' Total ' , digits = ( 16 , 4 ) ) ,
2010-06-06 16:29:11 +00:00
}
2010-10-06 12:44:54 +00:00
_defaults = {
' date ' : lambda * a : time . strftime ( ' % Y- % m- %d ' ) ,
}
2010-06-06 16:29:11 +00:00
contrib_register_line ( )
2011-02-25 13:07:26 +00:00
class salary_head_type ( osv . osv ) :
"""
Salary Head Type
"""
_name = ' salary.head.type '
_description = ' Salary Head Type '
_columns = {
' name ' : fields . char ( ' Type Name ' , size = 64 , required = True , readonly = False ) ,
}
salary_head_type ( )
2010-06-06 16:29:11 +00:00
class payment_category ( osv . osv ) :
2010-06-09 14:38:22 +00:00
"""
Allowance , Deduction Heads
House Rent Allowance , Medical Allowance , Food Allowance
2010-07-01 07:31:46 +00:00
Professional Tax , Advance TDS , Providend Funds , etc
2010-06-09 14:38:22 +00:00
"""
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
_name = ' hr.allounce.deduction.categoty '
2010-06-09 14:38:22 +00:00
_description = ' Allowance Deduction Heads '
2010-06-06 16:29:11 +00:00
_columns = {
2011-01-13 07:55:36 +00:00
' name ' : fields . char ( ' Category Name ' , size = 64 , required = True , readonly = False ) ,
' code ' : fields . char ( ' Category Code ' , size = 64 , required = True , readonly = False ) ,
2011-03-01 13:29:38 +00:00
' type ' : fields . many2one ( ' salary.head.type ' , ' Type ' , required = True , help = " It is used only for the reporting purpose. " ) ,
2010-07-02 10:37:15 +00:00
' base ' : fields . text ( ' Based on ' , required = True , readonly = False , help = ' This will use to computer the % f ields values, in general its on basic, but You can use all heads code field in small letter as a variable name i.e. hra, ma, lta, etc...., also you can use, static varible basic ' ) ,
2010-06-06 16:29:11 +00:00
' condition ' : fields . char ( ' Condition ' , size = 1024 , required = True , readonly = False , help = ' Applied this head for calculation if condition is true ' ) ,
' sequence ' : fields . integer ( ' Sequence ' , required = True , help = ' Use to arrange calculation sequence ' ) ,
2010-07-01 07:31:46 +00:00
' note ' : fields . text ( ' Description ' ) ,
2010-06-09 14:38:22 +00:00
' user_id ' : fields . char ( ' User ' , size = 64 , required = False , readonly = False ) ,
' state ' : fields . char ( ' Label ' , size = 64 , required = False , readonly = False ) ,
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' , required = False ) ,
2011-03-01 13:29:38 +00:00
' dispaly_payslip_report ' : fields . boolean ( ' Display on Payslip Report ' , help = " Used for the display of head on Payslip Report. " ) ,
2011-02-25 13:07:26 +00:00
' computation_based ' : fields . selection ( [
( ' rules ' , ' List of Rules ' ) ,
( ' exp ' , ' Expression ' ) ,
] , ' Computation Based On ' , select = True , required = True ) ,
2010-06-09 14:38:22 +00:00
}
_defaults = {
' condition ' : lambda * a : ' True ' ,
' base ' : lambda * a : ' basic ' ,
' sequence ' : lambda * a : 5 ,
' company_id ' : lambda self , cr , uid , context : \
self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid ,
context = context ) . company_id . id ,
2011-03-01 13:29:38 +00:00
' dispaly_payslip_report ' : 1 ,
2011-02-25 13:07:26 +00:00
' computation_based ' : ' rules ' ,
2010-06-09 14:38:22 +00:00
}
payment_category ( )
2010-06-06 16:29:11 +00:00
class hr_holidays_status ( osv . osv ) :
2010-10-26 12:23:32 +00:00
2010-06-06 16:29:11 +00:00
_inherit = " hr.holidays.status "
_columns = {
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' , required = False ) ,
' type ' : fields . selection ( [
2010-07-01 07:31:46 +00:00
( ' paid ' , ' Paid Holiday ' ) ,
( ' unpaid ' , ' Un-Paid Holiday ' ) ,
2010-06-06 16:29:11 +00:00
( ' halfpaid ' , ' Half-Pay Holiday ' )
] , string = ' Payment ' ) ,
2010-06-18 00:51:41 +00:00
' head_id ' : fields . many2one ( ' hr.allounce.deduction.categoty ' , ' Payroll Head ' , domain = [ ( ' type ' , ' = ' , ' deduction ' ) ] ) ,
2011-03-01 11:29:08 +00:00
# 'code': fields.related('head_id','code', type='char', relation='hr.allounce.deduction.categoty', string='Code'),
' code ' : fields . char ( ' Code ' , size = 64 , required = False , readonly = False ) ,
2010-06-06 16:29:11 +00:00
}
_defaults = {
' type ' : lambda * args : ' unpaid ' ,
' company_id ' : lambda self , cr , uid , context : \
self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid ,
context = context ) . company_id . id ,
}
hr_holidays_status ( )
class hr_payslip ( osv . osv ) :
'''
Pay Slip
'''
2010-10-26 12:23:32 +00:00
2010-06-06 16:29:11 +00:00
_name = ' hr.payslip '
_description = ' Pay Slip '
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
def _calculate ( self , cr , uid , ids , field_names , arg , context = None ) :
slip_line_obj = self . pool . get ( ' hr.payslip.line ' )
2010-06-06 16:29:11 +00:00
res = { }
2010-07-27 07:11:45 +00:00
for rs in self . browse ( cr , uid , ids , context = context ) :
2010-06-06 16:29:11 +00:00
allow = 0.0
deduct = 0.0
others = 0.0
2010-10-06 12:44:54 +00:00
obj = { ' basic ' : rs . basic }
2010-06-18 00:51:41 +00:00
if rs . igross > 0 :
2010-10-06 12:44:54 +00:00
obj [ ' gross ' ] = rs . igross
2010-06-18 00:51:41 +00:00
if rs . inet > 0 :
2010-10-06 12:44:54 +00:00
obj [ ' net ' ] = rs . inet
2010-06-06 16:29:11 +00:00
for line in rs . line_ids :
amount = 0.0
if line . amount_type == ' per ' :
2010-06-18 00:51:41 +00:00
try :
amount = line . amount * eval ( str ( line . category_id . base ) , obj )
except Exception , e :
2010-11-19 12:20:03 +00:00
raise osv . except_osv ( _ ( ' Variable Error ! ' ) , _ ( ' Variable Error: %s ' ) % ( e ) )
2010-06-06 16:29:11 +00:00
elif line . amount_type in ( ' fix ' , ' func ' ) :
amount = line . amount
cd = line . category_id . code . lower ( )
obj [ cd ] = amount
contrib = 0.0
2011-02-25 13:07:26 +00:00
if line . type . name == ' allowance ' :
2010-06-06 16:29:11 +00:00
allow + = amount
others + = contrib
amount - = contrib
2011-02-25 13:07:26 +00:00
elif line . type . name == ' deduction ' :
2010-06-06 16:29:11 +00:00
deduct + = amount
others - = contrib
amount + = contrib
2010-07-27 07:11:45 +00:00
slip_line_obj . write ( cr , uid , [ line . id ] , { ' total ' : amount } , context = context )
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
record = {
2010-11-03 08:04:42 +00:00
' allounce ' : allow ,
' deduction ' : deduct ,
' grows ' : rs . basic + allow ,
' net ' : rs . basic + allow - deduct ,
2010-06-06 16:29:11 +00:00
' other_pay ' : others ,
2010-11-03 08:04:42 +00:00
' total_pay ' : rs . basic + allow - deduct
2010-06-06 16:29:11 +00:00
}
res [ rs . id ] = record
return res
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
_columns = {
2010-10-06 12:44:54 +00:00
' deg_id ' : fields . many2one ( ' hr.payroll.structure ' , ' Designation ' , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
' register_id ' : fields . many2one ( ' hr.payroll.register ' , ' Register ' , required = False , readonly = True , states = { ' new ' : [ ( ' readonly ' , False ) ] } ) ,
' name ' : fields . char ( ' Name ' , size = 64 , required = False , readonly = True , states = { ' new ' : [ ( ' readonly ' , False ) ] } ) ,
2010-06-06 16:29:11 +00:00
' number ' : fields . char ( ' Number ' , size = 64 , required = False , readonly = True ) ,
2010-10-06 12:44:54 +00:00
' employee_id ' : fields . many2one ( ' hr.employee ' , ' Employee ' , required = True , readonly = True , states = { ' new ' : [ ( ' readonly ' , False ) ] } ) ,
' date ' : fields . date ( ' Date ' , readonly = True , states = { ' new ' : [ ( ' readonly ' , False ) ] } ) ,
2010-06-06 16:29:11 +00:00
' state ' : fields . selection ( [
( ' new ' , ' New Slip ' ) ,
( ' draft ' , ' Wating for Verification ' ) ,
( ' hr_check ' , ' Wating for HR Verification ' ) ,
( ' accont_check ' , ' Wating for Account Verification ' ) ,
( ' confirm ' , ' Confirm Sheet ' ) ,
( ' done ' , ' Paid Salary ' ) ,
( ' cancel ' , ' Reject ' ) ,
] , ' State ' , select = True , readonly = True ) ,
2010-11-03 08:04:42 +00:00
' basic_before_leaves ' : fields . float ( ' Basic Salary ' , readonly = True , digits_compute = dp . get_precision ( ' Account ' ) ) ,
' leaves ' : fields . float ( ' Leave Deductions ' , readonly = True , digits_compute = dp . get_precision ( ' Account ' ) ) ,
' basic ' : fields . float ( ' Net Basic ' , readonly = True , digits_compute = dp . get_precision ( ' Account ' ) ) ,
' grows ' : fields . function ( _calculate , method = True , store = True , multi = ' dc ' , string = ' Gross Salary ' , digits_compute = dp . get_precision ( ' Account ' ) ) ,
' net ' : fields . function ( _calculate , method = True , store = True , multi = ' dc ' , string = ' Net Salary ' , digits_compute = dp . get_precision ( ' Account ' ) ) ,
' allounce ' : fields . function ( _calculate , method = True , store = True , multi = ' dc ' , string = ' Allowance ' , digits_compute = dp . get_precision ( ' Account ' ) ) ,
' deduction ' : fields . function ( _calculate , method = True , store = True , multi = ' dc ' , string = ' Deduction ' , digits_compute = dp . get_precision ( ' Account ' ) ) ,
' other_pay ' : fields . function ( _calculate , method = True , store = True , multi = ' dc ' , string = ' Others ' , digits_compute = dp . get_precision ( ' Account ' ) ) ,
' total_pay ' : fields . function ( _calculate , method = True , store = True , multi = ' dc ' , string = ' Total Payment ' , digits_compute = dp . get_precision ( ' Account ' ) ) ,
2010-06-06 16:29:11 +00:00
' line_ids ' : fields . one2many ( ' hr.payslip.line ' , ' slip_id ' , ' Payslip Line ' , required = False , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2010-10-06 12:44:54 +00:00
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' , required = False , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
' holiday_days ' : fields . float ( ' No of Leaves ' , readonly = True ) ,
' worked_days ' : fields . float ( ' Worked Day ' , readonly = True ) ,
' working_days ' : fields . float ( ' Working Days ' , readonly = True ) ,
' paid ' : fields . boolean ( ' Paid ? ' , required = False , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2010-06-06 16:29:11 +00:00
' note ' : fields . text ( ' Description ' ) ,
2010-10-06 12:44:54 +00:00
' contract_id ' : fields . many2one ( ' hr.contract ' , ' Contract ' , required = False , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2010-06-18 00:51:41 +00:00
' igross ' : fields . float ( ' Calculaton Field ' , readonly = True , digits = ( 16 , 2 ) , help = " Calculation field used for internal calculation, do not place this on form " ) ,
' inet ' : fields . float ( ' Calculaton Field ' , readonly = True , digits = ( 16 , 2 ) , help = " Calculation field used for internal calculation, do not place this on form " ) ,
2010-06-06 16:29:11 +00:00
}
_defaults = {
' date ' : lambda * a : time . strftime ( ' % Y- % m- %d ' ) ,
' state ' : lambda * a : ' new ' ,
' company_id ' : lambda self , cr , uid , context : \
self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid ,
context = context ) . company_id . id ,
}
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
def copy ( self , cr , uid , id , default = None , context = None ) :
company_id = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context = context ) . company_id . id
default = {
' line_ids ' : False ,
' move_ids ' : False ,
' move_line_ids ' : False ,
' move_payment_ids ' : False ,
' company_id ' : company_id ,
' period_id ' : False ,
' basic_before_leaves ' : 0 ,
' basic ' : 0
}
2010-07-27 07:11:45 +00:00
res_id = super ( hr_payslip , self ) . copy ( cr , uid , id , default , context = context )
2010-06-06 16:29:11 +00:00
return res_id
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
def create_voucher ( self , cr , uid , ids , name , voucher , sequence = 5 ) :
slip_move = self . pool . get ( ' hr.payslip.account.move ' )
for slip in ids :
res = {
' slip_id ' : slip ,
' move_id ' : voucher ,
' sequence ' : sequence ,
' name ' : name
}
slip_move . create ( cr , uid , res )
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
def set_to_draft ( self , cr , uid , ids , context = None ) :
self . write ( cr , uid , ids , { ' state ' : ' draft ' } , context = context )
2010-06-06 16:29:11 +00:00
return True
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
def cancel_sheet ( self , cr , uid , ids , context = None ) :
self . write ( cr , uid , ids , { ' state ' : ' cancel ' } , context = context )
2010-06-06 16:29:11 +00:00
return True
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
def account_check_sheet ( self , cr , uid , ids , context = None ) :
self . write ( cr , uid , ids , { ' state ' : ' accont_check ' } , context = context )
2010-06-06 16:29:11 +00:00
return True
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
def hr_check_sheet ( self , cr , uid , ids , context = None ) :
self . write ( cr , uid , ids , { ' state ' : ' hr_check ' } , context = context )
2010-06-06 16:29:11 +00:00
return True
2010-07-27 07:11:45 +00:00
def process_sheet ( self , cr , uid , ids , context = None ) :
2010-10-06 12:44:54 +00:00
self . write ( cr , uid , ids , { ' paid ' : True , ' state ' : ' done ' } , context = context )
2010-07-02 10:37:15 +00:00
return True
2010-10-26 12:23:32 +00:00
2010-11-19 13:48:01 +00:00
def verify_sheet ( self , cr , uid , ids , context = None ) :
2011-03-01 09:59:10 +00:00
# register_pool = self.pool.get('company.contribution')
2010-10-06 12:44:54 +00:00
register_line_pool = self . pool . get ( ' hr.contibution.register.line ' )
2010-10-26 12:23:32 +00:00
2010-10-06 12:44:54 +00:00
for slip in self . browse ( cr , uid , ids , context = context ) :
base = {
' basic ' : slip . basic ,
' net ' : slip . net ,
' gross ' : slip . grows ,
}
2011-03-01 09:59:10 +00:00
# rules = slip.contract_id.struct_id.rule_ids
# if rules:
# for rl in rules:
# if rl.contribute_ids:
# base[rl.code.lower()] = rl.amount
# for contrib in rl.contribute_ids:
# if contrib.register_id:
# value = eval(rl.category_id.base, base)
# company_contrib = register_pool.compute(cr, uid, contrib.id, value, context)
# reg_line = {
# 'name':rl.name,
# 'register_id': contrib.register_id.id,
# 'code':rl.code,
# 'employee_id':slip.employee_id.id,
# 'emp_deduction':rl.amount,
# 'comp_deduction':company_contrib,
# 'total':rl.amount + rl.amount
# }
# register_line_pool.create(cr, uid, reg_line)
2010-10-26 12:23:32 +00:00
2010-07-27 07:11:45 +00:00
self . write ( cr , uid , ids , { ' state ' : ' confirm ' } , context = context )
2010-06-06 16:29:11 +00:00
return True
2010-07-27 07:11:45 +00:00
def get_contract ( self , cr , uid , employee , date , context = None ) :
2010-06-18 00:51:41 +00:00
sql_req = '''
SELECT c . id as id , c . wage as wage , struct_id as function
FROM hr_contract c
LEFT JOIN hr_employee emp on ( c . employee_id = emp . id )
LEFT JOIN hr_contract_wage_type cwt on ( cwt . id = c . wage_type_id )
LEFT JOIN hr_contract_wage_type_period p on ( cwt . period_id = p . id )
WHERE
( emp . id = % s ) AND
( date_start < = % s ) AND
( date_end IS NULL OR date_end > = % s )
LIMIT 1
'''
cr . execute ( sql_req , ( employee . id , date , date ) )
2010-07-01 07:31:46 +00:00
contract = cr . dictfetchone ( )
2010-06-29 17:22:04 +00:00
contract = contract and contract or { }
2010-06-18 00:51:41 +00:00
return contract
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
def _get_leaves ( self , cr , user , slip , employee , context = None ) :
2010-06-18 03:11:40 +00:00
"""
Compute leaves for an employee
2010-07-01 07:31:46 +00:00
2010-06-18 03:11:40 +00:00
@param cr : cursor to database
@param user : id of current user
@param slip : object of the hr . payroll . slip model
@param employee : object of the hr . employee model
@param context : context arguments , like lang , time zone
2010-07-01 07:31:46 +00:00
2010-06-18 03:11:40 +00:00
@return : return a result
"""
result = [ ]
dates = prev_bounds ( slip . date )
sql = ''' select id from hr_holidays
2010-07-01 07:31:46 +00:00
where date_from > = ' %s ' and date_to < = ' %s '
and employee_id = % s
2010-06-18 03:11:40 +00:00
and state = ' validate ' ''' % (dates[0], dates[1], slip.employee_id.id)
cr . execute ( sql )
res = cr . fetchall ( )
if res :
result = [ x [ 0 ] for x in res ]
2010-07-01 07:31:46 +00:00
2010-06-18 03:11:40 +00:00
return result
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
def compute_sheet ( self , cr , uid , ids , context = None ) :
2010-06-06 18:26:08 +00:00
func_pool = self . pool . get ( ' hr.payroll.structure ' )
2010-06-06 16:29:11 +00:00
slip_line_pool = self . pool . get ( ' hr.payslip.line ' )
holiday_pool = self . pool . get ( ' hr.holidays ' )
2010-07-27 07:11:45 +00:00
sequence_obj = self . pool . get ( ' ir.sequence ' )
if context is None :
context = { }
date = self . read ( cr , uid , ids , [ ' date ' ] , context = context ) [ 0 ] [ ' date ' ]
2010-07-01 07:31:46 +00:00
2010-06-18 03:11:40 +00:00
#Check for the Holidays
def get_days ( start , end , month , year , calc_day ) :
import datetime
count = 0
for day in range ( start , end ) :
if datetime . date ( year , month , day ) . weekday ( ) == calc_day :
count + = 1
return count
2010-07-01 07:31:46 +00:00
2010-10-26 12:23:32 +00:00
for slip in self . browse ( cr , uid , ids , context = context ) :
2010-10-06 12:44:54 +00:00
old_slip_ids = slip_line_pool . search ( cr , uid , [ ( ' slip_id ' , ' = ' , slip . id ) ] , context = context )
slip_line_pool . unlink ( cr , uid , old_slip_ids , context = context )
2010-10-06 13:47:24 +00:00
update = { }
ttyme = datetime . fromtimestamp ( time . mktime ( time . strptime ( slip . date , " % Y- % m- %d " ) ) )
contracts = self . get_contract ( cr , uid , slip . employee_id , date , context )
if contracts . get ( ' id ' , False ) == False :
update . update ( {
' basic ' : round ( 0.0 ) ,
' basic_before_leaves ' : round ( 0.0 ) ,
2010-12-24 12:05:44 +00:00
' name ' : ' Salary Slip of %s for %s ' % ( slip . employee_id . name , tools . ustr ( ttyme . strftime ( ' % B- % Y ' ) ) ) ,
2010-10-06 13:47:24 +00:00
' state ' : ' draft ' ,
' contract_id ' : False ,
' company_id ' : slip . employee_id . company_id . id
} )
self . write ( cr , uid , [ slip . id ] , update , context = context )
2010-06-06 16:29:11 +00:00
continue
2010-07-01 07:31:46 +00:00
2010-10-06 12:44:54 +00:00
contract = slip . employee_id . contract_id
2010-06-06 16:29:11 +00:00
sal_type = contract . wage_type_id . type
2010-06-18 00:51:41 +00:00
function = contract . struct_id . id
2010-06-06 16:29:11 +00:00
lines = [ ]
if function :
2011-02-24 13:12:20 +00:00
func = func_pool . read ( cr , uid , function , [ ' rule_ids ' ] , context = context )
lines = self . pool . get ( ' hr.salary.rule ' ) . browse ( cr , uid , func [ ' rule_ids ' ] , context = context )
2010-07-01 07:31:46 +00:00
2010-10-08 13:18:45 +00:00
#lines += slip.employee_id.line_ids
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
ad = [ ]
all_per = 0.0
ded_per = 0.0
all_fix = 0.0
ded_fix = 0.0
2010-07-01 07:31:46 +00:00
2010-10-06 12:44:54 +00:00
obj = { ' basic ' : 0.0 }
2010-06-06 16:29:11 +00:00
if contract . wage_type_id . type == ' gross ' :
obj [ ' gross ' ] = contract . wage
2010-06-18 00:51:41 +00:00
update [ ' igross ' ] = contract . wage
2010-06-06 16:29:11 +00:00
if contract . wage_type_id . type == ' net ' :
obj [ ' net ' ] = contract . wage
2010-06-18 00:51:41 +00:00
update [ ' inet ' ] = contract . wage
2010-06-06 16:29:11 +00:00
if contract . wage_type_id . type == ' basic ' :
obj [ ' basic ' ] = contract . wage
2010-06-18 00:51:41 +00:00
update [ ' basic ' ] = contract . wage
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
for line in lines :
cd = line . code . lower ( )
2010-06-18 00:51:41 +00:00
obj [ cd ] = line . amount or 0.0
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
for line in lines :
if line . category_id . code in ad :
continue
ad . append ( line . category_id . code )
cd = line . category_id . code . lower ( )
2010-06-18 00:51:41 +00:00
calculate = False
2010-06-06 16:29:11 +00:00
try :
exp = line . category_id . condition
calculate = eval ( exp , obj )
except Exception , e :
2010-11-19 12:20:03 +00:00
raise osv . except_osv ( _ ( ' Variable Error ! ' ) , _ ( ' Variable Error: %s ' ) % ( e ) )
2010-06-06 16:29:11 +00:00
if not calculate :
continue
2010-07-01 07:31:46 +00:00
2010-06-18 00:51:41 +00:00
percent = 0.0
2010-06-06 16:29:11 +00:00
value = 0.0
base = False
2010-10-28 04:27:05 +00:00
# company_contrib = 0.0
2010-06-18 00:51:41 +00:00
base = line . category_id . base
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
try :
2010-10-06 13:47:24 +00:00
#Please have a look at the configuration guide.
2010-06-18 00:51:41 +00:00
amt = eval ( base , obj )
2010-06-06 16:29:11 +00:00
except Exception , e :
2010-11-19 12:20:03 +00:00
raise osv . except_osv ( _ ( ' Variable Error ! ' ) , _ ( ' Variable Error: %s ' ) % ( e ) )
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
if sal_type in ( ' gross ' , ' net ' ) :
if line . amount_type == ' per ' :
2010-06-18 00:51:41 +00:00
percent = line . amount
2010-06-06 16:29:11 +00:00
if amt > 1 :
2010-06-18 00:51:41 +00:00
value = percent * amt
elif amt > 0 and amt < = 1 :
percent = percent * amt
if value > 0 :
percent = 0.0
elif line . amount_type == ' fix ' :
2010-06-06 16:29:11 +00:00
value = line . amount
2010-06-18 00:51:41 +00:00
elif line . amount_type == ' func ' :
2011-02-24 13:12:20 +00:00
value = self . pool . get ( ' hr.salary.rule ' ) . execute_function ( cr , uid , line . id , amt , context )
2010-06-18 00:51:41 +00:00
line . amount = value
2010-06-06 16:29:11 +00:00
else :
if line . amount_type in ( ' fix ' , ' per ' ) :
value = line . amount
elif line . amount_type == ' func ' :
2011-02-24 13:12:20 +00:00
value = self . pool . get ( ' hr.salary.rule ' ) . execute_function ( cr , uid , line . id , amt , context )
2010-06-18 03:11:40 +00:00
line . amount = value
2011-02-25 13:07:26 +00:00
if line . type . name == ' allowance ' :
2010-06-18 00:51:41 +00:00
all_per + = percent
2010-06-06 16:29:11 +00:00
all_fix + = value
2011-02-25 13:07:26 +00:00
elif line . type . name == ' deduction ' :
2010-06-18 00:51:41 +00:00
ded_per + = percent
2010-06-06 16:29:11 +00:00
ded_fix + = value
2011-02-24 13:12:20 +00:00
# vals = {
# 'amount':line.amount,
# 'slip_id':slip.id,
# 'employee_id':False,
# 'function_id':False,
# 'base':base
# }
# slip_line_pool.copy(cr, uid, line.id, vals, {})
res = {
' name ' : line . name ,
' code ' : line . code ,
2011-02-25 13:07:26 +00:00
' type ' : line . type . id ,
2011-02-24 13:12:20 +00:00
' amount_type ' : line . amount_type ,
' category_id ' : line . category_id . id ,
' sequence ' : line . sequence ,
2010-07-01 07:31:46 +00:00
' amount ' : line . amount ,
' slip_id ' : slip . id ,
' employee_id ' : False ,
2011-03-02 07:12:38 +00:00
# 'function_id':False,
2010-06-06 16:29:11 +00:00
' base ' : base
}
2011-02-25 13:07:26 +00:00
if line . min_range or line . max_range :
if not ( ( line . amount < line . min_range ) or ( line . amount > line . max_range ) ) :
slip_line_pool . create ( cr , uid , res , context = context )
else :
slip_line_pool . create ( cr , uid , res , context = context )
2010-06-06 16:29:11 +00:00
if sal_type in ( ' gross ' , ' net ' ) :
sal = contract . wage
if sal_type == ' net ' :
sal + = ded_fix
sal - = all_fix
per = 0.0
if sal_type == ' net ' :
per = ( all_per - ded_per )
else :
per = all_per
2010-10-27 12:49:59 +00:00
if per < = 0 :
2010-06-06 16:29:11 +00:00
per * = - 1
final = ( per * 100 ) + 100
basic = ( sal * 100 ) / final
else :
basic = contract . wage
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
number = sequence_obj . get ( cr , uid , ' salary.slip ' )
2010-06-18 03:11:40 +00:00
update . update ( {
' deg_id ' : function ,
2010-07-01 07:31:46 +00:00
' number ' : number ,
2010-06-18 03:11:40 +00:00
' basic ' : round ( basic ) ,
' basic_before_leaves ' : round ( basic ) ,
2010-12-24 12:05:44 +00:00
' name ' : ' Salary Slip of %s for %s ' % ( slip . employee_id . name , tools . ustr ( ttyme . strftime ( ' % B- % Y ' ) ) ) ,
2010-06-18 03:11:40 +00:00
' state ' : ' draft ' ,
' contract_id ' : contract . id ,
' company_id ' : slip . employee_id . company_id . id
} )
2010-10-26 12:23:32 +00:00
2010-10-08 13:18:45 +00:00
for line in slip . employee_id . line_ids :
vals = {
' amount ' : line . amount ,
' slip_id ' : slip . id ,
' employee_id ' : False ,
2011-03-02 07:12:38 +00:00
# 'function_id':False,
2010-10-08 13:18:45 +00:00
' base ' : base
}
slip_line_pool . copy ( cr , uid , line . id , vals , { } )
2010-10-26 12:23:32 +00:00
2010-07-27 07:11:45 +00:00
self . write ( cr , uid , [ slip . id ] , update , context = context )
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
for slip in self . browse ( cr , uid , ids , context = context ) :
2010-10-06 13:47:24 +00:00
if not slip . contract_id :
2010-06-29 17:22:04 +00:00
continue
2010-07-01 07:31:46 +00:00
2010-06-29 17:22:04 +00:00
basic_before_leaves = slip . basic
2010-06-06 16:29:11 +00:00
working_day = 0
off_days = 0
2010-06-18 03:11:40 +00:00
dates = prev_bounds ( slip . date )
2010-07-01 07:31:46 +00:00
2010-06-18 03:11:40 +00:00
days_arr = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 ]
2010-10-06 12:44:54 +00:00
for dy in range ( slip . employee_id . contract_id . working_days_per_week , 7 ) :
2010-06-18 03:11:40 +00:00
off_days + = get_days ( 1 , dates [ 1 ] . day , dates [ 1 ] . month , dates [ 1 ] . year , days_arr [ dy ] )
total_off = off_days
working_day = dates [ 1 ] . day - total_off
perday = slip . net / working_day
2010-06-06 16:29:11 +00:00
total = 0.0
leave = 0.0
2010-06-18 03:11:40 +00:00
leave_ids = self . _get_leaves ( cr , uid , slip , slip . employee_id , context )
total_leave = 0.0
paid_leave = 0.0
2010-07-27 07:11:45 +00:00
for hday in holiday_pool . browse ( cr , uid , leave_ids , context = context ) :
2010-10-07 06:31:56 +00:00
if not hday . holiday_status_id . head_id :
2010-11-18 16:21:31 +00:00
raise osv . except_osv ( _ ( ' Error ! ' ) , _ ( ' Please check configuration of %s , payroll head is missing ' ) % ( hday . holiday_status_id . name ) )
2010-10-26 12:23:32 +00:00
2010-06-18 03:11:40 +00:00
res = {
' slip_id ' : slip . id ,
' name ' : hday . holiday_status_id . name + ' - %s ' % ( hday . number_of_days ) ,
' code ' : hday . holiday_status_id . code ,
' amount_type ' : ' fix ' ,
' category_id ' : hday . holiday_status_id . head_id . id ,
2010-10-06 12:44:54 +00:00
' sequence ' : hday . holiday_status_id . head_id . sequence
2010-06-18 03:11:40 +00:00
}
days = hday . number_of_days
if hday . number_of_days < 0 :
days = hday . number_of_days * - 1
total_leave + = days
if hday . holiday_status_id . type == ' paid ' :
paid_leave + = days
continue
2010-10-06 12:44:54 +00:00
# res['name'] = hday.holiday_status_id.name + '-%s' % (days)
# res['amount'] = perday * days
# res['type'] = 'allowance'
# leave += days
# total += perday * days
2010-10-26 12:23:32 +00:00
2010-06-18 03:11:40 +00:00
elif hday . holiday_status_id . type == ' halfpaid ' :
paid_leave + = ( days / 2 )
res [ ' name ' ] = hday . holiday_status_id . name + ' - %s /2 ' % ( days )
res [ ' amount ' ] = perday * ( days / 2 )
total + = perday * ( days / 2 )
leave + = days / 2
res [ ' type ' ] = ' deduction '
else :
res [ ' name ' ] = hday . holiday_status_id . name + ' - %s ' % ( days )
res [ ' amount ' ] = perday * days
res [ ' type ' ] = ' deduction '
leave + = days
total + = perday * days
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
slip_line_pool . create ( cr , uid , res , context = context )
2010-06-18 03:11:40 +00:00
basic = basic - total
2010-10-28 04:27:05 +00:00
# leaves = total
2010-06-18 00:51:41 +00:00
update . update ( {
2010-10-06 12:44:54 +00:00
' basic ' : basic ,
2010-06-06 16:29:11 +00:00
' basic_before_leaves ' : round ( basic_before_leaves ) ,
' leaves ' : total ,
' holiday_days ' : leave ,
' worked_days ' : working_day - leave ,
' working_days ' : working_day ,
2010-06-18 00:51:41 +00:00
} )
2010-07-27 07:11:45 +00:00
self . write ( cr , uid , [ slip . id ] , update , context = context )
2010-06-06 16:29:11 +00:00
return True
hr_payslip ( )
class hr_payslip_line ( osv . osv ) :
'''
Payslip Line
'''
2010-10-26 12:23:32 +00:00
2010-06-06 16:29:11 +00:00
_name = ' hr.payslip.line '
_description = ' Payslip Line '
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
def onchange_category ( self , cr , uid , ids , category_id ) :
2010-06-18 00:51:41 +00:00
res = {
}
2010-06-06 16:29:11 +00:00
if category_id :
2010-06-18 00:51:41 +00:00
category = self . pool . get ( ' hr.allounce.deduction.categoty ' ) . browse ( cr , uid , category_id )
res . update ( {
' sequence ' : category . sequence ,
' name ' : category . name ,
' code ' : category . code ,
2011-02-25 13:07:26 +00:00
' type ' : category . type . id
2010-06-18 00:51:41 +00:00
} )
return { ' value ' : res }
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
def onchange_amount ( self , cr , uid , ids , amount , typ ) :
amt = amount
if typ and typ == ' per ' :
if int ( amt ) > 0 :
amt = amt / 100
return { ' value ' : { ' amount ' : amt } }
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
_columns = {
' slip_id ' : fields . many2one ( ' hr.payslip ' , ' Pay Slip ' , required = False ) ,
2011-03-02 07:12:38 +00:00
# 'function_id':fields.many2one('hr.payroll.structure', 'Function', required=False),
2010-06-06 16:29:11 +00:00
' employee_id ' : fields . many2one ( ' hr.employee ' , ' Employee ' , required = False ) ,
' name ' : fields . char ( ' Name ' , size = 256 , required = True , readonly = False ) ,
' base ' : fields . char ( ' Formula ' , size = 1024 , required = False , readonly = False ) ,
2010-10-26 12:23:32 +00:00
' code ' : fields . char ( ' Code ' , size = 64 , required = False , readonly = False ) ,
2010-10-07 06:31:56 +00:00
' category_id ' : fields . many2one ( ' hr.allounce.deduction.categoty ' , ' Category ' , required = True ) ,
2011-02-25 13:07:26 +00:00
' type ' : fields . many2one ( ' salary.head.type ' , ' Type ' , required = True ) ,
2010-06-06 16:29:11 +00:00
' amount_type ' : fields . selection ( [
( ' per ' , ' Percentage ( % ) ' ) ,
( ' fix ' , ' Fixed Amount ' ) ,
2011-03-01 11:29:08 +00:00
( ' code ' , ' Python Code ' ) ,
2010-10-07 06:31:56 +00:00
] , ' Amount Type ' , select = True , required = True ) ,
2010-06-06 16:29:11 +00:00
' amount ' : fields . float ( ' Amount / Percentage ' , digits = ( 16 , 4 ) ) ,
2010-11-03 08:04:42 +00:00
' total ' : fields . float ( ' Sub Total ' , readonly = True , digits_compute = dp . get_precision ( ' Account ' ) ) ,
2010-07-07 06:21:07 +00:00
' company_contrib ' : fields . float ( ' Company Contribution ' , readonly = True , digits = ( 16 , 4 ) ) ,
2010-06-06 16:29:11 +00:00
' sequence ' : fields . integer ( ' Sequence ' ) ,
' note ' : fields . text ( ' Description ' ) ,
2011-03-01 11:29:08 +00:00
' line_ids ' : fields . one2many ( ' hr.payslip.line.line ' , ' slipline_id ' , ' Calculations ' , required = False ) ,
' exp ' : fields . text ( ' Expression ' ) ,
2010-06-06 16:29:11 +00:00
}
_order = ' sequence '
2010-10-07 06:31:56 +00:00
_defaults = {
' amount_type ' : lambda * a : ' per '
}
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
def execute_function ( self , cr , uid , id , value , context = None ) :
2010-06-06 16:29:11 +00:00
line_pool = self . pool . get ( ' hr.payslip.line.line ' )
res = 0
2010-07-27 07:11:45 +00:00
ids = line_pool . search ( cr , uid , [ ( ' slipline_id ' , ' = ' , id ) , ( ' from_val ' , ' <= ' , value ) , ( ' to_val ' , ' >= ' , value ) ] , context = context )
2010-06-06 16:29:11 +00:00
if not ids :
2010-07-27 07:11:45 +00:00
ids = line_pool . search ( cr , uid , [ ( ' slipline_id ' , ' = ' , id ) , ( ' from_val ' , ' <= ' , value ) ] , context = context )
2010-06-06 16:29:11 +00:00
if not ids :
2010-06-18 00:51:41 +00:00
return res
2010-07-01 07:31:46 +00:00
2010-07-27 07:11:45 +00:00
res = line_pool . browse ( cr , uid , ids , context = context ) [ - 1 ] . value
2010-06-06 16:29:11 +00:00
return res
2010-07-01 07:31:46 +00:00
2010-06-06 16:29:11 +00:00
hr_payslip_line ( )
2011-02-24 13:12:20 +00:00
class hr_salary_rule ( osv . osv ) :
_inherit = ' hr.payslip.line '
_name = ' hr.salary.rule '
_columns = {
2011-03-02 08:48:15 +00:00
' appears_on_payslip ' : fields . boolean ( ' Appears on Payslip ' , help = " Do you want to display rule on payslip? " ) ,
2011-03-02 08:53:59 +00:00
' min_range ' : fields . float ( ' Minimum Range ' , required = False , help = " The minimum amount, applied for this rule. " ) ,
' max_range ' : fields . float ( ' Maximum Range ' , required = False , help = " The maximum amount, applied for this rule. " ) ,
2011-02-25 13:33:39 +00:00
' sal_rule_id ' : fields . many2one ( ' hr.salary.rule ' , ' Parent Salary Structure ' , select = True ) ,
2011-02-25 13:35:52 +00:00
' child_depend ' : fields . boolean ( ' Children Rule ' ) ,
2011-02-25 13:33:39 +00:00
' child_ids ' : fields . one2many ( ' hr.salary.rule ' , ' sal_rule_id ' , ' Child Salary Sructure ' ) ,
2011-03-01 09:59:10 +00:00
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' , required = False ) ,
' register_id ' : fields . many2one ( ' hr.contibution.register ' , ' Contri Reg ' , select = True ) ,
2011-02-24 13:12:20 +00:00
}
_defaults = {
2011-03-01 11:29:08 +00:00
' appears_on_payslip ' : 1
2011-02-24 13:12:20 +00:00
}
hr_salary_rule ( )
2010-06-06 16:29:11 +00:00
class hr_payslip_line_line ( osv . osv ) :
'''
Function Line
'''
2010-10-26 12:23:32 +00:00
2010-06-06 16:29:11 +00:00
_name = ' hr.payslip.line.line '
_description = ' Function Line '
_order = ' sequence '
_columns = {
' slipline_id ' : fields . many2one ( ' hr.payslip.line ' , ' Slip Line ' , required = False ) ,
' name ' : fields . char ( ' Name ' , size = 64 , required = False , readonly = False ) ,
2010-07-07 06:21:07 +00:00
' from_val ' : fields . float ( ' From ' , digits = ( 16 , 4 ) ) ,
' to_val ' : fields . float ( ' To ' , digits = ( 16 , 4 ) ) ,
2010-06-06 16:29:11 +00:00
' amount_type ' : fields . selection ( [
( ' fix ' , ' Fixed Amount ' ) ,
] , ' Amount Type ' , select = True ) ,
' sequence ' : fields . integer ( ' Sequence ' ) ,
2010-07-07 06:21:07 +00:00
' value ' : fields . float ( ' Value ' , digits = ( 16 , 4 ) ) ,
2010-06-06 16:29:11 +00:00
}
hr_payslip_line_line ( )
2011-02-24 13:12:20 +00:00
class hr_payroll_structure ( osv . osv ) :
_inherit = ' hr.payroll.structure '
_columns = {
2011-02-25 13:07:26 +00:00
' rule_ids ' : fields . many2many ( ' hr.salary.rule ' , ' hr_structure_salary_rule_rel ' , ' struct_id ' , ' rule_id ' , ' Salary Rules ' , readonly = False ) ,
2011-02-24 13:12:20 +00:00
}
hr_payroll_structure ( )
2010-06-06 16:29:11 +00:00
class hr_employee ( osv . osv ) :
'''
Employee
'''
2010-10-26 12:23:32 +00:00
2010-06-06 16:29:11 +00:00
_inherit = ' hr.employee '
_description = ' Employee '
2010-10-26 12:23:32 +00:00
2010-10-08 09:05:55 +00:00
def _calculate_salary ( self , cr , uid , ids , field_names , arg , context = None ) :
vals = { }
slip_line_pool = self . pool . get ( ' hr.payslip.line ' )
2010-10-26 12:23:32 +00:00
2010-11-19 13:48:01 +00:00
for employee in self . browse ( cr , uid , ids , context = context ) :
2010-10-08 09:05:55 +00:00
if not employee . contract_id :
vals [ employee . id ] = { ' basic ' : 0.0 , ' gross ' : 0.0 , ' net ' : 0.0 , ' advantages_gross ' : 0.0 , ' advantages_net ' : 0.0 }
continue
2010-10-26 12:23:32 +00:00
2010-10-08 09:05:55 +00:00
basic = employee . contract_id . basic
gross = employee . contract_id . gross
net = employee . contract_id . net
allowance = employee . contract_id . advantages_gross
deduction = employee . contract_id . advantages_net
2010-10-26 12:23:32 +00:00
2010-10-08 09:05:55 +00:00
obj = {
2010-10-26 12:23:32 +00:00
' basic ' : basic ,
' gross ' : gross ,
2010-10-08 09:05:55 +00:00
' net ' : net
}
for line in employee . line_ids :
base = line . category_id . base
try :
amt = eval ( base , obj )
except Exception , e :
2010-11-18 16:21:31 +00:00
raise osv . except_osv ( _ ( ' Variable Error ! ' ) , _ ( ' Variable Error: %s ' ) % ( e ) )
2010-10-08 09:05:55 +00:00
amount = 0.0
if line . amount_type == ' per ' :
amount = amt * line . amount
elif line . amount_type == ' func ' :
amount = slip_line_pool . execute_function ( cr , uid , line . id , amt , context )
elif line . amount_type == ' fix ' :
amount = line . amount
2010-10-26 12:23:32 +00:00
2011-02-25 13:07:26 +00:00
if line . type . name == ' allowance ' :
2010-10-08 09:05:55 +00:00
allowance + = amount
2011-02-25 13:07:26 +00:00
elif line . type . name == ' deduction ' :
2010-10-08 09:05:55 +00:00
deduction + = amount
2010-10-26 12:23:32 +00:00
2010-10-08 09:05:55 +00:00
vals [ employee . id ] = {
2010-10-26 12:23:32 +00:00
' basic ' : basic ,
' advantages_gross ' : allowance ,
' gross ' : basic + allowance ,
2010-10-08 09:05:55 +00:00
' advantages_net ' : deduction ,
' net ' : basic + allowance - deduction
}
return vals
2010-10-26 12:23:32 +00:00
2010-06-06 16:29:11 +00:00
_columns = {
2010-12-13 08:21:34 +00:00
' passport_id ' : fields . many2one ( ' hr.passport ' , ' Passport No ' , required = False , domain = " [( ' employee_id ' , ' = ' ,active_id), ( ' address_id ' , ' = ' ,address_home_id)] " , help = " Employee Passport Information " ) ,
2010-06-06 16:29:11 +00:00
' line_ids ' : fields . one2many ( ' hr.payslip.line ' , ' employee_id ' , ' Salary Structure ' , required = False ) ,
' slip_ids ' : fields . one2many ( ' hr.payslip ' , ' employee_id ' , ' Payslips ' , required = False , readonly = True ) ,
2010-10-08 09:05:55 +00:00
' otherid ' : fields . char ( ' Other Id ' , size = 64 ) ,
2010-10-26 12:23:32 +00:00
2010-10-08 09:05:55 +00:00
' basic ' : fields . function ( _calculate_salary , method = True , multi = ' dc ' , type = ' float ' , string = ' Basic Salary ' , digits = ( 14 , 2 ) ) ,
' gross ' : fields . function ( _calculate_salary , method = True , multi = ' dc ' , type = ' float ' , string = ' Gross Salary ' , digits = ( 14 , 2 ) ) ,
' net ' : fields . function ( _calculate_salary , method = True , multi = ' dc ' , type = ' float ' , string = ' Net Salary ' , digits = ( 14 , 2 ) ) ,
' advantages_net ' : fields . function ( _calculate_salary , method = True , multi = ' dc ' , type = ' float ' , string = ' Deductions ' , digits = ( 14 , 2 ) ) ,
' advantages_gross ' : fields . function ( _calculate_salary , method = True , multi = ' dc ' , type = ' float ' , string = ' Allowances ' , digits = ( 14 , 2 ) ) ,
2011-02-25 13:07:26 +00:00
' emp_sal_rule_ids ' : fields . many2many ( ' hr.salary.rule ' , ' hr_emp_salary_rule_rel ' , ' employee_id ' , ' rule_id ' , ' Salary Rules ' , readonly = False ) ,
2010-06-06 16:29:11 +00:00
}
hr_employee ( )
2010-07-02 10:37:15 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: