2
##############################################################################
4
# OpenERP, Open Source Management Solution
5
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
8
# This program is free software: you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation, either version 3 of the License, or
11
# (at your option) any later version.
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
18
# You should have received a copy of the GNU General Public License
19
# along with this program. If not, see <http://www.gnu.org/licenses/>.
21
##############################################################################
26
from osv import fields
27
from tools import config
28
from tools.translate import _
30
from datetime import date
31
from datetime import datetime
32
from datetime import timedelta
34
def prev_bounds(cdate=False):
35
when = date.fromtimestamp(time.mktime(time.strptime(cdate,"%Y-%m-%d")))
36
this_first = date(when.year, when.month, 1)
37
month = when.month + 1
42
next_month = date(year, month, 1)
43
prev_end = next_month - timedelta(days=1)
44
return this_first, prev_end
46
class hr_payslip(osv.osv):
50
_inherit = 'hr.payslip'
51
_description = 'Pay Slip'
54
'move_ids':fields.one2many('hr.payslip.account.move', 'slip_id', 'Accounting vouchers', required=False),
55
'move_line_ids':fields.many2many('account.move.line', 'payslip_lines_rel', 'slip_id', 'line_id', 'Accounting Lines', readonly=True),
56
'move_payment_ids':fields.many2many('account.move.line', 'payslip_payment_rel', 'slip_id', 'payment_id', 'Payment Lines', readonly=True),
57
'period_id': fields.many2one('account.period', 'Force Period', domain=[('state','<>','done')], help="Keep empty to use the period of the validation(Payslip) date."),
60
def create_voucher(self, cr, uid, ids, name, voucher, sequence=5):
61
slip_move = self.pool.get('hr.payslip.account.move')
69
slip_move.create(cr, uid, res)
71
def cancel_sheet(self, cr, uid, ids, context={}):
72
move_pool = self.pool.get('account.move')
74
for slip in self.browse(cr, uid, ids, context):
76
if slip.move_id.state == 'posted':
77
move_pool.button_cancel(cr, uid [slip.move_id.id], context)
78
move_pool.unlink(cr, uid, [slip.move_id.id])
81
if slip.adj_move_id.state == 'posted':
82
move_pool.button_cancel(cr, uid [slip.adj_move_id.id], context)
83
move_pool.unlink(cr, uid, [slip.adj_move_id.id])
85
if slip.other_move_id:
86
if slip.other_move_id.state == 'posted':
87
move_pool.button_cancel(cr, uid [slip.other_move_id.id], context)
88
move_pool.unlink(cr, uid, [slip.other_move_id.id])
90
self.write(cr, uid, ids, {'state':'cancel'})
93
def process_sheet(self, cr, uid, ids, context={}):
94
move_pool = self.pool.get('account.move')
95
movel_pool = self.pool.get('account.move.line')
96
invoice_pool = self.pool.get('account.invoice')
98
for slip in self.browse(cr,uid,ids):
104
partner = slip.employee_id.address_home_id.partner_id
105
partner_id = partner.id
107
fiscal_year_ids = self.pool.get('account.fiscalyear').search(cr, uid, [])
108
if not fiscal_year_ids:
109
raise osv.except_osv(_('Warning !'), _('Please define fiscal year for perticular contract'))
110
fiscal_year_objs = self.pool.get('account.fiscalyear').read(cr, uid, fiscal_year_ids, ['date_start','date_stop'])
112
for fiscal_year in fiscal_year_objs:
113
if ((fiscal_year['date_start'] <= slip.date) and (fiscal_year['date_stop'] >= slip.date)):
116
raise osv.except_osv(_('Warning !'), _('Fiscal Year is not defined for slip date %s'%slip.date))
117
search_period = self.pool.get('account.period').search(cr,uid,[('date_start','<=',slip.date),('date_stop','>=',slip.date)])
118
if not search_period:
119
raise osv.except_osv(_('Warning !'), _('Period is not defined for slip date %s'%slip.date))
120
period_id = search_period[0]
121
name = 'Payment of Salary to %s' % (slip.employee_id.name)
123
'journal_id': slip.bank_journal_id.id,
124
'period_id': period_id,
126
'type':'bank_pay_voucher',
130
move_id = move_pool.create(cr, uid, move)
131
self.create_voucher(cr, uid, [slip.id], name, move_id)
133
name = "To %s account" % (slip.employee_id.name)
137
#'partner_id': partner_id,
139
'account_id': slip.employee_id.property_bank_account.id,
141
'credit' : slip.total_pay,
142
'journal_id' : slip.journal_id.id,
143
'period_id' :period_id,
146
line_ids += [movel_pool.create(cr, uid, ded_rec)]
147
name = "By %s account" % (slip.employee_id.property_bank_account.name)
151
'partner_id': partner_id,
153
'account_id': partner.property_account_payable.id,
154
'debit': slip.total_pay,
156
'journal_id' : slip.journal_id.id,
157
'period_id' :period_id,
160
line_ids += [movel_pool.create(cr, uid, cre_rec)]
162
other_pay = slip.other_pay
163
#Process all Reambuse Entries
164
for line in slip.line_ids:
165
if line.type == 'otherpay' and line.expanse_id.invoice_id:
166
if not line.expanse_id.invoice_id.move_id:
167
raise osv.except_osv(_('Warning !'), _('Please Confirm all Expanse Invoice appear for Reimbursement'))
168
invids = [line.expanse_id.invoice_id.id]
170
acc_id = slip.bank_journal_id.default_credit_account_id and slip.bank_journal_id.default_credit_account_id.id
171
period_id = slip.period_id.id
172
journal_id = slip.bank_journal_id.id
173
name = '[%s]-%s' % (slip.number, line.name)
174
invoice_pool.pay_and_reconcile(cr, uid, invids, amount, acc_id, period_id, journal_id, False, period_id, False, context, name)
176
#TODO: link this account entries to the Payment Lines also Expanse Entries to Account Lines
177
l_ids = movel_pool.search(cr, uid, [('name','=',name)])
180
l_ids = movel_pool.search(cr, uid, [('invoice','=',line.expanse_id.invoice_id.id)])
183
#Process for Other payment if any
184
other_move_id = False
185
if slip.other_pay > 0:
186
narration = 'Payment of Other Payeble amounts to %s' % (slip.employee_id.name)
188
'journal_id': slip.bank_journal_id.id,
189
'period_id': period_id,
191
'type':'bank_pay_voucher',
193
'narration': narration
195
other_move_id = move_pool.create(cr, uid, move)
196
self.create_voucher(cr, uid, [slip.id], narration, move_id)
198
name = "To %s account" % (slip.employee_id.name)
200
'move_id':other_move_id,
203
'account_id':slip.employee_id.property_bank_account.id,
206
'journal_id':slip.journal_id.id,
207
'period_id':period_id,
210
line_ids += [movel_pool.create(cr, uid, ded_rec)]
211
name = "By %s account" % (slip.employee_id.property_bank_account.name)
213
'move_id':other_move_id,
215
'partner_id':partner_id,
217
'account_id':partner.property_account_payable.id,
220
'journal_id':slip.journal_id.id,
221
'period_id':period_id,
224
line_ids += [movel_pool.create(cr, uid, cre_rec)]
228
'move_payment_ids':[(6, 0, line_ids)],
231
self.write(cr, uid, [slip.id], rec)
232
for exp_id in exp_ids:
233
self.write(cr, uid, [slip.id], {'move_line_ids':[(4, exp_id)]})
237
def account_check_sheet(self, cr, uid, ids, context={}):
238
self.write(cr, uid, ids, {'state':'accont_check'})
241
def hr_check_sheet(self, cr, uid, ids, context={}):
242
self.write(cr, uid, ids, {'state':'hr_check'})
245
def verify_sheet(self, cr, uid, ids, context={}):
247
move_pool = self.pool.get('account.move')
248
movel_pool = self.pool.get('account.move.line')
249
exp_pool = self.pool.get('hr.expense.expense')
251
for slip in self.browse(cr,uid,ids):
258
if not slip.employee_id.address_home_id:
259
raise osv.except_osv(_('Integrity Error !'), _('Please defined the Employee Home Address Along with Partners !!'))
261
if not slip.employee_id.address_home_id.partner_id:
262
raise osv.except_osv(_('Integrity Error !'), _('Please defined the Partner in Home Address !!'))
264
partner = slip.employee_id.address_home_id.partner_id
265
partner_id = slip.employee_id.address_home_id.partner_id.id
270
period_id = slip.period_id.id
272
fiscal_year_ids = self.pool.get('account.fiscalyear').search(cr, uid, [])
273
if not fiscal_year_ids:
274
raise osv.except_osv(_('Warning !'), _('Please define fiscal year for perticular contract'))
275
fiscal_year_objs = self.pool.get('account.fiscalyear').read(cr, uid, fiscal_year_ids, ['date_start','date_stop'])
277
for fiscal_year in fiscal_year_objs:
278
if ((fiscal_year['date_start'] <= slip.date) and (fiscal_year['date_stop'] >= slip.date)):
281
raise osv.except_osv(_('Warning !'), _('Fiscal Year is not defined for slip date %s'%slip.date))
282
search_period = self.pool.get('account.period').search(cr,uid,[('date_start','<=',slip.date),('date_stop','>=',slip.date)])
283
if not search_period:
284
raise osv.except_osv(_('Warning !'), _('Period is not defined for slip date %s'%slip.date))
285
period_id = search_period[0]
289
'journal_id': slip.journal_id.id,
290
'period_id': period_id,
293
'narration': slip.name
295
move_id = move_pool.create(cr, uid, move)
296
self.create_voucher(cr, uid, [slip.id], slip.name, move_id)
300
'name': "By Basic Salary / " + slip.employee_id.name,
302
'account_id': slip.employee_id.salary_account.id,
305
'quantity':slip.working_days,
306
'journal_id': slip.journal_id.id,
307
'period_id': period_id,
308
'analytic_account_id': False,
312
#Setting Analysis Account for Basic Salary
313
if slip.employee_id.analytic_account:
314
line['analytic_account_id'] = slip.employee_id.analytic_account.id
316
move_line_id = movel_pool.create(cr, uid, line)
317
line_ids += [move_line_id]
321
'name': "To Basic Paysble Salary / " + slip.employee_id.name,
322
'partner_id': partner_id,
324
'account_id': slip.employee_id.employee_account.id,
326
'quantity':slip.working_days,
327
'credit': slip.basic,
328
'journal_id': slip.journal_id.id,
329
'period_id': period_id,
332
line_ids += [movel_pool.create(cr, uid, line)]
334
for line in slip.line_ids:
335
name = "[%s] - %s / %s" % (line.code, line.name, slip.employee_id.name)
338
if line.type == 'leaves':
345
'account_id': line.account_id.id,
348
'journal_id' : slip.journal_id.id,
349
'period_id' :period_id,
350
'analytic_account_id':False,
355
#Setting Analysis Account for Salary Slip Lines
356
if line.analytic_account_id:
357
rec['analytic_account_id'] = line.analytic_account_id.id
359
rec['analytic_account_id'] = slip.deg_id.account_id.id
361
if line.type == 'allounce' or line.type == 'otherpay':
362
rec['debit'] = amount
363
if not partner.property_account_payable:
364
raise osv.except_osv(_('Integrity Error !'), _('Please Configure Partners Payable Account!!'))
368
'partner_id': partner_id,
370
'account_id': partner.property_account_payable.id,
374
'journal_id' : slip.journal_id.id,
375
'period_id' :period_id,
378
line_ids += [movel_pool.create(cr, uid, ded_rec)]
379
elif line.type == 'deduction' or line.type == 'otherdeduct':
380
if not partner.property_account_receivable:
381
raise osv.except_osv(_('Integrity Error !'), _('Please Configure Partners Receivable Account!!'))
382
rec['credit'] = amount
383
total_deduct += amount
387
'partner_id': partner_id,
390
'account_id': partner.property_account_receivable.id,
393
'journal_id' : slip.journal_id.id,
394
'period_id' :period_id,
397
line_ids += [movel_pool.create(cr, uid, ded_rec)]
399
line_ids += [movel_pool.create(cr, uid, rec)]
401
if line.company_contrib > 0:
402
company_contrib = line.company_contrib
403
# if line.category_id.amount_type == 'per':
404
# company_contrib = (amount * line.category_id.contribute_per)
406
narration = """Company Contribution of %s Encode same as a Company Expanse @ %s""" % (line.name, company_contrib)
409
'journal_id': slip.journal_id.id,
410
'period_id': period_id,
413
'narration': narration
415
company_contrib_move_id = move_pool.create(cr, uid, move)
416
name = "[%s] - %s / %s - Company Contribution" % (line.code, line.name, slip.employee_id.name)
417
self.create_voucher(cr, uid, [slip.id], name, company_contrib_move_id)
420
'move_id':company_contrib_move_id,
424
'account_id': line.category_id.account_id.id,
425
'debit': company_contrib,
427
'journal_id': slip.journal_id.id,
428
'period_id': period_id,
431
line_ids += [movel_pool.create(cr, uid, ded_deb)]
433
'move_id':company_contrib_move_id,
437
'account_id': line.category_id.register_id.account_id.id,
439
'credit' : company_contrib,
440
'journal_id': slip.journal_id.id,
441
'period_id': period_id,
444
line_ids += [movel_pool.create(cr, uid, ded_cre)]
446
if line.category_id.include_in_salary:
447
narration = """Company Contribution of %s Deducted from Employee %s""" % (line.name, company_contrib)
450
'journal_id': slip.journal_id.id,
451
'period_id': period_id,
454
'narration': narration
456
include_in_salary_move_id = move_pool.create(cr, uid, move)
457
self.create_voucher(cr, uid, [slip.id], narration, include_in_salary_move_id)
459
total_deduct += company_contrib
461
'move_id':include_in_salary_move_id,
463
'partner_id': partner_id,
466
'account_id': partner.property_account_receivable.id,
467
'debit': company_contrib,
469
'journal_id': slip.journal_id.id,
470
'period_id': period_id,
473
line_ids += [movel_pool.create(cr, uid, ded_deb)]
475
'move_id':include_in_salary_move_id,
479
'account_id': line.category_id.account_id.id,
481
'credit' : company_contrib,
482
'journal_id': slip.journal_id.id,
483
'period_id': period_id,
486
line_ids += [movel_pool.create(cr, uid, ded_cre)]
488
#make an entry line to contribution register
489
# if line.category_id.register_id:
491
# 'register_id':line.category_id.register_id.id,
494
# 'employee_id':slip.employee_id.id,
495
# 'period_id':period_id,
496
# 'emp_deduction':amount,
498
# if line.category_id.contribute:
499
# ctr['comp_deduction'] = amount
503
# if line.category_id.contribute and line.category_id.include_in_salary and line.category_id.amount_type == 'per':
504
# new_amount = (amount * (line.category_id.contribute_per / (1+line.category_id.contribute_per)))
505
# company = new_amount
506
# employee = amount - company
508
# elif line.category_id.contribute and line.category_id.include_in_salary and line.category_id.amount_type == 'fix':
509
# company = line.category_id.contribute_per
510
# employee = amount - company
512
# elif line.category_id.contribute and line.category_id.include_in_salary and line.category_id.amount_type == 'func':
513
# company = self.pool.get('hr.allounce.deduction.categoty').execute_function(cr, uid, line.category_id.id, line.slip_id.basic, context)
516
# elif line.category_id.contribute and not line.category_id.include_in_salary and line.category_id.amount_type == 'per':
517
# company = amount * line.category_id.contribute_per
520
# elif line.category_id.contribute and not line.category_id.include_in_salary and line.category_id.amount_type == 'fix':
521
# company = line.category_id.contribute_per
524
# elif line.category_id.contribute and not line.category_id.include_in_salary and line.category_id.amount_type == 'func':
525
# company = self.pool.get('hr.allounce.deduction.categoty').execute_function(cr, uid, line.category_id.id, line.slip_id.basic, context)
528
# ctr['emp_deduction'] = employee
529
# ctr['comp_deduction'] = company
531
# self.pool.get('hr.contibution.register.line').create(cr, uid, ctr)
536
'journal_id': slip.journal_id.id,
537
'period_id': period_id,
540
'narration': 'Adjustment : %s' % (slip.name)
542
adj_move_id = move_pool.create(cr, uid, move)
543
name = "Adjustment Entry - %s" % (slip.employee_id.name)
544
self.create_voucher(cr, uid, [slip.id], name, adj_move_id)
547
'move_id':adj_move_id,
549
'partner_id': partner_id,
551
'account_id': partner.property_account_receivable.id,
554
'credit' : total_deduct,
555
'journal_id' : slip.journal_id.id,
556
'period_id' :period_id,
559
line_ids += [movel_pool.create(cr, uid, ded_rec)]
561
'move_id':adj_move_id,
563
'partner_id': partner_id,
565
'account_id': partner.property_account_payable.id,
566
'debit': total_deduct,
569
'journal_id' : slip.journal_id.id,
570
'period_id' :period_id,
573
line_ids += [movel_pool.create(cr, uid, cre_rec)]
577
'move_line_ids':[(6, 0,line_ids)],
579
if not slip.period_id:
580
rec['period_id'] = period_id
582
dates = prev_bounds(slip.date)
583
exp_ids = exp_pool.search(cr, uid, [('date_valid','>=',dates[0]), ('date_valid','<=',dates[1]), ('state','=','invoiced')])
585
acc = self.pool.get('ir.property').get(cr, uid, 'property_account_expense_categ', 'product.category')
586
for exp in exp_pool.browse(cr, uid, exp_ids):
591
'category_id':exp.category_id.id,
597
self.pool.get('hr.payslip.line').create(cr, uid, exp_res)
599
self.write(cr, uid, [slip.id], rec)
605
class account_move_link_slip(osv.osv):
607
Account Move Link to Pay Slip
609
_name = 'hr.payslip.account.move'
610
_description = 'Account Move Link to Pay Slip'
612
'name':fields.char('Name', size=256, required=True, readonly=False),
613
'move_id':fields.many2one('account.move', 'Expanse Entries', required=False, readonly=True),
614
'slip_id':fields.many2one('hr.payslip', 'Pay Slip', required=False),
615
'sequence': fields.integer('Sequence'),
617
account_move_link_slip()