2012-05-15 08:41:29 +00:00
#-*- coding:utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2011 OpenERP SA (<http://openerp.com>). All Rights Reserved
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# 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
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
2012-05-21 07:06:43 +00:00
import time
2012-05-24 11:24:12 +00:00
from datetime import datetime
2012-05-21 07:06:43 +00:00
from dateutil . relativedelta import relativedelta
2012-06-04 06:18:28 +00:00
from calendar import isleap
2012-05-23 12:12:10 +00:00
2012-06-12 05:57:10 +00:00
from tools . translate import _
2012-05-23 09:03:31 +00:00
from osv import fields , osv
import decimal_precision as dp
2012-05-21 07:06:43 +00:00
2012-06-12 05:57:10 +00:00
DATETIME_FORMAT = " % Y- % m- %d "
2012-06-15 12:29:01 +00:00
class hr_contract ( osv . osv ) :
2012-06-18 11:10:22 +00:00
"""
Employee contract allows to add different values in fields .
Fields are used in salary rule computation .
"""
2012-05-15 08:41:29 +00:00
_inherit = ' hr.contract '
2012-06-26 06:03:54 +00:00
_description = ' HR Contract '
2012-05-23 12:12:10 +00:00
2012-05-23 07:29:45 +00:00
_columns = {
2012-06-26 06:03:54 +00:00
' tds ' : fields . float ( ' TDS ' , digits_compute = dp . get_precision ( ' Payroll ' ) , help = " Amount for Tax Deduction at Source " ) ,
2012-06-26 10:48:58 +00:00
' house_rent_income ' : fields . float ( ' House Rent Income ' , digits_compute = dp . get_precision ( ' Payroll ' ) , help = " Income from house property " ) ,
' saving_bank_account ' : fields . float ( ' Saving Bank Account Income ' , digits_compute = dp . get_precision ( ' Payroll ' ) , help = " Saving income for bank account " ) ,
' other_income ' : fields . float ( ' Other Income ' , digits_compute = dp . get_precision ( ' Payroll ' ) , help = " Other income of employee " ) ,
' short_term_gain ' : fields . float ( ' Short Term Gain from Share Trading/Equity MFs ' , digits_compute = dp . get_precision ( ' Payroll ' ) , help = " Stocks/equity mutual funds are sold before one year " ) ,
' long_term_gain ' : fields . float ( ' Long Term Gain from Share Trading/Equity MFs ' , digits_compute = dp . get_precision ( ' Payroll ' ) , help = " Stocks/equity mutual funds are kept for more than a year " ) ,
' food_coupon_amount ' : fields . float ( ' Food Coupons ' , digits_compute = dp . get_precision ( ' Payroll ' ) , help = " Amount of food coupon per day " ) ,
' driver_salay ' : fields . boolean ( ' Driver Salary ' , help = " Allowance for company provided driver " ) ,
2012-05-23 12:12:10 +00:00
' professional_tax ' : fields . float ( ' Professional Tax ' , digits_compute = dp . get_precision ( ' Payroll ' ) , help = " Professional tax deducted from salary " ) ,
2012-06-26 10:48:58 +00:00
' leave_avail_dedution ' : fields . float ( ' Leave Availed Deduction ' , digits_compute = dp . get_precision ( ' Payroll ' ) , help = " Deduction for emergency leave of employee " ) ,
' medical_insurance ' : fields . float ( ' Medical Insurance ' , digits_compute = dp . get_precision ( ' Payroll ' ) , help = " Deduction towards company provided medical insurance " ) ,
' voluntary_provident_fund ' : fields . float ( ' Voluntary Provident Fund ' , digits_compute = dp . get_precision ( ' Payroll ' ) , help = " VPF computed as percentage( % ) " ) ,
' company_transport ' : fields . float ( ' Company Provided Transport ' , digits_compute = dp . get_precision ( ' Payroll ' ) , help = " Deduction for company provided transport " ) ,
2012-05-23 07:29:45 +00:00
}
2012-06-15 12:29:01 +00:00
hr_contract ( )
2012-05-23 07:29:45 +00:00
class hr_employee ( osv . osv ) :
2012-06-18 11:10:22 +00:00
'''
Employee ' s Join date allows to compute total working
experience of Employee and it is used to calculate Gratuity rule .
'''
2012-05-23 07:29:45 +00:00
_inherit = ' hr.employee '
2012-06-12 05:57:10 +00:00
_description = ' Employee '
2012-05-23 12:12:10 +00:00
2012-05-21 07:06:43 +00:00
def _compute_year ( self , cr , uid , ids , fields , args , context = None ) :
"""
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
2012-05-24 11:24:12 +00:00
@param ids : List of employee ’ s IDs
2012-05-21 07:06:43 +00:00
@return : No . of years of experience .
@param context : A standard dictionary for contextual values
"""
res = { }
2012-05-24 11:24:12 +00:00
c_date = time . strftime ( DATETIME_FORMAT )
2012-06-26 07:12:07 +00:00
current_date = datetime . strptime ( c_date , DATETIME_FORMAT )
2012-05-23 12:12:10 +00:00
for employee in self . browse ( cr , uid , ids , context = context ) :
2012-05-23 05:45:19 +00:00
if employee . join_date :
date_start = datetime . strptime ( employee . join_date , DATETIME_FORMAT )
diffyears = current_date . year - date_start . year
2012-06-26 07:14:59 +00:00
difference = current_date - date_start . replace ( current_date . year )
2012-05-23 05:45:19 +00:00
days_in_year = isleap ( current_date . year ) and 366 or 365
2012-06-26 07:14:59 +00:00
difference_in_years = diffyears + ( difference . days + difference . seconds / 86400.0 ) / days_in_year
2012-05-23 05:45:19 +00:00
total_years = relativedelta ( current_date , date_start ) . years
total_months = relativedelta ( current_date , date_start ) . months
if total_months < 10 :
2012-06-26 07:14:59 +00:00
year_month = float ( total_months ) / 10 + total_years
2012-05-23 05:45:19 +00:00
else :
2012-06-26 07:14:59 +00:00
year_month = float ( total_months ) / 100 + total_years
2012-05-23 09:03:31 +00:00
res [ employee . id ] = year_month
2012-05-23 13:35:05 +00:00
else :
res [ employee . id ] = 0.0
2012-05-21 07:06:43 +00:00
return res
2012-05-23 07:29:45 +00:00
2012-05-23 05:45:19 +00:00
_columns = {
2012-06-26 10:48:58 +00:00
' join_date ' : fields . date ( ' Join Date ' , help = " Joining date of employee " ) ,
' number_of_year ' : fields . function ( _compute_year , string = ' No. of Years of Service ' , type = " float " , store = True , help = " Total years of work experience " ) ,
2012-06-12 05:57:10 +00:00
}
2012-05-23 05:45:19 +00:00
hr_employee ( )
2012-06-04 06:18:28 +00:00
class payroll_advice ( osv . osv ) :
'''
2012-06-15 12:29:01 +00:00
Bank Advice
2012-06-04 06:18:28 +00:00
'''
_name = ' hr.payroll.advice '
2012-06-15 12:29:01 +00:00
_description = ' Bank Advice '
2012-06-04 06:18:28 +00:00
_columns = {
2012-06-12 05:57:10 +00:00
' name ' : fields . char ( ' Name ' , size = 32 , readonly = True , required = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } , ) ,
2012-06-04 06:18:28 +00:00
' note ' : fields . text ( ' Description ' ) ,
2012-06-26 10:48:58 +00:00
' date ' : fields . date ( ' Date ' , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } , help = " Advice Date is used to search Payslips " ) ,
2012-06-04 06:18:28 +00:00
' state ' : fields . selection ( [
2012-06-26 07:14:59 +00:00
( ' draft ' , ' Draft ' ) ,
2012-06-27 05:44:41 +00:00
( ' confirm ' , ' Confirmed ' ) ,
2012-06-26 07:14:59 +00:00
( ' cancel ' , ' Cancelled ' ) ,
] , ' State ' , select = True , readonly = True ) ,
2012-06-11 11:10:55 +00:00
' number ' : fields . char ( ' Number ' , size = 16 , readonly = True ) ,
2012-06-13 06:58:07 +00:00
' line_ids ' : fields . one2many ( ' hr.payroll.advice.line ' , ' advice_id ' , ' Employee Salary ' , states = { ' draft ' : [ ( ' readonly ' , False ) ] } , readonly = True ) ,
2012-06-27 09:11:01 +00:00
' chaque_nos ' : fields . char ( ' Cheque Numbers ' , size = 256 ) ,
2012-06-14 12:45:33 +00:00
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' , required = True , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2012-06-27 09:00:04 +00:00
' bank_id ' : fields . many2one ( ' res.bank ' , ' Bank ' , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } , help = " Select the Bank from which the salary is going to be paid " ) ,
2012-06-04 06:18:28 +00:00
}
2012-06-11 11:10:55 +00:00
2012-06-04 06:18:28 +00:00
_defaults = {
2012-06-26 07:14:59 +00:00
' date ' : lambda * a : time . strftime ( ' % Y- % m- %d ' ) ,
' state ' : lambda * a : ' draft ' ,
2012-06-04 06:18:28 +00:00
' company_id ' : lambda self , cr , uid , context : \
self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid ,
context = context ) . company_id . id ,
2012-06-13 12:26:05 +00:00
' note ' : " Please make the payroll transfer from above account number to the below mentioned account numbers towards employee salaries: "
2012-06-13 06:58:07 +00:00
2012-06-04 06:18:28 +00:00
}
def compute_advice ( self , cr , uid , ids , context = None ) :
2012-06-18 11:10:22 +00:00
"""
Advice - Create Advice lines in Payment Advice and
compute Advice lines .
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param ids : List of Advice ’ s IDs
@return : Advice lines
@param context : A standard dictionary for contextual values
"""
2012-06-04 06:18:28 +00:00
payslip_pool = self . pool . get ( ' hr.payslip ' )
advice_line_pool = self . pool . get ( ' hr.payroll.advice.line ' )
payslip_line_pool = self . pool . get ( ' hr.payslip.line ' )
for advice in self . browse ( cr , uid , ids , context = context ) :
2012-06-26 07:14:59 +00:00
old_line_ids = advice_line_pool . search ( cr , uid , [ ( ' advice_id ' , ' = ' , advice . id ) ] , context = context )
2012-06-06 09:55:08 +00:00
if old_line_ids :
advice_line_pool . unlink ( cr , uid , old_line_ids , context = context )
2012-06-26 07:14:59 +00:00
slip_ids = payslip_pool . search ( cr , uid , [ ( ' date_from ' , ' <= ' , advice . date ) , ( ' date_to ' , ' >= ' , advice . date ) , ( ' state ' , ' = ' , ' done ' ) ] , context = context )
2012-06-15 07:08:20 +00:00
# if not slip_ids:
# advice_date = datetime.strptime(advice.date,DATETIME_FORMAT)
# a_date = advice_date.strftime('%B')+'-'+advice_date.strftime('%Y')
# raise osv.except_osv(_('Error !'), _('No Payslips for found for %s Month') % (a_date))
2012-06-06 09:55:08 +00:00
for slip in payslip_pool . browse ( cr , uid , slip_ids , context = context ) :
2012-06-12 05:57:10 +00:00
if not slip . employee_id . bank_account_id :
raise osv . except_osv ( _ ( ' Error ! ' ) , _ ( ' Please define bank account for the %s employee ' ) % ( slip . employee_id . name ) )
2012-06-26 07:14:59 +00:00
line_ids = payslip_line_pool . search ( cr , uid , [ ( ' slip_id ' , ' = ' , slip . id ) , ( ' code ' , ' = ' , ' NET ' ) ] , context = context )
2012-06-12 05:57:10 +00:00
if line_ids :
line = payslip_line_pool . browse ( cr , uid , line_ids , context = context ) [ 0 ]
2012-06-26 07:14:59 +00:00
advice_line = {
2012-06-12 05:57:10 +00:00
' advice_id ' : advice . id ,
' name ' : slip . employee_id . bank_account_id . acc_number ,
' employee_id ' : slip . employee_id . id ,
' bysal ' : line . total
2012-06-06 09:55:08 +00:00
}
2012-06-12 05:57:10 +00:00
advice_line_pool . create ( cr , uid , advice_line , context = context )
2012-06-26 10:48:58 +00:00
payslip_pool . write ( cr , uid , slip_ids , { ' advice_id ' : advice . id } , context = context )
2012-06-12 05:57:10 +00:00
return True
2012-06-04 06:18:28 +00:00
def confirm_sheet ( self , cr , uid , ids , context = None ) :
2012-06-18 11:10:22 +00:00
"""
confirm Advice - confirmed Advice after computing Advice Lines . .
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param ids : List of confirm Advice ’ s IDs
@return : confirmed Advice lines and set sequence of Advice .
@param context : A standard dictionary for contextual values
"""
2012-06-15 12:29:01 +00:00
seq_obj = self . pool . get ( ' ir.sequence ' )
2012-06-13 06:59:30 +00:00
for advice in self . browse ( cr , uid , ids , context = context ) :
if not advice . line_ids :
2012-06-15 07:08:20 +00:00
raise osv . except_osv ( _ ( ' Error ! ' ) , _ ( ' You can not confirm Payment advice without advice lines. ' ) )
2012-06-26 07:14:59 +00:00
advice_date = datetime . strptime ( advice . date , DATETIME_FORMAT )
2012-06-15 12:29:01 +00:00
advice_year = advice_date . strftime ( ' % m ' ) + ' - ' + advice_date . strftime ( ' % Y ' )
number = seq_obj . get ( cr , uid , ' payment.advice ' )
sequence_num = ' PAY ' + ' / ' + advice_year + ' / ' + number
self . write ( cr , uid , [ advice . id ] , { ' number ' : sequence_num , ' state ' : ' confirm ' } , context = context )
2012-06-15 11:06:56 +00:00
return True
2012-06-04 06:18:28 +00:00
def set_to_draft ( self , cr , uid , ids , context = None ) :
2012-06-18 11:10:22 +00:00
""" Resets Advice as draft.
"""
2012-06-11 11:10:55 +00:00
return self . write ( cr , uid , ids , { ' state ' : ' draft ' } , context = context )
2012-06-04 06:18:28 +00:00
def cancel_sheet ( self , cr , uid , ids , context = None ) :
2012-06-18 11:10:22 +00:00
""" Marks Advice as cancelled.
"""
2012-06-11 11:10:55 +00:00
return self . write ( cr , uid , ids , { ' state ' : ' cancel ' } , context = context )
2012-06-04 06:18:28 +00:00
def onchange_company_id ( self , cr , uid , ids , company_id = False , context = None ) :
res = { }
if company_id :
2012-06-12 05:57:10 +00:00
company = self . pool . get ( ' res.company ' ) . browse ( cr , uid , [ company_id ] , context = context ) [ 0 ]
2012-06-04 06:18:28 +00:00
if company . partner_id . bank_ids :
res . update ( { ' bank ' : company . partner_id . bank_ids [ 0 ] . bank . name } )
return {
' value ' : res
}
payroll_advice ( )
class payroll_advice_line ( osv . osv ) :
'''
Bank Advice Lines
'''
_name = ' hr.payroll.advice.line '
_description = ' Bank Advice Lines '
_columns = {
2012-06-26 10:48:58 +00:00
' advice_id ' : fields . many2one ( ' hr.payroll.advice ' , ' Bank Advice ' ) ,
2012-06-26 07:13:46 +00:00
' name ' : fields . char ( ' Bank Account No. ' , size = 32 , required = True ) ,
' employee_id ' : fields . many2one ( ' hr.employee ' , ' Employee ' , required = True ) ,
2012-06-04 06:18:28 +00:00
' bysal ' : fields . float ( ' By Salary ' , digits_compute = dp . get_precision ( ' Payroll ' ) ) ,
2012-06-27 08:54:47 +00:00
' company_id ' : fields . related ( ' advice_id ' , ' company_id ' , type = ' many2one ' , required = True , relation = ' res.company ' , string = ' Company ' , store = True ) ,
2012-06-04 06:18:28 +00:00
}
payroll_advice_line ( )
2012-06-26 10:48:58 +00:00
class hr_payslip ( osv . osv ) :
'''
Employee Pay Slip
'''
_inherit = ' hr.payslip '
_description = ' Pay Slip '
_columns = {
' advice_id ' : fields . many2one ( ' hr.payroll.advice ' , ' Bank Advice ' )
}
2012-06-26 10:51:40 +00:00
hr_payslip ( )
2012-06-26 07:14:59 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: