HR_EXPENSE: add generate invoice

bzr revid: ced-3f35d552568a9b349f3ca1ffa39b17b77f65ebb9
This commit is contained in:
ced 2007-04-18 13:57:37 +00:00
parent 8e5c782a06
commit 113a71bed5
4 changed files with 94 additions and 73 deletions

View File

@ -4,7 +4,7 @@
"author" : "Tiny",
"category" : "Generic Modules/Human Resources",
"website" : "http://tinyerp.com/module_hr.html",
"depends" : ["hr","account"],
"depends" : ["hr","account", "account_tax_include",],
"module": "This module manage the whole expenses flow. It also uses the cost accounting to put costs on analytic accounts.",
"init_xml" : [],
"demo_xml" : [],

View File

@ -52,9 +52,8 @@ class hr_expense_expense(osv.osv):
'id': fields.integer('Sheet ID', readonly=True),
'ref': fields.char('Reference', size=32),
'date': fields.date('Date'),
'account_id': fields.many2one('account.account', 'Payable Account'),
'journal_id': fields.many2one('account.journal', 'Journal'),
'analytic_journal_id': fields.many2one('account.analytic.journal', 'Analytic Journal'),
'journal_id': fields.many2one('account.journal', 'Force Journal'),
'analytic_journal_id': fields.many2one('account.analytic.journal', 'Force Analytic Journal'),
'employee_id': fields.many2one('hr.employee', 'Employee', required=True),
'user_id': fields.many2one('res.users', 'User', required=True),
'date_confirm': fields.date('Date Confirmed'),
@ -67,12 +66,13 @@ class hr_expense_expense(osv.osv):
# fields.function
'amount': fields.function(_amount, method=True, string='Total Amount'),
'move_id': fields.many2one('account.move','Accounting Entries'),
'invoice_id': fields.many2one('account.invoice', 'Invoice'),
'state': fields.selection([
('draft', 'Draft'),
('confirm', 'Waiting confirmation'),
('accepted', 'Accepted'),
('invoiced', 'Invoiced'),
('paid', 'Reimbursed'),
('canceled', 'Canceled')],
'State', readonly=True),
@ -92,68 +92,10 @@ class hr_expense_expense(osv.osv):
return True
def expense_accept(self, cr, uid, ids, *args):
for exp in self.browse(cr, uid, ids):
if not (exp.journal_id and exp.account_id):
raise osv.except_osv('No account or journal defined !', 'You have to define a journal and an account to validate this expense note.')
lines = []
total = 0
for line in exp.line_ids:
if line.product_id:
acc = line.product_id.product_tmpl_id.property_account_expense
if not acc:
acc = line.product_id.categ_id.property_account_expense_categ
acc = acc[0]
lines.append({
'name': line.name,
'date': line.date_value or time.strftime('%Y-%m-%d'),
'quantity': line.unit_quantity,
'ref': line.ref,
'debit': (line.total_amount>0 and line.total_amount) or 0,
'credit': (line.total_amount<0 and -line.total_amount) or 0,
'account_id': acc,
})
total += line.total_amount
if line.analytic_account:
if not exp.analytic_journal_id:
raise osv.except_osv('No analytic journal defined !', 'You have to define an analytic journal to validate this expense note.')
self.pool.get('account.analytic.line').create(cr, uid, {
'name': line.name,
'date': line.date_value,
'product_id': line.product_id.id,
'product_uom_id': line.uom_id.id,
'unit_amount': line.unit_quantity,
'code': line.ref,
'amount': -line.total_amount,
'journal_id': exp.analytic_journal_id.id,
'general_account_id': acc,
'account_id': line.analytic_account.id
})
move_id = False
if lines:
lines.append({
'name': exp.name+'['+str(exp.id)+']',
'date': exp.date or time.strftime('%Y-%m-%d'),
'ref': exp.ref,
'debit': (total<0 and -total) or 0,
'credit': (total>0 and total) or 0,
'account_id': exp.account_id.id,
})
if exp.journal_id.sequence_id:
name = self.pool.get('ir.sequence').get_id(cr, uid, exp.journal_id.sequence_id.id)
else:
name = "EXP "+time.strftime('%Y-%m-%d')
move_id = self.pool.get('account.move').create(cr, uid, {
'name': name,
'journal_id': exp.journal_id.id,
'line_id': map(lambda x: (0,0,x), lines)
})
self.write(cr, uid, [exp.id], {
'move_id': move_id,
'state':'accepted',
'date_valid': time.strftime('%Y-%m-%d'),
'user_valid': uid
self.write(cr, uid, ids, {
'state':'accepted',
'date_valid':time.strftime('%Y-%m-%d'),
'user_valid': uid,
})
return True
@ -164,6 +106,51 @@ class hr_expense_expense(osv.osv):
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
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
if not acc:
acc = l.product_id.categ_id.property_account_expense_categ[0]
else:
acc = acc[0]
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')
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,
'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:
raise osv.except_osv('Error !', 'The employee must have a contact address')
acc = exp.employee_id.address_id.partner_id.property_account_payable[0]
inv = {
'name': exp.name,
'reference': "EMP%dEXP%d" % (exp.employee_id.id, exp.id),
'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',
'journal_id': exp.journal_id and exp.journal_id.id or False,
}
inv_id = self.pool.get('account.invoice').create(cr, uid, inv, {'type':'in_invoice'})
self.write(cr, uid, [exp.id], {'invoice_id': inv_id, 'state': 'invoiced'})
res = inv_id
return res
hr_expense_expense()

View File

@ -68,20 +68,19 @@
<button string="Confirm" name="confirm" states="draft" type="workflow"/>
<button string="Cancel" name="cancel" states="cancel" type="workflow"/>
<button string="Accept" name="validate" states="confirm" type="workflow"/>
<button string="Paid" name="paid" states="accepted" type="workflow"/>
<button string="Invoice" name="invoice" states="accepted" type="workflow"/>
<button string="Set to Draft" name="draft" states="confirm" type="workflow"/>
<button string="Refuse" name="refuse" states="confirm,draft,accepted" type="workflow"/>
</group>
</page><page string="Other Info">
<separator string="Accounting data" colspan="4"/>
<field name="journal_id"/>
<field name="account_id"/>
<field name="analytic_journal_id"/>
<separator string="Validation" colspan="4"/>
<field name="date_confirm" select="1"/>
<field name="date_valid" select="1"/>
<field name="user_valid" select="1"/>
<field name="move_id" select="1"/>
<field name="invoice_id" select="1"/>
<separator string="Notes" colspan="4"/>
<field name="note" colspan="4" nolabel="1"/>
</page>
@ -128,9 +127,20 @@
<field name="domain">[('state','=','accepted')]</field>
</record>
<menuitem
name="Human Resources/Expenses/All Expenses/Expenses waiting payment"
name="Human Resources/Expenses/All Expenses/Expenses waiting invoice"
id="menu_expense_all_valid"
action="expense_all_valid"/>
<record model="ir.actions.act_window" id="expense_all_invoiced">
<field name="name">hr.expense.expense.all.valid</field>
<field name="res_model">hr.expense.expense</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('state','=','invoiced')]</field>
</record>
<menuitem
name="Human Resources/Expenses/All Expenses/Expenses waiting payment"
id="menu_expense_all_invoiced"
action="expense_all_invoiced"/>
#
# My expenses menu

View File

@ -47,6 +47,13 @@
<field name="action">expense_canceled()</field>
<field name="flow_stop">True</field>
</record>
<record model="workflow.activity" id="act_invoice">
<field name="wkf_id" ref="wkf_expenses"/>
<field name="name">invoice</field>
<field name="kind">subflow</field>
<field name="subflow_id" ref="account.wkf"/>
<field name="action">action_invoice_create()</field>
</record>
<record model="workflow.transition" id="t1">
<field name="act_from" ref="act_draft" />
@ -59,12 +66,12 @@
<field name="signal">validate</field>
<field name="role_id" ref="HR"/>
</record>
<record model="workflow.transition" id="t3">
<!--record model="workflow.transition" id="t3">
<field name="act_from" ref="act_accepted" />
<field name="act_to" ref="act_paid" />
<field name="signal">paid</field>
<field name="role_id" ref="HR"/>
</record>
</record-->
<record model="workflow.transition" id="t4">
<field name="act_from" ref="act_confirm" />
<field name="act_to" ref="act_refused" />
@ -89,5 +96,22 @@
<field name="signal">draft</field>
<field name="role_id" ref="HR"/>
</record>
<record model="workflow.transition" id="t8">
<field name="act_from" ref="act_accepted" />
<field name="act_to" ref="act_invoice" />
<field name="signal">invoice</field>
<field name="role_id" ref="HR"/>
</record>
<record model="workflow.transition" id="t9">
<field name="act_from" ref="act_invoice" />
<field name="act_to" ref="act_paid" />
<field name="signal">subflow.paid</field>
</record>
<record model="workflow.transition" id="t10">
<field name="act_from" ref="act_invoice" />
<field name="act_to" ref="act_refused" />
<field name="signal">subflow.cancel</field>
</record>
</data>
</terp>