diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index 96412077840..f7d2406dc61 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -60,6 +60,7 @@ module named account_voucher. 'wizard/account_period_close_view.xml', 'wizard/account_fiscalyear_close_state.xml', 'wizard/account_chart_view.xml', + 'wizard/account_tax_chart_view.xml', 'wizard/account_move_journal_view.xml', 'wizard/account_move_line_reconcile_select_view.xml', 'wizard/account_open_closed_fiscalyear_view.xml', @@ -74,7 +75,6 @@ module named account_voucher. 'wizard/account_journal_select_view.xml', 'wizard/account_change_currency_view.xml', 'wizard/account_validate_move_view.xml', - 'wizard/account_pay_invoice_view.xml', 'wizard/account_unreconcile_view.xml', 'wizard/account_report_general_ledger_view.xml', 'wizard/account_invoice_state_view.xml', diff --git a/addons/account/account.py b/addons/account/account.py index fbbc93d1f85..6aa71c10545 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -18,6 +18,7 @@ # along with this program. If not, see . # ############################################################################## + import time from datetime import datetime, timedelta from dateutil.relativedelta import relativedelta @@ -60,7 +61,7 @@ class account_payment_term(osv.osv): 'line_ids': fields.one2many('account.payment.term.line', 'payment_id', 'Terms'), } _defaults = { - 'active': lambda *a: 1, + 'active': 1, } _order = "name" @@ -120,9 +121,9 @@ class account_payment_term_line(osv.osv): 'payment_id': fields.many2one('account.payment.term', 'Payment Term', required=True, select=True), } _defaults = { - 'value': lambda *a: 'balance', - 'sequence': lambda *a: 5, - 'days2': lambda *a: 0, + 'value': 'balance', + 'sequence': 5, + 'days2': 0, } _order = "sequence" @@ -405,10 +406,10 @@ class account_account(osv.osv): } _defaults = { - 'type': lambda *a : 'view', - 'reconcile': lambda *a: False, - 'active': lambda *a: True, - 'currency_mode': lambda *a: 'current', + 'type': 'view', + 'reconcile': False, + 'active': True, + 'currency_mode': 'current', 'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'account.account', context=c), } @@ -502,7 +503,7 @@ class account_account(osv.osv): default['child_parent_ids'] = False return super(account_account, self).copy(cr, uid, id, default, context=context) - def _check_moves(self, cr, uid, ids, method, context): + def _check_moves(self, cr, uid, ids, method, context=None): line_obj = self.pool.get('account.move.line') account_ids = self.search(cr, uid, [('id', 'child_of', ids)]) @@ -518,7 +519,7 @@ class account_account(osv.osv): 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): + def _check_allow_type_change(self, cr, uid, ids, new_type, context=None): group1 = ['payable', 'receivable', 'other'] group2 = ['consolidation','view'] line_obj = self.pool.get('account.move.line') @@ -537,7 +538,7 @@ class account_account(osv.osv): def write(self, cr, uid, ids, vals, context=None): if context is None: context = {} - + if 'company_id' in vals: move_lines = self.pool.get('account.move.line').search(cr, uid, [('account_id', 'in', ids)]) if move_lines: @@ -548,9 +549,9 @@ class account_account(osv.osv): 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={}): - self._check_moves(cr, uid, ids, "unlink", context) - return super(account_account, self).unlink(cr, uid, ids, context) + def unlink(self, cr, uid, ids, context=None): + self._check_moves(cr, uid, ids, "unlink", context=context) + return super(account_account, self).unlink(cr, uid, ids, context=context) account_account() @@ -562,6 +563,7 @@ class account_journal_view(osv.osv): 'columns_id': fields.one2many('account.journal.column', 'view_id', 'Columns') } _order = "name" + account_journal_view() @@ -587,6 +589,7 @@ class account_journal_column(osv.osv): 'readonly': fields.boolean('Readonly'), } _order = "sequence" + account_journal_column() class account_journal(osv.osv): @@ -595,7 +598,7 @@ class account_journal(osv.osv): _columns = { 'name': fields.char('Journal Name', size=64, required=True, translate=True,help="Name of the journal"), 'code': fields.char('Code', size=16,required=True,help="Code of the journal"), - 'type': fields.selection([('sale', 'Sale'),('sale_refund','Sale Refund'), ('purchase', 'Purchase'), ('purchase_refund','Purchase Refund'),('expense', 'Expense'), ('cash', 'Cash'), ('bank', 'Bank'), ('general', 'General'), ('situation', 'Situation')], 'Type', size=32, required=True, + 'type': fields.selection([('sale', 'Sale'),('sale_refund','Sale Refund'), ('purchase', 'Purchase'), ('purchase_refund','Purchase Refund'),('expense', 'Expense'), ('cash', 'Cash'), ('bank', 'Bank and Cheques'), ('general', 'General'), ('situation', 'Situation')], 'Type', size=32, required=True, help="Select 'Sale' for Sale journal to be used at the time of making invoice."\ " Select 'Purchase' for Purchase Journal to be used at the time of approving purchase order."\ " Select 'Cash' to be used at the time of making payment."\ @@ -835,7 +838,7 @@ class account_period(osv.osv): 'company_id': fields.related('fiscalyear_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True) } _defaults = { - 'state': lambda *a: 'draft', + 'state': 'draft', } _order = "date_start" @@ -1001,9 +1004,9 @@ class account_move(osv.osv): """ if not args: - args=[] + args = [] if not context: - context={} + context = {} ids = [] if name: ids += self.search(cr, user, [('name','ilike',name)]+args, limit=limit, context=context) @@ -1019,7 +1022,7 @@ class account_move(osv.osv): def name_get(self, cursor, user, ids, context=None): if not len(ids): return [] - res=[] + res = [] data_move = self.pool.get('account.move').browse(cursor,user,ids) for move in data_move: if move.state=='draft': @@ -1033,8 +1036,7 @@ class account_move(osv.osv): periods = self.pool.get('account.period').find(cr, uid) if periods: return periods[0] - else: - return False + return False def _amount_compute(self, cr, uid, ids, name, args, context, where =''): if not ids: return {} @@ -1048,21 +1050,25 @@ class account_move(osv.osv): return result def _search_amount(self, cr, uid, obj, name, args, context): - ids = [] - cr.execute('select move_id,sum(debit) from account_move_line group by move_id') - result = dict(cr.fetchall()) - - for item in args: - if item[1] == '>=': - res = [('id', 'in', [k for k,v in result.iteritems() if v >= item[2]])] + ids = set() + for cond in args: + amount = cond[2] + if isinstance(cond[2],(list,tuple)): + if cond[1] in ['in','not in']: + amount = tuple(cond[2]) + else: + continue else: - res = [('id', 'in', [k for k,v in result.iteritems() if v <= item[2]])] - ids += res + if cond[1] in ['=like', 'like', 'not like', 'ilike', 'not ilike', 'in', 'not in', 'child_of']: + continue - if not ids: - return [('id', '>', '0')] - - return ids + cr.execute("select move_id from account_move_line group by move_id having sum(debit) %s %%s" % (cond[1]) ,(amount,)) + res_ids = set(id[0] for id in cr.fetchall()) + ids = ids and (ids & res_ids) or res_ids + if ids: + return [('id','in',tuple(ids))] + else: + return [('id', '=', '0')] _columns = { 'name': fields.char('Number', size=64, required=True), @@ -1143,8 +1149,26 @@ class account_move(osv.osv): else: raise osv.except_osv(_('Integrity Error !'), _('You can not validate a non-balanced entry !\nMake sure you have configured Payment Term properly !\nIt should contain atleast one Payment Term Line with type "Balance" !')) return True - + def button_validate(self, cursor, user, ids, context=None): + def _get_chart_account(cursor, user, account): + if account.parent_id: + chart_account = _get_chart_account(cursor, user, account.parent_id) + else: + chart_account = account + return chart_account + + for move in self.browse(cursor, user, ids): + lines = move.line_id + if lines: + ref_line = lines[0] + ref_chart_account = _get_chart_account(cursor, user, ref_line.account_id) + parent_left = ref_chart_account.parent_left + parent_right = ref_chart_account.parent_right + result = True + for line in lines[1:]: + if not(line.account_id.parent_left > parent_left and line.account_id.parent_left < parent_right): + raise osv.except_osv(_('Error !'), _('You cannot validate a move unless accounts in its entry lines are in same Chart Of Accounts !')) return self.post(cursor, user, ids, context=context) def button_cancel(self, cr, uid, ids, context={}): @@ -1450,7 +1474,7 @@ class account_tax_code(osv.osv): This code is used for some tax declarations. """ - def _sum(self, cr, uid, ids, name, args, context,where ='', where_params=()): + def _sum(self, cr, uid, ids, name, args, context, where ='', where_params=()): parent_ids = tuple(self.search(cr, uid, [('parent_id', 'child_of', ids)])) if context.get('based_on', 'invoices') == 'payments': cr.execute('SELECT line.tax_code_id, sum(line.tax_amount) \ @@ -1463,13 +1487,15 @@ class account_tax_code(osv.osv): AND ((invoice.state = \'paid\') \ OR (invoice.id IS NULL)) \ GROUP BY line.tax_code_id', - (parent_ids,)+where_params) + (parent_ids,) + where_params) else: cr.execute('SELECT line.tax_code_id, sum(line.tax_amount) \ - FROM account_move_line AS line \ + FROM account_move_line AS line, \ + account_move AS move \ WHERE line.tax_code_id IN %s '+where+' \ + AND move.id = line.move_id \ GROUP BY line.tax_code_id', - (parent_ids,)+where_params) + (parent_ids,) + where_params) res=dict(cr.fetchall()) for record in self.browse(cr, uid, ids, context): def _rec_get(record): @@ -1480,7 +1506,12 @@ class account_tax_code(osv.osv): res[record.id] = round(_rec_get(record), self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')) return res - def _sum_year(self, cr, uid, ids, name, args, context): + def _sum_year(self, cr, uid, ids, name, args, context=None): + if context is None: + context = {} + move_state = ('posted', ) + if 'state' in context and context['state'] == 'all': + move_state = ('draft', 'posted', ) if 'fiscalyear_id' in context and context['fiscalyear_id']: fiscalyear_id = context['fiscalyear_id'] else: @@ -1490,12 +1521,17 @@ class account_tax_code(osv.osv): if fiscalyear_id: pids = map(lambda x: str(x.id), self.pool.get('account.fiscalyear').browse(cr, uid, fiscalyear_id).period_ids) if pids: - where = ' and period_id IN %s' - where_params = (tuple(pids),) + where = ' AND line.period_id IN %s AND move.state IN %s ' + where_params = (tuple(pids), move_state) return self._sum(cr, uid, ids, name, args, context, where=where, where_params=where_params) def _sum_period(self, cr, uid, ids, name, args, context): + if context is None: + context = {} + move_state = ('posted', ) + if 'state' in context and context['state'] == 'all': + move_state = ('draft', 'posted', ) if 'period_id' in context and context['period_id']: period_id = context['period_id'] else: @@ -1504,7 +1540,7 @@ class account_tax_code(osv.osv): return dict.fromkeys(ids, 0.0) period_id = period_id[0] return self._sum(cr, uid, ids, name, args, context, - where=' and line.period_id=%s', where_params=(period_id,)) + where=' AND line.period_id=%s AND move.state IN %s', where_params=(period_id, move_state)) _name = 'account.tax.code' _description = 'Tax Code' @@ -1639,9 +1675,9 @@ class account_tax(osv.osv): @return: Returns a list of tupples containing id and name """ if not args: - args=[] + args = [] if not context: - context={} + context = {} ids = [] ids = self.search(cr, user, args, limit=limit, context=context) return self.name_get(cr, user, ids, context=context) @@ -1662,37 +1698,37 @@ class account_tax(osv.osv): return super(account_tax, self).search(cr, uid, args, offset, limit, order, context, count) - def name_get(self, cr, uid, ids, context={}): + def name_get(self, cr, uid, ids, context=None): if not len(ids): return [] res = [] - for record in self.read(cr, uid, ids, ['description','name'], context): + for record in self.read(cr, uid, ids, ['description','name'], context=context): name = record['description'] and record['description'] or record['name'] res.append((record['id'],name )) return res - def _default_company(self, cr, uid, context={}): + def _default_company(self, cr, uid, context=None): user = self.pool.get('res.users').browse(cr, uid, uid, context=context) if user.company_id: return user.company_id.id return self.pool.get('res.company').search(cr, uid, [('parent_id', '=', False)])[0] _defaults = { - 'python_compute': lambda *a: '''# price_unit\n# address : res.partner.address object or False\n# product : product.product object or None\n# partner : res.partner object or None\n\nresult = price_unit * 0.10''', - 'python_compute_inv': lambda *a: '''# price_unit\n# address : res.partner.address object or False\n# product : product.product object or False\n\nresult = price_unit * 0.10''', - '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, - 'tax_group': lambda *a: 'vat', - 'ref_tax_sign': lambda *a: 1, - 'ref_base_sign': lambda *a: 1, - 'tax_sign': lambda *a: 1, - 'base_sign': lambda *a: 1, - 'include_base_amount': lambda *a: False, + 'python_compute': '''# price_unit\n# address : res.partner.address object or False\n# product : product.product object or None\n# partner : res.partner object or None\n\nresult = price_unit * 0.10''', + 'python_compute_inv': '''# price_unit\n# address : res.partner.address object or False\n# product : product.product object or False\n\nresult = price_unit * 0.10''', + 'applicable_type': 'true', + 'type': 'percent', + 'amount': 0, + 'price_include': 0, + 'active': 1, + 'type_tax_use': 'all', + 'sequence': 1, + 'tax_group': 'vat', + 'ref_tax_sign': 1, + 'ref_base_sign': 1, + 'tax_sign': 1, + 'base_sign': 1, + 'include_base_amount': False, 'company_id': _default_company, } _order = 'sequence' @@ -1796,7 +1832,7 @@ class account_tax(osv.osv): tin = self.compute_inv(cr, uid, tin, price_unit, quantity, address_id=address_id, product=product, partner=partner) for r in tin: totalex -= r['amount'] - totlex_qty=0.0 + totlex_qty = 0.0 try: totlex_qty=totalex/quantity except: @@ -2217,12 +2253,12 @@ class account_add_tmpl_wizard(osv.osv_memory): } def action_create(self,cr,uid,ids,context=None): - acc_obj=self.pool.get('account.account') - tmpl_obj=self.pool.get('account.account.template') - data= self.read(cr, uid, ids) + acc_obj = self.pool.get('account.account') + tmpl_obj = self.pool.get('account.account.template') + data = self.read(cr, uid, ids) company_id = acc_obj.read(cr, uid, [data[0]['cparent_id']], ['company_id'])[0]['company_id'][0] account_template = tmpl_obj.browse(cr, uid, context['tmpl_ids']) - vals={ + vals = { 'name': account_template.name, 'currency_id': account_template.currency_id and account_template.currency_id.id or False, 'code': account_template.code, @@ -2621,13 +2657,13 @@ class wizard_multi_charts_accounts(osv.osv_memory): data_id = data_pool.search(cr, uid, [('model','=','account.journal.view'), ('name','=','account_journal_bank_view_multi')]) data = data_pool.browse(cr, uid, data_id[0]) - ref_acc_bank = data.res_id + view_id_cur = data.res_id ref_acc_bank = obj_multi.chart_template_id.bank_account_view_id current_num = 1 for line in obj_multi.bank_accounts_id: #create the account_account for this bank journal - tmp = self.pool.get('res.partner.bank').name_get(cr, uid, [line.acc_no.id])[0][1] + tmp = line.acc_name dig = obj_multi.code_digits if ref_acc_bank.code: try: @@ -2635,7 +2671,7 @@ class wizard_multi_charts_accounts(osv.osv_memory): except Exception,e: new_code = str(ref_acc_bank.code.ljust(dig-len(str(current_num)),'0')) + str(current_num) vals = { - 'name': line.acc_no.bank and line.acc_no.bank.name+' '+tmp or tmp, + 'name': tmp, 'currency_id': line.currency_id and line.currency_id.id or False, 'code': new_code, 'type': 'other', diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py index 270384a1d9f..6d5a6ac470b 100644 --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@ -104,8 +104,7 @@ class account_bank_statement(osv.osv): periods = self.pool.get('account.period').find(cr, uid) if periods: return periods[0] - else: - return False + return False def _currency(self, cursor, user, ids, name, args, context=None): res = {} @@ -201,6 +200,7 @@ class account_bank_statement(osv.osv): res_users_obj = self.pool.get('res.users') account_move_obj = self.pool.get('account.move') account_move_line_obj = self.pool.get('account.move.line') + account_analytic_line_obj = self.pool.get('account.analytic.line') account_bank_statement_line_obj = self.pool.get('account.bank.statement.line') obj_seq = self.pool.get('ir.sequence') @@ -222,6 +222,11 @@ class account_bank_statement(osv.osv): raise osv.except_osv(_('Configuration Error !'), _('Please verify that an account is defined in the journal.')) + if not st.name == '/': + next_number = st.name + else: + next_number = obj_seq.get(cr, uid, 'account.bank.statement') + for line in st.move_line_ids: if line.state <> 'valid': raise osv.except_osv(_('Error !'), @@ -230,14 +235,18 @@ class account_bank_statement(osv.osv): # In line we get reconcile_id on bank.ste.rec. # in bank stat.rec we get line_new_ids on bank.stat.rec.line for move in st.line_ids: - context.update({'date':move.date}) + if move.analytic_account_id: + if not st.journal_id.analytic_journal_id: + raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal on the '%s' journal!") % (st.journal_id.name,)) + + context.update({'date': move.date}) move_id = account_move_obj.create(cr, uid, { 'journal_id': st.journal_id.id, 'period_id': st.period_id.id, 'date': move.date, }, context=context) account_bank_statement_line_obj.write(cr, uid, [move.id], { - 'move_ids': [(4,move_id, False)] + 'move_ids': [(4, move_id, False)] }) if not move.amount: continue @@ -268,6 +277,7 @@ class account_bank_statement(osv.osv): 'journal_id': st.journal_id.id, 'period_id': st.period_id.id, 'currency_id': st.currency.id, + 'analytic_account_id': move.analytic_account_id and move.analytic_account_id.id or False } amount = res_currency_obj.compute(cr, uid, st.currency.id, @@ -289,7 +299,28 @@ class account_bank_statement(osv.osv): account=acc_cur) val['amount_currency'] = amount_cur - torec.append(account_move_line_obj.create(cr, uid, val , context=context)) + move_line_id = account_move_line_obj.create(cr, uid, val , context=context) + torec.append(move_line_id) + + if move.analytic_account_id: + anal_val = {} + amt = (val['credit'] or 0.0) - (val['debit'] or 0.0) + anal_val = { + 'name': val['name'], + 'ref': val['ref'], + 'date': val['date'], + 'amount': amt, + 'account_id': val['analytic_account_id'], + 'currency_id': val['currency_id'], + 'general_account_id': val['account_id'], + 'journal_id': st.journal_id.analytic_journal_id.id, + 'period_id': val['period_id'], + 'user_id': uid, + 'move_id': move_line_id + } + if val.get('amount_currency', False): + anal_val['amount_currency'] = val['amount_currency'] + account_analytic_line_obj.create(cr, uid, anal_val, context=context) if move.reconcile_id and move.reconcile_id.line_new_ids: for newline in move.reconcile_id.line_new_ids: @@ -367,17 +398,11 @@ class account_bank_statement(osv.osv): account_move_line_obj.reconcile(cr, uid, torec, 'statement', writeoff_acc_id=writeoff_acc_id, writeoff_period_id=st.period_id.id, writeoff_journal_id=st.journal_id.id, context=context) else: account_move_line_obj.reconcile_partial(cr, uid, torec, 'statement', context) - - if st.journal_id.entry_posted: - account_move_obj.write(cr, uid, [move_id], {'state': 'posted'}) + move_name = next_number + ' - ' + str(move.sequence) + account_move_obj.write(cr, uid, [move_id], {'name': move_name, 'state': 'posted'}) # Bank statements will not consider boolean on journal entry_posted self.log(cr, uid, st.id, 'Statement %s is confirmed and entries are created.' % st.name) done.append(st.id) - - next_number = obj_seq.get(cr, uid, 'account.bank.statement') - if not st.name == '/': - next_number = st.name + '/' + next_number[-1:] - account_move_obj.write(cr, uid, [move_id], {'state': 'posted', 'name': next_number}) self.write(cr, uid, [st.id], {'name': next_number}, context=context) self.write(cr, uid, done, {'state':'confirm'}, context=context) @@ -397,28 +422,15 @@ class account_bank_statement(osv.osv): return True def onchange_journal_id(self, cursor, user, statement_id, journal_id, context=None): - if not journal_id: - return {'value': {'currency': False}} - account_journal_obj = self.pool.get('account.journal') res_users_obj = self.pool.get('res.users') - res_currency_obj = self.pool.get('res.currency') - cursor.execute('SELECT balance_end_real \ FROM account_bank_statement \ - WHERE journal_id = %s \ - ORDER BY date DESC,id DESC LIMIT 1', (journal_id,)) + WHERE journal_id = %s AND NOT state = %s \ + ORDER BY date DESC,id DESC LIMIT 1', (journal_id, 'draft')) res = cursor.fetchone() balance_start = res and res[0] or 0.0 - - currency_id = account_journal_obj.browse(cursor, user, journal_id, - context=context).currency.id - if not currency_id: - currency_id = res_users_obj.browse(cursor, user, user, - context=context).company_id.currency_id.id - currency = res_currency_obj.name_get(cursor, user, [currency_id], - context=context)[0] - return {'value': {'balance_start': balance_start, 'currency': currency}} + return {'value': {'balance_start': balance_start}} def unlink(self, cr, uid, ids, context=None): stat = self.read(cr, uid, ids, ['state']) @@ -629,6 +641,26 @@ class account_bank_statement_line(osv.osv): else: account_id = part.property_account_receivable.id res['value']['account_id'] = account_id + + 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)) + pgres = cursor.fetchone() + balance = pgres and pgres[0] or 0.0 + + balance = res_currency_obj.compute(cursor, user, company_currency_id, + currency_id, balance, context=context) + res['value']['amount'] = balance return res def _reconcile_amount(self, cursor, user, ids, name, args, context=None): @@ -669,6 +701,7 @@ class account_bank_statement_line(osv.osv): select=True, required=True, ondelete='cascade'), 'reconcile_id': fields.many2one('account.bank.statement.reconcile', 'Reconcile'), + 'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account'), 'move_ids': fields.many2many('account.move', 'account_bank_statement_line_move_rel', 'move_id','statement_id', 'Moves'), diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml index 9df1880f61a..ad48ea86c23 100644 --- a/addons/account/account_invoice_view.xml +++ b/addons/account/account_invoice_view.xml @@ -65,9 +65,8 @@ - - + @@ -137,7 +136,6 @@