diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index d3a58272b89..a6d2f0c9e69 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -21,7 +21,7 @@ { "name" : "Accounting and Financial Management", "version" : "1.1", - "author" : "Tiny", + "author" : "OpenERP SA", "category": 'Generic Modules/Accounting', "description": """Financial and accounting module that covers: General accountings @@ -79,7 +79,7 @@ module named account_vouchers 'wizard/account_invoice_state_view.xml', 'wizard/account_partner_balance_report_view.xml', 'wizard/account_balance_report_view.xml', - 'wizard/account_move_line_select_view.xml', +# 'wizard/account_move_line_select_view.xml', 'wizard/account_aged_trial_balance_view.xml', 'wizard/account_compare_account_balance_report_view.xml', 'wizard/account_third_party_ledger.xml', @@ -133,10 +133,10 @@ module named account_vouchers 'test/chart_of_account.yml', 'test/account_period_close.yml', 'test/account_fiscalyear_close_state.yml', - 'test/account_invoice_state.yml', + #'test/account_invoice_state.yml', 'test/account_use_model.yml', 'test/account_validate_account_move.yml', -# 'test/account_fiscalyear_close.yml', + 'test/account_fiscalyear_close.yml', ], 'installable': True, 'active': False, diff --git a/addons/account/account.py b/addons/account/account.py index 73e1fdd0b7e..2e7ce17196b 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -248,59 +248,59 @@ class account_account(osv.osv): def __compute(self, cr, uid, ids, field_names, arg=None, context=None, query='', query_params=()): - """ compute the balance, debit and/or credit for the provided - account ids - Arguments: - `ids`: account ids - `field_names`: the fields to compute (a list of any of - 'balance', 'debit' and 'credit') - `arg`: unused fields.function stuff - `query`: additional query filter (as a string) - `query_params`: parameters for the provided query string - (__compute will handle their escaping) as a - tuple - """ - mapping = { - '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" - } - #get all the necessary accounts - children_and_consolidated = self._get_children_and_consol(cr, uid, ids, context=context) - #compute for each account the balance/debit/credit from the move lines - accounts = {} - if children_and_consolidated: - aml_query = self.pool.get('account.move.line')._query_get(cr, uid, context=context) + """ compute the balance, debit and/or credit for the provided + account ids + Arguments: + `ids`: account ids + `field_names`: the fields to compute (a list of any of + 'balance', 'debit' and 'credit') + `arg`: unused fields.function stuff + `query`: additional query filter (as a string) + `query_params`: parameters for the provided query string + (__compute will handle their escaping) as a + tuple + """ + mapping = { + '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" + } + #get all the necessary accounts + children_and_consolidated = self._get_children_and_consol(cr, uid, ids, context=context) + #compute for each account the balance/debit/credit from the move lines + accounts = {} + if children_and_consolidated: + aml_query = self.pool.get('account.move.line')._query_get(cr, uid, context=context) - wheres = [""] - if query.strip(): - wheres.append(query.strip()) - if aml_query.strip(): - wheres.append(aml_query.strip()) - filters = " AND ".join(wheres) - self.logger.notifyChannel('addons.'+self._name, netsvc.LOG_DEBUG, - 'Filters: %s'%filters) - # IN might not work ideally in case there are too many - # children_and_consolidated, in that case join on a - # values() e.g.: - # SELECT l.account_id as id FROM account_move_line l - # INNER JOIN (VALUES (id1), (id2), (id3), ...) AS tmp (id) - # 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)) + - " FROM account_move_line l" \ - " WHERE l.account_id IN %s " \ - + filters + - " GROUP BY l.account_id") - params = (tuple(children_and_consolidated),) + query_params - cr.execute(request, params) - self.logger.notifyChannel('addons.'+self._name, netsvc.LOG_DEBUG, - 'Status: %s'%cr.statusmessage) + wheres = [""] + if query.strip(): + wheres.append(query.strip()) + if aml_query.strip(): + wheres.append(aml_query.strip()) + filters = " AND ".join(wheres) + self.logger.notifyChannel('addons.'+self._name, netsvc.LOG_DEBUG, + 'Filters: %s'%filters) + # IN might not work ideally in case there are too many + # children_and_consolidated, in that case join on a + # values() e.g.: + # SELECT l.account_id as id FROM account_move_line l + # INNER JOIN (VALUES (id1), (id2), (id3), ...) AS tmp (id) + # 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)) + + " FROM account_move_line l" \ + " WHERE l.account_id IN %s " \ + + filters + + " GROUP BY l.account_id") + params = (tuple(children_and_consolidated),) + query_params + cr.execute(request, params) + self.logger.notifyChannel('addons.'+self._name, netsvc.LOG_DEBUG, + 'Status: %s'%cr.statusmessage) - for res in cr.dictfetchall(): - accounts[res['id']] = res + for res in cr.dictfetchall(): + accounts[res['id']] = res # consolidate accounts with direct children children_and_consolidated.reverse() @@ -656,9 +656,18 @@ class account_journal(osv.osv): @param context: context arguments, like lang, time zone @return: return a result """ + + journal_type = ('sale', 'sale_refund', 'purchase', 'purchase_refund') + journal_seq = { + 'sale':'seq_out_invoice', + 'purchase':'seq_in_invoice', + 'purchase_refund':'seq_out_refund', + 'sale_refund':'seq_in_refund' + } seq_pool = self.pool.get('ir.sequence') seq_typ_pool = self.pool.get('ir.sequence.type') + date_pool = self.pool.get('ir.model.data') result = True @@ -685,10 +694,13 @@ class account_journal(osv.osv): res.update({ 'sequence_id':seq_id }) - - if not journal.invoice_sequence_id: + + if journal.type in journal_type and not journal.invoice_sequence_id: + res_ids = date_pool.search(cr, uid, [('model','=','ir.sequence'), ('name','=',journal_seq.get(journal.type, 'sale'))]) + inv_seq_id = date_pool.browse(cr, uid, res_ids[0]).res_id + inv_seq_id res.update({ - 'invoice_sequence_id':seq_id + 'invoice_sequence_id':inv_seq_id }) result = self.write(cr, uid, [journal.id], res) @@ -1018,7 +1030,6 @@ class account_move(osv.osv): res.append((move.id, name)) return res - def _get_period(self, cr, uid, context): periods = self.pool.get('account.period').find(cr, uid) if periods: @@ -1066,24 +1077,13 @@ class account_move(osv.osv): 'partner_id': fields.related('line_id', 'partner_id', type="many2one", relation="res.partner", string="Partner"), 'amount': fields.function(_amount_compute, method=True, string='Amount', digits_compute=dp.get_precision('Account'), type='float', fnct_search=_search_amount), 'date': fields.date('Date', required=True, states={'posted':[('readonly',True)]}), - 'type': fields.selection([ - ('pay_voucher','Cash Payment'), - ('bank_pay_voucher','Bank Payment'), - ('rec_voucher','Cash Receipt'), - ('bank_rec_voucher','Bank Receipt'), - ('cont_voucher','Contra'), - ('journal_sale_vou','Journal Sale'), - ('journal_pur_voucher','Journal Purchase'), - ('journal_voucher','Journal Voucher'), - ],'Entry Type', select=True , size=128, readonly=True, states={'draft':[('readonly',False)]}), - 'narration':fields.text('Narration', readonly=True, select=True, states={'draft':[('readonly',False)]}), + 'narration':fields.text('Narration', select=True), 'company_id': fields.related('journal_id','company_id',type='many2one',relation='res.company',string='Company',store=True), } _defaults = { 'name': lambda *a: '/', 'state': lambda *a: 'draft', 'period_id': _get_period, - 'type' : lambda *a : 'journal_voucher', 'date': lambda *a:time.strftime('%Y-%m-%d'), 'company_id': lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.id, } @@ -1116,6 +1116,7 @@ class account_move(osv.osv): 'You cannot create entries on different periods/journals in the same move', ['line_id']), ] + def post(self, cr, uid, ids, context=None): if self.validate(cr, uid, ids, context) and len(ids): for move in self.browse(cr, uid, ids): @@ -1162,8 +1163,20 @@ class account_move(osv.osv): # TODO: Check if period is closed ! # def create(self, cr, uid, vals, context={}): - if 'line_id' in vals: - if 'journal_id' in vals: + if 'line_id' in vals and context.get('copy'): + for l in vals['line_id']: + if not l[0]: + l[2].update({ + 'reconcile_id':False, + 'reconcil_partial_id':False, + 'analytic_lines':False, + 'invoice':False, + 'ref':False, + 'balance':False, + 'account_tax_id':False, + }) + + if 'journal_id' in vals and vals.get('journal_id', False): for l in vals['line_id']: if not l[0]: l[2]['journal_id'] = vals['journal_id'] @@ -1189,11 +1202,14 @@ class account_move(osv.osv): result = super(account_move, self).create(cr, uid, vals, context) return result - def copy(self, cr, uid, id, default=None, context=None): - if default is None: - default = {} - default = default.copy() - default.update({'state':'draft', 'name':'/',}) + def copy(self, cr, uid, id, default={}, context={}): + default.update({ + 'state':'draft', + 'name':'/', + }) + context.update({ + 'copy':True + }) return super(account_move, self).copy(cr, uid, id, default, context) def unlink(self, cr, uid, ids, context={}, check=True): @@ -1604,13 +1620,44 @@ class account_tax(osv.osv): 'type_tax_use': fields.selection([('sale','Sale'),('purchase','Purchase'),('all','All')], 'Tax Application', required=True) } - def search(self, cr, uid, args, offset=0, limit=None, order=None, - context=None, count=False): + + def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80): + """ + Returns a list of tupples containing id, name, as internally it is called {def name_get} + result format : {[(id, name), (id, name), ...]} + + @param cr: A database cursor + @param user: ID of the user currently logged in + @param name: name to search + @param args: other arguments + @param operator: default operator is 'ilike', it can be changed + @param context: context arguments, like lang, time zone + @param limit: Returns first 'n' ids of complete result, default is 80. + + @return: Returns a list of tupples containing id and name + """ + if not args: + args=[] + if not context: + context={} + ids = [] + ids = self.search(cr, user, args, limit=limit, context=context) + return self.name_get(cr, user, ids, context=context) + + def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False): + journal_pool = self.pool.get('account.journal') + if context and context.has_key('type'): - if context['type'] in ('out_invoice','out_refund'): - args.append(('type_tax_use','in',['sale','all'])) - elif context['type'] in ('in_invoice','in_refund'): - args.append(('type_tax_use','in',['purchase','all'])) + if context.get('type') in ('out_invoice','out_refund'): + args += [('type_tax_use','in',['sale','all'])] + elif context.get('type') in ('in_invoice','in_refund'): + args += [('type_tax_use','in',['purchase','all'])] + + if context and context.has_key('journal_id'): + journal = journal_pool.browse(cr, uid, context.get('journal_id')) + if journal.type in ('sale', 'purchase'): + args += [('type_tax_use','in',[journal.type,'all'])] + return super(account_tax, self).search(cr, uid, args, offset, limit, order, context, count) def name_get(self, cr, uid, ids, context={}): @@ -1627,6 +1674,7 @@ class account_tax(osv.osv): 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''', @@ -1746,7 +1794,12 @@ 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'] - tex = self._compute(cr, uid, tex, totalex/quantity, quantity, address_id=address_id, product=product, partner=partner) + totlex_qty=0.0 + try: + totlex_qty=totalex/quantity + except: + pass + tex = self._compute(cr, uid, tex, totlex_qty, quantity, address_id=address_id, product=product, partner=partner) for r in tex: totalin += r['amount'] return { @@ -2522,9 +2575,9 @@ class wizard_multi_charts_accounts(osv.osv_memory): 'account_paid_id': acc_template_ref[value['account_paid_id']], }) - # Creating Journals + # Creating Journals Sales and Purchase vals_journal={} - data_id = data_pool.search(cr, uid, [('model','=','account.journal.view'), ('name','=','account_journal_view')]) + data_id = data_pool.search(cr, uid, [('model','=','account.journal.view'), ('name','=','account_sp_journal_view')]) data = data_pool.browse(cr, uid, data_id[0]) view_id = data.res_id @@ -2556,6 +2609,7 @@ class wizard_multi_charts_accounts(osv.osv_memory): vals_journal['type'] = 'purchase' vals_journal['code'] = _('EXJ') vals_journal['sequence_id'] = seq_id_purchase + vals_journal['view_id'] = view_id if obj_multi.chart_template_id.property_account_payable: vals_journal['default_credit_account_id'] = acc_template_ref[obj_multi.chart_template_id.property_account_expense_categ.id] @@ -2567,12 +2621,10 @@ class wizard_multi_charts_accounts(osv.osv_memory): data_id = data_pool.search(cr, uid, [('model','=','account.journal.view'), ('name','=','account_journal_bank_view')]) data = data_pool.browse(cr, uid, data_id[0]) view_id_cash = data.res_id - #view_id_cash = self.pool.get('account.journal.view').search(cr, uid, [('name','=','Bank/Cash Journal View')])[0] #TOFIX: why put fix name - + 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 - #ref_acc_bank = self.pool.get('account.journal.view').search(cr, uid, [('name','=','Bank/Cash Journal (Multi-Currency) View')])[0] #TOFIX: why put fix name ref_acc_bank = obj_multi.chart_template_id.bank_account_view_id current_num = 1 @@ -2599,8 +2651,8 @@ class wizard_multi_charts_accounts(osv.osv_memory): if obj_multi.seq_journal: vals_seq={ - 'name': _('Bank Journal ') + vals['name'], - 'code': 'account.journal', + 'name': _('Bank Journal ') + vals['name'], + 'code': 'account.journal', } seq_id = obj_sequence.create(cr,uid,vals_seq) @@ -2656,9 +2708,9 @@ class wizard_multi_charts_accounts(osv.osv_memory): for position in obj_fiscal_position_template.browse(cr, uid, fp_ids): vals_fp = { - 'company_id' : company_id, - 'name' : position.name, - } + 'company_id' : company_id, + 'name' : position.name, + } new_fp = obj_fiscal_position.create(cr, uid, vals_fp) obj_tax_fp = self.pool.get('account.fiscal.position.tax') @@ -2666,19 +2718,28 @@ class wizard_multi_charts_accounts(osv.osv_memory): for tax in position.tax_ids: vals_tax = { - 'tax_src_id' : tax_template_ref[tax.tax_src_id.id], - 'tax_dest_id' : tax.tax_dest_id and tax_template_ref[tax.tax_dest_id.id] or False, - 'position_id' : new_fp, - } + 'tax_src_id' : tax_template_ref[tax.tax_src_id.id], + 'tax_dest_id' : tax.tax_dest_id and tax_template_ref[tax.tax_dest_id.id] or False, + 'position_id' : new_fp, + } obj_tax_fp.create(cr, uid, vals_tax) for acc in position.account_ids: vals_acc = { - 'account_src_id' : acc_template_ref[acc.account_src_id.id], - 'account_dest_id' : acc_template_ref[acc.account_dest_id.id], - 'position_id' : new_fp, - } + 'account_src_id' : acc_template_ref[acc.account_src_id.id], + 'account_dest_id' : acc_template_ref[acc.account_dest_id.id], + 'position_id' : new_fp, + } obj_ac_fp.create(cr, uid, vals_acc) + + #fially inactive the demo chart of accounts + data_id = data_pool.search(cr, uid, [('model','=','account.account'), ('name','=','chart0')]) + if data_id: + data = data_pool.browse(cr, uid, data_id[0]) + account_id = data.res_id + if account_id: + cr.execute("update account_account set active='f' where id=%s" % (account_id)) + wizard_multi_charts_accounts() class account_bank_accounts_wizard(osv.osv_memory): diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py index e0d31b9cf18..52e1b20a744 100644 --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@ -25,6 +25,7 @@ from osv import fields, osv from tools.misc import currency from tools.translate import _ +import decimal_precision as dp class account_bank_statement(osv.osv): @@ -48,9 +49,16 @@ class account_bank_statement(osv.osv): } def _default_journal_id(self, cr, uid, context={}): - if context.get('journal_id', False): - return context['journal_id'] - return False + journal_pool = self.pool.get('account.journal') + journal_type = context.get('journal_type', False) + journal_id = False + + if journal_type: + ids = journal_pool.search(cr, uid, [('type', '=', journal_type)]) + if ids: + journal_id = ids[0] + + return journal_id def _default_balance_start(self, cr, uid, context={}): cr.execute('select id from account_bank_statement where journal_id=%s order by date desc limit 1', (1,)) @@ -127,12 +135,12 @@ class account_bank_statement(osv.osv): 'date': fields.date('Date', required=True, states={'confirm': [('readonly', True)]}), 'journal_id': fields.many2one('account.journal', 'Journal', required=True, - states={'confirm': [('readonly', True)]}, domain=[('type', '=', 'cash')]), + states={'confirm': [('readonly', True)]}, domain=[('type', '=', 'bank')]), 'period_id': fields.many2one('account.period', 'Period', required=True, states={'confirm':[('readonly', True)]}), - 'balance_start': fields.float('Starting Balance', digits=(16,2), + 'balance_start': fields.float('Starting Balance', digits_compute=dp.get_precision('Account'), states={'confirm':[('readonly',True)]}), - 'balance_end_real': fields.float('Ending Balance', digits=(16,2), + 'balance_end_real': fields.float('Ending Balance', digits_compute=dp.get_precision('Account'), states={'confirm':[('readonly', True)]}), 'balance_end': fields.function(_end_balance, method=True, string='Balance'), 'line_ids': fields.one2many('account.bank.statement.line', @@ -159,6 +167,32 @@ class account_bank_statement(osv.osv): 'period_id': _get_period, } + def onchange_date(self, cr, user, ids, date, context={}): + """ + Returns a dict that contains new values and context + @param cr: A database cursor + @param user: ID of the user currently logged in + @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 + """ + res = {} + period_pool = self.pool.get('account.period') + pids = period_pool.search(cr, user, [('date_start','<=',date), ('date_stop','>=',date)]) + if pids: + res.update({ + 'period_id':pids[0] + }) + context.update({ + 'period_id':pids[0] + }) + + return { + 'value':res, + 'context':context, + } + def button_confirm_bank(self, cr, uid, ids, context={}): done = [] res_currency_obj = self.pool.get('res.currency') @@ -334,6 +368,7 @@ class account_bank_statement(osv.osv): if st.journal_id.entry_posted: account_move_obj.write(cr, uid, [move_id], {'state':'posted'}) + self.log(cr, uid, st.id, 'Statement %s is confirmed and entries are created.' % st.name) done.append(st.id) self.write(cr, uid, done, {'state':'confirm'}, context=context) return True diff --git a/addons/account/account_cash_statement.py b/addons/account/account_cash_statement.py index 1a0727e626f..f618bcfeefd 100644 --- a/addons/account/account_cash_statement.py +++ b/addons/account/account_cash_statement.py @@ -25,6 +25,7 @@ import time from mx import DateTime from decimal import Decimal from tools.translate import _ +import decimal_precision as dp class account_cashbox_line(osv.osv): @@ -55,9 +56,9 @@ class account_cashbox_line(osv.osv): return {'value':{'subtotal': sub or 0.0}} _columns = { - 'pieces': fields.float('Values', digits=(16,2)), + 'pieces': fields.float('Values', digits_compute=dp.get_precision('Account')), 'number': fields.integer('Number'), - 'subtotal': fields.function(_sub_total, method=True, string='Sub Total', type='float',digits=(16,2)), + 'subtotal': fields.function(_sub_total, method=True, string='Sub Total', type='float', digits_compute=dp.get_precision('Account')), 'starting_id': fields.many2one('account.bank.statement',ondelete='cascade'), 'ending_id': fields.many2one('account.bank.statement',ondelete='cascade'), } @@ -117,18 +118,18 @@ class account_cash_statement(osv.osv): res2[statement.id]=encoding_total return res2 - def _default_journal_id(self, cr, uid, context={}): +# def _default_journal_id(self, cr, uid, context={}): - """ To get default journal for the object" - @param name: Names of fields. - @return: journal - """ - company_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.id - journal = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', company_id)]) - if journal: - return journal[0] - else: - return False +# """ To get default journal for the object" +# @param name: Names of fields. +# @return: journal +# """ +# company_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.id +# journal = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', company_id)]) +# if journal: +# return journal[0] +# else: +# return False def _end_balance(self, cursor, user, ids, name, attr, context=None): res_currency_obj = self.pool.get('res.currency') @@ -173,10 +174,32 @@ class account_cash_statement(osv.osv): return company_id + def _get_cash_open_box_lines(self, cr, uid, ids, context={}): + res = [] + curr = [1, 2, 5, 10, 20, 50, 100, 500] + for rs in curr: + dct = { + 'pieces':rs, + 'number':0 + } + res.append(dct) + return res + + def _get_cash_close_box_lines(self, cr, uid, ids, context={}): + res = [] + curr = [1, 2, 5, 10, 20, 50, 100, 500] + for rs in curr: + dct = { + 'pieces':rs, + 'number':0 + } + res.append((0, 0, dct)) + return res + _columns = { 'company_id':fields.many2one('res.company', 'Company', required=False), - 'journal_id': fields.many2one('account.journal', 'Journal', required=True), - 'balance_end_real': fields.float('Closing Balance', digits=(16,2), states={'confirm':[('readonly', True)]}, help="closing balance entered by the cashbox verifier"), + 'journal_id': fields.many2one('account.journal', 'Journal', required=True, domain=[('type', '=', 'cash')]), + 'balance_end_real': fields.float('Closing Balance', digits_compute=dp.get_precision('Account'), states={'confirm':[('readonly', True)]}, help="closing balance entered by the cashbox verifier"), 'state': fields.selection( [('draft', 'Draft'), ('confirm', 'Confirm'), @@ -194,26 +217,36 @@ class account_cash_statement(osv.osv): 'state': lambda *a: 'draft', 'name': lambda *a: '/', 'date': lambda *a:time.strftime("%Y-%m-%d %H:%M:%S"), - 'journal_id': _default_journal_id, 'user_id': lambda self, cr, uid, context=None: uid, - 'company_id': _get_company + 'company_id': _get_company, + 'starting_details_ids':_get_cash_open_box_lines, + 'ending_details_ids':_get_cash_open_box_lines } def create(self, cr, uid, vals, context=None): company_id = vals and vals.get('company_id',False) if company_id: - open_jrnl = self.search(cr, uid, [('company_id', '=', vals['company_id']), ('journal_id', '=', vals['journal_id']), ('state', '=', 'open')]) + sql = [ + ('company_id', '=', vals['company_id']), + ('journal_id', '=', vals['journal_id']), + ('state', '=', 'open') + ] + open_jrnl = self.search(cr, uid, sql) if open_jrnl: - raise osv.except_osv('Error', u'Une caisse de type espèce est déjà ouverte') - if 'starting_details_ids' in vals: - vals['starting_details_ids'] = starting_details_ids = map(list, vals['starting_details_ids']) - for i in starting_details_ids: - if i and i[0] and i[1]: - i[0], i[1] = 0, 0 + raise osv.except_osv('Error', _('You can not have two open register for the same journal')) + + if self.pool.get('account.journal').browse(cr, uid, vals['journal_id']).type == 'cash': + lines = end_lines = self._get_cash_close_box_lines(cr, uid, [], context) + vals.update({ + 'ending_details_ids':lines + }) + else: + vals.update({ + 'ending_details_ids':False, + 'starting_details_ids':False + }) res_id = super(account_cash_statement, self).create(cr, uid, vals, context=context) - res = self._get_starting_balance(cr, uid, [res_id]) - for rs in res: - super(account_cash_statement, self).write(cr, uid, rs, res.get(rs)) + self.write(cr, uid, [res_id], {}) return res_id def write(self, cr, uid, ids, vals, context=None): @@ -283,27 +316,26 @@ class account_cash_statement(osv.osv): number = self.pool.get('ir.sequence').get(cr, uid, statement.journal_id.sequence_id.code) - if len(statement.starting_details_ids) > 0: - sid = [] - for line in statement.starting_details_ids: - sid.append(line.id) - - cash_pool.unlink(cr, uid, sid) - - cr.execute("select id from account_bank_statement where journal_id=%s and user_id=%s and state=%s order by id desc limit 1", (statement.journal_id.id, uid, 'confirm')) - rs = cr.fetchone() - rs = rs and rs[0] or None - if rs: - statement = statement_pool.browse(cr, uid, rs) - balance_start = statement.balance_end_real or 0.0 - open_ids = cash_pool.search(cr, uid, [('ending_id','=',statement.id)]) - for sid in open_ids: - default = { - 'ending_id': False, - 'starting_id':ids[0] - } - cash_pool.copy(cr, uid, sid, default) - +# if len(statement.starting_details_ids) > 0: +# sid = [] +# for line in statement.starting_details_ids: +# sid.append(line.id) +# cash_pool.unlink(cr, uid, sid) +# +# cr.execute("select id from account_bank_statement where journal_id=%s and user_id=%s and state=%s order by id desc limit 1", (statement.journal_id.id, uid, 'confirm')) +# rs = cr.fetchone() +# rs = rs and rs[0] or None +# if rs: +# statement = statement_pool.browse(cr, uid, rs) +# balance_start = statement.balance_end_real or 0.0 +# open_ids = cash_pool.search(cr, uid, [('ending_id','=',statement.id)]) +# for sid in open_ids: +# default = { +# 'ending_id': False, +# 'starting_id':ids[0] +# } +# cash_pool.copy(cr, uid, sid, default) +# vals = { 'date':time.strftime("%Y-%m-%d %H:%M:%S"), 'state':'open', diff --git a/addons/account/account_end_fy.xml b/addons/account/account_end_fy.xml index ee2ad952e6a..fe7b6e682fe 100644 --- a/addons/account/account_end_fy.xml +++ b/addons/account/account_end_fy.xml @@ -8,6 +8,7 @@ form [('state','=','draft')] + After closing a period, you will no longer be able to post entries to the period once it has been closed. + + diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml index 99d1181fb7b..22df9059305 100644 --- a/addons/account/account_invoice_view.xml +++ b/addons/account/account_invoice_view.xml @@ -5,7 +5,6 @@ - account.invoice.calendar account.invoice @@ -17,6 +16,7 @@ + account.invoice.graph account.invoice @@ -28,6 +28,7 @@ + account.invoice.line.tree account.invoice.line @@ -44,6 +45,7 @@ + account.invoice.line.form account.invoice.line @@ -74,6 +76,7 @@ + account.invoice.tax.tree account.invoice.tax @@ -89,6 +92,7 @@ + account.invoice.tax.form account.invoice.tax @@ -115,7 +119,7 @@ account.invoice tree - + @@ -131,6 +135,12 @@ + + + + Forward to Partner crm.lead.forward.to.partner form form + new diff --git a/addons/crm/wizard/crm_lead_to_opportunity.py b/addons/crm/wizard/crm_lead_to_opportunity.py index 7f47e27a4ff..79c833b278c 100644 --- a/addons/crm/wizard/crm_lead_to_opportunity.py +++ b/addons/crm/wizard/crm_lead_to_opportunity.py @@ -79,6 +79,7 @@ class crm_lead2opportunity(osv.osv_memory): 'probability': this.probability, 'name': this.name, 'partner_id': this.partner_id.id, + 'user_id': (this.partner_id.user_id and this.partner_id.user_id.id) or (lead.user_id and lead.user_id.id), 'type': 'opportunity' } lead_obj.write(cr, uid, lead.id, vals, context=context) @@ -126,9 +127,9 @@ class crm_lead2opportunity(osv.osv_memory): if lead.state in ['done', 'cancel']: raise osv.except_osv(_("Warning !"), _("Closed/Cancelled \ Leads Could not convert into Opportunity")) - if lead.state != 'open': + if lead.state not in ('open', 'pending'): raise osv.except_osv(_('Warning !'), _('Lead should be in \ -\'Open\' state before converting to Opportunity.')) +\'Open\' or \'Pending\' state before converting to Opportunity.')) return False def default_get(self, cr, uid, fields, context=None): @@ -221,7 +222,7 @@ class crm_lead2opportunity_partner(osv.osv_memory): res = mod_obj.read(cr, uid, result, ['res_id']) value = {} data_obj = self.pool.get('ir.model.data') - data_id = data_obj._get_id(cr, uid, 'crm', 'view_crm_lead2opportunity_create') + data_id = data_obj._get_id(cr, uid, 'crm', 'view_crm_lead2opportunity_action') view_id = False if data_id: view_id = data_obj.browse(cr, uid, data_id, context=context).res_id @@ -231,7 +232,7 @@ class crm_lead2opportunity_partner(osv.osv_memory): 'name': _('Create Opportunity'), 'view_type': 'form', 'view_mode': 'form,tree', - 'res_model': 'crm.lead2opportunity', + 'res_model': 'crm.lead2opportunity.action', 'view_id': False, 'context': context, 'views': [(view_id, 'form')], @@ -289,12 +290,75 @@ class crm_lead2opportunity_partner(osv.osv_memory): if lead.state in ['done', 'cancel']: raise osv.except_osv(_("Warning !"), _("Closed/Cancelled \ Leads Could not convert into Opportunity")) - if lead.state != 'open': + if lead.state not in ('open', 'pending'): raise osv.except_osv(_('Warning !'), _('Lead should be in \ -\'Open\' state before converting to Opportunity.')) +\'Open\' or \'Pending\' state before converting to Opportunity.')) return False crm_lead2opportunity_partner() +class crm_lead2opportunity_action(osv.osv_memory): + ''' + Merge with Existing Opportunity or Convert to Opportunity + ''' + _name = 'crm.lead2opportunity.action' + _description = 'Convert/Merge Opportunity' + + _columns = { + 'name': fields.selection([('convert', 'Convert to Opportunity'), ('merge', 'Merge with existing Opportunity')],'Select Action', required=True), + + } + + _defaults = { + 'name': 'convert', + } + + def do_action(self, cr, uid, ids, context=None): + """ + This function opens form according to selected Action + @param self: The object pointer + @param cr: the current row, from the database cursor, + @param uid: the current user’s ID for security checks, + @param ids: List of Lead to Opportunity IDs + @param context: A standard dictionary for contextual values + @return : Dictionary value for Opportunity form + """ + value = {} + data_obj = self.pool.get('ir.model.data') + view_id = False + for this in self.browse(cr, uid, ids, context=context): + if this.name == 'convert': + data_id = data_obj._get_id(cr, uid, 'crm', 'view_crm_lead2opportunity_create') + if data_id: + view_id = data_obj.browse(cr, uid, data_id, context=context).res_id + value = { + 'name': _('Create Opportunity'), + 'view_type': 'form', + 'view_mode': 'form,tree', + 'res_model': 'crm.lead2opportunity', + 'view_id': False, + 'context': context, + 'views': [(view_id, 'form')], + 'type': 'ir.actions.act_window', + 'target': 'new', + } + elif this.name == 'merge': + data_id = data_obj._get_id(cr, uid, 'crm', 'merge_opportunity_form') + if data_id: + view_id = data_obj.browse(cr, uid, data_id, context=context).res_id + value = { + 'name': _('Merge with Existing Opportunity'), + 'view_type': 'form', + 'view_mode': 'form,tree', + 'res_model': 'crm.merge.opportunity', + 'view_id': False, + 'context': context, + 'views': [(view_id, 'form')], + 'type': 'ir.actions.act_window', + 'target': 'new', + } + return value + +crm_lead2opportunity_action() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/wizard/crm_lead_to_opportunity_view.xml b/addons/crm/wizard/crm_lead_to_opportunity_view.xml index 25d9017c8cb..d41030789b6 100644 --- a/addons/crm/wizard/crm_lead_to_opportunity_view.xml +++ b/addons/crm/wizard/crm_lead_to_opportunity_view.xml @@ -3,7 +3,7 @@ - + crm.lead2opportunity.create crm.lead2opportunity form @@ -61,5 +61,25 @@ + + crm.lead2opportunity.action.form + crm.lead2opportunity.action + form + +
+ +