diff --git a/addons/account/account.py b/addons/account/account.py index 6095c2aa113..88a9848f3bb 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -124,10 +124,10 @@ class account_account_type(osv.osv): 'sign': fields.selection([(-1, 'Negative'), (1, 'Positive')], 'Sign on Reports', required=True, help='Allows you to change the sign of the balance amount displayed in the reports, so that you can see positive figures instead of negative ones in expenses accounts.'), 'report_type':fields.selection([ ('none','/'), - ('income','Profilt & Loss (Income Accounts)'), - ('expanse','Profilt & Loss (Expanse Accounts)'), + ('income','Profit & Loss (Income Accounts)'), + ('expense','Profit & Loss (Expense Accounts)'), ('asset','Balance Sheet (Assets Accounts)'), - ('liabilities','Balance Sheet (Liabilities Accounts)') + ('liability','Balance Sheet (Liability Accounts)') ],'Type Heads', select=True, readonly=False, help="According value related accounts will be display on respective reports (Balance Sheet Profit & Loss Account)"), 'parent_id':fields.many2one('account.account.type', 'Parent Type', required=False), 'child_ids':fields.one2many('account.account.type', 'parent_id', 'Child Types', required=False), @@ -231,9 +231,9 @@ class account_account(osv.osv): aml_query = self.pool.get('account.move.line')._query_get(cr, uid, context=context) wheres = [""] - if query: + if query.strip(): wheres.append(query.strip()) - if aml_query: + if aml_query.strip(): wheres.append(aml_query.strip()) query = " AND ".join(wheres) @@ -251,6 +251,7 @@ class account_account(osv.osv): # consolidate accounts with direct children + ids2.reverse() brs = list(self.browse(cr, uid, ids2, context=context)) sums = {} while brs: @@ -270,8 +271,9 @@ class account_account(osv.osv): if current.child_id: sums[current.id][fn] += sum(sums[child.id][fn] for child in current.child_id) res = {} + null_result = dict((fn, 0.0) for fn in field_names) for id in ids: - res[id] = sums[id] + res[id] = sums.get(id, null_result) return res def _get_company_currency(self, cr, uid, ids, field_name, arg, context={}): @@ -313,7 +315,7 @@ class account_account(osv.osv): 'user_type': fields.many2one('account.account.type', 'Account Type', required=True, help="These types are defined according to your country. The type contains more information "\ "about the account and its specificities."), - 'parent_id': fields.many2one('account.account', 'Parent', ondelete='cascade'), + 'parent_id': fields.many2one('account.account', 'Parent', ondelete='cascade', domain=[('type','=','view')]), 'child_parent_ids': fields.one2many('account.account','parent_id','Children'), 'child_consol_ids': fields.many2many('account.account', 'account_account_consol_rel', 'child_id', 'parent_id', 'Consolidated Children'), 'child_id': fields.function(_get_child_ids, method=True, type='many2many', relation="account.account", string="Child Accounts"), @@ -450,18 +452,42 @@ class account_account(osv.osv): def _check_moves(self, cr, uid, ids, method, context): line_obj = self.pool.get('account.move.line') account_ids = self.search(cr, uid, [('id', 'child_of', ids)]) + if line_obj.search(cr, uid, [('account_id', 'in', account_ids)]): if method == 'write': raise osv.except_osv(_('Error !'), _('You cannot deactivate an account that contains account moves.')) elif method == 'unlink': raise osv.except_osv(_('Error !'), _('You cannot remove an account which has account entries!. ')) + #Checking whether the account is set as a property to any Partner or not + value = 'account.account,' + str(ids[0]) + partner_prop_acc = self.pool.get('ir.property').search(cr, uid, [('value_reference','=',value)], context=context) + if partner_prop_acc: + raise osv.except_osv(_('Warning !'), _('You cannot remove/deactivate an account which is set as a property to any Partner.')) + return True + + def _check_allow_type_change(self, cr, uid, ids, new_type, context): + group1 = ['payable', 'receivable', 'other'] + group2 = ['consolidation','view'] + line_obj = self.pool.get('account.move.line') + for account in self.browse(cr, uid, ids, context=context): + old_type = account.type + account_ids = self.search(cr, uid, [('id', 'child_of', [account.id])]) + if line_obj.search(cr, uid, [('account_id', 'in', account_ids)]): + #Check for 'Closed' type + if old_type == 'closed' and new_type !='closed': + raise osv.except_osv(_('Warning !'), _("You cannot change the type of account from 'Closed' to any other type which contains account entries!")) + #Check for change From group1 to group2 and vice versa + if (old_type in group1 and new_type in group2) or (old_type in group2 and new_type in group1): + raise osv.except_osv(_('Warning !'), _("You cannot change the type of account from '%s' to '%s' type as it contains account entries!") % (old_type,new_type,)) return True def write(self, cr, uid, ids, vals, context=None): - if not context: + if context is None: context = {} if 'active' in vals and not vals['active']: self._check_moves(cr, uid, ids, "write", context) + if 'type' in vals.keys(): + self._check_allow_type_change(cr, uid, ids, vals['type'], context=context) return super(account_account, self).write(cr, uid, ids, vals, context=context) def unlink(self, cr, uid, ids, context={}): @@ -557,15 +583,16 @@ class account_journal(osv.osv): def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100): if not args: - args=[] - if not context: - context={} + args = [] + if context is None: + context = {} ids = [] if name: - ids = self.search(cr, user, [('code','ilike',name)]+ args, limit=limit) + ids = self.search(cr, user, [('code','ilike',name)]+ args, limit=limit, context=context) if not ids: - ids = self.search(cr, user, [('name',operator,name)]+ args, limit=limit) + ids = self.search(cr, user, [('name',operator,name)]+ args, limit=limit, context=context) return self.name_get(cr, user, ids, context=context) + account_journal() class account_fiscalyear(osv.osv): @@ -631,6 +658,19 @@ class account_fiscalyear(osv.osv): else: return False return ids[0] + + def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80): + if args is None: + args = [] + if context is None: + context = {} + ids = [] + if name: + ids = self.search(cr, user, [('code','ilike',name)]+ args, limit=limit) + if not ids: + ids = self.search(cr, user, [('name',operator,name)]+ args, limit=limit) + return self.name_get(cr, user, ids, context=context) + account_fiscalyear() class account_period(osv.osv): @@ -706,12 +746,24 @@ class account_period(osv.osv): cr.execute('update account_journal_period set state=%s where period_id=%s', (mode, id)) cr.execute('update account_period set state=%s where id=%s', (mode, id)) return True + + def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80): + if args is None: + args = [] + if context is None: + context = {} + ids = [] + if name: + ids = self.search(cr, user, [('code','ilike',name)]+ args, limit=limit) + if not ids: + ids = self.search(cr, user, [('name',operator,name)]+ args, limit=limit) + return self.name_get(cr, user, ids, context=context) account_period() class account_journal_period(osv.osv): _name = "account.journal.period" - _description = "Journal - Period" + _description = "Journal Period" def _icon_get(self, cr, uid, ids, field_name, arg=None, context={}): result = {}.fromkeys(ids, 'STOCK_NEW') @@ -950,7 +1002,6 @@ class account_move(osv.osv): l[2]['period_id'] = default_period context['period_id'] = default_period - accnt_journal = self.pool.get('account.journal').browse(cr, uid, vals['journal_id']) if 'line_id' in vals: c = context.copy() c['novalidate'] = True @@ -1248,7 +1299,7 @@ class account_tax_code(osv.osv): _description = 'Tax Code' _rec_name = 'code' _columns = { - 'name': fields.char('Tax Case Name', size=64, required=True), + 'name': fields.char('Tax Case Name', size=64, required=True, translate=True), 'code': fields.char('Case Code', size=64), 'info': fields.text('Description'), 'sum': fields.function(_sum_year, method=True, string="Year Sum"), @@ -1262,6 +1313,15 @@ class account_tax_code(osv.osv): } + def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80): + if not args: + args = [] + if context is None: + context = {} + ids = self.search(cr, user, ['|',('name',operator,name),('code',operator,name)] + args, limit=limit, context=context) + return self.name_get(cr, user, ids, context) + + def name_get(self, cr, uid, ids, context=None): if not len(ids): return [] @@ -1290,7 +1350,15 @@ class account_tax_code(osv.osv): return False level -= 1 return True + + def copy(self, cr, uid, id, default=None, context=None): + if default is None: + default = {} + default = default.copy() + default.update({'line_ids': []}) + return super(account_tax_code, self).copy(cr, uid, id, default, context) + _constraints = [ (_check_recursion, 'Error ! You can not create recursive accounts.', ['parent_id']) ] @@ -1348,7 +1416,6 @@ class account_tax(osv.osv): 'include_base_amount': fields.boolean('Included in base amount', help="Indicates if the amount of tax must be included in the base amount for the computation of the next taxes"), 'company_id': fields.many2one('res.company', 'Company', required=True), 'description': fields.char('Tax Code',size=32), - 'price_include': fields.boolean('Tax Included in Price', help="Check this if the price you use on the product and invoices includes this tax."), 'type_tax_use': fields.selection([('sale','Sale'),('purchase','Purchase'),('all','All')], 'Tax Application', required=True) } @@ -1381,7 +1448,6 @@ class account_tax(osv.osv): 'applicable_type': lambda *a: 'true', 'type': lambda *a: 'percent', 'amount': lambda *a: 0, - 'price_include': lambda *a: 0, 'active': lambda *a: 1, 'type_tax_use': lambda *a: 'all', 'sequence': lambda *a: 1, diff --git a/addons/account/account_analytic_line.py b/addons/account/account_analytic_line.py index ce6341cc9b2..64a22d65b21 100644 --- a/addons/account/account_analytic_line.py +++ b/addons/account/account_analytic_line.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2010 Tiny SPRL (). # @@ -15,7 +15,7 @@ # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see . # ############################################################################## @@ -30,7 +30,7 @@ from tools import config class account_analytic_line(osv.osv): _inherit = 'account.analytic.line' - _description = 'Analytic lines' + _description = 'Analytic Line' _columns = { 'product_uom_id' : fields.many2one('product.uom', 'UoM'), 'product_id' : fields.many2one('product.product', 'Product'), @@ -42,23 +42,23 @@ class account_analytic_line(osv.osv): } _defaults = { '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.analytic.line', c), + 'company_id': lambda self,cr,uid,context: self.pool.get('res.company')._company_default_get(cr, uid, 'account.analytic.line', context=context), } _order = 'date' - + def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False): if context is None: context = {} if context.get('from_date',False): args.append(['date', '>=',context['from_date']]) - + if context.get('to_date',False): args.append(['date','<=',context['to_date']]) - + return super(account_analytic_line, self).search(cr, uid, args, offset, limit, order, context=context, count=count) - + def _check_company(self, cr, uid, ids): lines = self.browse(cr, uid, ids) for l in lines: @@ -68,7 +68,7 @@ class account_analytic_line(osv.osv): _constraints = [ # (_check_company, 'You can not create analytic line that is not in the same company than the account line', ['account_id']) ] - + # Compute the cost based on the price type define into company # property_valuation_price_type property def on_change_unit_amount(self, cr, uid, id, prod_id, unit_amount,company_id, @@ -90,7 +90,7 @@ class account_analytic_line(osv.osv): (prod.name, prod.id,)) if not company_id: company_id=company_obj._company_default_get(cr, uid, 'account.analytic.line', context) - + # Compute based on pricetype pricetype=self.pool.get('product.price.type').browse(cr,uid,company_obj.browse(cr,uid,company_id).property_valuation_price_type.id) # Take the company currency as the reference one @@ -118,7 +118,7 @@ account_analytic_line() class timesheet_invoice(osv.osv): _name = "report.hr.timesheet.invoice.journal" - _description = "Analytic account costs and revenues" + _description = "Analytic Account Costs and Revenues" _auto = False _columns = { 'name': fields.char('Year',size=64,required=False, readonly=True), @@ -164,10 +164,10 @@ timesheet_invoice() class res_partner(osv.osv): """ Inherits partner and adds contract information in the partner form """ _inherit = 'res.partner' - + _columns = { 'contract_ids': fields.one2many('account.analytic.account', \ - 'partner_id', 'Contracts'), + 'partner_id', 'Contracts'), } res_partner() diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py index deb010c7cd0..9b1497b563f 100644 --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@ -387,7 +387,7 @@ account_bank_statement() class account_bank_statement_reconcile(osv.osv): _name = "account.bank.statement.reconcile" - _description = "Statement reconcile" + _description = "Statement Reconcile" def _total_entry(self, cursor, user, ids, name, attr, context=None): result = {} @@ -558,35 +558,40 @@ class account_bank_statement_line(osv.osv): def onchange_partner_id(self, cursor, user, line_id, partner_id, type, currency_id, context={}): + res = {'value': {}} if not partner_id: - return {} - res_currency_obj = self.pool.get('res.currency') - res_users_obj = self.pool.get('res.users') - - company_currency_id = res_users_obj.browse(cursor, user, user, - context=context).company_id.currency_id.id - - if not currency_id: - currency_id = company_currency_id - - part = self.pool.get('res.partner').browse(cursor, user, partner_id, + return res + line = self.browse(cursor, user, line_id) + + if not line or (line and not line[0].account_id): + part = self.pool.get('res.partner').browse(cursor, user, partner_id, context=context) - if type == 'supplier': - account_id = part.property_account_payable.id - else: - account_id = part.property_account_receivable.id + if type == 'supplier': + account_id = part.property_account_payable.id + else: + account_id = part.property_account_receivable.id + res['value']['account_id'] = account_id - cursor.execute('SELECT sum(debit-credit) \ + if not line or (line and not line[0].amount): + res_users_obj = self.pool.get('res.users') + res_currency_obj = self.pool.get('res.currency') + company_currency_id = res_users_obj.browse(cursor, user, user, + context=context).company_id.currency_id.id + if not currency_id: + currency_id = company_currency_id + + cursor.execute('SELECT sum(debit-credit) \ FROM account_move_line \ WHERE (reconcile_id is null) \ AND partner_id = %s \ AND account_id=%s', (partner_id, account_id)) - res = cursor.fetchone() - balance = res and res[0] or 0.0 + pgres = cursor.fetchone() + balance = pgres and pgres[0] or 0.0 - balance = res_currency_obj.compute(cursor, user, company_currency_id, + balance = res_currency_obj.compute(cursor, user, company_currency_id, currency_id, balance, context=context) - return {'value': {'amount': balance, 'account_id': account_id}} + res['value']['amount'] = balance + return res def _reconcile_amount(self, cursor, user, ids, name, args, context=None): if not ids: @@ -633,7 +638,7 @@ class account_bank_statement_line(osv.osv): 'note': fields.text('Notes'), 'reconcile_amount': fields.function(_reconcile_amount, string='Amount reconciled', method=True, type='float'), - 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of bank statement line."), + 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of bank statement lines."), } _defaults = { 'name': lambda self,cr,uid,context={}: self.pool.get('ir.sequence').get(cr, uid, 'account.bank.statement.line'), diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml index dcbaf683674..18d817f41bd 100644 --- a/addons/account/account_invoice_view.xml +++ b/addons/account/account_invoice_view.xml @@ -484,22 +484,22 @@ + + - + res.partner.invoice.info.inherit res.partner form - - - + + + - - diff --git a/addons/account/account_invoice_workflow.xml b/addons/account/account_invoice_workflow.xml index 374a436e9ac..4c919765596 100644 --- a/addons/account/account_invoice_workflow.xml +++ b/addons/account/account_invoice_workflow.xml @@ -50,7 +50,7 @@ write({'state':'open'}) paid - write({'state':'paid'}) + confirm_paid() function subflow.paid diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index a86fce20772..36b65d20dca 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -30,7 +30,7 @@ import tools class account_move_line(osv.osv): _name = "account.move.line" - _description = "Entry lines" + _description = "Entry Lines" def _query_get(self, cr, uid, obj='l', context={}): fiscalyear_obj = self.pool.get('account.fiscalyear') @@ -577,11 +577,12 @@ class account_move_line(osv.osv): merges_rec = [] for line in self.browse(cr, uid, ids, context): if line.reconcile_id: - raise osv.except_osv(_('Already Reconciled'), _('Already Reconciled')) + raise osv.except_osv(_('Warning'), _('Already Reconciled!')) if line.reconcile_partial_id: for line2 in line.reconcile_partial_id.line_partial_ids: if not line2.reconcile_id: - merges.append(line2.id) + if line2.id not in merges: + merges.append(line2.id) total += (line2.debit or 0.0) - (line2.credit or 0.0) merges_rec.append(line.reconcile_partial_id.id) else: @@ -774,6 +775,17 @@ class account_move_line(osv.osv): result['fields'] = self.fields_get(cr, uid, fields, context) return result + def _check_moves(self, cr, uid, context): + # use the first move ever created for this journal and period + cr.execute('select id, state, name from account_move where journal_id=%s and period_id=%s order by id limit 1', (context['journal_id'],context['period_id'])) + res = cr.fetchone() + if res: + if res[1] != 'draft': + raise osv.except_osv(_('UserError'), + _('The account move (%s) for centralisation ' \ + 'has been confirmed!') % res[2]) + return res + def unlink(self, cr, uid, ids, context={}, check=True): self._update_check(cr, uid, ids, context) result = False @@ -809,7 +821,7 @@ class account_move_line(osv.osv): return True def write(self, cr, uid, ids, vals, context=None, check=True, update_check=True): - if not context: + if context is None: context={} if vals.get('account_tax_id', False): raise osv.except_osv(_('Unable to change tax !'), _('You can not change the tax, you should remove and recreate lines !')) @@ -825,6 +837,24 @@ class account_move_line(osv.osv): if vals.get('date', False): todo_date = vals['date'] del vals['date'] + + for line in self.browse(cr, uid, ids,context=context): + ctx = context.copy() + if ('journal_id' not in ctx): + if line.move_id: + ctx['journal_id'] = line.move_id.journal_id.id + else: + ctx['journal_id'] = line.journal_id.id + if ('period_id' not in ctx): + if line.move_id: + ctx['period_id'] = line.move_id.period_id.id + else: + ctx['period_id'] = line.period_id.id + #Check for centralisation + journal = self.pool.get('account.journal').browse(cr, uid, ctx['journal_id'], context=ctx) + if journal.centralisation: + self._check_moves(cr, uid, context=ctx) + result = super(account_move_line, self).write(cr, uid, ids, vals, context) if check: @@ -891,14 +921,9 @@ class account_move_line(osv.osv): is_new_move = False if not move_id: if journal.centralisation: - # use the first move ever created for this journal and period - cr.execute('select id, state, name from account_move where journal_id=%s and period_id=%s order by id limit 1', (context['journal_id'],context['period_id'])) - res = cr.fetchone() + #Check for centralisation + res = self._check_moves(cr, uid, context) if res: - if res[1] != 'draft': - raise osv.except_osv(_('UserError'), - _('The Ledger Posting (%s) for centralisation ' \ - 'has been confirmed!') % res[2]) vals['move_id'] = res[0] if not vals.get('move_id', False): @@ -926,7 +951,7 @@ class account_move_line(osv.osv): break if journal.account_control_ids and not ok: for a in journal.account_control_ids: - if a.id==vals['account_id']: + if a.id == vals['account_id']: ok = True break if (account.currency_id) and 'amount_currency' not in vals and account.currency_id.id <> company_currency: @@ -941,7 +966,7 @@ class account_move_line(osv.osv): if not ok: raise osv.except_osv(_('Bad account !'), _('You can not use this general account in this journal !')) - if 'analytic_account_id' in vals and vals['analytic_account_id']: + if vals.get('analytic_account_id',False): if journal.analytic_journal_id: vals['analytic_lines'] = [(0,0, { 'name': vals['name'], @@ -961,8 +986,8 @@ class account_move_line(osv.osv): result = super(osv.osv, self).create(cr, uid, vals, context) # CREATE Taxes - if 'account_tax_id' in vals and vals['account_tax_id']: - tax_id=tax_obj.browse(cr,uid,vals['account_tax_id']) + if vals.get('account_tax_id',False): + tax_id = tax_obj.browse(cr, uid, vals['account_tax_id']) total = vals['debit'] - vals['credit'] if journal.refund_journal: base_code = 'ref_base_code_id' @@ -978,7 +1003,7 @@ class account_move_line(osv.osv): tax_sign = 'tax_sign' tmp_cnt = 0 - for tax in tax_obj.compute(cr,uid,[tax_id],total,1.00): + for tax in tax_obj.compute(cr, uid, [tax_id], total, 1.00): #create the base movement if tmp_cnt == 0: if tax[base_code]: @@ -1031,7 +1056,7 @@ class account_move_line(osv.osv): # if context and ('__last_update' in context): # del context['__last_update'] # self.pool.get('account.move').write(cr, uid, [move_id], {'date':vals['date']}, context=context) - if check and not context.get('no_store_function'): + if check and ((not context.get('no_store_function')) or journal.entry_posted): tmp = self.pool.get('account.move').validate(cr, uid, [vals['move_id']], context) if journal.entry_posted and tmp: self.pool.get('account.move').button_validate(cr,uid, [vals['move_id']],context) diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml index d4bf99c85ac..88e5249735f 100644 --- a/addons/account/account_view.xml +++ b/addons/account/account_view.xml @@ -284,7 +284,7 @@ - + @@ -531,7 +531,10 @@ + + + @@ -551,6 +554,7 @@ + @@ -562,7 +566,7 @@
- + @@ -596,7 +600,6 @@ - @@ -628,7 +631,6 @@