2009-10-13 05:58:37 +00:00
# -*- coding: utf-8 -*-
2008-11-03 19:18:56 +00:00
##############################################################################
2009-12-24 09:39:00 +00:00
#
2009-10-14 11:15:34 +00:00
# OpenERP, Open Source Management Solution
2010-01-12 09:18:39 +00:00
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
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.
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.
2008-11-03 19:18:56 +00:00
#
2009-10-14 11:15:34 +00:00
# You should have received a copy of the GNU Affero General Public License
2009-12-24 09:39:00 +00:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2008-11-03 19:18:56 +00:00
#
##############################################################################
2009-05-14 07:06:09 +00:00
2008-10-23 05:53:55 +00:00
import time
2010-08-16 20:14:32 +00:00
import netsvc
2010-05-27 19:55:40 +00:00
from osv import fields
from osv import osv
2010-07-22 08:43:54 +00:00
from tools . translate import _
2010-07-07 13:05:41 +00:00
2010-08-26 00:14:59 +00:00
class account_move_line ( osv . osv ) :
_inherit = ' account.move.line '
def _unreconciled ( self , cr , uid , ids , prop , unknow_none , context ) :
res = { }
for line in self . browse ( cr , uid , ids , context = context ) :
res [ line . id ] = line . debit - line . credit
if line . reconcile_partial_id :
res [ line . id ] = 0
for partial in line . reconcile_partial_id . line_partial_ids :
res [ line . id ] + = partial . debit - partial . credit
res [ line . id ] = abs ( res [ line . id ] )
2010-08-18 20:13:20 +00:00
return res
2010-08-26 00:14:59 +00:00
2010-08-18 20:13:20 +00:00
_columns = {
2010-08-26 00:14:59 +00:00
' amount_unreconciled ' : fields . function ( _unreconciled , method = True , string = ' Unreconciled Amount ' ) ,
2010-08-18 20:13:20 +00:00
}
2010-08-26 00:14:59 +00:00
account_move_line ( )
2010-08-18 20:13:20 +00:00
2008-10-23 05:53:55 +00:00
class account_voucher ( osv . osv ) :
2010-08-26 15:04:35 +00:00
def _get_type ( self , cr , uid , ids , context = { } ) :
return context . get ( ' type ' )
2010-05-27 19:55:40 +00:00
def _get_period ( self , cr , uid , context = { } ) :
if context . get ( ' period_id ' , False ) :
return context . get ( ' period_id ' )
2008-10-23 05:53:55 +00:00
periods = self . pool . get ( ' account.period ' ) . find ( cr , uid )
2010-08-26 00:14:59 +00:00
return periods and periods [ 0 ] or False
2009-12-24 09:39:00 +00:00
2010-05-26 19:30:21 +00:00
def _get_journal ( self , cr , uid , context = { } ) :
journal_pool = self . pool . get ( ' account.journal ' )
if context . get ( ' journal_id ' , False ) :
return context . get ( ' journal_id ' )
2010-08-13 21:02:45 +00:00
ttype = context . get ( ' type ' , ' bank ' )
2010-05-26 19:30:21 +00:00
res = journal_pool . search ( cr , uid , [ ( ' type ' , ' = ' , ttype ) ] , limit = 1 )
2010-08-26 00:14:59 +00:00
return res and res [ 0 ] or False
2009-12-24 09:39:00 +00:00
2010-08-25 16:42:19 +00:00
def _get_tax ( self , cr , uid , context = { } ) :
journal_id = context . get ( ' journal_id ' , False )
2010-08-26 00:14:59 +00:00
if not journal_id :
return False
journal_pool = self . pool . get ( ' account.journal ' )
2010-08-25 16:42:19 +00:00
journal = journal_pool . browse ( cr , uid , journal_id )
2010-08-26 00:14:59 +00:00
account_id = journal . default_credit_account_id or journal . default_debit_account_id
2010-08-25 16:42:19 +00:00
if account_id and account_id . tax_ids :
tax_id = account_id . tax_ids [ 0 ] . id
2010-08-26 00:14:59 +00:00
return tax_id
return False
2010-08-17 13:24:18 +00:00
2008-10-23 05:53:55 +00:00
def _get_currency ( self , cr , uid , context ) :
2010-07-07 13:05:41 +00:00
user = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid )
2008-10-23 05:53:55 +00:00
if user . company_id :
return user . company_id . currency_id . id
2010-08-26 00:14:59 +00:00
return False
2009-12-24 09:39:00 +00:00
2008-10-23 05:53:55 +00:00
_name = ' account.voucher '
_description = ' Accounting Voucher '
2010-08-26 00:14:59 +00:00
_order = " date desc, id desc "
2010-08-16 20:14:32 +00:00
_rec_name = ' number '
2008-10-23 05:53:55 +00:00
_columns = {
2010-08-26 15:04:35 +00:00
' type ' : fields . selection ( [
( ' sale ' , ' Sale ' ) ,
( ' purchase ' , ' Purchase ' ) ,
( ' payment ' , ' Payment ' ) ,
( ' receipt ' , ' Receipt ' ) ,
] , ' Type ' ) ,
2010-08-20 18:57:46 +00:00
' name ' : fields . char ( ' Memo ' , size = 256 , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2010-07-14 05:51:50 +00:00
' date ' : fields . date ( ' Date ' , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } , help = " Effective date for accounting entries " ) ,
2008-10-23 05:53:55 +00:00
' journal_id ' : fields . many2one ( ' account.journal ' , ' Journal ' , required = True , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2010-08-19 14:01:41 +00:00
' account_id ' : fields . many2one ( ' account.account ' , ' Account ' , required = True , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2010-08-26 00:14:59 +00:00
' line_ids ' : fields . one2many ( ' account.voucher.line ' , ' voucher_id ' , ' Voucher Lines ' , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
' line_cr_ids ' : fields . one2many ( ' account.voucher.line ' , ' voucher_id ' , ' Credits ' ,
domain = [ ( ' type ' , ' = ' , ' cr ' ) ] , context = { ' default_type ' : ' cr ' } ) ,
' line_dr_ids ' : fields . one2many ( ' account.voucher.line ' , ' voucher_id ' , ' Debits ' ,
domain = [ ( ' type ' , ' = ' , ' dr ' ) ] , context = { ' default_type ' : ' dr ' } ) ,
2010-08-13 21:02:45 +00:00
' period_id ' : fields . many2one ( ' account.period ' , ' Period ' , required = True , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2010-07-28 18:35:57 +00:00
' narration ' : fields . text ( ' Narration ' , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2008-10-23 05:53:55 +00:00
' currency_id ' : fields . many2one ( ' res.currency ' , ' Currency ' , required = True , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' , required = True ) ,
' state ' : fields . selection (
2010-05-26 18:00:17 +00:00
[ ( ' draft ' , ' Draft ' ) ,
( ' proforma ' , ' Pro-forma ' ) ,
( ' posted ' , ' Posted ' ) ,
2010-08-26 00:14:59 +00:00
( ' cancel ' , ' Cancelled ' )
2010-05-26 18:00:17 +00:00
] , ' State ' , readonly = True , size = 32 ,
help = ' * The \' Draft \' state is used when a user is encoding a new and unconfirmed Voucher. \
2009-12-24 09:39:00 +00:00
\n * The \' Pro-forma \' when voucher is in Pro-forma state,voucher does not have an voucher number. \
\n * The \' Posted \' state is used when user create voucher,a voucher number is generated and voucher entries are created in account \
2010-06-18 13:39:57 +00:00
\n * The \' Cancelled \' state is used when user cancel voucher. ' ) ,
2010-08-25 16:42:19 +00:00
' amount ' : fields . float ( ' Total ' , digits = ( 16 , 2 ) , required = True , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2010-08-23 11:09:08 +00:00
' tax_amount ' : fields . float ( ' Tax Amount ' , digits = ( 14 , 2 ) , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2010-08-17 07:32:51 +00:00
' reference ' : fields . char ( ' Ref # ' , size = 64 , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } , help = " Payment or Receipt transaction number, i.e. Bank cheque number or payorder number or Wire transfer number or Acknowledge number. " ) ,
2010-07-07 13:05:41 +00:00
' number ' : fields . related ( ' move_id ' , ' name ' , type = " char " , readonly = True , string = ' Number ' ) ,
2008-10-23 05:53:55 +00:00
' move_id ' : fields . many2one ( ' account.move ' , ' Account Entry ' ) ,
2010-08-26 15:04:35 +00:00
' move_ids ' : fields . related ( ' move_id ' , ' line_id ' , type = ' many2many ' , relation = ' account.move.line ' , string = ' Journal Items ' , readonly = True ) ,
2010-08-13 21:12:34 +00:00
' partner_id ' : fields . many2one ( ' res.partner ' , ' Partner ' , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2010-08-14 07:53:03 +00:00
' audit ' : fields . related ( ' move_id ' , ' to_check ' , type = ' boolean ' , relation = ' account.move ' , string = ' Audit Complete ? ' ) ,
2010-08-18 20:13:20 +00:00
' pay_now ' : fields . selection ( [
2010-08-19 07:57:59 +00:00
( ' pay_now ' , ' Pay Directly ' ) ,
( ' pay_later ' , ' Pay Later or Group Funds ' ) ,
2010-08-18 20:13:20 +00:00
] , ' Payment ' , select = True , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2010-08-19 14:01:41 +00:00
' tax_id ' : fields . many2one ( ' account.tax ' , ' Tax ' , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2010-08-25 16:42:19 +00:00
' pre_line ' : fields . boolean ( ' Previous Payments ? ' , required = False ) ,
2010-08-26 15:04:35 +00:00
' date_due ' : fields . date ( ' Due Date ' ) ,
' term_id ' : fields . many2one ( ' account.payment.term ' , ' Term ' , required = False ) ,
2008-10-23 05:53:55 +00:00
}
_defaults = {
' period_id ' : _get_period ,
' journal_id ' : _get_journal ,
' currency_id ' : _get_currency ,
2010-08-26 15:04:35 +00:00
' type ' : _get_type ,
2010-05-27 19:55:40 +00:00
' state ' : lambda * a : ' draft ' ,
2010-08-19 07:57:59 +00:00
' pay_now ' : lambda * a : ' pay_later ' ,
2010-08-20 11:40:55 +00:00
' name ' : lambda * a : ' ' ,
2010-05-27 19:55:40 +00:00
' date ' : lambda * a : time . strftime ( ' % Y- % m- %d ' ) ,
' company_id ' : lambda self , cr , uid , c : self . pool . get ( ' res.company ' ) . _company_default_get ( cr , uid , ' account.voucher ' , context = c ) ,
2010-08-25 16:42:19 +00:00
' tax_id ' : _get_tax ,
2008-10-23 05:53:55 +00:00
}
2010-08-23 19:02:28 +00:00
2010-08-26 00:14:59 +00:00
# TODO: review this code.
def onchange_price ( self , cr , uid , ids , line_ids , tax_id , partner_id = False , context = { } ) :
2010-08-23 11:09:08 +00:00
tax_pool = self . pool . get ( ' account.tax ' )
partner_pool = self . pool . get ( ' res.partner ' )
position_pool = self . pool . get ( ' account.fiscal.position ' )
2010-08-25 16:42:19 +00:00
voucher_line_pool = self . pool . get ( ' account.voucher.line ' )
2010-08-19 14:01:41 +00:00
res = {
2010-08-20 11:40:55 +00:00
' tax_amount ' : False ,
2010-08-25 16:42:19 +00:00
' amount ' : False ,
2010-08-19 14:01:41 +00:00
}
2010-08-25 16:42:19 +00:00
voucher_total_tax = 0.0
voucher_total = 0.0
2010-08-26 00:14:59 +00:00
voucher_line_ids = [ ]
2010-08-25 16:42:19 +00:00
2010-08-20 11:40:55 +00:00
total = 0.0
2010-08-25 16:42:19 +00:00
total_tax = 0.0
2010-08-26 00:14:59 +00:00
for line in line_ids :
voucher_line_ids + = [ line [ 1 ] ]
2010-08-25 16:42:19 +00:00
voucher_total + = line [ 2 ] . get ( ' amount ' )
total = voucher_total
if tax_id :
tax = [ tax_pool . browse ( cr , uid , tax_id ) ]
if partner_id :
partner = partner_pool . browse ( cr , uid , partner_id ) or False
taxes = position_pool . map_tax ( cr , uid , partner and partner . property_account_position or False , tax )
tax = tax_pool . browse ( cr , uid , taxes )
if not tax [ 0 ] . price_include :
for tax_line in tax_pool . compute_all ( cr , uid , tax , voucher_total , 1 ) . get ( ' taxes ' ) :
total_tax + = tax_line . get ( ' amount ' )
total + = total_tax
else :
2010-08-26 00:14:59 +00:00
line_ids2 = [ ]
for line in line_ids :
2010-08-25 16:42:19 +00:00
line_total = 0.0
line_tax = 0.0
operation = line [ 0 ]
rec_id = line [ 1 ]
rec = line [ 2 ]
for tax_line in tax_pool . compute_all ( cr , uid , tax , rec . get ( ' amount ' ) , 1 ) . get ( ' taxes ' ) :
line_tax + = tax_line . get ( ' amount ' )
line_total + = tax_line . get ( ' price_unit ' )
total_tax + = line_tax
if rec_id :
voucher_line_pool . write ( cr , uid , [ rec_id ] , { ' amount ' : line_total } )
2010-08-26 00:14:59 +00:00
line_ids2 + = [ rec_id ]
2010-08-25 16:42:19 +00:00
else :
rec . update ( {
' amount ' : line_total
} )
res . update ( {
2010-08-26 00:14:59 +00:00
' line_ids ' : line_ids2
} )
2010-08-20 11:40:55 +00:00
res . update ( {
2010-08-23 19:02:28 +00:00
' amount ' : total ,
2010-08-25 16:42:19 +00:00
' tax_amount ' : total_tax
2010-08-20 11:40:55 +00:00
} )
2010-08-19 14:01:41 +00:00
return {
' value ' : res
}
2010-08-26 15:04:35 +00:00
def onchange_term_id ( self , cr , uid , ids , term_id , amount ) :
term_pool = self . pool . get ( ' account.payment.term ' )
terms = False
due_date = False
default = { ' date_due ' : False }
if term_id and amount :
terms = term_pool . compute ( cr , uid , term_id , amount )
if terms :
due_date = terms [ - 1 ] [ 0 ]
default . update ( {
' date_due ' : due_date
} )
return { ' value ' : default }
2010-08-26 19:09:33 +00:00
def onchange_partner_id ( self , cr , uid , ids , partner_id , journal_id = False , price = 0.0 , ttype = False , context = { } ) :
2010-08-26 15:04:35 +00:00
""" price
2010-08-18 20:13:20 +00:00
Returns a dict that contains new values and context
@param partner_id : latest value from user input for field partner_id
@param args : other arguments
@param context : context arguments , like lang , time zone
@return : Returns a dict which contains new values , and context
"""
2010-08-26 00:14:59 +00:00
if not journal_id :
return { }
2010-08-18 20:13:20 +00:00
move_pool = self . pool . get ( ' account.move ' )
line_pool = self . pool . get ( ' account.voucher.line ' )
2010-08-20 11:40:55 +00:00
move_line_pool = self . pool . get ( ' account.move.line ' )
2010-08-19 14:01:41 +00:00
partner_pool = self . pool . get ( ' res.partner ' )
2010-08-20 11:40:55 +00:00
journal_pool = self . pool . get ( ' account.journal ' )
2010-08-18 20:13:20 +00:00
default = {
2010-08-26 15:04:35 +00:00
' value ' : { ' line_ids ' : [ ] , ' line_dr_ids ' : [ ] , ' line_cr_ids ' : [ ] , ' pre_line ' : False } ,
2010-08-18 20:13:20 +00:00
}
2010-08-26 00:14:59 +00:00
2010-08-23 11:09:08 +00:00
if not partner_id :
2010-08-26 15:04:35 +00:00
return default
if not partner_id and ids :
line_ids = line_pool . search ( cr , uid , [ ( ' voucher_id ' , ' = ' , ids [ 0 ] ) ] )
if line_ids :
line_pool . unlink ( cr , uid , line_ids )
2010-08-18 20:13:20 +00:00
return default
2010-08-26 00:14:59 +00:00
journal = journal_pool . browse ( cr , uid , journal_id )
2010-08-19 14:01:41 +00:00
partner = partner_pool . browse ( cr , uid , partner_id )
2010-08-26 00:14:59 +00:00
account_id = False
2010-08-26 15:04:35 +00:00
term_id = False
2010-08-26 00:14:59 +00:00
if journal . type in ( ' sale ' , ' sale_refund ' ) :
2010-08-19 14:01:41 +00:00
account_id = partner . property_account_receivable . id
2010-08-26 00:14:59 +00:00
elif journal . type in ( ' purchase ' , ' purchase_refund ' , ' expense ' ) :
2010-08-26 15:04:35 +00:00
term_id = partner . property_payment_term . id
if term_id :
vals = self . onchange_term_id ( cr , uid , ids , term_id , price )
default [ ' value ' ] . update ( vals . get ( ' value ' ) )
2010-08-19 14:01:41 +00:00
account_id = partner . property_account_payable . id
2010-08-26 00:14:59 +00:00
else :
account_id = journal . default_credit_account_id . id or journal . default_debit_account_id . id
2010-08-19 14:01:41 +00:00
default [ ' value ' ] . update ( {
2010-08-26 15:04:35 +00:00
' account_id ' : account_id ,
' term_id ' : term_id
2010-08-19 14:01:41 +00:00
} )
2010-08-26 00:14:59 +00:00
if journal . type not in ( ' cash ' , ' bank ' ) :
2010-08-18 20:13:20 +00:00
return default
2010-08-26 19:09:33 +00:00
account_type = ' receivable '
if ttype == ' payment ' :
account_type = ' payable '
else :
account_type = ' receivable '
ids = move_line_pool . search ( cr , uid , [ ( ' account_id.type ' , ' = ' , account_type ) , ( ' reconcile_id ' , ' = ' , False ) , ( ' partner_id ' , ' = ' , partner_id ) ] , context = context )
2010-08-26 00:14:59 +00:00
moves = move_line_pool . browse ( cr , uid , ids )
total_credit = price or 0.0
total_debit = 0.0
for line in moves :
if line . credit and line . reconcile_partial_id :
continue
total_credit + = line . credit or 0.0
total_debit + = line . debit or 0.0
for line in moves :
if line . credit and line . reconcile_partial_id :
continue
rs = {
2010-08-20 13:47:29 +00:00
' name ' : line . move_id . name ,
2010-08-26 00:14:59 +00:00
' type ' : line . credit and ' dr ' or ' cr ' ,
2010-08-20 11:40:55 +00:00
' move_line_id ' : line . id ,
2010-08-26 00:14:59 +00:00
' account_id ' : line . account_id . id ,
' amount_original ' : line . credit or line . debit or 0.0 ,
' date_original ' : line . date ,
' date_due ' : line . date_maturity ,
' amount_unreconciled ' : line . amount_unreconciled
}
if line . credit :
rs [ ' amount ' ] = min ( line . amount_unreconciled , total_debit )
total_debit - = rs [ ' amount ' ]
else :
rs [ ' amount ' ] = min ( line . debit , total_credit )
total_credit - = rs [ ' amount ' ]
default [ ' value ' ] [ ' line_ids ' ] . append ( rs )
if rs [ ' type ' ] == ' cr ' :
default [ ' value ' ] [ ' line_cr_ids ' ] . append ( rs )
else :
default [ ' value ' ] [ ' line_dr_ids ' ] . append ( rs )
2010-08-26 19:09:33 +00:00
if ttype == ' payment ' and len ( default [ ' value ' ] [ ' line_cr_ids ' ] ) > 0 :
2010-08-26 00:14:59 +00:00
default [ ' value ' ] [ ' pre_line ' ] = 1
2010-08-26 19:09:33 +00:00
elif ttype == ' receipt ' and len ( default [ ' value ' ] [ ' line_dr_ids ' ] ) > 0 :
default [ ' value ' ] [ ' pre_line ' ] = 1
2010-08-26 00:14:59 +00:00
return default
2010-08-20 13:47:29 +00:00
2010-08-13 21:08:42 +00:00
def onchange_date ( self , cr , user , ids , date , context = { } ) :
"""
@param date : latest value from user input for field date
@param args : other arguments
@param context : context arguments , like lang , time zone
@return : Returns a dict which contains new values , and context
"""
period_pool = self . pool . get ( ' account.period ' )
pids = period_pool . search ( cr , user , [ ( ' date_start ' , ' <= ' , date ) , ( ' date_stop ' , ' >= ' , date ) ] )
2010-08-26 00:14:59 +00:00
if not pids :
return { }
2010-08-13 21:08:42 +00:00
return {
2010-08-26 00:14:59 +00:00
' value ' : {
' period_id ' : pids [ 0 ]
2010-05-27 19:55:40 +00:00
}
2010-08-13 21:02:45 +00:00
}
2010-08-26 00:14:59 +00:00
def onchange_journal ( self , cr , uid , ids , journal_id ) :
return { }
2010-08-14 12:20:54 +00:00
2010-08-26 15:04:35 +00:00
def proforma_voucher ( self , cr , uid , ids ) :
2009-05-14 07:06:09 +00:00
self . action_move_line_create ( cr , uid , ids )
2008-10-23 05:53:55 +00:00
return True
2010-08-14 12:20:54 +00:00
2010-07-09 04:54:54 +00:00
def action_cancel_draft ( self , cr , uid , ids , context = { } ) :
2010-08-16 20:14:32 +00:00
wf_service = netsvc . LocalService ( " workflow " )
for voucher_id in ids :
wf_service . trg_create ( uid , ' account.voucher ' , voucher_id , cr )
2010-07-07 15:04:16 +00:00
self . write ( cr , uid , ids , { ' state ' : ' draft ' } )
return True
2010-08-14 12:20:54 +00:00
2010-06-16 11:51:39 +00:00
def cancel_voucher ( self , cr , uid , ids , context = { } ) :
2010-07-07 13:05:41 +00:00
move_pool = self . pool . get ( ' account.move ' )
2010-08-13 21:02:45 +00:00
voucher_line_pool = self . pool . get ( ' account.voucher.line ' )
2010-07-07 13:05:41 +00:00
for voucher in self . browse ( cr , uid , ids ) :
if voucher . move_id :
move_pool . button_cancel ( cr , uid , [ voucher . move_id . id ] )
move_pool . unlink ( cr , uid , [ voucher . move_id . id ] )
res = {
2010-08-14 12:20:54 +00:00
' state ' : ' cancel ' ,
2010-07-07 13:05:41 +00:00
' move_id ' : False ,
}
self . write ( cr , uid , ids , res )
2008-10-23 05:53:55 +00:00
return True
2009-12-24 09:39:00 +00:00
2010-06-21 13:19:12 +00:00
def unlink ( self , cr , uid , ids , context = None ) :
2010-08-26 00:14:59 +00:00
for t in self . read ( cr , uid , ids , [ ' state ' ] , context = context ) :
if t [ ' state ' ] not in ( ' draft ' , ' cancel ' ) :
raise osv . except_osv ( _ ( ' Invalid action ! ' ) , _ ( ' Cannot delete Voucher(s) which are already opened or paid ! ' ) )
return super ( account_voucher , self ) . unlink ( cr , uid , ids , context = context )
2009-12-24 09:39:00 +00:00
2010-08-26 00:14:59 +00:00
# TODO
def onchange_payment ( self , cr , uid , ids , pay_now , journal_id , partner_id , ttype = ' sale ' ) :
if not partner_id :
return { }
2010-08-19 14:01:41 +00:00
partner_pool = self . pool . get ( ' res.partner ' )
res = { ' account_id ' : False }
2010-08-26 00:14:59 +00:00
if pay_now == ' pay_later ' :
2010-08-19 14:01:41 +00:00
partner = partner_pool . browse ( cr , uid , partner_id )
if ttype == ' sale ' :
res . update ( {
' account_id ' : partner . property_account_receivable . id ,
} )
elif ttype == ' purchase ' :
res . update ( {
' account_id ' : partner . property_account_payable . id ,
} )
return {
' value ' : res
}
2010-08-26 00:14:59 +00:00
2010-08-19 14:01:41 +00:00
def action_move_line_create ( self , cr , uid , ids , * args ) :
2010-08-26 19:09:33 +00:00
def _get_payment_term_lines ( term_id , amount ) :
term_pool = self . pool . get ( ' account.payment.term ' )
if term_id and amount :
terms = term_pool . compute ( cr , uid , term_id , amount )
return terms
return False
2010-07-07 13:05:41 +00:00
move_pool = self . pool . get ( ' account.move ' )
move_line_pool = self . pool . get ( ' account.move.line ' )
analytic_pool = self . pool . get ( ' account.analytic.line ' )
currency_pool = self . pool . get ( ' res.currency ' )
2010-07-28 18:35:57 +00:00
invoice_pool = self . pool . get ( ' account.invoice ' )
2010-08-19 14:01:41 +00:00
2008-10-23 05:53:55 +00:00
for inv in self . browse ( cr , uid , ids ) :
if inv . move_id :
continue
2010-08-14 12:20:54 +00:00
2010-08-26 00:14:59 +00:00
if not inv . line_ids :
raise osv . except_osv ( _ ( ' Error ! ' ) , _ ( ' You can not validate a voucher without lines ! ' ) )
if inv . journal_id . sequence_id :
name = self . pool . get ( ' ir.sequence ' ) . get_id ( cr , uid , inv . journal_id . sequence_id . id )
2010-07-28 18:35:57 +00:00
else :
2010-08-26 00:14:59 +00:00
raise osv . except_osv ( _ ( ' Error ! ' ) , _ ( ' Please define a sequence on the journal ! ' ) )
2010-08-13 21:02:45 +00:00
2009-05-14 07:06:09 +00:00
move = {
2010-08-13 21:02:45 +00:00
' name ' : name ,
2010-08-26 00:14:59 +00:00
' journal_id ' : inv . journal_id . id ,
' narration ' : inv . narration ,
2010-07-14 05:51:50 +00:00
' date ' : inv . date ,
2010-08-26 00:14:59 +00:00
' ref ' : inv . reference ,
' period_id ' : inv . period_id and inv . period_id . id or False
2009-05-14 07:06:09 +00:00
}
2010-07-07 13:05:41 +00:00
move_id = move_pool . create ( cr , uid , move )
2010-08-26 00:14:59 +00:00
company_currency = inv . account_id . company_id . currency_id . id
2010-08-26 19:09:33 +00:00
2010-07-07 13:05:41 +00:00
#create the first line manually
2010-08-26 00:14:59 +00:00
debit = 0.0
credit = 0.0
2010-08-26 15:04:35 +00:00
# TODO: is there any other alternative then the voucher type ??
if inv . type in ( ' purchase ' , ' payment ' ) :
credit = currency_pool . compute ( cr , uid , inv . currency_id . id , company_currency , inv . amount )
elif inv . type in ( ' sale ' , ' receipt ' ) :
2010-08-26 00:14:59 +00:00
debit = currency_pool . compute ( cr , uid , inv . currency_id . id , company_currency , inv . amount )
2010-08-26 19:09:33 +00:00
if inv . type == ' purchase ' and inv . term_id and _get_payment_term_lines ( inv . term_id . id , credit or debit ) :
terms = _get_payment_term_lines ( inv . term_id . id , credit or debit )
for term in terms :
due_date = term [ 0 ]
amount = term [ 1 ]
move_line = {
' name ' : inv . name or ' / ' ,
' debit ' : 0.0 ,
' credit ' : amount ,
' date_maturity ' : due_date ,
' account_id ' : inv . account_id . id ,
' move_id ' : move_id ,
' journal_id ' : inv . journal_id . id ,
' period_id ' : inv . period_id . id ,
' partner_id ' : inv . partner_id . id ,
' currency_id ' : inv . currency_id . id ,
' date ' : inv . date
}
master_line = move_line_pool . create ( cr , uid , move_line )
else :
move_line = {
' name ' : inv . name or ' / ' ,
' debit ' : debit ,
' credit ' : credit ,
' account_id ' : inv . account_id . id ,
' move_id ' : move_id ,
' journal_id ' : inv . journal_id . id ,
' period_id ' : inv . period_id . id ,
' partner_id ' : inv . partner_id . id ,
' currency_id ' : inv . currency_id . id ,
' date ' : inv . date
}
master_line = move_line_pool . create ( cr , uid , move_line )
2010-08-19 14:01:41 +00:00
2010-08-26 00:14:59 +00:00
rec_list_ids = [ ]
line_total = debit - credit
for line in inv . line_ids :
if not line . amount :
continue
amount = currency_pool . compute ( cr , uid , inv . currency_id . id , company_currency , line . amount )
2010-08-19 14:01:41 +00:00
move_line = {
2010-08-26 00:14:59 +00:00
' name ' : line . name and line . name or ' / ' ,
' account_id ' : line . account_id . id ,
' move_id ' : move_id ,
' partner_id ' : inv . partner_id . id ,
' currency_id ' : inv . currency_id . id ,
2010-08-19 14:01:41 +00:00
}
2010-08-26 00:14:59 +00:00
if ( line . type == ' dr ' ) :
line_total + = amount
move_line [ ' debit ' ] = amount
else :
line_total - = amount
move_line [ ' credit ' ] = amount
master_line = move_line_pool . create ( cr , uid , move_line )
if line . move_line_id . id :
rec_ids = [ master_line , line . move_line_id . id ]
rec_list_ids . append ( rec_ids )
2010-08-19 14:01:41 +00:00
2010-08-26 00:14:59 +00:00
if inv . tax_amount > 0 :
amount = currency_pool . compute ( cr , uid , inv . currency_id . id , company_currency , inv . tax_amount )
name = inv . tax_id and inv . tax_id . name or ' / '
2008-12-15 11:48:52 +00:00
move_line = {
2010-08-23 06:43:16 +00:00
' name ' : name ,
2010-08-17 13:24:18 +00:00
' move_id ' : move_id ,
2010-08-19 14:01:41 +00:00
' journal_id ' : inv . journal_id . id ,
2010-08-17 13:24:18 +00:00
' period_id ' : inv . period_id . id ,
' partner_id ' : inv . partner_id . id ,
2010-08-26 00:14:59 +00:00
' currency_id ' : inv . currency_id . id ,
2010-07-07 13:05:41 +00:00
}
2010-08-14 12:20:54 +00:00
2010-08-26 00:14:59 +00:00
if inv . journal_id . type in ( ' sale ' , ' purchase_refund ' ) :
line_total - = amount
move_line [ ' credit ' ] = amount
else :
line_total + = amount
move_line [ ' debit ' ] = amount
account_id = False
if inv . tax_id :
if inv . journal_id . type in ( ' sale_refund ' , ' purchase_refund ' ) :
account_id = inv . tax_id . account_paid_id
else :
account_id = inv . tax_id . account_collected_id . id
if not account_id :
raise osv . except_osv ( _ ( ' Invalid Error ! ' ) , _ ( ' No account defined on the related tax ! ' ) )
move_line [ ' account_id ' ] = account_id
2010-08-19 14:01:41 +00:00
move_line_id = move_line_pool . create ( cr , uid , move_line )
2010-08-25 16:42:19 +00:00
2010-08-26 00:14:59 +00:00
if not self . pool . get ( ' res.currency ' ) . is_zero ( cr , uid , inv . currency_id , line_total ) :
diff = line_total
2010-08-23 11:09:08 +00:00
move_line = {
' name ' : name ,
' account_id ' : False ,
' move_id ' : move_id ,
' partner_id ' : inv . partner_id . id ,
2010-08-26 00:14:59 +00:00
' date ' : inv . date ,
' credit ' : diff > 0 and diff or 0.0 ,
' debit ' : diff < 0 and - diff or 0.0 ,
2010-08-23 11:09:08 +00:00
}
account_id = False
2010-08-26 00:14:59 +00:00
if inv . journal_id . type in ( ' sale ' , ' sale_refund ' , ' cash ' , ' bank ' ) :
account_id = inv . partner_id . property_account_receivable . id
else :
account_id = inv . partner_id . property_account_payable . id
move_line [ ' account_id ' ] = account_id
2010-08-25 16:42:19 +00:00
move_line_id = move_line_pool . create ( cr , uid , move_line )
2010-08-26 00:14:59 +00:00
self . write ( cr , uid , [ inv . id ] , {
2010-08-23 11:09:08 +00:00
' move_id ' : move_id ,
' state ' : ' posted '
2010-08-26 00:14:59 +00:00
} )
2010-08-16 20:14:32 +00:00
move_pool . post ( cr , uid , [ move_id ] , context = { } )
2010-08-23 11:09:08 +00:00
for rec_ids in rec_list_ids :
2010-08-25 16:42:19 +00:00
if len ( rec_ids ) > = 2 :
move_line_pool . reconcile_partial ( cr , uid , rec_ids )
2008-10-23 05:53:55 +00:00
return True
2009-05-14 07:06:09 +00:00
2010-08-14 12:20:54 +00:00
def copy ( self , cr , uid , id , default = { } , context = None ) :
2010-08-26 00:14:59 +00:00
default . update ( {
2010-08-13 21:02:45 +00:00
' state ' : ' draft ' ,
' number ' : False ,
2010-08-19 14:01:41 +00:00
' move_id ' : False
2010-08-26 00:14:59 +00:00
} )
2008-10-23 05:53:55 +00:00
if ' date ' not in default :
default [ ' date ' ] = time . strftime ( ' % Y- % m- %d ' )
return super ( account_voucher , self ) . copy ( cr , uid , id , default , context )
2010-08-26 00:14:59 +00:00
# TODO
2010-08-18 20:13:20 +00:00
def fields_view_get ( self , cr , uid , view_id = None , view_type = ' form ' , context = None , toolbar = False , submenu = False ) :
"""
Returns views and fields for current model where view will depend on { view_type } .
@param view_id : list of fields , which required to read signatures
@param view_type : defines a view type . it can be one of ( form , tree , graph , calender , gantt , search , mdx )
@param context : context arguments , like lang , time zone
@param toolbar : contains a list of reports , wizards , and links related to current model
@return : Returns a dict that contains definition for fields , views , and toolbars
"""
data_pool = self . pool . get ( ' ir.model.data ' )
journal_pool = self . pool . get ( ' account.journal ' )
voucher_type = {
' sale ' : ' view_sale_receipt_form ' ,
' purchase ' : ' view_purchase_receipt_form ' ,
' payment ' : ' view_vendor_payment_form ' ,
' receipt ' : ' view_vendor_receipt_form '
}
if view_type == ' form ' :
tview = voucher_type . get ( context . get ( ' type ' ) )
result = data_pool . _get_id ( cr , uid , ' account_voucher ' , tview )
view_id = data_pool . browse ( cr , uid , result , context = context ) . res_id
res = super ( account_voucher , self ) . fields_view_get ( cr , uid , view_id , view_type , context , toolbar , submenu )
#Restrict the list of journal view in search view
if view_type == ' search ' :
journal_list = journal_pool . name_search ( cr , uid , ' ' , [ ] , context = context )
2010-08-20 11:40:55 +00:00
res [ ' fields ' ] [ ' journal_id ' ] [ ' selection ' ] = journal_list
2010-08-18 20:13:20 +00:00
return res
2010-08-20 18:57:46 +00:00
2008-10-23 05:53:55 +00:00
account_voucher ( )
2010-02-16 07:06:49 +00:00
class account_voucher_line ( osv . osv ) :
2008-10-23 05:53:55 +00:00
_name = ' account.voucher.line '
2010-08-26 00:14:59 +00:00
_description = ' Voucher Lines '
2010-08-25 16:42:19 +00:00
def _compute_balance ( self , cr , uid , ids , name , args , context = None ) :
res = { }
for line in self . browse ( cr , uid , ids ) :
2010-08-26 00:14:59 +00:00
move_line = line . move_line_id or False
if not move_line :
res [ line . id ] = 0.0
elif move_line and move_line . credit > 0 :
2010-08-25 16:42:19 +00:00
res [ line . id ] = move_line . credit
2010-08-26 00:14:59 +00:00
else :
2010-08-25 16:42:19 +00:00
res [ line . id ] = move_line . debit
return res
2010-08-17 13:24:18 +00:00
2008-10-23 05:53:55 +00:00
_columns = {
2010-08-26 19:09:33 +00:00
' voucher_id ' : fields . many2one ( ' account.voucher ' , ' Voucher ' , required = 1 , ondelete = ' cascade ' ) ,
2010-08-23 11:09:08 +00:00
' name ' : fields . char ( ' Description ' , size = 256 ) ,
2010-08-26 15:04:35 +00:00
' account_id ' : fields . many2one ( ' account.account ' , ' Account ' , required = True ) ,
2010-08-17 07:32:51 +00:00
' partner_id ' : fields . related ( ' voucher_id ' , ' partner_id ' , type = ' many2one ' , relation = ' res.partner ' , string = ' Partner ' ) ,
2008-10-23 05:53:55 +00:00
' amount ' : fields . float ( ' Amount ' ) ,
2010-08-25 16:42:19 +00:00
' type ' : fields . selection ( [ ( ' dr ' , ' Debit ' ) , ( ' cr ' , ' Credit ' ) ] , ' Cr/Dr ' ) ,
2010-08-13 21:02:45 +00:00
' account_analytic_id ' : fields . many2one ( ' account.analytic.account ' , ' Analytic Account ' ) ,
2010-08-19 07:57:59 +00:00
' move_line_id ' : fields . many2one ( ' account.move.line ' , ' Journal Item ' ) ,
2010-08-26 00:14:59 +00:00
' date_original ' : fields . related ( ' move_line_id ' , ' date ' , type = ' date ' , relation = ' account.move.line ' , string = ' Date ' , readonly = 1 ) ,
' date_due ' : fields . related ( ' move_line_id ' , ' date_maturity ' , type = ' date ' , relation = ' account.move.line ' , string = ' Due Date ' , readonly = 1 ) ,
2010-08-25 16:42:19 +00:00
' amount_original ' : fields . function ( _compute_balance , method = True , type = ' float ' , string = ' Originial Amount ' , store = True ) ,
2010-08-26 00:14:59 +00:00
' amount_unreconciled ' : fields . related ( ' move_line_id ' , ' amount_unreconciled ' , type = ' float ' , relation = ' account.move.line ' , string = ' Open Balance ' , readonly = " 1 " ) ,
2008-10-23 05:53:55 +00:00
}
_defaults = {
2010-08-26 00:14:59 +00:00
' name ' : lambda * a : ' '
2008-10-23 05:53:55 +00:00
}
2009-12-24 09:39:00 +00:00
2010-08-20 18:57:46 +00:00
def onchange_move_line_id ( self , cr , user , ids , move_line_id , context = { } ) :
"""
Returns a dict that contains new values and context
@param move_line_id : latest value from user input for field move_line_id
@param args : other arguments
@param context : context arguments , like lang , time zone
@return : Returns a dict which contains new values , and context
"""
res = { }
move_line_pool = self . pool . get ( ' account.move.line ' )
if move_line_id :
2010-08-26 00:14:59 +00:00
move_line = move_line_pool . browse ( cr , user , move_line_id , context = context )
2010-08-20 18:57:46 +00:00
move_id = move_line . move_id . id
2010-08-26 00:14:59 +00:00
if move_line . credit :
ttype = ' dr '
amount = move_line . credit
else :
ttype = ' cr '
amount = move_line . debit
2010-08-20 18:57:46 +00:00
account_id = move_line . account_id . id
res . update ( {
2010-08-26 00:14:59 +00:00
' account_id ' : account_id ,
' type ' : ttype
2010-08-20 18:57:46 +00:00
} )
return {
' value ' : res ,
}
2010-08-26 00:14:59 +00:00
2010-08-20 11:40:55 +00:00
def default_get ( self , cr , user , fields_list , context = None ) :
"""
Returns default values for fields
@param fields_list : list of fields , for which default values are required to be read
@param context : context arguments , like lang , time zone
@return : Returns a dict that contains default values for fields
"""
2010-08-26 00:14:59 +00:00
journal_id = context . get ( ' journal_id ' , False )
partner_id = context . get ( ' partner_id ' , False )
2010-08-20 11:40:55 +00:00
journal_pool = self . pool . get ( ' account.journal ' )
partner_pool = self . pool . get ( ' res.partner ' )
values = super ( account_voucher_line , self ) . default_get ( cr , user , fields_list , context = context )
2010-08-26 00:14:59 +00:00
if ( not journal_id ) or ( ' account_id ' not in fields_list ) :
return values
journal = journal_pool . browse ( cr , user , journal_id )
account_id = False
if journal . type in ( ' sale ' , ' purchase_refund ' ) :
account_id = journal . default_credit_account_id and journal . default_credit_account_id . id or False
elif journal . type in ( ' purchase ' , ' expense ' , ' sale_refund ' ) :
account_id = journal . default_debit_account_id and journal . default_debit_account_id . id or False
elif partner_id :
2010-08-26 19:09:33 +00:00
partner = partner_pool . browse ( cr , user , partner_id , context = context )
if context . get ( ' type ' ) == ' payment ' :
account_id = partner . property_account_payable . id
elif context . get ( ' type ' ) == ' receipt ' :
account_id = partner . property_account_receivable . id
2010-08-26 00:14:59 +00:00
if ( not account_id ) and ' account_id ' in fields_list :
2010-08-20 18:57:46 +00:00
raise osv . except_osv ( _ ( ' Invalid Error ! ' ) , _ ( ' Please change partner and try again ! ' ) )
2010-08-20 11:40:55 +00:00
values . update ( {
2010-08-25 16:42:19 +00:00
' account_id ' : account_id ,
2010-08-20 11:40:55 +00:00
} )
return values
2010-02-16 07:06:49 +00:00
account_voucher_line ( )