diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0575bebb52d..d26e35559e9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,68 +1,10 @@ Contributing to Odoo ==================== -Reporting Issues ----------------- -If possible, always attach a pull request when creating an issue (GitHub will automatically create an issue when submitting the changes). The issues not linked to a pull request or an internal request on odoo.com will be handled with a lower priority. +[Full contribution guidelines](https://github.com/odoo/odoo/wiki/Contributing) -If later on you create a pull request solving an opened issue, do not forget to reference to it in your pull request (e.g.: "This patch fixes issue #42"). +TL;DR -When reporting an issue or creating a pull request, use the following structure: - -> **Quantity field is ignored in a sale order** -> -> Impacted versions: -> -> - 7.0 and above -> -> Steps to reproduce: -> -> 1. create a new sale order -> 2. add a line with product 'Service', quantity 2, unit price 10.0 -> 3. validate the sale order -> -> Current behavior: -> -> - Total price of 10.0 -> -> Expected behavior: -> -> - Total price of 20.0 (2 * 10 = 20) - -For web or rendering issues, do not forget to specify the operating system and browser you are using. - -Against which version should I submit a patch? ----------------------------------------------- -Periodically, we forward port the fixes realized in the latest stable version to master and intermediate saas repositories. This means that you should submit your pull request against the lowest supported version. If applying, you should always submit your code against `odoo/7.0`. The `saas-x` versions are intermediate versions between stable versions. - -![Submiting against the right version](/doc/_static/pull-request-version.png) - -However your change **must** be submitted against `odoo/master` if - -* it modifies the database structure (e.g.: adding a new field) -* it adds a new feature - -Why was my fix labeled as blocked? ----------------------------------- -The label *blocked* is used when an action is required from the submitter. The typical reasons are: - -* the fix is incomplete/incorrect and a change is required -* more information is required - -Pull requests with the blocked label will not be processed as long as the label remains. Once the correction done, we will review it and eventually remove the label. - -Why was my issue closed without merging? ----------------------------------------- -A pull request is closed when it will not be merged into odoo. This will typically happens if the fix/issue: - -* is not relevant to odoo development (label *invalid*) -* is not considered as a bug or we have no plan to change the current behavior (label *wontfix*) -* is a duplicated of another opened issue (label *duplicate*) -* the pull request should be resubmitted against another version - -What is this odoo-dev repository? Should I use it? --------------------------------------------------- - -The `odoo-dev/odoo` repository is an internal repository used by the R&D of Odoo to keep the main repository clean. If you are coming from Launchpad, this is the equivalent of the `~openerp-dev` repository. - -When forking odoo to submit a patch, always use the `github.com/odoo/odoo` repository. Be also careful of the version you are branching as it will determine the history once the pull request will be realized (e.g.: `git checkout -b 7.0-my-branch odoo/7.0`). +* Use this [template](https://raw.githubusercontent.com/odoo/odoo/master/doc/_templates/issue_template.md) when reporting issues, and please search for duplicates first! +* Pull requests must be made against the [correct version](https://github.com/odoo/odoo/wiki/Contributing#against-which-version-should-i-submit-a-patch) +* There are restrictions on the kind of [changes allowed in stable series](https://github.com/odoo/odoo/wiki/Contributing#what-does-stable-mean) diff --git a/setup/MANIFEST.in b/MANIFEST.in similarity index 100% rename from setup/MANIFEST.in rename to MANIFEST.in diff --git a/README.md b/README.md index 9e77856701a..d76976405b3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - +[![Build Status](http://runbot.odoo.com/runbot/badge/default/1/master.svg)](http://runbot.odoo.com/runbot) Odoo ---- diff --git a/addons/.bzrignore b/addons/.bzrignore deleted file mode 100644 index 8c348710117..00000000000 --- a/addons/.bzrignore +++ /dev/null @@ -1,2 +0,0 @@ -.* -**/node_modules diff --git a/addons/account/account.py b/addons/account/account.py index 4e075be9cbf..93d3dfb5d4a 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -59,7 +59,7 @@ class account_payment_term(osv.osv): _name = "account.payment.term" _description = "Payment Term" _columns = { - 'name': fields.char('Payment Term', size=64, translate=True, required=True), + 'name': fields.char('Payment Term', translate=True, required=True), 'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the payment term without removing it."), 'note': fields.text('Description', translate=True), 'line_ids': fields.one2many('account.payment.term.line', 'payment_id', 'Terms'), @@ -180,7 +180,7 @@ class account_account_type(osv.osv): return obj_financial_report.write(cr, uid, [financial_report_ref[field_value].id], {'account_type_ids': [(4, account_type_id)]}) _columns = { - 'name': fields.char('Account Type', size=64, required=True, translate=True), + 'name': fields.char('Account Type', required=True, translate=True), 'code': fields.char('Code', size=32, required=True, select=True), 'close_method': fields.selection([('none', 'None'), ('balance', 'Balance'), ('detail', 'Detail'), ('unreconciled', 'Unreconciled')], 'Deferral Method', required=True, help="""Set here the method that will be used to generate the end of year journal entries for all the accounts of this type. @@ -444,7 +444,7 @@ class account_account(osv.osv): return True _columns = { - 'name': fields.char('Name', size=256, required=True, select=True), + 'name': fields.char('Name', required=True, select=True), 'currency_id': fields.many2one('res.currency', 'Secondary Currency', help="Forces all moves for this account to have this secondary currency."), 'code': fields.char('Code', size=64, required=True, select=1), 'type': fields.selection([ @@ -580,7 +580,14 @@ class account_account(osv.osv): pass if name: if operator not in expression.NEGATIVE_TERM_OPERATORS: - ids = self.search(cr, user, ['|', ('code', '=like', name+"%"), '|', ('shortcut', '=', name), ('name', operator, name)]+args, limit=limit) + plus_percent = lambda n: n+'%' + code_op, code_conv = { + 'ilike': ('=ilike', plus_percent), + 'like': ('=like', plus_percent), + }.get(operator, (operator, lambda n: n)) + + ids = self.search(cr, user, ['|', ('code', code_op, code_conv(name)), '|', ('shortcut', '=', name), ('name', operator, name)]+args, limit=limit) + if not ids and len(name.split()) >= 2: #Separating code and name of account for searching operand1,operand2 = name.split(' ',1) #name can contain spaces e.g. OpenERP S.A. @@ -708,7 +715,7 @@ class account_journal(osv.osv): _description = "Journal" _columns = { 'with_last_closing_balance' : fields.boolean('Opening With Last Closing Balance'), - 'name': fields.char('Journal Name', size=64, required=True), + 'name': fields.char('Journal Name', required=True), 'code': fields.char('Code', size=5, required=True, help="The code will be displayed on reports."), 'type': fields.selection([('sale', 'Sale'),('sale_refund','Sale Refund'), ('purchase', 'Purchase'), ('purchase_refund','Purchase Refund'), ('cash', 'Cash'), ('bank', 'Bank and Checks'), ('general', 'General'), ('situation', 'Opening/Closing Situation')], 'Type', size=32, required=True, help="Select 'Sale' for customer invoices journals."\ @@ -852,7 +859,7 @@ class account_fiscalyear(osv.osv): _name = "account.fiscalyear" _description = "Fiscal Year" _columns = { - 'name': fields.char('Fiscal Year', size=64, required=True), + 'name': fields.char('Fiscal Year', required=True), 'code': fields.char('Code', size=6, required=True), 'company_id': fields.many2one('res.company', 'Company', required=True), 'date_start': fields.date('Start Date', required=True), @@ -945,10 +952,9 @@ class account_period(osv.osv): _name = "account.period" _description = "Account period" _columns = { - 'name': fields.char('Period Name', size=64, required=True), + 'name': fields.char('Period Name', required=True), 'code': fields.char('Code', size=12), - 'special': fields.boolean('Opening/Closing Period', size=12, - help="These periods can overlap."), + 'special': fields.boolean('Opening/Closing Period',help="These periods can overlap."), 'date_start': fields.date('Start of Period', required=True, states={'done':[('readonly',True)]}), 'date_stop': fields.date('End of Period', required=True, states={'done':[('readonly',True)]}), 'fiscalyear_id': fields.many2one('account.fiscalyear', 'Fiscal Year', required=True, states={'done':[('readonly',True)]}, select=True), @@ -1085,10 +1091,10 @@ class account_journal_period(osv.osv): return result _columns = { - 'name': fields.char('Journal-Period Name', size=64, required=True), + 'name': fields.char('Journal-Period Name', required=True), 'journal_id': fields.many2one('account.journal', 'Journal', required=True, ondelete="cascade"), 'period_id': fields.many2one('account.period', 'Period', required=True, ondelete="cascade"), - 'icon': fields.function(_icon_get, string='Icon', type='char', size=32), + 'icon': fields.function(_icon_get, string='Icon', type='char'), 'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the journal period without removing it."), 'state': fields.selection([('draft','Draft'), ('printed','Printed'), ('done','Done')], 'Status', required=True, readonly=True, help='When journal period is created. The status is \'Draft\'. If a report is printed it comes to \'Printed\' status. When all transactions are done, it comes in \'Done\' status.'), @@ -1228,8 +1234,8 @@ class account_move(osv.osv): return [line.move_id.id for line in line_obj.browse(cr, uid, ids, context=context)] _columns = { - 'name': fields.char('Number', size=64, required=True), - 'ref': fields.char('Reference', size=64), + 'name': fields.char('Number', required=True), + 'ref': fields.char('Reference'), 'period_id': fields.many2one('account.period', 'Period', required=True, states={'posted':[('readonly',True)]}), 'journal_id': fields.many2one('account.journal', 'Journal', required=True, states={'posted':[('readonly',True)]}), 'state': fields.selection([('draft','Unposted'), ('posted','Posted')], 'Status', required=True, readonly=True, @@ -1622,8 +1628,8 @@ class account_move_reconcile(osv.osv): _name = "account.move.reconcile" _description = "Account Reconciliation" _columns = { - 'name': fields.char('Name', size=64, required=True), - 'type': fields.char('Type', size=16, required=True), + 'name': fields.char('Name', required=True), + 'type': fields.char('Type', required=True), 'line_id': fields.one2many('account.move.line', 'reconcile_id', 'Entry Lines'), 'line_partial_ids': fields.one2many('account.move.line', 'reconcile_partial_id', 'Partial Entry lines'), 'create_date': fields.date('Creation date', readonly=True), @@ -1780,7 +1786,7 @@ class account_tax_code(osv.osv): _description = 'Tax Code' _rec_name = 'code' _columns = { - 'name': fields.char('Tax Case Name', size=64, required=True, translate=True), + 'name': fields.char('Tax Case Name', required=True, translate=True), 'code': fields.char('Case Code', size=64), 'info': fields.text('Description'), 'sum': fields.function(_sum_year, string="Year Sum"), @@ -1869,7 +1875,7 @@ class account_tax(osv.osv): _name = 'account.tax' _description = 'Tax' _columns = { - 'name': fields.char('Tax Name', size=64, required=True, translate=True, help="This name will be displayed on reports"), + 'name': fields.char('Tax Name', required=True, translate=True, help="This name will be displayed on reports"), 'sequence': fields.integer('Sequence', required=True, help="The sequence field is used to order the tax lines from the lowest sequences to the higher ones. The order is important if you have a tax with several tax children. In this case, the evaluation order is important."), 'amount': fields.float('Amount', required=True, digits_compute=get_precision_tax(), help="For taxes of type percentage, enter % ratio between 0-1."), 'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the tax without removing it."), @@ -1877,7 +1883,7 @@ class account_tax(osv.osv): help="The computation method for the tax amount."), 'applicable_type': fields.selection( [('true','Always'), ('code','Given by Python Code')], 'Applicability', required=True, help="If not applicable (computed through a Python code), the tax won't appear on the invoice."), - 'domain':fields.char('Domain', size=32, help="This field is only used if you develop your own module allowing developers to create specific taxes in a custom domain."), + 'domain':fields.char('Domain', help="This field is only used if you develop your own module allowing developers to create specific taxes in a custom domain."), 'account_collected_id':fields.many2one('account.account', 'Invoice Tax Account', help="Set the account that will be set by default on invoice tax lines for invoices. Leave empty to use the expense account."), 'account_paid_id':fields.many2one('account.account', 'Refund Tax Account', help="Set the account that will be set by default on invoice tax lines for refunds. Leave empty to use the expense account."), 'account_analytic_collected_id':fields.many2one('account.analytic.account', 'Invoice Tax Analytic Account', help="Set the analytic account that will be used by default on the invoice tax lines for invoices. Leave empty if you don't want to use an analytic account on the invoice tax lines by default."), @@ -2260,7 +2266,7 @@ class account_model(osv.osv): _name = "account.model" _description = "Account Model" _columns = { - 'name': fields.char('Model Name', size=64, required=True, help="This is a model for recurring accounting entries"), + 'name': fields.char('Model Name', required=True, help="This is a model for recurring accounting entries"), 'journal_id': fields.many2one('account.journal', 'Journal', required=True), 'company_id': fields.related('journal_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True), 'lines_id': fields.one2many('account.model.line', 'model_id', 'Model Entries'), @@ -2367,7 +2373,7 @@ class account_model_line(osv.osv): _name = "account.model.line" _description = "Account Model Entries" _columns = { - 'name': fields.char('Name', size=64, required=True), + 'name': fields.char('Name', required=True), 'sequence': fields.integer('Sequence', required=True, help="The sequence field is used to order the resources from lower sequences to higher ones."), 'quantity': fields.float('Quantity', digits_compute=dp.get_precision('Account'), help="The optional quantity on entries."), 'debit': fields.float('Debit', digits_compute=dp.get_precision('Account')), @@ -2395,8 +2401,8 @@ class account_subscription(osv.osv): _name = "account.subscription" _description = "Account Subscription" _columns = { - 'name': fields.char('Name', size=64, required=True), - 'ref': fields.char('Reference', size=16), + 'name': fields.char('Name', required=True), + 'ref': fields.char('Reference'), 'model_id': fields.many2one('account.model', 'Model', required=True), 'date_start': fields.date('Start Date', required=True), 'period_total': fields.integer('Number of Periods', required=True), @@ -2500,7 +2506,7 @@ class account_account_template(osv.osv): _description ='Templates for Accounts' _columns = { - 'name': fields.char('Name', size=256, required=True, select=True), + 'name': fields.char('Name', required=True, select=True), 'currency_id': fields.many2one('res.currency', 'Secondary Currency', help="Forces all moves for this account to have this secondary currency."), 'code': fields.char('Code', size=64, required=True, select=1), 'type': fields.selection([ @@ -2681,7 +2687,7 @@ class account_tax_code_template(osv.osv): _order = 'code' _rec_name = 'code' _columns = { - 'name': fields.char('Tax Case Name', size=64, required=True), + 'name': fields.char('Tax Case Name', required=True), 'code': fields.char('Case Code', size=64), 'info': fields.text('Description'), 'parent_id': fields.many2one('account.tax.code.template', 'Parent Code', select=True), @@ -2751,7 +2757,7 @@ class account_chart_template(osv.osv): _description= "Templates for Account Chart" _columns={ - 'name': fields.char('Name', size=64, required=True), + 'name': fields.char('Name', required=True), 'parent_id': fields.many2one('account.chart.template', 'Parent Chart Template'), 'code_digits': fields.integer('# of Digits', required=True, help="No. of Digits to use for account code"), 'visible': fields.boolean('Can be Visible?', help="Set this to False if you don't want this template to be used actively in the wizard that generate Chart of Accounts from templates, this is useful when you want to generate accounts of this template only when loading its child template."), @@ -2785,12 +2791,12 @@ class account_tax_template(osv.osv): _columns = { 'chart_template_id': fields.many2one('account.chart.template', 'Chart Template', required=True), - 'name': fields.char('Tax Name', size=64, required=True), + 'name': fields.char('Tax Name', required=True), 'sequence': fields.integer('Sequence', required=True, help="The sequence field is used to order the taxes lines from lower sequences to higher ones. The order is important if you have a tax that has several tax children. In this case, the evaluation order is important."), 'amount': fields.float('Amount', required=True, digits_compute=get_precision_tax(), help="For Tax Type percent enter % ratio between 0-1."), 'type': fields.selection( [('percent','Percent'), ('fixed','Fixed'), ('none','None'), ('code','Python Code'), ('balance','Balance')], 'Tax Type', required=True), 'applicable_type': fields.selection( [('true','True'), ('code','Python Code')], 'Applicable Type', required=True, help="If not applicable (computed through a Python code), the tax won't appear on the invoice."), - 'domain':fields.char('Domain', size=32, help="This field is only used if you develop your own module allowing developers to create specific taxes in a custom domain."), + 'domain':fields.char('Domain', help="This field is only used if you develop your own module allowing developers to create specific taxes in a custom domain."), 'account_collected_id':fields.many2one('account.account.template', 'Invoice Tax Account'), 'account_paid_id':fields.many2one('account.account.template', 'Refund Tax Account'), 'parent_id':fields.many2one('account.tax.template', 'Parent Tax Account', select=True), @@ -2914,11 +2920,11 @@ class account_fiscal_position_template(osv.osv): _description = 'Template for Fiscal Position' _columns = { - 'name': fields.char('Fiscal Position Template', size=64, required=True), + 'name': fields.char('Fiscal Position Template', required=True), 'chart_template_id': fields.many2one('account.chart.template', 'Chart Template', required=True), 'account_ids': fields.one2many('account.fiscal.position.account.template', 'position_id', 'Account Mapping'), 'tax_ids': fields.one2many('account.fiscal.position.tax.template', 'position_id', 'Tax Mapping'), - 'note': fields.text('Notes', translate=True), + 'note': fields.text('Notes'), } def generate_fiscal_position(self, cr, uid, chart_temp_id, tax_template_ref, acc_template_ref, company_id, context=None): @@ -3546,10 +3552,10 @@ class account_bank_accounts_wizard(osv.osv_memory): _name='account.bank.accounts.wizard' _columns = { - 'acc_name': fields.char('Account Name.', size=64, required=True), + 'acc_name': fields.char('Account Name.', required=True), 'bank_account_id': fields.many2one('wizard.multi.charts.accounts', 'Bank Account', required=True, ondelete='cascade'), 'currency_id': fields.many2one('res.currency', 'Secondary Currency', help="Forces all moves for this account to have this secondary currency."), - 'account_type': fields.selection([('cash','Cash'), ('check','Check'), ('bank','Bank')], 'Account Type', size=32), + 'account_type': fields.selection([('cash','Cash'), ('check','Check'), ('bank','Bank')], 'Account Type'), } diff --git a/addons/account/account_analytic_line.py b/addons/account/account_analytic_line.py index e141f33b9d1..d5ec3496d92 100644 --- a/addons/account/account_analytic_line.py +++ b/addons/account/account_analytic_line.py @@ -33,7 +33,7 @@ class account_analytic_line(osv.osv): 'move_id': fields.many2one('account.move.line', 'Move Line', ondelete='cascade', select=True), 'journal_id': fields.many2one('account.analytic.journal', 'Analytic Journal', required=True, ondelete='restrict', select=True), 'code': fields.char('Code', size=8), - 'ref': fields.char('Ref.', size=64), + 'ref': fields.char('Ref.'), 'currency_id': fields.related('move_id', 'currency_id', type='many2one', relation='res.currency', string='Account Currency', store=True, help="The related account currency if not equal to the company one.", readonly=True), 'amount_currency': fields.related('move_id', 'amount_currency', type='float', string='Amount Currency', store=True, help="The amount expressed in the related account currency if not equal to the company one.", readonly=True), } diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py index 75940d2d83d..6a81e0b310f 100644 --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@ -26,6 +26,9 @@ from openerp.report import report_sxw class account_bank_statement(osv.osv): def create(self, cr, uid, vals, context=None): + if vals.get('name', '/') == '/': + journal_id = vals.get('journal_id', self._default_journal_id(cr, uid, context=context)) + vals['name'] = self._compute_default_statement_name(cr, uid, journal_id, context=context) if 'line_ids' in vals: for idx, line in enumerate(vals['line_ids']): line[2]['sequence'] = idx + 1 @@ -65,17 +68,14 @@ class account_bank_statement(osv.osv): return periods[0] return False - def _compute_default_statement_name(self, cr, uid, context=None): + def _compute_default_statement_name(self, cr, uid, journal_id, context=None): if context is None: context = {} obj_seq = self.pool.get('ir.sequence') - default_journal_id = self._default_journal_id(cr, uid, context=context) - if default_journal_id != False: - period = self.pool.get('account.period').browse(cr, uid, self._get_period(cr, uid, context=context), context=context) - context['fiscalyear_id'] = period.fiscalyear_id.id - journal = self.pool.get('account.journal').browse(cr, uid, default_journal_id, None) - return obj_seq.next_by_id(cr, uid, journal.sequence_id.id, context=context) - return obj_seq.next_by_code(cr, uid, 'account.bank.statement', context=context) + period = self.pool.get('account.period').browse(cr, uid, self._get_period(cr, uid, context=context), context=context) + context['fiscalyear_id'] = period.fiscalyear_id.id + journal = self.pool.get('account.journal').browse(cr, uid, journal_id, None) + return obj_seq.next_by_id(cr, uid, journal.sequence_id.id, context=context) def _currency(self, cursor, user, ids, name, args, context=None): res = {} @@ -114,7 +114,7 @@ class account_bank_statement(osv.osv): _description = "Bank Statement" _inherit = ['mail.thread'] _columns = { - 'name': fields.char('Reference', size=64, states={'draft': [('readonly', False)]}, readonly=True, help='if you give the Name other then /, its created Accounting Entries Move will be with same name as statement name. This allows the statement entries to have the same references than the statement itself'), # readonly for account_cash_statement + 'name': fields.char('Reference', states={'draft': [('readonly', False)]}, readonly=True, help='if you give the Name other then /, its created Accounting Entries Move will be with same name as statement name. This allows the statement entries to have the same references than the statement itself'), # readonly for account_cash_statement 'date': fields.date('Date', required=True, states={'confirm': [('readonly', True)]}, select=True), 'journal_id': fields.many2one('account.journal', 'Journal', required=True, readonly=True, states={'draft':[('readonly',False)]}), @@ -150,7 +150,7 @@ class account_bank_statement(osv.osv): } _defaults = { - 'name': _compute_default_statement_name, + 'name': '/', 'date': fields.date.context_today, 'state': 'draft', 'journal_id': _default_journal_id, @@ -213,11 +213,8 @@ class account_bank_statement(osv.osv): def _get_counter_part_account(sefl, cr, uid, st_line, context=None): """Retrieve the account to use in the counterpart move. - This method may be overridden to implement custom move generation (making sure to - call super() to establish a clean extension chain). - :param browse_record st_line: account.bank.statement.line record to - create the move from. + :param browse_record st_line: account.bank.statement.line record to create the move from. :return: int/long of the account.account to use as counterpart """ if st_line.amount >= 0: @@ -226,26 +223,19 @@ class account_bank_statement(osv.osv): def _get_counter_part_partner(sefl, cr, uid, st_line, context=None): """Retrieve the partner to use in the counterpart move. - This method may be overridden to implement custom move generation (making sure to - call super() to establish a clean extension chain). - :param browse_record st_line: account.bank.statement.line record to - create the move from. + :param browse_record st_line: account.bank.statement.line record to create the move from. :return: int/long of the res.partner to use as counterpart """ return st_line.partner_id and st_line.partner_id.id or False def _prepare_bank_move_line(self, cr, uid, st_line, move_id, amount, company_currency_id, context=None): """Compute the args to build the dict of values to create the counter part move line from a - statement line by calling the _prepare_move_line_vals. This method may be - overridden to implement custom move generation (making sure to call super() to - establish a clean extension chain). + statement line by calling the _prepare_move_line_vals. - :param browse_record st_line: account.bank.statement.line record to - create the move from. + :param browse_record st_line: account.bank.statement.line record to create the move from. :param int/long move_id: ID of the account.move to link the move line :param float amount: amount of the move line - :param int/long account_id: ID of account to use as counter part :param int/long company_currency_id: ID of currency of the concerned company :return: dict of value to create() the bank account.move.line """ @@ -258,7 +248,6 @@ class account_bank_statement(osv.osv): if st_line.statement_id.currency.id != company_currency_id: amt_cur = st_line.amount cur_id = st_line.currency_id or st_line.statement_id.currency.id - # TODO : FIXME the amount should be in the journal currency if st_line.currency_id and st_line.amount_currency: amt_cur = st_line.amount_currency cur_id = st_line.currency_id.id @@ -269,9 +258,7 @@ class account_bank_statement(osv.osv): def _prepare_move_line_vals(self, cr, uid, st_line, move_id, debit, credit, currency_id=False, amount_currency=False, account_id=False, partner_id=False, context=None): """Prepare the dict of values to create the move line from a - statement line. All non-mandatory args will replace the default computed one. - This method may be overridden to implement custom move generation (making sure to - call super() to establish a clean extension chain). + statement line. :param browse_record st_line: account.bank.statement.line record to create the move from. @@ -342,21 +329,29 @@ class account_bank_statement(osv.osv): move_ids.append(st_line.journal_entry_id.id) self.pool.get('account.move').post(cr, uid, move_ids, context=context) self.message_post(cr, uid, [st.id], body=_('Statement %s confirmed, journal items were created.') % (st.name,), context=context) + self.link_bank_to_partner(cr, uid, ids, context=context) return self.write(cr, uid, ids, {'state':'confirm'}, context=context) def button_cancel(self, cr, uid, ids, context=None): - done = [] account_move_obj = self.pool.get('account.move') + reconcile_pool = self.pool.get('account.move.reconcile') + move_line_pool = self.pool.get('account.move.line') + move_ids = [] for st in self.browse(cr, uid, ids, context=context): - if st.state=='draft': - continue - move_ids = [] for line in st.line_ids: - move_ids += [x.id for x in line.move_ids] + if line.journal_entry_id: + move_ids.append(line.journal_entry_id.id) + for aml in line.journal_entry_id.line_id: + if aml.reconcile_id: + move_lines = [l.id for l in aml.reconcile_id.line_id] + move_lines.remove(aml.id) + reconcile_pool.unlink(cr, uid, [aml.reconcile_id.id], context=context) + if len(move_lines) >= 2: + move_line_pool.reconcile_partial(cr, uid, move_lines, 'auto', context=context) + if move_ids: account_move_obj.button_cancel(cr, uid, move_ids, context=context) account_move_obj.unlink(cr, uid, move_ids, context) - done.append(st.id) - return self.write(cr, uid, done, {'state':'draft'}, context=context) + return self.write(cr, uid, ids, {'state': 'draft'}, context=context) def _compute_balance_end_real(self, cr, uid, journal_id, context=None): res = False @@ -417,18 +412,35 @@ class account_bank_statement(osv.osv): def number_of_lines_reconciled(self, cr, uid, id, context=None): bsl_obj = self.pool.get('account.bank.statement.line') - return bsl_obj.search_count(cr, uid, [('statement_id','=',id), ('journal_entry_id','!=',False)], context=context) - + return bsl_obj.search_count(cr, uid, [('statement_id', '=', id), ('journal_entry_id', '!=', False)], context=context) + def get_format_currency_js_function(self, cr, uid, id, context=None): """ Returns a string that can be used to instanciate a javascript function. - That function formats a number according to the statement's journal currency """ + That function formats a number according to the statement line's currency or the statement currency""" company_currency = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id - currency_obj = id and self.browse(cr, uid, id, context=context).journal_id.currency or company_currency + st = id and self.browse(cr, uid, id, context=context) + if not st: + return + statement_currency = st.journal_id.currency or company_currency digits = 2 # TODO : from currency_obj - if currency_obj.position == 'after': - return "return amount.toFixed("+str(digits)+") + ' "+currency_obj.symbol+"';" - elif currency_obj.position == 'before': - return "return '"+currency_obj.symbol+" ' + amount.toFixed("+str(digits)+");" + function = "" + done_currencies = [] + for st_line in st.line_ids: + st_line_currency = st_line.currency_id or statement_currency + if st_line_currency.id not in done_currencies: + if st_line_currency.position == 'after': + return_str = "return amount.toFixed(" + str(digits) + ") + ' " + st_line_currency.symbol + "';" + else: + return_str = "return '" + st_line_currency.symbol + " ' + amount.toFixed(" + str(digits) + ");" + function += "if (currency_id === " + str(st_line_currency.id) + "){ " + return_str + " }" + done_currencies.append(st_line_currency.id) + return function + + def link_bank_to_partner(self, cr, uid, ids, context=None): + for statement in self.browse(cr, uid, ids, context=context): + for st_line in statement.line_ids: + if st_line.bank_account_id and st_line.partner_id and st_line.bank_account_id.partner_id.id != st_line.partner_id.id: + self.pool.get('res.partner.bank').write(cr, uid, [st_line.bank_account_id.id], {'partner_id': st_line.partner_id.id}, context=context) class account_bank_statement_line(osv.osv): @@ -436,43 +448,64 @@ class account_bank_statement_line(osv.osv): """ Used to instanciate a batch of reconciliations in a single request """ # Build a list of reconciliations data ret = [] + statement_line_done = {} mv_line_ids_selected = [] + for st_line in self.browse(cr, uid, ids, context=context): + # look for structured communication first + exact_match_id = self.search_structured_com(cr, uid, st_line, context=context) + if exact_match_id: + reconciliation_data = { + 'st_line': self.get_statement_line_for_reconciliation(cr, uid, st_line.id, context), + 'reconciliation_proposition': self.make_counter_part_lines(cr, uid, st_line, [exact_match_id], context=context) + } + for mv_line in reconciliation_data['reconciliation_proposition']: + mv_line_ids_selected.append(mv_line['id']) + statement_line_done[st_line.id] = reconciliation_data + for st_line_id in ids: - reconciliation_data = { - 'st_line': self.get_statement_line_for_reconciliation(cr, uid, st_line_id, context), - 'reconciliation_proposition': self.get_reconciliation_proposition(cr, uid, st_line_id, mv_line_ids_selected, context) - } - for mv_line in reconciliation_data['reconciliation_proposition']: - mv_line_ids_selected.append(mv_line['id']) - ret.append(reconciliation_data); - + if statement_line_done.get(st_line_id): + ret.append(statement_line_done.get(st_line_id)) + else: + reconciliation_data = { + 'st_line': self.get_statement_line_for_reconciliation(cr, uid, st_line_id, context), + 'reconciliation_proposition': self.get_reconciliation_proposition(cr, uid, st_line_id, mv_line_ids_selected, context) + } + for mv_line in reconciliation_data['reconciliation_proposition']: + mv_line_ids_selected.append(mv_line['id']) + ret.append(reconciliation_data) + # Check if, now that 'candidate' move lines were selected, there are moves left for statement lines - for reconciliation_data in ret: - if not reconciliation_data['st_line']['has_no_partner']: - if self.get_move_lines_counterparts(cr, uid, reconciliation_data['st_line']['id'], excluded_ids=mv_line_ids_selected, count=True, context=context) == 0: - reconciliation_data['st_line']['no_match'] = True + #for reconciliation_data in ret: + # if not reconciliation_data['st_line']['has_no_partner']: + # st_line = self.browse(cr, uid, reconciliation_data['st_line']['id'], context=context) + # if not self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids=mv_line_ids_selected, count=True, context=context): + # reconciliation_data['st_line']['no_match'] = True return ret def get_statement_line_for_reconciliation(self, cr, uid, id, context=None): """ Returns the data required by the bank statement reconciliation use case """ line = self.browse(cr, uid, id, context=context) statement_currency = line.journal_id.currency or line.journal_id.company_id.currency_id + amount = line.amount rml_parser = report_sxw.rml_parse(cr, uid, 'statement_line_widget', context=context) amount_str = line.amount > 0 and line.amount or -line.amount amount_str = rml_parser.formatLang(amount_str, currency_obj=statement_currency) amount_currency_str = "" if line.amount_currency and line.currency_id: - amount_currency_str = rml_parser.formatLang(line.amount_currency, currency_obj=line.currency_id) + amount_currency_str = amount_str + amount_str = rml_parser.formatLang(line.amount_currency, currency_obj=line.currency_id) + amount = line.amount_currency - dict = { + data = { 'id': line.id, 'ref': line.ref, 'note': line.note or "", 'name': line.name, 'date': line.date, - 'amount': line.amount, + 'amount': amount, 'amount_str': amount_str, - 'no_match': self.get_move_lines_counterparts(cr, uid, id, count=True, context=context) == 0 and line.partner_id.id, + 'currency_id': line.currency_id.id or statement_currency.id, + 'no_match': self.get_move_lines_counterparts(cr, uid, line, count=True, context=context) == 0, 'partner_id': line.partner_id.id, 'statement_id': line.statement_id.id, 'account_code': line.journal_id.default_debit_account_id.code, @@ -482,93 +515,105 @@ class account_bank_statement_line(osv.osv): 'has_no_partner': not line.partner_id.id, } if line.partner_id.id: - if line.amount > 0: - dict['open_balance_account_id'] = line.partner_id.property_account_receivable.id - else: - dict['open_balance_account_id'] = line.partner_id.property_account_payable.id - return dict + data['open_balance_account_id'] = line.partner_id.property_account_payable.id + if amount > 0: + data['open_balance_account_id'] = line.partner_id.property_account_receivable.id + return data + + def search_structured_com(self, cr, uid, st_line, context=None): + if not st_line.ref: + return + domain = [('ref', '=', st_line.ref)] + if st_line.partner_id: + domain += [('partner_id', '=', st_line.partner_id.id)] + ids = self.pool.get('account.move.line').search(cr, uid, domain, limit=1, context=context) + return ids and ids[0] or False def get_reconciliation_proposition(self, cr, uid, id, excluded_ids=[], context=None): """ Returns move lines that constitute the best guess to reconcile a statement line. """ st_line = self.browse(cr, uid, id, context=context) company_currency = st_line.journal_id.company_id.currency_id.id statement_currency = st_line.journal_id.currency.id or company_currency - # either use the unsigned debit/credit fields or the signed amount_currency field sign = 1 if statement_currency == company_currency: + amount_field = 'credit' if st_line.amount > 0: amount_field = 'debit' - else: - amount_field = 'credit' else: amount_field = 'amount_currency' if st_line.amount < 0: sign = -1 + #we don't propose anything if there is no partner detected + if not st_line.partner_id.id: + return [] # look for exact match - exact_match_id = self.get_move_lines_counterparts(cr, uid, id, excluded_ids=excluded_ids, limit=1, additional_domain=[(amount_field,'=',(sign*st_line.amount))]) + exact_match_id = self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids=excluded_ids, additional_domain=[(amount_field, '=', (sign * st_line.amount))]) if exact_match_id: - return exact_match_id + return exact_match_id[0] # select oldest move lines if sign == -1: - mv_lines = self.get_move_lines_counterparts(cr, uid, id, excluded_ids=excluded_ids, limit=50, additional_domain=[(amount_field,'<',0)]) + mv_lines = self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids=excluded_ids, additional_domain=[(amount_field, '<', 0)]) else: - mv_lines = self.get_move_lines_counterparts(cr, uid, id, excluded_ids=excluded_ids, limit=50, additional_domain=[(amount_field,'>',0)]) + mv_lines = self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids=excluded_ids, additional_domain=[(amount_field, '>', 0)]) ret = [] total = 0 # get_move_lines_counterparts inverts debit and credit amount_field = 'debit' if amount_field == 'credit' else 'credit' for line in mv_lines: - if total + line[amount_field] <= st_line.amount: + if total + line[amount_field] <= abs(st_line.amount): ret.append(line) total += line[amount_field] - else: + if total >= abs(st_line.amount): break - return ret - def get_move_lines_counterparts(self, cr, uid, id, excluded_ids=[], str="", offset=0, limit=None, count=False, additional_domain=[], context=None): + def get_move_lines_counterparts_id(self, cr, uid, st_line_id, excluded_ids=[], additional_domain=[], count=False, context=None): + st_line = self.browse(cr, uid, st_line_id, context=context) + return self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids, additional_domain, count, context=context) + + def get_move_lines_counterparts(self, cr, uid, st_line, excluded_ids=[], additional_domain=[], count=False, context=None): """ Find the move lines that could be used to reconcile a statement line and returns the counterpart that could be created to reconcile them If count is true, only returns the count. - :param integer id: the id of the statement line + :param st_line: the browse record of the statement line :param integers list excluded_ids: ids of move lines that should not be fetched - :param string str: string to filter lines + :param string filter_str: string to filter lines :param integer offset: offset of the request :param integer limit: number of lines to fetch :param boolean count: just return the number of records :param tuples list domain: additional domain restrictions """ - if context is None: - context = {} - - rml_parser = report_sxw.rml_parse(cr, uid, 'statement_line_counterpart_widget', context=context) - st_line = self.browse(cr, uid, id, context=context) - company_currency = st_line.journal_id.company_id.currency_id - statement_currency = st_line.journal_id.currency or company_currency mv_line_pool = self.pool.get('account.move.line') - currency_obj = self.pool.get('res.currency') - domain = additional_domain + [ - ('partner_id', '=', st_line.partner_id.id), - ('reconcile_id', '=', False), - ('state','=','valid'), - '|',('account_id.type', '=', 'receivable'), - ('account_id.type', '=', 'payable'), #Let the front-end warn the user if he tries to mix payable and receivable in the same reconciliation - ] + domain = additional_domain + [('reconcile_id', '=', False),('state', '=', 'valid')] + if st_line.partner_id.id: + domain += [('partner_id', '=', st_line.partner_id.id), + '|', ('account_id.type', '=', 'receivable'), + ('account_id.type', '=', 'payable')] + else: + domain += [('account_id.reconcile', '=', True)] + #domain += [('account_id.reconcile', '=', True), ('account_id.type', '=', 'other')] if excluded_ids: domain.append(('id', 'not in', excluded_ids)) - if str: - domain += ['|', ('move_id.name', 'ilike', str), ('move_id.ref', 'ilike', str)] + line_ids = mv_line_pool.search(cr, uid, domain, order="date_maturity asc, id asc", context=context) + return self.make_counter_part_lines(cr, uid, st_line, line_ids, count=count, context=context) + + def make_counter_part_lines(self, cr, uid, st_line, line_ids, count=False, context=None): + if context is None: + context = {} + mv_line_pool = self.pool.get('account.move.line') + currency_obj = self.pool.get('res.currency') + company_currency = st_line.journal_id.company_id.currency_id + statement_currency = st_line.journal_id.currency or company_currency + rml_parser = report_sxw.rml_parse(cr, uid, 'statement_line_counterpart_widget', context=context) #partially reconciled lines can be displayed only once reconcile_partial_ids = [] - ids = mv_line_pool.search(cr, uid, domain, offset=offset, limit=limit, order="date_maturity asc, id asc", context=context) - if count: nb_lines = 0 - for line in mv_line_pool.browse(cr, uid, ids, context=context): + for line in mv_line_pool.browse(cr, uid, line_ids, context=context): if line.reconcile_partial_id and line.reconcile_partial_id.id in reconcile_partial_ids: continue nb_lines += 1 @@ -577,7 +622,7 @@ class account_bank_statement_line(osv.osv): return nb_lines else: ret = [] - for line in mv_line_pool.browse(cr, uid, ids, context=context): + for line in mv_line_pool.browse(cr, uid, line_ids, context=context): if line.reconcile_partial_id and line.reconcile_partial_id.id in reconcile_partial_ids: continue amount_currency_str = "" @@ -595,8 +640,12 @@ class account_bank_statement_line(osv.osv): 'period_name': line.period_id.name, 'journal_name': line.journal_id.name, 'amount_currency_str': amount_currency_str, + 'partner_id': line.partner_id.id, + 'partner_name': line.partner_id.name, + 'has_no_partner': not bool(st_line.partner_id.id), } - if statement_currency.id != company_currency.id and line.currency_id and line.currency_id.id == statement_currency.id: + st_line_currency = st_line.currency_id or statement_currency + if st_line.currency_id and line.currency_id and line.currency_id.id == st_line.currency_id.id: if line.amount_residual_currency < 0: ret_line['debit'] = 0 ret_line['credit'] = -line.amount_residual_currency @@ -613,21 +662,46 @@ class account_bank_statement_line(osv.osv): ret_line['credit'] = line.amount_residual if line.debit != 0 else 0 ctx = context.copy() ctx.update({'date': st_line.date}) - ret_line['debit'] = currency_obj.compute(cr, uid, statement_currency.id, company_currency.id, ret_line['debit'], context=ctx) - ret_line['credit'] = currency_obj.compute(cr, uid, statement_currency.id, company_currency.id, ret_line['credit'], context=ctx) - ret_line['debit_str'] = rml_parser.formatLang(ret_line['debit'], currency_obj=statement_currency) - ret_line['credit_str'] = rml_parser.formatLang(ret_line['credit'], currency_obj=statement_currency) + ret_line['debit'] = currency_obj.compute(cr, uid, st_line_currency.id, company_currency.id, ret_line['debit'], context=ctx) + ret_line['credit'] = currency_obj.compute(cr, uid, st_line_currency.id, company_currency.id, ret_line['credit'], context=ctx) + ret_line['debit_str'] = rml_parser.formatLang(ret_line['debit'], currency_obj=st_line_currency) + ret_line['credit_str'] = rml_parser.formatLang(ret_line['credit'], currency_obj=st_line_currency) ret.append(ret_line) if line.reconcile_partial_id: reconcile_partial_ids.append(line.reconcile_partial_id.id) return ret + def get_currency_rate_line(self, cr, uid, st_line, currency_diff, move_id, context=None): + if currency_diff < 0: + account_id = st_line.company_id.expense_currency_exchange_account_id.id + if not account_id: + raise osv.except_osv(_('Insufficient Configuration!'), _("You should configure the 'Loss Exchange Rate Account' in the accounting settings, to manage automatically the booking of accounting entries related to differences between exchange rates.")) + else: + account_id = st_line.company_id.income_currency_exchange_account_id.id + if not account_id: + raise osv.except_osv(_('Insufficient Configuration!'), _("You should configure the 'Gain Exchange Rate Account' in the accounting settings, to manage automatically the booking of accounting entries related to differences between exchange rates.")) + return { + 'move_id': move_id, + 'name': _('change') + ': ' + (st_line.name or '/'), + 'period_id': st_line.statement_id.period_id.id, + 'journal_id': st_line.journal_id.id, + 'partner_id': st_line.partner_id.id, + 'company_id': st_line.company_id.id, + 'statement_id': st_line.statement_id.id, + 'debit': currency_diff < 0 and -currency_diff or 0, + 'credit': currency_diff > 0 and currency_diff or 0, + 'date': st_line.date, + 'account_id': account_id + } + def process_reconciliation(self, cr, uid, id, mv_line_dicts, context=None): """ Creates a move line for each item of mv_line_dicts and for the statement line. Reconcile a new move line with its counterpart_move_line_id if specified. Finally, mark the statement line as reconciled by putting the newly created move id in the column journal_entry_id. :param int id: id of the bank statement line :param list of dicts mv_line_dicts: move lines to create. If counterpart_move_line_id is specified, reconcile with it """ + if context is None: + context = {} st_line = self.browse(cr, uid, id, context=context) company_currency = st_line.journal_id.company_id.currency_id statement_currency = st_line.journal_id.currency or company_currency @@ -637,7 +711,7 @@ class account_bank_statement_line(osv.osv): currency_obj = self.pool.get('res.currency') # Checks - if st_line.journal_entry_id.id != False: + if st_line.journal_entry_id.id: raise osv.except_osv(_('Error!'), _('The bank statement line was already reconciled.')) for mv_line_dict in mv_line_dicts: for field in ['debit', 'credit', 'amount_currency']: @@ -657,37 +731,50 @@ class account_bank_statement_line(osv.osv): amount = currency_obj.compute(cr, uid, st_line.statement_id.currency.id, company_currency.id, st_line.amount, context=context) bank_st_move_vals = bs_obj._prepare_bank_move_line(cr, uid, st_line, move_id, amount, company_currency.id, context=context) aml_obj.create(cr, uid, bank_st_move_vals, context=context) - st_line_currency_rate = bank_st_move_vals['amount_currency'] and statement_currency.id == company_currency.id and (bank_st_move_vals['amount_currency'] / st_line.amount) or False - st_line_currency = bank_st_move_vals['currency_id'] # Complete the dicts - st_line_statement_id = st_line.statement_id.id - st_line_journal_id = st_line.journal_id.id - st_line_partner_id = st_line.partner_id.id - st_line_company_id = st_line.company_id.id - st_line_period_id = st_line.statement_id.period_id.id + st_line_currency = st_line.currency_id or statement_currency + st_line_currency_rate = st_line.currency_id and statement_currency.id == company_currency.id and (st_line.amount_currency / st_line.amount) or False + to_create = [] for mv_line_dict in mv_line_dicts: mv_line_dict['ref'] = move_name mv_line_dict['move_id'] = move_id - mv_line_dict['period_id'] = st_line_period_id - mv_line_dict['journal_id'] = st_line_journal_id - mv_line_dict['partner_id'] = st_line_partner_id - mv_line_dict['company_id'] = st_line_company_id - mv_line_dict['statement_id'] = st_line_statement_id + mv_line_dict['period_id'] = st_line.statement_id.period_id.id + mv_line_dict['journal_id'] = st_line.journal_id.id + mv_line_dict['company_id'] = st_line.company_id.id + mv_line_dict['statement_id'] = st_line.statement_id.id if mv_line_dict.get('counterpart_move_line_id'): mv_line = aml_obj.browse(cr, uid, mv_line_dict['counterpart_move_line_id'], context=context) mv_line_dict['account_id'] = mv_line.account_id.id - if statement_currency.id != company_currency.id: + if st_line_currency.id != company_currency.id: mv_line_dict['amount_currency'] = mv_line_dict['debit'] - mv_line_dict['credit'] - mv_line_dict['currency_id'] = statement_currency.id - mv_line_dict['debit'] = currency_obj.compute(cr, uid, statement_currency.id, company_currency.id, mv_line_dict['debit']) - mv_line_dict['credit'] = currency_obj.compute(cr, uid, statement_currency.id, company_currency.id, mv_line_dict['credit']) - elif st_line_currency and st_line_currency_rate: - mv_line_dict['amount_currency'] = self.pool.get('res.currency').round(cr, uid, st_line.currency_id, (mv_line_dict['debit'] - mv_line_dict['credit']) * st_line_currency_rate) - mv_line_dict['currency_id'] = st_line_currency - + mv_line_dict['currency_id'] = st_line_currency.id + if st_line.currency_id and statement_currency.id == company_currency.id and st_line_currency_rate: + debit_at_current_rate = self.pool.get('res.currency').round(cr, uid, company_currency, mv_line_dict['debit'] / st_line_currency_rate) + credit_at_current_rate = self.pool.get('res.currency').round(cr, uid, company_currency, mv_line_dict['credit'] / st_line_currency_rate) + else: + debit_at_current_rate = currency_obj.compute(cr, uid, st_line_currency.id, company_currency.id, mv_line_dict['debit'], context=context) + credit_at_current_rate = currency_obj.compute(cr, uid, st_line_currency.id, company_currency.id, mv_line_dict['credit'], context=context) + if mv_line_dict.get('counterpart_move_line_id'): + #post an account line that use the same currency rate than the counterpart (to balance the account) and post the difference in another line + ctx = context.copy() + ctx['date'] = mv_line.date + debit_at_old_rate = currency_obj.compute(cr, uid, st_line_currency.id, company_currency.id, mv_line_dict['debit'], context=ctx) + credit_at_old_rate = currency_obj.compute(cr, uid, st_line_currency.id, company_currency.id, mv_line_dict['credit'], context=ctx) + mv_line_dict['credit'] = credit_at_old_rate + mv_line_dict['debit'] = debit_at_old_rate + if debit_at_old_rate - debit_at_current_rate: + currency_diff = debit_at_current_rate - debit_at_old_rate + to_create.append(self.get_currency_rate_line(cr, uid, st_line, currency_diff, move_id, context=context)) + if credit_at_old_rate - credit_at_current_rate: + currency_diff = credit_at_current_rate - credit_at_old_rate + to_create.append(self.get_currency_rate_line(cr, uid, st_line, currency_diff, move_id, context=context)) + else: + mv_line_dict['debit'] = debit_at_current_rate + mv_line_dict['credit'] = credit_at_current_rate + to_create.append(mv_line_dict) # Create move lines move_line_pairs_to_reconcile = [] - for mv_line_dict in mv_line_dicts: + for mv_line_dict in to_create: counterpart_move_line_id = None # NB : this attribute is irrelevant for aml_obj.create() and needs to be removed from the dict if mv_line_dict.get('counterpart_move_line_id'): counterpart_move_line_id = mv_line_dict['counterpart_move_line_id'] @@ -723,7 +810,7 @@ class account_bank_statement_line(osv.osv): 'bank_account_id': fields.many2one('res.partner.bank','Bank Account'), 'statement_id': fields.many2one('account.bank.statement', 'Statement', select=True, required=True, ondelete='cascade'), 'journal_id': fields.related('statement_id', 'journal_id', type='many2one', relation='account.journal', string='Journal', store=True, readonly=True), - 'ref': fields.char('Reference', size=32), + 'ref': fields.char('Structured Communication'), 'note': fields.text('Notes'), 'sequence': fields.integer('Sequence', select=True, help="Gives the sequence order when displaying a list of bank statement lines."), 'company_id': fields.related('statement_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True), diff --git a/addons/account/account_financial_report.py b/addons/account/account_financial_report.py index 0c2e5845b89..9ca53718fdc 100644 --- a/addons/account/account_financial_report.py +++ b/addons/account/account_financial_report.py @@ -97,7 +97,7 @@ class account_financial_report(osv.osv): return res _columns = { - 'name': fields.char('Report Name', size=128, required=True, translate=True), + 'name': fields.char('Report Name', required=True, translate=True), 'parent_id': fields.many2one('account.financial.report', 'Parent'), 'children_ids': fields.one2many('account.financial.report', 'parent_id', 'Account Report'), 'sequence': fields.integer('Sequence'), diff --git a/addons/account/account_installer.xml b/addons/account/account_installer.xml index 8d1b25b299f..4e3ea7ee28e 100644 --- a/addons/account/account_installer.xml +++ b/addons/account/account_installer.xml @@ -5,7 +5,7 @@ account.installer -
+ Accounting Application Configuration