2009-10-13 05:58:37 +00:00
# -*- coding: utf-8 -*-
2006-12-07 13:41:40 +00:00
##############################################################################
2009-11-13 05:41:16 +00:00
#
2009-02-11 13:32:54 +00:00
# OpenERP, Open Source Management Solution
2010-01-12 09:18:39 +00:00
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
2006-12-07 13:41:40 +00:00
#
2008-11-03 19:18:56 +00:00
# This program is free software: you can redistribute it and/or modify
2009-10-14 11:15:34 +00:00
# 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.
2006-12-07 13:41:40 +00:00
#
2008-11-03 19:18:56 +00:00
# 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
2009-10-14 11:15:34 +00:00
# GNU Affero General Public License for more details.
2006-12-07 13:41:40 +00:00
#
2009-10-14 11:15:34 +00:00
# You should have received a copy of the GNU Affero General Public License
2009-11-13 05:41:16 +00:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2006-12-07 13:41:40 +00:00
#
##############################################################################
from mx import DateTime
import time
from osv import fields , osv
2008-07-08 08:13:12 +00:00
from tools . translate import _
2006-12-07 13:41:40 +00:00
def _employee_get ( obj , cr , uid , context = { } ) :
2008-07-22 15:11:28 +00:00
ids = obj . pool . get ( ' hr.employee ' ) . search ( cr , uid , [ ( ' user_id ' , ' = ' , uid ) ] )
if ids :
return ids [ 0 ]
return False
2006-12-07 13:41:40 +00:00
class hr_expense_expense ( osv . osv ) :
2008-07-22 15:11:28 +00:00
def copy ( self , cr , uid , id , default = None , context = { } ) :
if not default : default = { }
default . update ( { ' invoice_id ' : False , ' date_confirm ' : False , ' date_valid ' : False , ' user_valid ' : False } )
return super ( hr_expense_expense , self ) . copy ( cr , uid , id , default , context )
def _amount ( self , cr , uid , ids , field_name , arg , context ) :
2009-11-26 11:17:31 +00:00
cr . execute ( " SELECT s.id,COALESCE(SUM(l.unit_amount*l.unit_quantity),0) AS amount FROM hr_expense_expense s LEFT OUTER JOIN hr_expense_line l ON (s.id=l.expense_id) WHERE s.id =ANY( %s ) GROUP BY s.id " , ( ids , ) )
2008-07-22 15:11:28 +00:00
res = dict ( cr . fetchall ( ) )
return res
def _get_currency ( self , cr , uid , context ) :
user = self . pool . get ( ' res.users ' ) . browse ( cr , uid , [ uid ] ) [ 0 ]
if user . company_id :
return user . company_id . currency_id . id
else :
return self . pool . get ( ' res.currency ' ) . search ( cr , uid , [ ( ' rate ' , ' = ' , 1.0 ) ] ) [ 0 ]
_name = " hr.expense.expense "
_description = " Expense "
_columns = {
' name ' : fields . char ( ' Expense Sheet ' , size = 128 , required = True ) ,
' id ' : fields . integer ( ' Sheet ID ' , readonly = True ) ,
' ref ' : fields . char ( ' Reference ' , size = 32 ) ,
' date ' : fields . date ( ' Date ' ) ,
' journal_id ' : fields . many2one ( ' account.journal ' , ' Force Journal ' ) ,
2009-12-21 09:50:54 +00:00
' employee_id ' : fields . many2one ( ' hr.employee ' , " Employee ' s Name " , required = True ) ,
2008-07-22 15:11:28 +00:00
' user_id ' : fields . many2one ( ' res.users ' , ' User ' , required = True ) ,
' date_confirm ' : fields . date ( ' Date Confirmed ' ) ,
2009-04-02 09:55:23 +00:00
' date_valid ' : fields . date ( ' Date Validated ' ) ,
2008-07-22 15:11:28 +00:00
' user_valid ' : fields . many2one ( ' res.users ' , ' Validation User ' ) ,
2009-11-13 05:41:16 +00:00
' account_move_id ' : fields . many2one ( ' account.move ' , ' Ledger Posting ' ) ,
2009-03-09 07:05:47 +00:00
' line_ids ' : fields . one2many ( ' hr.expense.line ' , ' expense_id ' , ' Expense Lines ' , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2008-07-22 15:11:28 +00:00
' note ' : fields . text ( ' Note ' ) ,
' amount ' : fields . function ( _amount , method = True , string = ' Total Amount ' ) ,
' invoice_id ' : fields . many2one ( ' account.invoice ' , ' Invoice ' ) ,
' currency_id ' : fields . many2one ( ' res.currency ' , ' Currency ' , required = True ) ,
2010-02-17 05:25:53 +00:00
' department_id ' : fields . many2one ( ' hr.department ' , ' Department ' ) ,
2010-02-17 09:41:19 +00:00
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' , required = True ) ,
2008-07-22 15:11:28 +00:00
' state ' : fields . selection ( [
( ' draft ' , ' Draft ' ) ,
( ' confirm ' , ' Waiting confirmation ' ) ,
( ' accepted ' , ' Accepted ' ) ,
( ' invoiced ' , ' Invoiced ' ) ,
( ' paid ' , ' Reimbursed ' ) ,
2009-04-02 09:55:23 +00:00
( ' cancelled ' , ' Cancelled ' ) ] ,
2009-11-25 10:03:47 +00:00
' State ' , readonly = True , help = ' When the expense request is created the state is \' Draft \' . \n It is confirmed by the user and request is sent to admin, the state is \' Waiting Confirmation \' . \
\nIf the admin accepts it , the state is \' Accepted \' . \n If an invoice is made for the expense request, the state is \' Invoiced \' . \n If the expense is paid to user, the state is \' Reimbursed \' . ' ) ,
2008-07-22 15:11:28 +00:00
}
_defaults = {
' date ' : lambda * a : time . strftime ( ' % Y- % m- %d ' ) ,
' state ' : lambda * a : ' draft ' ,
' employee_id ' : _employee_get ,
' user_id ' : lambda cr , uid , id , c = { } : id ,
' currency_id ' : _get_currency ,
2010-02-17 09:41:19 +00:00
' company_id ' : lambda self , cr , uid , c : self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , c ) . company_id . id ,
2008-07-22 15:11:28 +00:00
}
def expense_confirm ( self , cr , uid , ids , * args ) :
#for exp in self.browse(cr, uid, ids):
self . write ( cr , uid , ids , {
' state ' : ' confirm ' ,
' date_confirm ' : time . strftime ( ' % Y- % m- %d ' )
} )
return True
def expense_accept ( self , cr , uid , ids , * args ) :
self . write ( cr , uid , ids , {
' state ' : ' accepted ' ,
' date_valid ' : time . strftime ( ' % Y- % m- %d ' ) ,
' user_valid ' : uid ,
} )
return True
def expense_canceled ( self , cr , uid , ids , * args ) :
2009-04-02 09:55:23 +00:00
self . write ( cr , uid , ids , { ' state ' : ' cancelled ' } )
2008-07-22 15:11:28 +00:00
return True
def expense_paid ( self , cr , uid , ids , * args ) :
self . write ( cr , uid , ids , { ' state ' : ' paid ' } )
return True
def action_invoice_create ( self , cr , uid , ids ) :
res = False
invoice_obj = self . pool . get ( ' account.invoice ' )
for exp in self . browse ( cr , uid , ids ) :
lines = [ ]
for l in exp . line_ids :
tax_id = [ ]
if l . product_id :
acc = l . product_id . product_tmpl_id . property_account_expense . id
if not acc :
acc = l . product_id . categ_id . property_account_expense_categ . id
tax_id = [ x . id for x in l . product_id . supplier_taxes_id ]
else :
acc = self . pool . get ( ' ir.property ' ) . get ( cr , uid , ' property_account_expense_categ ' , ' product.category ' )
2009-03-09 11:09:46 +00:00
if not acc :
raise osv . except_osv ( _ ( ' Error ! ' ) , _ ( ' Please configure Default Expanse account for Product purchase, `property_account_expense_categ` ' ) )
2009-11-13 05:41:16 +00:00
2008-07-22 15:11:28 +00:00
lines . append ( ( 0 , False , {
' name ' : l . name ,
' account_id ' : acc ,
' price_unit ' : l . unit_amount ,
' quantity ' : l . unit_quantity ,
' uos_id ' : l . uom_id . id ,
' product_id ' : l . product_id and l . product_id . id or False ,
' invoice_line_tax_id ' : tax_id and [ ( 6 , 0 , tax_id ) ] or False ,
' account_analytic_id ' : l . analytic_account . id ,
} ) )
if not exp . employee_id . address_id :
2009-10-13 14:50:16 +00:00
raise osv . except_osv ( _ ( ' Error ! ' ) , _ ( ' The employee must have a working address ' ) )
2008-07-22 15:11:28 +00:00
acc = exp . employee_id . address_id . partner_id . property_account_payable . id
payment_term_id = exp . employee_id . address_id . partner_id . property_payment_term . id
inv = {
' name ' : exp . name ,
' reference ' : self . pool . get ( ' ir.sequence ' ) . get ( cr , uid , ' hr.expense.invoice ' ) ,
' account_id ' : acc ,
' type ' : ' in_invoice ' ,
' partner_id ' : exp . employee_id . address_id . partner_id . id ,
' address_invoice_id ' : exp . employee_id . address_id . id ,
' address_contact_id ' : exp . employee_id . address_id . id ,
' origin ' : exp . name ,
' invoice_line ' : lines ,
' price_type ' : ' tax_included ' ,
' currency_id ' : exp . currency_id . id ,
' payment_term ' : payment_term_id ,
2009-02-11 13:32:54 +00:00
' fiscal_position ' : exp . employee_id . address_id . partner_id . property_account_position . id
2008-07-22 15:11:28 +00:00
}
if payment_term_id :
to_update = invoice_obj . onchange_payment_term_date_invoice ( cr , uid , [ ] ,
payment_term_id , None )
if to_update :
inv . update ( to_update [ ' value ' ] )
if exp . journal_id :
inv [ ' journal_id ' ] = exp . journal_id . id
inv_id = invoice_obj . create ( cr , uid , inv , { ' type ' : ' in_invoice ' } )
invoice_obj . button_compute ( cr , uid , [ inv_id ] , { ' type ' : ' in_invoice ' } ,
set_total = True )
self . write ( cr , uid , [ exp . id ] , { ' invoice_id ' : inv_id , ' state ' : ' invoiced ' } )
res = inv_id
return res
2006-12-07 13:41:40 +00:00
hr_expense_expense ( )
2009-04-02 09:44:17 +00:00
class product_product ( osv . osv ) :
_inherit = " product.product "
2009-11-13 05:41:16 +00:00
2009-04-02 09:44:17 +00:00
_columns = {
2010-02-23 16:05:50 +00:00
' hr_expense_ok ' : fields . boolean ( ' Can constitute an Expense ' , help = " Determines if the product can be visible in the list of product within a selection from an HR expense sheet line. " ) ,
2009-04-02 09:44:17 +00:00
}
2009-11-13 05:41:16 +00:00
2009-04-02 09:44:17 +00:00
product_product ( )
2006-12-07 13:41:40 +00:00
class hr_expense_line ( osv . osv ) :
2008-07-22 15:11:28 +00:00
_name = " hr.expense.line "
_description = " Expense Line "
def _amount ( self , cr , uid , ids , field_name , arg , context ) :
if not len ( ids ) :
return { }
2009-11-26 11:17:31 +00:00
cr . execute ( " SELECT l.id,COALESCE(SUM(l.unit_amount*l.unit_quantity),0) AS amount FROM hr_expense_line l WHERE id =ANY( %s ) GROUP BY l.id " , ( ids , ) )
2008-07-22 15:11:28 +00:00
res = dict ( cr . fetchall ( ) )
return res
_columns = {
' name ' : fields . char ( ' Short Description ' , size = 128 , required = True ) ,
' date_value ' : fields . date ( ' Date ' , required = True ) ,
' expense_id ' : fields . many2one ( ' hr.expense.expense ' , ' Expense ' , ondelete = ' cascade ' , select = True ) ,
' total_amount ' : fields . function ( _amount , method = True , string = ' Total ' ) ,
2009-03-09 07:05:47 +00:00
' unit_amount ' : fields . float ( ' Unit Price ' ) ,
' unit_quantity ' : fields . float ( ' Quantities ' ) ,
2009-04-02 09:55:23 +00:00
' product_id ' : fields . many2one ( ' product.product ' , ' Product ' , domain = [ ( ' hr_expense_ok ' , ' = ' , True ) ] ) ,
2009-03-09 07:05:47 +00:00
' uom_id ' : fields . many2one ( ' product.uom ' , ' UoM ' ) ,
2008-07-22 15:11:28 +00:00
' description ' : fields . text ( ' Description ' ) ,
' analytic_account ' : fields . many2one ( ' account.analytic.account ' , ' Analytic account ' ) ,
' ref ' : fields . char ( ' Reference ' , size = 32 ) ,
2009-12-21 13:14:12 +00:00
' sequence ' : fields . integer ( ' Sequence ' , help = " Gives the sequence order when displaying a list of expense lines. " ) ,
2008-07-22 15:11:28 +00:00
}
_defaults = {
' unit_quantity ' : lambda * a : 1 ,
' date_value ' : lambda * a : time . strftime ( ' % Y- % m- %d ' ) ,
}
_order = " sequence "
2009-12-23 16:34:53 +00:00
def onchange_product_id ( self , cr , uid , ids , product_id , uom_id , employee_id , context = { } ) :
2008-07-22 15:11:28 +00:00
v = { }
if product_id :
product = self . pool . get ( ' product.product ' ) . browse ( cr , uid , product_id , context = context )
v [ ' name ' ] = product . name
2010-02-17 05:25:53 +00:00
2009-12-23 16:34:53 +00:00
# Compute based on pricetype of employee company
pricetype_id = self . pool . get ( ' hr.employee ' ) . browse ( cr , uid , employee_id ) . user_id . company_id . property_valuation_price_type . id
2010-03-25 10:59:36 +00:00
context [ ' currency_id ' ] = self . pool . get ( ' hr.employee ' ) . browse ( cr , uid , employee_id ) . user_id . company_id . currency_id . id
2009-12-23 16:34:53 +00:00
pricetype = self . pool . get ( ' product.price.type ' ) . browse ( cr , uid , pricetype_id )
amount_unit = product . price_get ( pricetype . field , context ) [ product . id ]
2010-02-17 05:25:53 +00:00
2009-12-23 16:34:53 +00:00
v [ ' unit_amount ' ] = amount_unit
2008-07-22 15:11:28 +00:00
if not uom_id :
v [ ' uom_id ' ] = product . uom_id . id
return { ' value ' : v }
2006-12-07 13:41:40 +00:00
hr_expense_line ( )
2008-07-23 14:41:47 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: