diff --git a/addons/account/account.py b/addons/account/account.py index c3ead387fba..ef3df95a317 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -144,7 +144,7 @@ class account_account_type(osv.osv): ('none','/'), ('income','Profit & Loss (Income Accounts)'), ('expense','Profit & Loss (Expense Accounts)'), - ('asset','Balance Sheet (Assets Accounts)'), + ('asset','Balance Sheet (Asset Accounts)'), ('liability','Balance Sheet (Liability Accounts)') ],'P&L / BS Category', select=True, readonly=False, help="This field is used to generate legal reports: profit and loss, balance sheet.", required=True), 'note': fields.text('Description'), @@ -243,7 +243,8 @@ class account_account(osv.osv): 'balance': "COALESCE(SUM(l.debit),0) " \ "- COALESCE(SUM(l.credit), 0) as balance", 'debit': "COALESCE(SUM(l.debit), 0) as debit", - 'credit': "COALESCE(SUM(l.credit), 0) as credit" + 'credit': "COALESCE(SUM(l.credit), 0) as credit", + 'foreign_balance': "COALESCE(SUM(l.amount_currency), 0) as foreign_balance", } #get all the necessary accounts children_and_consolidated = self._get_children_and_consol(cr, uid, ids, context=context) @@ -270,7 +271,7 @@ class account_account(osv.osv): # ON l.account_id = tmp.id # or make _get_children_and_consol return a query and join on that request = ("SELECT l.account_id as id, " +\ - ', '.join(map(mapping.__getitem__, field_names)) + + ', '.join(map(mapping.__getitem__, mapping.keys())) + " FROM account_move_line l" \ " WHERE l.account_id IN %s " \ + filters + @@ -289,7 +290,7 @@ class account_account(osv.osv): sums = {} currency_obj = self.pool.get('res.currency') while brs: - current = brs[0] + current = brs.pop(0) # can_compute = True # for child in current.child_id: # if child.id not in sums: @@ -299,7 +300,6 @@ class account_account(osv.osv): # except ValueError: # brs.insert(0, child) # if can_compute: - brs.pop(0) for fn in field_names: sums.setdefault(current.id, {})[fn] = accounts.get(current.id, {}).get(fn, 0.0) for child in current.child_id: @@ -307,6 +307,16 @@ class account_account(osv.osv): sums[current.id][fn] += sums[child.id][fn] else: sums[current.id][fn] += currency_obj.compute(cr, uid, child.company_id.currency_id.id, current.company_id.currency_id.id, sums[child.id][fn], context=context) + + # as we have to relay on values computed before this is calculated separately than previous fields + if current.currency_id and current.exchange_rate and \ + ('adjusted_balance' in field_names or 'unrealized_gain_loss' in field_names): + # Computing Adjusted Balance and Unrealized Gains and losses + # Adjusted Balance = Foreign Balance / Exchange Rate + # Unrealized Gains and losses = Adjusted Balance - Balance + adj_bal = sums[current.id].get('foreign_balance', 0.0) / current.exchange_rate + sums[current.id].update({'adjusted_balance': adj_bal, 'unrealized_gain_loss': adj_bal - sums[current.id].get('balance', 0.0)}) + for id in ids: res[id] = sums.get(id, null_result) else: @@ -340,9 +350,10 @@ class account_account(osv.osv): accounts = self.browse(cr, uid, ids, context=context) for account in accounts: level = 0 - if account.parent_id: - obj = self.browse(cr, uid, account.parent_id.id) - level = obj.level + 1 + parent = account.parent_id + while parent: + level += 1 + parent = parent.parent_id res[account.id] = level return res @@ -367,8 +378,8 @@ class account_account(osv.osv): move_obj = self.pool.get('account.move.line') move_id = move_obj.search(cr, uid, [ - ('journal_id','=',jids[0]), - ('period_id','=',pids[0]), + ('journal_id','=',jids[0]), + ('period_id','=',pids[0]), ('account_id','=', account_id), (name,'>', 0.0), ('name','=', _('Opening Balance')) @@ -418,7 +429,14 @@ class account_account(osv.osv): 'balance': fields.function(__compute, digits_compute=dp.get_precision('Account'), string='Balance', multi='balance'), 'credit': fields.function(__compute, fnct_inv=_set_credit_debit, digits_compute=dp.get_precision('Account'), string='Credit', multi='balance'), 'debit': fields.function(__compute, fnct_inv=_set_credit_debit, digits_compute=dp.get_precision('Account'), string='Debit', multi='balance'), + 'foreign_balance': fields.function(__compute, digits_compute=dp.get_precision('Account'), string='Foreign Balance', multi='balance', + help="Total amount (in Secondary currency) for transactions held in secondary currency for this account."), + 'adjusted_balance': fields.function(__compute, digits_compute=dp.get_precision('Account'), string='Adjusted Balance', multi='balance', + help="Total amount (in Company currency) for transactions held in secondary currency for this account."), + 'unrealized_gain_loss': fields.function(__compute, digits_compute=dp.get_precision('Account'), string='Unrealized Gain or Loss', multi='balance', + help="Value of Loss or Gain due to changes in exchange rate when doing multi-currency transactions."), 'reconcile': fields.boolean('Allow Reconciliation', help="Check this box if this account allows reconciliation of journal items."), + 'exchange_rate': fields.related('currency_id', 'rate', type='float', string='Exchange Rate', digits=(12,6)), 'shortcut': fields.char('Shortcut', size=12), 'tax_ids': fields.many2many('account.tax', 'account_account_tax_default_rel', 'account_id', 'tax_id', 'Default Taxes'), @@ -436,7 +454,10 @@ class account_account(osv.osv): 'manage this. So if you import from another software system you may have to use the rate at date. ' \ 'Incoming transactions always use the rate at date.', \ required=True), - 'level': fields.function(_get_level, string='Level', store=True, type='integer'), + 'level': fields.function(_get_level, string='Level', method=True, type='integer', + store={ + 'account.account': (_get_children_and_consol, ['level', 'parent_id'], 10), + }), } _defaults = { @@ -884,9 +905,16 @@ class account_fiscalyear(osv.osv): return True def find(self, cr, uid, dt=None, exception=True, context=None): + if context is None: context = {} if not dt: dt = time.strftime('%Y-%m-%d') - ids = self.search(cr, uid, [('date_start', '<=', dt), ('date_stop', '>=', dt)]) + args = [('date_start', '<=' ,dt), ('date_stop', '>=', dt)] + if context.get('company_id', False): + args.append(('company_id', '=', context['company_id'])) + else: + company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id + args.append(('company_id', '=', company_id)) + ids = self.search(cr, uid, args, context=context) if not ids: if exception: raise osv.except_osv(_('Error !'), _('No fiscal year defined for this date !\nPlease create one.')) @@ -930,7 +958,7 @@ class account_period(osv.osv): _sql_constraints = [ ('name_company_uniq', 'unique(name, company_id)', 'The name of the period must be unique per company!'), ] - + def _check_duration(self,cr,uid,ids,context=None): obj_period = self.browse(cr, uid, ids[0], context=context) if obj_period.date_stop < obj_period.date_start: @@ -966,10 +994,17 @@ class account_period(osv.osv): return False def find(self, cr, uid, dt=None, context=None): + if context is None: context = {} if not dt: dt = time.strftime('%Y-%m-%d') #CHECKME: shouldn't we check the state of the period? - ids = self.search(cr, uid, [('date_start','<=',dt),('date_stop','>=',dt)]) + args = [('date_start', '<=' ,dt), ('date_stop', '>=', dt)] + if context.get('company_id', False): + args.append(('company_id', '=', context['company_id'])) + else: + company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id + args.append(('company_id', '=', company_id)) + ids = self.search(cr, uid, args, context=context) if not ids: raise osv.except_osv(_('Error !'), _('No period defined for this date: %s !\nPlease create one.')%dt) return ids @@ -2160,12 +2195,13 @@ class account_model(osv.osv): raise osv.except_osv(_('No period found !'), _('Unable to find a valid period !')) period_id = period_id[0] + move_date = context.get('date', time.strftime('%Y-%m-%d')) + move_date = datetime.strptime(move_date,"%Y-%m-%d") for model in self.browse(cr, uid, ids, context=context): try: - entry['name'] = model.name%{'year':time.strftime('%Y'), 'month':time.strftime('%m'), 'date':time.strftime('%Y-%m')} + entry['name'] = model.name%{'year': move_date.strftime('%Y'), 'month': move_date.strftime('%m'), 'date': move_date.strftime('%Y-%m')} except: raise osv.except_osv(_('Wrong model !'), _('You have a wrong expression "%(...)s" in your model !')) - move_id = account_move_obj.create(cr, uid, { 'ref': entry['name'], 'period_id': period_id, @@ -2186,7 +2222,7 @@ class account_model(osv.osv): 'analytic_account_id': analytic_account_id } - date_maturity = time.strftime('%Y-%m-%d') + date_maturity = context.get('date',time.strftime('%Y-%m-%d')) if line.date_maturity == 'partner': if not line.partner_id: raise osv.except_osv(_('Error !'), _("Maturity date of entry line generated by model line '%s' of model '%s' is based on partner payment term!" \ diff --git a/addons/account/account_bank.py b/addons/account/account_bank.py index a3d66ccdf7c..2a9e432894f 100644 --- a/addons/account/account_bank.py +++ b/addons/account/account_bank.py @@ -37,6 +37,10 @@ class bank(osv.osv): self.post_write(cr, uid, ids, context=context) return result + def _prepare_name(self, bank): + "Return the name to use when creating a bank journal" + return (bank.bank_name or '') + ' ' + bank.acc_number + def post_write(self, cr, uid, ids, context={}): obj_acc = self.pool.get('account.account') obj_data = self.pool.get('ir.model.data') @@ -45,7 +49,7 @@ class bank(osv.osv): # Find the code and parent of the bank account to create dig = 6 current_num = 1 - ids = obj_acc.search(cr, uid, [('type','=','liquidity')], context=context) + ids = obj_acc.search(cr, uid, [('type','=','liquidity')], context=context) # No liquidity account exists, no template available if not ids: continue @@ -57,9 +61,9 @@ class bank(osv.osv): if not ids: break current_num += 1 - + name = self._prepare_name(bank) acc = { - 'name': (bank.bank_name or '')+' '+bank.acc_number, + 'name': name, 'currency_id': bank.company_id.currency_id.id, 'code': new_code, 'type': 'liquidity', @@ -74,7 +78,7 @@ class bank(osv.osv): data_id = obj_data.search(cr, uid, [('model','=','account.journal.view'), ('name','=','account_journal_bank_view')]) data = obj_data.browse(cr, uid, data_id[0], context=context) view_id_cash = data.res_id - + jour_obj = self.pool.get('account.journal') new_code = 1 while True: @@ -86,7 +90,7 @@ class bank(osv.osv): #create the bank journal vals_journal = { - 'name': (bank.bank_name or '')+' '+bank.acc_number, + 'name': name, 'code': code, 'type': 'bank', 'company_id': bank.company_id.id, @@ -100,4 +104,3 @@ class bank(osv.osv): self.write(cr, uid, [bank.id], {'journal_id': journal_id}, context=context) return True - diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py index 98051a319fd..57472e228ef 100644 --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@ -137,7 +137,7 @@ class account_bank_statement(osv.osv): states={'confirm':[('readonly',True)]}), 'balance_end_real': fields.float('Ending Balance', digits_compute=dp.get_precision('Account'), states={'confirm': [('readonly', True)]}), - 'balance_end': fields.function(_end_balance, + 'balance_end': fields.function(_end_balance, store = { 'account.bank.statement': (lambda self, cr, uid, ids, c={}: ids, ['line_ids','move_line_ids'], 10), 'account.bank.statement.line': (_get_statement, ['amount'], 10), @@ -219,6 +219,7 @@ class account_bank_statement(osv.osv): 'period_id': st.period_id.id, 'date': st_line.date, 'name': st_line_number, + 'ref': st_line.ref, }, context=context) account_bank_statement_line_obj.write(cr, uid, [st_line.id], { 'move_ids': [(4, move_id, False)] diff --git a/addons/account/account_installer.xml b/addons/account/account_installer.xml index b35b37aa972..230078c4e33 100644 --- a/addons/account/account_installer.xml +++ b/addons/account/account_installer.xml @@ -28,7 +28,8 @@ - + + diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py index 146dbe019ec..cce7d22d673 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -209,7 +209,7 @@ class account_invoice(osv.osv): \n* The \'Open\' state is used when user create invoice,a invoice number is generated.Its in open state till user does not pay invoice. \ \n* The \'Paid\' state is set automatically when invoice is paid.\ \n* The \'Cancelled\' state is used when user cancel invoice.'), - 'date_invoice': fields.date('Invoice Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'close':[('readonly',True)]}, select=True, help="Keep empty to use the current date"), + 'date_invoice': fields.date('Invoice Date', readonly=True, states={'draft':[('readonly',False)]}, select=True, help="Keep empty to use the current date"), 'date_due': fields.date('Due Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'close':[('readonly',True)]}, select=True, help="If you use payment terms, the due date will be computed automatically at the generation "\ "of accounting entries. If you keep the payment term and the due date empty, it means direct payment. The payment term may compute several due dates, for example 50% now, 50% in one month."), @@ -306,9 +306,9 @@ class account_invoice(osv.osv): view_id = view_id[0] res = super(account_invoice,self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu) - type = context.get('journal_type', 'sale') + type = context.get('journal_type', False) for field in res['fields']: - if field == 'journal_id': + if field == 'journal_id' and type: journal_select = journal_obj._name_search(cr, uid, '', [('type', '=', type)], context=context, limit=None, name_get_uid=1) res['fields'][field]['selection'] = journal_select diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml index a84eb5f5a32..efc7a24031c 100644 --- a/addons/account/account_invoice_view.xml +++ b/addons/account/account_invoice_view.xml @@ -208,10 +208,10 @@ -