1 ##############################################################################
3 # Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
5 # $Id: hr.py 3751 2006-08-09 13:15:36Z mvd $
7 # WARNING: This program as such is intended to be used by professional
8 # programmers who take the whole responsability of assessing all potential
9 # consequences resulting from its eventual inadequacies and bugs
10 # End users who are looking for a ready-to-use solution with commercial
11 # garantees and support are strongly adviced to contract a Free Software
14 # This program is Free Software; you can redistribute it and/or
15 # modify it under the terms of the GNU General Public License
16 # as published by the Free Software Foundation; either version 2
17 # of the License, or (at your option) any later version.
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
24 # You should have received a copy of the GNU General Public License
25 # along with this program; if not, write to the Free Software
26 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 ##############################################################################
30 from mx import DateTime
33 from osv import fields, osv
35 def _employee_get(obj,cr,uid,context={}):
36 ids = obj.pool.get('hr.employee').search(cr, uid, [('user_id','=', uid)])
41 class hr_expense_expense(osv.osv):
42 def _amount(self, cr, uid, ids, field_name, arg, context):
43 id_set = ",".join(map(str, ids))
44 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 IN ("+id_set+") GROUP BY s.id ")
45 res = dict(cr.fetchall())
48 _name = "hr.expense.expense"
49 _description = "Expense"
51 'name': fields.char('Expense Sheet', size=128, required=True),
52 'id': fields.integer('Sheet ID', readonly=True),
53 'ref': fields.char('Reference', size=32),
54 'date': fields.date('Date'),
55 'journal_id': fields.many2one('account.journal', 'Force Journal'),
56 'analytic_journal_id': fields.many2one('account.analytic.journal', 'Force Analytic Journal'),
57 'employee_id': fields.many2one('hr.employee', 'Employee', required=True),
58 'user_id': fields.many2one('res.users', 'User', required=True),
59 'date_confirm': fields.date('Date Confirmed'),
60 'date_valid': fields.date('Date Valided'),
61 'user_valid': fields.many2one('res.users', 'Validation User'),
63 'account_move_id': fields.many2one('account.move', 'Account Move'),
64 'line_ids': fields.one2many('hr.expense.line', 'expense_id', 'Expense Lines'),
65 'note': fields.text('Note'),
68 'amount': fields.function(_amount, method=True, string='Total Amount'),
69 'invoice_id': fields.many2one('account.invoice', 'Invoice'),
71 'state': fields.selection([
73 ('confirm', 'Waiting confirmation'),
74 ('accepted', 'Accepted'),
75 ('invoiced', 'Invoiced'),
76 ('paid', 'Reimbursed'),
77 ('canceled', 'Canceled')],
78 'State', readonly=True),
81 'date' : lambda *a: time.strftime('%Y-%m-%d'),
82 'state': lambda *a: 'draft',
83 'employee_id' : _employee_get,
84 'user_id' : lambda cr,uid,id,c={}: id
86 def expense_confirm(self, cr, uid, ids, *args):
87 #for exp in self.browse(cr, uid, ids):
88 self.write(cr, uid, ids, {
90 'date_confirm': time.strftime('%Y-%m-%d')
94 def expense_accept(self, cr, uid, ids, *args):
95 self.write(cr, uid, ids, {
97 'date_valid':time.strftime('%Y-%m-%d'),
102 def expense_canceled(self, cr, uid, ids, *args):
103 self.write(cr, uid, ids, {'state':'canceled'})
106 def expense_paid(self, cr, uid, ids, *args):
107 self.write(cr, uid, ids, {'state':'paid'})
110 def action_invoice_create(self, cr, uid, ids):
112 for exp in self.browse(cr, uid, ids):
114 for l in exp.line_ids:
117 acc = l.product_id.product_tmpl_id.property_account_expense
119 acc = l.product_id.categ_id.property_account_expense_categ[0]
122 tax_id = [x.id for x in l.product_id.supplier_taxes_id]
124 acc = self.pool.get('ir.property').get(cr, uid, 'property_account_expense_categ', 'product.category')
125 lines.append((0, False, {
128 'price_unit': l.unit_amount,
129 'quantity': l.unit_quantity,
130 'uos_id': l.uom_id.id,
131 'invoice_line_tax_id': tax_id and [(6, 0, tax_id)] or False,
132 'account_analytic_id': l.analytic_account.id,
134 if not exp.employee_id.address_id:
135 raise osv.except_osv('Error !', 'The employee must have a contact address')
136 acc = exp.employee_id.address_id.partner_id.property_account_payable[0]
139 'reference': "EMP%dEXP%d" % (exp.employee_id.id, exp.id),
141 'type': 'in_invoice',
142 'partner_id': exp.employee_id.address_id.partner_id.id,
143 'address_invoice_id': exp.employee_id.address_id.id,
144 'address_contact_id': exp.employee_id.address_id.id,
146 'invoice_line': lines,
147 'price_type': 'tax_included',
148 'journal_id': exp.journal_id and exp.journal_id.id or False,
150 inv_id = self.pool.get('account.invoice').create(cr, uid, inv, {'type':'in_invoice'})
151 self.write(cr, uid, [exp.id], {'invoice_id': inv_id, 'state': 'invoiced'})
157 class hr_expense_line(osv.osv):
158 _name = "hr.expense.line"
159 _description = "Expense Line"
160 def _amount(self, cr, uid, ids, field_name, arg, context):
163 id_set = ",".join(map(str, ids))
164 cr.execute("SELECT l.id,COALESCE(SUM(l.unit_amount*l.unit_quantity),0) AS amount FROM hr_expense_line l WHERE id IN ("+id_set+") GROUP BY l.id ")
165 res = dict(cr.fetchall())
169 'name': fields.char('Short Description', size=128, required=True),
170 'date_value': fields.date('Date', required=True),
171 'expense_id': fields.many2one('hr.expense.expense', 'Expense', ondelete='cascade', select=True),
172 'total_amount': fields.function(_amount, method=True, string='Total'),
173 'unit_amount': fields.float('Unit Price', readonly=True, states={'draft':[('readonly',False)]}),
174 'unit_quantity': fields.float('Quantities', readonly=True, states={'draft':[('readonly',False)]}),
175 'product_id': fields.many2one('product.product', 'Product', readonly=True, states={'draft':[('readonly',False)]}),
176 'uom_id': fields.many2one('product.uom', 'UoM', readonly=True, states={'draft':[('readonly',False)]}),
177 'description': fields.text('Description'),
178 'analytic_account': fields.many2one('account.analytic.account','Analytic account'),
179 'ref': fields.char('Reference', size=32),
180 'sequence' : fields.integer('Sequence'),
183 'unit_quantity': lambda *a: 1,
184 'date_value' : lambda *a: time.strftime('%Y-%m-%d'),
187 def onchange_product_id(self, cr, uid, ids, product_id, uom_id, context={}):
190 product=self.pool.get('product.product').browse(cr,uid,product_id, context=context)
191 v['name']=product.name
192 v['unit_amount']=product.standard_price
194 v['uom_id']=product.uom_id.id
199 # vim:tw=0:noexpandtab