diff --git a/addons/account/account.py b/addons/account/account.py
index 6d6abd9226d..ee0da138daf 100644
--- a/addons/account/account.py
+++ b/addons/account/account.py
@@ -299,8 +299,84 @@ class AccountJournal(models.Model):
seq['company_id'] = vals['company_id']
return self.env['ir.sequence'].create(seq)
+ @api.model
+ def _prepare_bank_account(self, name, company, currency_id):
+ '''
+ This function prepares the value to use for the creation of the default debit and credit accounts of a
+ bank journal (created through the wizard of generating COA from templates for example).
+
+ :param name: name of the bank account
+ :param company: company for which the wizard is running
+ :param currency_id: ID of the currency in wich is the bank account
+ :return: mapping of field names and values
+ :rtype: dict
+ '''
+
+ # Seek the next available number for the account code
+ code_digits = company.accounts_code_digits or 0
+ bank_account_code_char = company.bank_account_code_char or ''
+ for num in xrange(1, 100):
+ new_code = str(bank_account_code_char.ljust(code_digits - 1, '0')) + str(num)
+ rec = self.env['account.account'].search([('code', '=', new_code), ('company_id', '=', company.id)], limit=1)
+ if not rec:
+ break
+ else:
+ raise UserError(_('Cannot generate an unused account code.'))
+
+ liquidity_type = self.env.ref('account.data_account_type_liquidity')
+ return {
+ 'name': name,
+ 'currency_id': currency_id or False,
+ 'code': new_code,
+ 'user_type': liquidity_type and liquidity_type.id or False,
+ 'company_id': company.id,
+ }
+
+ @api.model
+ def _prepare_bank_journal(self, company, line):
+ '''
+ This function prepares the value to use for the creation of a bank journal created through the wizard of
+ generating COA from templates.
+
+ :param company: company for which the wizard is running
+ :param line: dictionary containing the values encoded by the user related to his bank account with keys
+ - acc_name (char): name of the bank account
+ - account_type (char): kind of liquidity journal to create. Either 'bank' or 'cash'
+ - currency_id (int): id of the currency related to this account if its different than the company currency (False otherwise)
+ :return: mapping of field names and values
+ :rtype: dict
+ '''
+ # we need to loop to find next number for journal code
+ for num in xrange(1, 100):
+ # journal_code has a maximal size of 5, hence we can enforce the boundary num < 100
+ journal_code = line.get('account_type', 'bank') == 'cash' and 'CSH' or 'BNK'
+ journal_code += str(num)
+ journal = self.env['account.journal'].search([('code', '=', journal_code), ('company_id', '=', company.id)], limit=1)
+ if not journal:
+ break
+ else:
+ raise UserError(_('Cannot generate an unused journal code.'))
+
+ return {
+ 'name': line['acc_name'],
+ 'code': journal_code,
+ 'type': line.get('account_type', 'bank'),
+ 'company_id': company.id,
+ 'analytic_journal_id': False,
+ 'currency_id': line.get('currency_id', False),
+ 'show_on_dashboard': True,
+ }
+
@api.model
def create(self, vals):
+ if vals.get('type') in ('bank', 'cash'):
+ default_account = vals.get('default_debit_account_id') or vals.get('default_credit_account_id')
+ if not default_account:
+ company = self.env['res.company'].browse(vals['company_id'])
+ account_vals = self._prepare_bank_account(vals.get('name'), company, vals.get('currency_id'))
+ default_account = self.env['account.account'].create(account_vals)
+ vals['default_debit_account_id'] = default_account.id
+ vals['default_credit_account_id'] = default_account.id
# We just need to create the relevant sequences according to the chosen options
if not vals.get('sequence_id'):
vals.update({'sequence_id': self.sudo()._create_sequence(vals).id})
@@ -555,4 +631,4 @@ class AccountOperationTemplate(models.Model):
@api.onchange('name')
def onchange_name(self):
- self.label = self.name
\ No newline at end of file
+ self.label = self.name
diff --git a/addons/account/account_bank.py b/addons/account/account_bank.py
index e93847f4465..96b69d81bab 100644
--- a/addons/account/account_bank.py
+++ b/addons/account/account_bank.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-from openerp import api, fields, models, _
+from openerp import api, fields, models
class Bank(models.Model):
@@ -8,8 +8,6 @@ class Bank(models.Model):
journal_id = fields.Many2one('account.journal', string='Account Journal',
help="This journal will be created automatically for this bank account when you save the record")
- currency_id = fields.Many2one('res.currency', related='journal_id.currency_id', string='Currency',
- readonly=True, help="Currency of the related account journal.")
@api.model
def create(self, data):
@@ -26,70 +24,21 @@ class Bank(models.Model):
@api.model
def _prepare_name(self, bank):
"Return the name to use when creating a bank journal"
- return (bank.bank_name or '') + ' ' + (bank.acc_number or '')
-
- @api.model
- def _prepare_name_get(self, bank_dicts):
- """Add ability to have %(currency_name)s in the format_layout of res.partner.bank.type"""
- currency_ids = list(set(data['currency_id'][0] for data in bank_dicts if data.get('currency_id')))
- currencies = self.env['res.currency'].browse(currency_ids)
- currency_name = dict((currency.id, currency.name) for currency in currencies)
-
- for data in bank_dicts:
- data['currency_name'] = data.get('currency_id') and currency_name[data['currency_id'][0]] or ''
- return super(Bank, self)._prepare_name_get(bank_dicts)
+ name = bank.bank_name + ' ' if bank.bank_name else ''
+ name += bank.acc_number
+ return name
@api.multi
def post_write(self):
- AccountObj = self.env['account.account']
JournalObj = self.env['account.journal']
-
for bank in self:
# Create a journal for the bank account if it belongs to the company.
- if bank.partner_id in self.env.user.company_ids.mapped('partner_id') and not bank.journal_id:
- # TODO: this code is duplicated; refactor using _prepare_bank_account() in chart_template.py
- # Find the code and parent of the bank account to create
- dig = 6
- current_num = 1
- account = AccountObj.search([('internal_type', '=', 'liquidity'), ('company_id', '=', bank.company_id.id)], limit=1)
- # No liquidity account exists, no template available
- if not account: continue
-
- ref_acc_bank = account
- while True:
- new_code = str(ref_acc_bank.code.ljust(dig-len(str(current_num)), '0')) + str(current_num)
- account = AccountObj.search([('code', '=', new_code), ('company_id', '=', bank.company_id.id)], limit=1)
- if not account:
- break
- current_num += 1
- name = self._prepare_name(bank)
- acc = {
- 'name': name,
- 'code': new_code,
- 'user_type': ref_acc_bank.user_type.id,
- 'reconcile': False,
- 'company_id': bank.company_id.id,
- }
- acc_bank = AccountObj.create(acc)
-
- new_code = 1
- while True:
- code = _('BNK')+str(new_code)
- account = JournalObj.search([('code', '=', code)], limit=1)
- if not account:
- break
- new_code += 1
-
- #create the bank journal
- vals_journal = {
- 'name': name,
- 'code': code,
- 'type': 'bank',
- 'company_id': bank.company_id.id,
- 'analytic_journal_id': False,
- 'default_credit_account_id': acc_bank.id,
- 'default_debit_account_id': acc_bank.id,
- }
-
- bank.journal_id = JournalObj.create(vals_journal)
- return True
+ if bank.company_id and not bank.journal_id:
+ journal_vals = JournalObj._prepare_bank_journal(bank.company_id, {'acc_name': self._prepare_name(bank), 'currency_id': bank.currency_id.id, 'account_type': 'bank'})
+ journal = JournalObj.create(journal_vals)
+ missing_vals = {'journal_id': journal.id}
+ if not bank.partner_id:
+ missing_vals['partner_id'] = bank.company_id.partner_id.id
+ if not bank.owner_name:
+ missing_vals['owner_name'] = bank.company_id.partner_id.name
+ bank.write(missing_vals)
diff --git a/addons/account/account_payment.py b/addons/account/account_payment.py
index 7201e3a9bce..10b9faa182d 100644
--- a/addons/account/account_payment.py
+++ b/addons/account/account_payment.py
@@ -32,6 +32,8 @@ class account_abstract_payment(models.AbstractModel):
payment_type = fields.Selection([('outbound', 'Send Money'), ('inbound', 'Receive Money')], default='outbound', required=True)
payment_method = fields.Many2one('account.payment.method', string='Payment Method', required=True)
+ payment_method_code = fields.Char(related='payment_method.code',
+ help="Technical field used to adapt the interface to the payment method selected.")
partner_type = fields.Selection([('customer', 'Customer'), ('supplier', 'Supplier')], default='supplier')
partner_id = fields.Many2one('res.partner', string='Partner')
@@ -52,18 +54,6 @@ class account_abstract_payment(models.AbstractModel):
if not self.amount > 0.0:
raise ValidationError('The payment amount must be strictly positive.')
- @api.one
- @api.constrains('communication')
- def _check_communication(self):
- """ This method is to be overwritten by payment type modules. The method body would look like :
- if self.payment_method == self.env.ref('my_module.payment_method'):
- try:
- self.communication.decode('ascii')
- except UnicodeDecodeError:
- raise ValidationError(_t("The communication cannot contain any special character"))
- """
- pass
-
@api.one
@api.depends('payment_type', 'journal_id')
def _compute_hide_payment_method(self):
@@ -272,6 +262,21 @@ class account_payment(models.Model):
def _get_invoices(self):
return self.invoice_ids
+ @api.model
+ def create(self, vals):
+ self._check_communication(vals['payment_method'], vals.get('communication', ''))
+ return super(account_payment, self).create(vals)
+
+ def _check_communication(self, payment_method_id, communication):
+ """ This method is to be overwritten by payment type modules. The method body would look like :
+ if payment_method_id == self.env.ref('my_module.payment_method').id:
+ try:
+ communication.decode('ascii')
+ except UnicodeError:
+ raise ValidationError(_("The communication cannot contain any special character"))
+ """
+ pass
+
@api.multi
def button_journal_entries(self):
return {
diff --git a/addons/account/chart_template.py b/addons/account/chart_template.py
index 90f5fee6e14..42495463e52 100644
--- a/addons/account/chart_template.py
+++ b/addons/account/chart_template.py
@@ -50,55 +50,6 @@ class AccountAccountTemplate(models.Model):
return res
-class AccountAddTmplWizard(models.TransientModel):
- """Add one more account from the template.
-
- With the 'nocreate' option, some accounts may not be created. Use this to add them later."""
- _name = 'account.addtmpl.wizard'
-
- @api.model
- def _get_def_cparent(self):
- context = self._context or {}
- tmpl_obj = self.env['account.account.template']
-
- tids = tmpl_obj.read([context['tmpl_ids']], ['parent_id'])
- if not tids or not tids[0]['parent_id']:
- return False
- ptids = tmpl_obj.read([tids[0]['parent_id'][0]], ['code'])
- account = False
- if not ptids or not ptids[0]['code']:
- raise UserError(_('There is no parent code for the template account.'))
- account = self.env['account.account'].search([('code', '=', ptids[0]['code'])], limit=1)
- return account
-
- cparent_id = fields.Many2one('account.account', string='Parent target', default=lambda self: self._get_def_cparent(),
- help="Creates an account with the selected template under this existing parent.", required=True, domain=[('deprecated', '=', False)])
-
- @api.multi
- def action_create(self):
- context = self._context or {}
- AccountObj = self.env['account.account']
- data = self.read()[0]
- company_id = AccountObj.read([data['cparent_id'][0]], ['company_id'])[0]['company_id'][0]
- account_template = self.env['account.account.template'].browse(context['tmpl_ids'])
- vals = {
- 'name': account_template.name,
- 'currency_id': account_template.currency_id and account_template.currency_id.id or False,
- 'code': account_template.code,
- 'user_type': account_template.user_type and account_template.user_type.id or False,
- 'reconcile': account_template.reconcile,
- 'note': account_template.note,
- 'parent_id': data['cparent_id'][0],
- 'company_id': company_id,
- }
- AccountObj.create(vals)
- return {'type': 'state', 'state': 'end'}
-
- @api.multi
- def action_cancel(self):
- return {'type': 'state', 'state': 'end'}
-
-
class AccountChartTemplate(models.Model):
_name = "account.chart.template"
_description = "Templates for Account Chart"
@@ -776,74 +727,6 @@ class WizardMultiChartsAccounts(models.TransientModel):
self._create_bank_journals_from_o2m(company, acc_template_ref)
return {}
- @api.model
- def _prepare_bank_journal(self, company, line, default_account_id):
- '''
- This function prepares the value to use for the creation of a bank journal created through the wizard of
- generating COA from templates.
-
- :param line: dictionary containing the values encoded by the user related to his bank account
- :param default_account_id: id of the default debit.credit account created before for this journal.
- :param company_id: id of the company for which the wizard is running
- :return: mapping of field names and values
- :rtype: dict
- '''
- # we need to loop to find next number for journal code
- for num in xrange(1, 100):
- # journal_code has a maximal size of 5, hence we can enforce the boundary num < 100
- journal_code = line['account_type'] == 'cash' and 'CSH' or 'BNK'
- journal_code += str(num)
- journal = self.env['account.journal'].search([('code', '=', journal_code), ('company_id', '=', company.id)], limit=1)
- if not journal:
- break
- else:
- raise UserError(_('Cannot generate an unused journal code.'))
-
- return {
- 'name': line['acc_name'],
- 'code': journal_code,
- 'type': line['account_type'],
- 'company_id': company.id,
- 'analytic_journal_id': False,
- 'currency_id': line['currency_id'] or False,
- 'default_credit_account_id': default_account_id,
- 'default_debit_account_id': default_account_id,
- 'show_on_dashboard': True,
- }
-
- @api.model
- def _prepare_bank_account(self, company, line):
- '''
- This function prepares the value to use for the creation of the default debit and credit accounts of a
- bank journal created through the wizard of generating COA from templates.
-
- :param company: company for which the wizard is running
- :param line: dictionary containing the values encoded by the user related to his bank account
- :return: mapping of field names and values
- :rtype: dict
- '''
-
- # Seek the next available number for the account code
- code_digits = company.accounts_code_digits or 0
- bank_account_code_char = company.bank_account_code_char or ''
- for num in xrange(1, 100):
- new_code = str(bank_account_code_char.ljust(code_digits - 1, '0')) + str(num)
- rec = self.env['account.account'].search([('code', '=', new_code), ('company_id', '=', company.id)], limit=1)
- if not rec:
- break
- else:
- raise UserError(_('Cannot generate an unused account code.'))
-
- liquidity_type = self.env.ref('account.data_account_type_liquidity')
-
- return {
- 'name': line['acc_name'],
- 'currency_id': line['currency_id'] or False,
- 'code': new_code,
- 'user_type': liquidity_type and liquidity_type.id or False,
- 'company_id': company.id,
- }
-
@api.multi
def _create_bank_journals_from_o2m(self, company, acc_template_ref):
'''
@@ -872,13 +755,21 @@ class WizardMultiChartsAccounts(models.TransientModel):
company.write({'bank_account_code_char': ref_acc_bank})
for line in journal_data:
- # Create the default debit/credit accounts for this bank journal
- vals = self._prepare_bank_account(company, line)
- default_account = self.env['account.account'].create(vals)
-
- #create the bank journal
- vals_journal = self._prepare_bank_journal(company, line, default_account.id)
- self.env['account.journal'].create(vals_journal)
+ if line['account_type'] == 'bank':
+ #create the bank account that will trigger the journal and account.account creation
+ res_partner_bank_vals = {
+ 'acc_number': line['acc_name'],
+ 'currency_id': line['currency_id'],
+ 'company_id': company.id,
+ 'owner_name': company.partner_id.name,
+ 'partner_id': company.partner_id.id,
+ 'footer': True
+ }
+ self.env['res.partner.bank'].create(res_partner_bank_vals)
+ else:
+ #create the cash journal that will trigger the account.account creation
+ vals_journal = self.env['account.journal']._prepare_bank_journal(company, line)
+ self.env['account.journal'].create(vals_journal)
return True
@@ -889,4 +780,4 @@ class AccountBankAccountsWizard(models.TransientModel):
bank_account_id = fields.Many2one('wizard.multi.charts.accounts', string='Bank Account', required=True, ondelete='cascade')
currency_id = fields.Many2one('res.currency', string='Secondary Currency',
help="Forces all moves for this account to have this secondary currency.")
- account_type = fields.Selection([('cash', 'Cash'), ('bank', 'Bank')])
\ No newline at end of file
+ account_type = fields.Selection([('cash', 'Cash'), ('bank', 'Bank')])
diff --git a/addons/account/company.py b/addons/account/company.py
index c78ad5f34bb..2ea1c6a7c00 100644
--- a/addons/account/company.py
+++ b/addons/account/company.py
@@ -32,22 +32,6 @@ class ResCompany(models.Model):
string="Loss Exchange Rate Account", domain="[('internal_type', '=', 'other'), ('deprecated', '=', False), ('company_id', '=', id)]")
anglo_saxon_accounting = fields.Boolean(string="Use anglo-saxon accounting")
- @api.multi
- def _create_bank_account_and_journal(self, account_number, currency_id=None):
- """ Create a journal and its account """
- MultiChartsAccounts = self.env['wizard.multi.charts.accounts']
-
- if currency_id is None:
- currency_id = self.currency_id.id
-
- vals_account = {'currency_id': currency_id, 'acc_name': account_number, 'account_type': 'bank'}
- vals_account = MultiChartsAccounts._prepare_bank_account(self, vals_account)
- account_id = self.env['account.account'].create(vals_account).id
-
- vals_journal = {'currency_id': currency_id, 'acc_name': _('Bank') + ' ' + account_number, 'account_type': 'bank'}
- vals_journal = MultiChartsAccounts._prepare_bank_journal(self, vals_journal, account_id)
- return self.env['account.journal'].create(vals_journal).id
-
@api.multi
def compute_fiscalyear_dates(self, date):
""" Computes the start and end dates of the fiscalyear where the given 'date' belongs to
diff --git a/addons/account/tests/test_payment.py b/addons/account/tests/test_payment.py
index 74c1e7dd95e..00ec04c25e1 100644
--- a/addons/account/tests/test_payment.py
+++ b/addons/account/tests/test_payment.py
@@ -26,11 +26,11 @@ class TestPayment(AccountingTestCase):
self.account_payable = self.env['account.account'].search([('user_type', '=', self.env.ref('account.data_account_type_payable').id)])[0]
self.account_revenue = self.env['account.account'].search([('user_type', '=', self.env.ref('account.data_account_type_revenue').id)])[0]
- self.bank_euro = self.env['res.partner.bank'].create({'acc_number': '0123456789', 'bank_name': 'Test Bank'})
+ self.bank_euro = self.env['res.partner.bank'].create({'acc_number': '0123456789', 'bank_name': 'Test Bank', 'company_id': self.env.user.company_id.id})
self.bank_journal_euro = self.bank_euro.journal_id
self.account_eur = self.bank_journal_euro.default_debit_account_id
- self.bank_usd = self.env['res.partner.bank'].create({'acc_number': '0123456789', 'bank_name': 'Test Bank USD'})
+ self.bank_usd = self.env['res.partner.bank'].create({'acc_number': '0123456789', 'bank_name': 'Test Bank USD', 'company_id': self.env.user.company_id.id})
self.bank_journal_usd = self.bank_usd.journal_id
self.account_usd = self.bank_journal_usd.default_debit_account_id
self.account_usd.write({'currency_id': self.currency_usd_id})
@@ -40,7 +40,6 @@ class TestPayment(AccountingTestCase):
self.diff_income_account = self.env['res.users'].browse(self.env.uid).company_id.income_currency_exchange_account_id
self.diff_expense_account = self.env['res.users'].browse(self.env.uid).company_id.expense_currency_exchange_account_id
-
def create_invoice(self, amount=100, type='out_invoice', currency_id=None):
""" Returns an open invoice """
invoice = self.invoice_model.create({
diff --git a/addons/account/tests/test_reconciliation.py b/addons/account/tests/test_reconciliation.py
index 8442334c035..056232e701d 100644
--- a/addons/account/tests/test_reconciliation.py
+++ b/addons/account/tests/test_reconciliation.py
@@ -25,12 +25,12 @@ class TestReconciliation(AccountingTestCase):
self.account_rsa = self.env['account.account'].search([('user_type', '=', self.env.ref('account.data_account_type_payable').id)])[0]
self.product = self.env.ref("product.product_product_4")
- self.bank_euro = self.env['res.partner.bank'].create({'acc_number': 'Reconciliation test', 'bank_name': 'Test Bank'})
+ self.bank_euro = self.env['res.partner.bank'].create({'acc_number': 'Reconciliation test', 'bank_name': 'Test Bank', 'company_id': self.env.user.company_id.id})
self.bank_journal_euro = self.bank_euro.journal_id
self.account_euro = self.bank_journal_euro.default_debit_account_id
self.bank_usd = self.env['res.partner.bank'].create({'acc_number': 'Reconciliation test USD',
- 'bank_name': 'Test Bank USD'})
+ 'bank_name': 'Test Bank USD', 'company_id': self.env.user.company_id.id})
self.bank_journal_usd = self.bank_usd.journal_id
self.account_usd = self.bank_journal_usd.default_debit_account_id
self.account_usd.write({'currency_id': self.currency_usd_id})
diff --git a/addons/account/views/account_payment_view.xml b/addons/account/views/account_payment_view.xml
index cd14deef6b7..20b1d81ae1e 100644
--- a/addons/account/views/account_payment_view.xml
+++ b/addons/account/views/account_payment_view.xml
@@ -82,8 +82,9 @@