[IMP] account: Misc. improvements

Miscellaneous changes aiming to improve the user experience in the accounting module,
mainly in the journal model and its form view.

Also aim to improve the bank account creation wizard.

Task ID: #2250349

closes odoo/odoo#54494

Related: odoo/upgrade#1546
Related: odoo/enterprise#11862
Signed-off-by: oco-odoo <oco-odoo@users.noreply.github.com>
This commit is contained in:
Nicolas (vin)
2020-08-11 12:41:13 +00:00
parent 7386a2b1ac
commit 41f119d532
33 changed files with 270 additions and 236 deletions
+3 -6
View File
@@ -123,8 +123,7 @@ class AccountAccount(models.Model):
self.env['account.account'].flush(['currency_id']) self.env['account.account'].flush(['currency_id'])
self.env['account.journal'].flush([ self.env['account.journal'].flush([
'currency_id', 'currency_id',
'default_debit_account_id', 'default_account_id',
'default_credit_account_id',
'payment_debit_account_id', 'payment_debit_account_id',
'payment_credit_account_id', 'payment_credit_account_id',
'suspense_account_id', 'suspense_account_id',
@@ -134,9 +133,7 @@ class AccountAccount(models.Model):
FROM account_account account FROM account_account account
JOIN res_company company ON company.id = account.company_id JOIN res_company company ON company.id = account.company_id
JOIN account_journal journal ON JOIN account_journal journal ON
journal.default_debit_account_id = account.id journal.default_account_id = account.id
OR
journal.default_credit_account_id = account.id
WHERE account.id IN %s WHERE account.id IN %s
AND journal.type IN ('bank', 'cash') AND journal.type IN ('bank', 'cash')
AND journal.currency_id IS NOT NULL AND journal.currency_id IS NOT NULL
@@ -179,7 +176,7 @@ class AccountAccount(models.Model):
SELECT account.id SELECT account.id
FROM account_account account FROM account_account account
JOIN account_account_type acc_type ON account.user_type_id = acc_type.id JOIN account_account_type acc_type ON account.user_type_id = acc_type.id
JOIN account_journal journal ON journal.default_credit_account_id = account.id OR journal.default_debit_account_id = account.id JOIN account_journal journal ON journal.default_account_id = account.id
WHERE account.id IN %s WHERE account.id IN %s
AND acc_type.type IN ('receivable', 'payable') AND acc_type.type IN ('receivable', 'payable')
AND journal.type IN ('sale', 'purchase') AND journal.type IN ('sale', 'purchase')
@@ -538,7 +538,7 @@ class AccountBankStatementLine(models.Model):
other_lines = self.env['account.move.line'] other_lines = self.env['account.move.line']
for line in self.move_id.line_ids: for line in self.move_id.line_ids:
if line.account_id in (self.journal_id.default_debit_account_id, self.journal_id.default_credit_account_id): if line.account_id == self.journal_id.default_account_id:
liquidity_lines += line liquidity_lines += line
elif line.account_id == self.journal_id.suspense_account_id: elif line.account_id == self.journal_id.suspense_account_id:
suspense_lines += line suspense_lines += line
@@ -590,7 +590,7 @@ class AccountBankStatementLine(models.Model):
'move_id': self.move_id.id, 'move_id': self.move_id.id,
'partner_id': self.partner_id.id, 'partner_id': self.partner_id.id,
'currency_id': currency_id, 'currency_id': currency_id,
'account_id': journal.default_debit_account_id.id if balance >= 0 else journal.default_credit_account_id.id, 'account_id': journal.default_account_id.id,
'debit': balance > 0 and balance or 0.0, 'debit': balance > 0 and balance or 0.0,
'credit': balance < 0 and -balance or 0.0, 'credit': balance < 0 and -balance or 0.0,
'amount_currency': amount_currency, 'amount_currency': amount_currency,
+77 -63
View File
@@ -57,33 +57,39 @@ class AccountJournal(models.Model):
account_control_ids = fields.Many2many('account.account', 'journal_account_control_rel', 'journal_id', 'account_id', string='Accounts Allowed', account_control_ids = fields.Many2many('account.account', 'journal_account_control_rel', 'journal_id', 'account_id', string='Accounts Allowed',
check_company=True, check_company=True,
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]") domain="[('deprecated', '=', False), ('company_id', '=', company_id)]")
default_credit_account_id = fields.Many2one('account.account', string='Default Credit Account', copy=False, default_account_type = fields.Many2one('account.account.type', compute="_compute_default_account_type")
domain=[('deprecated', '=', False)], help="It acts as a default account for credit amount", default_account_id = fields.Many2one(
check_company=True, comodel_name='account.account', check_company=True, copy=False, ondelete='restrict',
ondelete='restrict') string='Default Account', help="It acts as a default account",
default_debit_account_id = fields.Many2one('account.account', string='Default Debit Account', copy=False, domain="[('deprecated', '=', False), ('company_id', '=', company_id),"
check_company=True, "('user_type_id', '=', default_account_type),"
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]", help="It acts as a default account for debit amount", ondelete='restrict') "('user_type_id.type', 'not in', ('receivable', 'payable'))]")
payment_debit_account_id = fields.Many2one('account.account', string='Outstanding Receipts Account', copy=False, payment_debit_account_id = fields.Many2one(
ondelete='restrict', comodel_name='account.account', check_company=True, copy=False, ondelete='restrict',
domain=[('deprecated', '=', False)],
help="Incoming payments entries triggered by invoices/refunds will be posted on the Outstanding Receipts Account " help="Incoming payments entries triggered by invoices/refunds will be posted on the Outstanding Receipts Account "
"and displayed as blue lines in the bank reconciliation widget. During the reconciliation process, concerned " "and displayed as blue lines in the bank reconciliation widget. During the reconciliation process, concerned "
"transactions will be reconciled with entries on the Outstanding Receipts Account instead of the " "transactions will be reconciled with entries on the Outstanding Receipts Account instead of the "
"receivable account.") "receivable account.", string='Outstanding Receipts Account',
payment_credit_account_id = fields.Many2one('account.account', string='Outstanding Payments Account', copy=False, domain=lambda self: "[('deprecated', '=', False), ('company_id', '=', company_id), \
ondelete='restrict', ('user_type_id.type', 'not in', ('receivable', 'payable')), \
domain=[('deprecated', '=', False)], ('user_type_id', '=', %s)]" % self.env.ref('account.data_account_type_current_assets').id)
payment_credit_account_id = fields.Many2one(
comodel_name='account.account', check_company=True, copy=False, ondelete='restrict',
help="Outgoing payments entries triggered by bills/credit notes will be posted on the Outstanding Payments Account " help="Outgoing payments entries triggered by bills/credit notes will be posted on the Outstanding Payments Account "
"and displayed as blue lines in the bank reconciliation widget. During the reconciliation process, concerned " "and displayed as blue lines in the bank reconciliation widget. During the reconciliation process, concerned "
"transactions will be reconciled with entries on the Outstanding Payments Account instead of the " "transactions will be reconciled with entries on the Outstanding Payments Account instead of the "
"payable account.") "payable account.", string='Outstanding Payments Account',
suspense_account_id = fields.Many2one('account.account', string='Bank Suspense Account', domain=lambda self: "[('deprecated', '=', False), ('company_id', '=', company_id), \
ondelete='restrict', readonly=False, store=True, ('user_type_id.type', 'not in', ('receivable', 'payable')), \
('user_type_id', '=', %s)]" % self.env.ref('account.data_account_type_current_assets').id)
suspense_account_id = fields.Many2one(
comodel_name='account.account', check_company=True, ondelete='restrict', readonly=False, store=True,
compute='_compute_suspense_account_id', compute='_compute_suspense_account_id',
domain=[('deprecated', '=', False), ('reconcile', '=', True)],
help="Bank statements transactions will be posted on the suspense account until the final reconciliation " help="Bank statements transactions will be posted on the suspense account until the final reconciliation "
"allowing finding the right account.") "allowing finding the right account.", string='Suspense Account',
domain=lambda self: "[('deprecated', '=', False), ('company_id', '=', company_id), \
('user_type_id.type', 'not in', ('receivable', 'payable')), \
('user_type_id', '=', %s)]" % self.env.ref('account.data_account_type_current_liabilities').id)
restrict_mode_hash_table = fields.Boolean(string="Lock Posted Entries with Hash", restrict_mode_hash_table = fields.Boolean(string="Lock Posted Entries with Hash",
help="If ticked, the accounting entry or invoice receives a hash as soon as it is posted and cannot be modified anymore.") help="If ticked, the accounting entry or invoice receives a hash as soon as it is posted and cannot be modified anymore.")
sequence = fields.Integer(help='Used to order Journals in the dashboard view', default=10) sequence = fields.Integer(help='Used to order Journals in the dashboard view', default=10)
@@ -104,27 +110,32 @@ class AccountJournal(models.Model):
"e.g: ^(?P<prefix1>.*?)(?P<year>\d{4})(?P<prefix2>\D*?)(?P<month>\d{2})(?P<prefix3>\D+?)(?P<seq>\d+)(?P<suffix>\D*?)$") "e.g: ^(?P<prefix1>.*?)(?P<year>\d{4})(?P<prefix2>\D*?)(?P<month>\d{2})(?P<prefix3>\D+?)(?P<seq>\d+)(?P<suffix>\D*?)$")
inbound_payment_method_ids = fields.Many2many('account.payment.method', 'account_journal_inbound_payment_method_rel', 'journal_id', 'inbound_payment_method', inbound_payment_method_ids = fields.Many2many('account.payment.method', 'account_journal_inbound_payment_method_rel', 'journal_id', 'inbound_payment_method',
domain=[('payment_type', '=', 'inbound')], string='For Incoming Payments', default=lambda self: self._default_inbound_payment_methods(), domain=[('payment_type', '=', 'inbound')], string='Inbound Payment Methods', default=lambda self: self._default_inbound_payment_methods(),
help="Manual: Get paid by cash, check or any other method outside of Odoo.\n"\ help="Manual: Get paid by cash, check or any other method outside of Odoo.\n"\
"Electronic: Get paid automatically through a payment acquirer by requesting a transaction on a card saved by the customer when buying or subscribing online (payment token).\n"\ "Electronic: Get paid automatically through a payment acquirer by requesting a transaction on a card saved by the customer when buying or subscribing online (payment token).\n"\
"Batch Deposit: Encase several customer checks at once by generating a batch deposit to submit to your bank. When encoding the bank statement in Odoo,you are suggested to reconcile the transaction with the batch deposit. Enable this option from the settings.") "Batch Deposit: Encase several customer checks at once by generating a batch deposit to submit to your bank. When encoding the bank statement in Odoo,you are suggested to reconcile the transaction with the batch deposit. Enable this option from the settings.")
outbound_payment_method_ids = fields.Many2many('account.payment.method', 'account_journal_outbound_payment_method_rel', 'journal_id', 'outbound_payment_method', outbound_payment_method_ids = fields.Many2many('account.payment.method', 'account_journal_outbound_payment_method_rel', 'journal_id', 'outbound_payment_method',
domain=[('payment_type', '=', 'outbound')], string='For Outgoing Payments', default=lambda self: self._default_outbound_payment_methods(), domain=[('payment_type', '=', 'outbound')], string='Outbound Payment Methods', default=lambda self: self._default_outbound_payment_methods(),
help="Manual:Pay bill by cash or any other method outside of Odoo.\n"\ help="Manual:Pay bill by cash or any other method outside of Odoo.\n"\
"Check:Pay bill by check and print it from Odoo.\n"\ "Check:Pay bill by check and print it from Odoo.\n"\
"SEPA Credit Transfer: Pay bill from a SEPA Credit Transfer file you submit to your bank. Enable this option from the settings.") "SEPA Credit Transfer: Pay bill from a SEPA Credit Transfer file you submit to your bank. Enable this option from the settings.")
at_least_one_inbound = fields.Boolean(compute='_methods_compute', store=True) at_least_one_inbound = fields.Boolean(compute='_methods_compute', store=True)
at_least_one_outbound = fields.Boolean(compute='_methods_compute', store=True) at_least_one_outbound = fields.Boolean(compute='_methods_compute', store=True)
profit_account_id = fields.Many2one('account.account', profit_account_id = fields.Many2one(
comodel_name='account.account', check_company=True,
help="Used to register a profit when the ending balance of a cash register differs from what the system computes",
string='Profit Account', string='Profit Account',
domain="[('company_id', '=', company_id)]", domain=lambda self: "[('deprecated', '=', False), ('company_id', '=', company_id), \
check_company=True, ('user_type_id.type', 'not in', ('receivable', 'payable')), \
help="Used to register a profit when the ending balance of a cash register differs from what the system computes") ('user_type_id', 'in', %s)]" % [self.env.ref('account.data_account_type_revenue').id,
loss_account_id = fields.Many2one('account.account', self.env.ref('account.data_account_type_other_income').id])
loss_account_id = fields.Many2one(
comodel_name='account.account', check_company=True,
help="Used to register a loss when the ending balance of a cash register differs from what the system computes",
string='Loss Account', string='Loss Account',
domain="[('company_id', '=', company_id)]", domain=lambda self: "[('deprecated', '=', False), ('company_id', '=', company_id), \
check_company=True, ('user_type_id.type', 'not in', ('receivable', 'payable')), \
help="Used to register a loss when the ending balance of a cash register differs from what the system computes") ('user_type_id', '=', %s)]" % self.env.ref('account.data_account_type_expenses').id)
# Bank journals fields # Bank journals fields
company_partner_id = fields.Many2one('res.partner', related='company_id.partner_id', string='Account Holder', readonly=True, store=False) company_partner_id = fields.Many2one('res.partner', related='company_id.partner_id', string='Account Holder', readonly=True, store=False)
@@ -143,9 +154,11 @@ class AccountJournal(models.Model):
sale_activity_note = fields.Text('Activity Summary') sale_activity_note = fields.Text('Activity Summary')
# alias configuration for journals # alias configuration for journals
alias_id = fields.Many2one('mail.alias', string='Alias', copy=False) alias_id = fields.Many2one('mail.alias', string='Email Alias', help="Send one separate email for each invoice.\n\n"
"Any file extension will be accepted.\n\n"
"Only PDF and XML files will be interpreted by Odoo", copy=False)
alias_domain = fields.Char('Alias domain', compute='_compute_alias_domain', default=_default_alias_domain, compute_sudo=True) alias_domain = fields.Char('Alias domain', compute='_compute_alias_domain', default=_default_alias_domain, compute_sudo=True)
alias_name = fields.Char('Alias Name', related='alias_id.alias_name', help="It creates draft invoices and bills by sending an email.", readonly=False) alias_name = fields.Char('Alias Name', copy=False, related='alias_id.alias_name', help="It creates draft invoices and bills by sending an email.", readonly=False)
journal_group_ids = fields.Many2many('account.journal.group', journal_group_ids = fields.Many2many('account.journal.group',
domain="[('company_id', '=', company_id)]", domain="[('company_id', '=', company_id)]",
@@ -161,6 +174,21 @@ class AccountJournal(models.Model):
('code_company_uniq', 'unique (code, name, company_id)', 'The code and name of the journal must be unique per company !'), ('code_company_uniq', 'unique (code, name, company_id)', 'The code and name of the journal must be unique per company !'),
] ]
@api.depends('type')
def _compute_default_account_type(self):
default_account_id_types = {
'bank': 'account.data_account_type_liquidity',
'cash': 'account.data_account_type_liquidity',
'sale': 'account.data_account_type_revenue',
'purchase': 'account.data_account_type_expenses'
}
for journal in self:
if journal.type in default_account_id_types:
journal.default_account_type = self.env.ref(default_account_id_types[journal.type]).id
else:
journal.default_account_type = False
@api.depends('company_id', 'type') @api.depends('company_id', 'type')
def _compute_suspense_account_id(self): def _compute_suspense_account_id(self):
for journal in self: for journal in self:
@@ -235,10 +263,9 @@ class AccountJournal(models.Model):
if self._cr.fetchone(): if self._cr.fetchone():
raise UserError(_("You can't change the company of your journal since there are some journal entries linked to it.")) raise UserError(_("You can't change the company of your journal since there are some journal entries linked to it."))
@api.constrains('default_debit_account_id', 'default_credit_account_id', 'payment_debit_account_id', 'payment_credit_account_id') @api.constrains('default_account_id', 'payment_debit_account_id', 'payment_credit_account_id')
def _check_journal_not_shared_accounts(self): def _check_journal_not_shared_accounts(self):
accounts = self.default_debit_account_id \ accounts = self.default_account_id \
+ self.default_credit_account_id \
+ self.payment_debit_account_id \ + self.payment_debit_account_id \
+ self.payment_credit_account_id + self.payment_credit_account_id
@@ -246,8 +273,7 @@ class AccountJournal(models.Model):
return return
self.env['account.journal'].flush([ self.env['account.journal'].flush([
'default_debit_account_id', 'default_account_id',
'default_credit_account_id',
'payment_debit_account_id', 'payment_debit_account_id',
'payment_credit_account_id', 'payment_credit_account_id',
]) ])
@@ -257,9 +283,7 @@ class AccountJournal(models.Model):
ARRAY_AGG(DISTINCT journal.name) AS journal_names ARRAY_AGG(DISTINCT journal.name) AS journal_names
FROM account_account account FROM account_account account
LEFT JOIN account_journal journal ON LEFT JOIN account_journal journal ON
journal.default_debit_account_id = account.id journal.default_account_id = account.id
OR
journal.default_credit_account_id = account.id
OR OR
journal.payment_debit_account_id = account.id journal.payment_debit_account_id = account.id
OR OR
@@ -276,22 +300,11 @@ class AccountJournal(models.Model):
journals=', '.join(res[1]) journals=', '.join(res[1])
)) ))
@api.constrains('type', 'default_credit_account_id', 'default_debit_account_id') @api.constrains('type', 'default_account_id')
def _check_type_default_credit_account_id_type(self): def _check_type_default_account_id_type(self):
journals_to_check = self.filtered(lambda journal: journal.type in ('sale', 'purchase')) for journal in self:
accounts_to_check = journals_to_check.mapped('default_debit_account_id') + journals_to_check.mapped('default_credit_account_id') if journal.type in ('sale', 'purchase') and journal.default_account_id.user_type_id.type in ('receivable', 'payable'):
if any(account.user_type_id.type in ('receivable', 'payable') for account in accounts_to_check): raise ValidationError(_("The type of the journal's default credit/debit account shouldn't be 'receivable' or 'payable'."))
raise ValidationError(_("The type of the journal's default credit/debit account shouldn't be 'receivable' or 'payable'."))
@api.onchange('default_debit_account_id')
def onchange_debit_account_id(self):
if not self.default_credit_account_id:
self.default_credit_account_id = self.default_debit_account_id
@api.onchange('default_credit_account_id')
def onchange_credit_account_id(self):
if not self.default_debit_account_id:
self.default_debit_account_id = self.default_credit_account_id
@api.onchange('type') @api.onchange('type')
def _onchange_type(self): def _onchange_type(self):
@@ -374,8 +387,7 @@ class AccountJournal(models.Model):
for journal in self: for journal in self:
# Ensure the liquidity accounts are sharing the same foreign currency. # Ensure the liquidity accounts are sharing the same foreign currency.
accounts = journal.default_debit_account_id + journal.default_credit_account_id journal.default_account_id.currency_id = journal.currency_id
accounts.write({'currency_id': journal.currency_id.id})
# Create the bank_account_id if necessary # Create the bank_account_id if necessary
if 'bank_acc_number' in vals: if 'bank_acc_number' in vals:
@@ -417,7 +429,7 @@ class AccountJournal(models.Model):
current_assets_type = self.env.ref('account.data_account_type_current_assets') current_assets_type = self.env.ref('account.data_account_type_current_assets')
if journal_type in ('bank', 'cash'): if journal_type in ('bank', 'cash'):
has_liquidity_accounts = vals.get('default_debit_account_id') or vals.get('default_credit_account_id') has_liquidity_accounts = vals.get('default_account_id')
has_payment_accounts = vals.get('payment_debit_account_id') or vals.get('payment_credit_account_id') has_payment_accounts = vals.get('payment_debit_account_id') or vals.get('payment_credit_account_id')
has_profit_account = vals.get('profit_account_id') has_profit_account = vals.get('profit_account_id')
has_loss_account = vals.get('loss_account_id') has_loss_account = vals.get('loss_account_id')
@@ -447,8 +459,7 @@ class AccountJournal(models.Model):
}) })
vals.update({ vals.update({
'default_debit_account_id': liquidity_account.id, 'default_account_id': liquidity_account.id,
'default_credit_account_id': liquidity_account.id,
}) })
if not has_payment_accounts: if not has_payment_accounts:
vals['payment_debit_account_id'] = self.env['account.account'].create({ vals['payment_debit_account_id'] = self.env['account.account'].create({
@@ -474,6 +485,10 @@ class AccountJournal(models.Model):
if 'refund_sequence' not in vals: if 'refund_sequence' not in vals:
vals['refund_sequence'] = vals['type'] in ('sale', 'purchase') vals['refund_sequence'] = vals['type'] in ('sale', 'purchase')
# === Fill missing alias name ===
if journal_type in ('sale', 'purchase') and 'alias_name' not in vals:
vals['alias_name'] = '%s.%s' % (company.name, vals.get('code'))
@api.model @api.model
def create(self, vals): def create(self, vals):
# OVERRIDE # OVERRIDE
@@ -615,12 +630,11 @@ class AccountJournal(models.Model):
self.ensure_one() self.ensure_one()
self.env['account.move.line'].check_access_rights('read') self.env['account.move.line'].check_access_rights('read')
accounts = self.default_debit_account_id + self.default_credit_account_id if not self.default_account_id:
if not accounts:
return 0.0 return 0.0
domain = (domain or []) + [ domain = (domain or []) + [
('account_id', 'in', tuple(accounts.ids)), ('account_id', 'in', tuple(self.default_account_id.ids)),
('display_type', 'not in', ('line_section', 'line_note')), ('display_type', 'not in', ('line_section', 'line_note')),
('move_id.state', '!=', 'cancel'), ('move_id.state', '!=', 'cancel'),
] ]
+15 -29
View File
@@ -1620,12 +1620,7 @@ class AccountMove(models.Model):
# Doing line.account_id triggers a default_get(['account_id']) that could returns a result. # Doing line.account_id triggers a default_get(['account_id']) that could returns a result.
# A section / note must not have an account_id set. # A section / note must not have an account_id set.
if not line._cache.get('account_id') and not line.display_type and not line._origin: if not line._cache.get('account_id') and not line.display_type and not line._origin:
line.account_id = line._get_computed_account() line.account_id = line._get_computed_account() or self.journal_id.default_account_id
if not line.account_id:
if self.is_sale_document(include_receipts=True):
line.account_id = self.journal_id.default_credit_account_id
elif self.is_purchase_document(include_receipts=True):
line.account_id = self.journal_id.default_debit_account_id
if line.product_id and not line._cache.get('name'): if line.product_id and not line._cache.get('name'):
line.name = line._get_computed_name() line.name = line._get_computed_name()
@@ -3834,20 +3829,12 @@ class AccountMoveLine(models.Model):
# OVERRIDE # OVERRIDE
values = super(AccountMoveLine, self).default_get(default_fields) values = super(AccountMoveLine, self).default_get(default_fields)
if 'account_id' in default_fields \ if 'account_id' in default_fields and not values.get('account_id') \
and (self._context.get('journal_id') or self._context.get('default_journal_id')) \ and (self._context.get('journal_id') or self._context.get('default_journal_id')) \
and not values.get('account_id') \ and self._context.get('default_move_type') in ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt'):
and self._context.get('default_move_type') in self.move_id.get_inbound_types():
# Fill missing 'account_id'. # Fill missing 'account_id'.
journal = self.env['account.journal'].browse(self._context.get('default_journal_id') or self._context['journal_id']) journal = self.env['account.journal'].browse(self._context.get('default_journal_id') or self._context['journal_id'])
values['account_id'] = journal.default_credit_account_id.id values['account_id'] = journal.default_account_id.id
elif 'account_id' in default_fields \
and (self._context.get('journal_id') or self._context.get('default_journal_id')) \
and not values.get('account_id') \
and self._context.get('default_move_type') in self.move_id.get_outbound_types():
# Fill missing 'account_id'.
journal = self.env['account.journal'].browse(self._context.get('default_journal_id') or self._context['journal_id'])
values['account_id'] = journal.default_debit_account_id.id
elif self._context.get('line_ids') and any(field_name in default_fields for field_name in ('debit', 'credit', 'account_id', 'partner_id')): elif self._context.get('line_ids') and any(field_name in default_fields for field_name in ('debit', 'credit', 'account_id', 'partner_id')):
move = self.env['account.move'].new({'line_ids': self._context['line_ids']}) move = self.env['account.move'].new({'line_ids': self._context['line_ids']})
@@ -4076,18 +4063,17 @@ class AccountMoveLine(models.Model):
# amount_residual_currency == 0 and amount_residual has to be fixed. # amount_residual_currency == 0 and amount_residual has to be fixed.
if line.amount_residual > 0.0: if line.amount_residual > 0.0:
exchange_line_account = journal.default_debit_account_id exchange_line_account = journal.company_id.expense_currency_exchange_account_id
else: else:
exchange_line_account = journal.default_credit_account_id exchange_line_account = journal.company_id.income_currency_exchange_account_id
elif line.currency_id and not line.currency_id.is_zero(line.amount_residual_currency): elif line.currency_id and not line.currency_id.is_zero(line.amount_residual_currency):
# amount_residual == 0 and amount_residual_currency has to be fixed. # amount_residual == 0 and amount_residual_currency has to be fixed.
if line.amount_residual_currency > 0.0: if line.amount_residual_currency > 0.0:
exchange_line_account = journal.default_debit_account_id exchange_line_account = journal.company_id.expense_currency_exchange_account_id
else: else:
exchange_line_account = journal.default_credit_account_id exchange_line_account = journal.company_id.income_currency_exchange_account_id
else: else:
continue continue
@@ -4222,9 +4208,9 @@ class AccountMoveLine(models.Model):
journal = account.company_id.currency_exchange_journal_id journal = account.company_id.currency_exchange_journal_id
if balance > 0.0: if balance > 0.0:
exchange_line_account = journal.default_debit_account_id exchange_line_account = journal.company_id.expense_currency_exchange_account_id
else: else:
exchange_line_account = journal.default_credit_account_id exchange_line_account = journal.company_id.income_currency_exchange_account_id
sequence = len(exchange_diff_move_vals['line_ids']) sequence = len(exchange_diff_move_vals['line_ids'])
exchange_diff_move_vals['line_ids'] += [ exchange_diff_move_vals['line_ids'] += [
@@ -4253,11 +4239,11 @@ class AccountMoveLine(models.Model):
# Check the configuration of the exchange difference journal. # Check the configuration of the exchange difference journal.
if not journal: if not journal:
raise UserError(_("You should configure the 'Exchange Rate Journal' in the accounting settings, to manage automatically the booking of accounting entries related to differences between exchange rates.")) raise UserError(_("You should configure the 'Exchange Gain or Loss Journal' in your company settings, to manage automatically the booking of accounting entries related to differences between exchange rates."))
if not journal.default_debit_account_id.id: if not journal.company_id.expense_currency_exchange_account_id:
raise UserError(_("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.")) raise UserError(_("You should configure the 'Loss Exchange Rate Account' in your company settings, to manage automatically the booking of accounting entries related to differences between exchange rates."))
if not journal.default_credit_account_id.id: if not journal.company_id.income_currency_exchange_account_id.id:
raise UserError(_("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.")) raise UserError(_("You should configure the 'Gain Exchange Rate Account' in your company settings, to manage automatically the booking of accounting entries related to differences between exchange rates."))
exchange_diff_move_vals = { exchange_diff_move_vals = {
'move_type': 'entry', 'move_type': 'entry',
+2
View File
@@ -7,10 +7,12 @@ from odoo.exceptions import UserError, ValidationError
class AccountPaymentMethod(models.Model): class AccountPaymentMethod(models.Model):
_name = "account.payment.method" _name = "account.payment.method"
_description = "Payment Methods" _description = "Payment Methods"
_order = 'sequence'
name = fields.Char(required=True, translate=True) name = fields.Char(required=True, translate=True)
code = fields.Char(required=True) # For internal identification code = fields.Char(required=True) # For internal identification
payment_type = fields.Selection([('inbound', 'Inbound'), ('outbound', 'Outbound')], required=True) payment_type = fields.Selection([('inbound', 'Inbound'), ('outbound', 'Outbound')], required=True)
sequence = fields.Integer(help='Used to order Methods in the form view', default=10)
class AccountPayment(models.Model): class AccountPayment(models.Model):
+4 -7
View File
@@ -256,6 +256,8 @@ class AccountChartTemplate(models.Model):
'default_cash_difference_expense_account_id': acc_template_ref.get(self.default_cash_difference_expense_account_id.id, False), 'default_cash_difference_expense_account_id': acc_template_ref.get(self.default_cash_difference_expense_account_id.id, False),
'account_journal_suspense_account_id': acc_template_ref.get(self.account_journal_suspense_account_id.id), 'account_journal_suspense_account_id': acc_template_ref.get(self.account_journal_suspense_account_id.id),
'account_cash_basis_base_account_id': acc_template_ref.get(self.property_cash_basis_base_account_id.id), 'account_cash_basis_base_account_id': acc_template_ref.get(self.property_cash_basis_base_account_id.id),
'income_currency_exchange_account_id': acc_template_ref.get(self.income_currency_exchange_account_id.id),
'expense_currency_exchange_account_id': acc_template_ref.get(self.expense_currency_exchange_account_id.id),
}) })
if not company.account_journal_suspense_account_id: if not company.account_journal_suspense_account_id:
@@ -427,11 +429,7 @@ class AccountChartTemplate(models.Model):
default_account = acc_template_ref.get(self.property_account_income_categ_id.id) default_account = acc_template_ref.get(self.property_account_income_categ_id.id)
elif journal['type'] == 'purchase': elif journal['type'] == 'purchase':
default_account = acc_template_ref.get(self.property_account_expense_categ_id.id) default_account = acc_template_ref.get(self.property_account_expense_categ_id.id)
elif journal['type'] == 'general' and journal['code'] == _('EXCH'):
if type=='credit':
default_account = acc_template_ref.get(self.income_currency_exchange_account_id.id)
else:
default_account = acc_template_ref.get(self.expense_currency_exchange_account_id.id)
return default_account return default_account
journals = [{'name': _('Customer Invoices'), 'type': 'sale', 'code': _('INV'), 'favorite': True, 'color': 11, 'sequence': 5}, journals = [{'name': _('Customer Invoices'), 'type': 'sale', 'code': _('INV'), 'favorite': True, 'color': 11, 'sequence': 5},
@@ -450,8 +448,7 @@ class AccountChartTemplate(models.Model):
'name': journal['name'], 'name': journal['name'],
'code': journal['code'], 'code': journal['code'],
'company_id': company.id, 'company_id': company.id,
'default_credit_account_id': _get_default_account(journal, 'credit'), 'default_account_id': _get_default_account(journal),
'default_debit_account_id': _get_default_account(journal, 'debit'),
'show_on_dashboard': journal['favorite'], 'show_on_dashboard': journal['favorite'],
'color': journal.get('color', False), 'color': journal.get('color', False),
'sequence': journal['sequence'] 'sequence': journal['sequence']
+11 -4
View File
@@ -60,10 +60,17 @@ class ResCompany(models.Model):
('round_globally', 'Round Globally'), ('round_globally', 'Round Globally'),
], default='round_per_line', string='Tax Calculation Rounding Method') ], default='round_per_line', string='Tax Calculation Rounding Method')
currency_exchange_journal_id = fields.Many2one('account.journal', string="Exchange Gain or Loss Journal", domain=[('type', '=', 'general')]) currency_exchange_journal_id = fields.Many2one('account.journal', string="Exchange Gain or Loss Journal", domain=[('type', '=', 'general')])
income_currency_exchange_account_id = fields.Many2one('account.account', related='currency_exchange_journal_id.default_credit_account_id', readonly=False, income_currency_exchange_account_id = fields.Many2one(
string="Gain Exchange Rate Account", domain="[('internal_type', '=', 'other'), ('deprecated', '=', False), ('company_id', '=', id)]") comodel_name='account.account',
expense_currency_exchange_account_id = fields.Many2one('account.account', related='currency_exchange_journal_id.default_debit_account_id', readonly=False, string="Gain Exchange Rate Account",
string="Loss Exchange Rate Account", domain="[('internal_type', '=', 'other'), ('deprecated', '=', False), ('company_id', '=', id)]") domain=lambda self: "[('internal_type', '=', 'other'), ('deprecated', '=', False), ('company_id', '=', id), \
('user_type_id', 'in', %s)]" % [self.env.ref('account.data_account_type_revenue').id,
self.env.ref('account.data_account_type_other_income').id])
expense_currency_exchange_account_id = fields.Many2one(
comodel_name='account.account',
string="Loss Exchange Rate Account",
domain=lambda self: "[('internal_type', '=', 'other'), ('deprecated', '=', False), ('company_id', '=', id), \
('user_type_id', '=', %s)]" % self.env.ref('account.data_account_type_expenses').id)
anglo_saxon_accounting = fields.Boolean(string="Use anglo-saxon accounting") anglo_saxon_accounting = fields.Boolean(string="Use anglo-saxon accounting")
property_stock_account_input_categ_id = fields.Many2one('account.account', string="Input Account for Stock Valuation") property_stock_account_input_categ_id = fields.Many2one('account.account', string="Input Account for Stock Valuation")
property_stock_account_output_categ_id = fields.Many2one('account.account', string="Output Account for Stock Valuation") property_stock_account_output_categ_id = fields.Many2one('account.account', string="Output Account for Stock Valuation")
+17 -2
View File
@@ -11,11 +11,26 @@ class ResConfigSettings(models.TransientModel):
currency_id = fields.Many2one('res.currency', related="company_id.currency_id", required=True, readonly=False, currency_id = fields.Many2one('res.currency', related="company_id.currency_id", required=True, readonly=False,
string='Currency', help="Main currency of the company.") string='Currency', help="Main currency of the company.")
currency_exchange_journal_id = fields.Many2one( currency_exchange_journal_id = fields.Many2one(
'account.journal', comodel_name='account.journal',
related='company_id.currency_exchange_journal_id', readonly=False, related='company_id.currency_exchange_journal_id', readonly=False,
string="Exchange Gain or Loss Journal", string="Currency Exchange Journal",
domain="[('company_id', '=', company_id), ('type', '=', 'general')]", domain="[('company_id', '=', company_id), ('type', '=', 'general')]",
help='The accounting journal where automatic exchange differences will be registered') help='The accounting journal where automatic exchange differences will be registered')
income_currency_exchange_account_id = fields.Many2one(
comodel_name="account.account",
related="company_id.income_currency_exchange_account_id",
string="Gain Account",
readonly=False,
domain=lambda self: "[('internal_type', '=', 'other'), ('deprecated', '=', False), ('company_id', '=', company_id),\
('user_type_id', 'in', %s)]" % [self.env.ref('account.data_account_type_revenue').id,
self.env.ref('account.data_account_type_other_income').id])
expense_currency_exchange_account_id = fields.Many2one(
comodel_name="account.account",
related="company_id.expense_currency_exchange_account_id",
string="Loss Account",
readonly=False,
domain=lambda self: "[('internal_type', '=', 'other'), ('deprecated', '=', False), ('company_id', '=', company_id),\
('user_type_id', '=', %s)]" % self.env.ref('account.data_account_type_expenses').id)
has_chart_of_accounts = fields.Boolean(compute='_compute_has_chart_of_accounts', string='Company has a chart of accounts') has_chart_of_accounts = fields.Boolean(compute='_compute_has_chart_of_accounts', string='Company has a chart of accounts')
chart_template_id = fields.Many2one('account.chart.template', string='Template', default=lambda self: self.env.company.chart_template_id, chart_template_id = fields.Many2one('account.chart.template', string='Template', default=lambda self: self.env.company.chart_template_id,
domain="[('visible','=', True)]") domain="[('visible','=', True)]")
+2 -2
View File
@@ -416,10 +416,10 @@ class TestAccountReconciliationCommon(AccountTestInvoicingCommon):
}) })
cls.bank_journal_euro = cls.env['account.journal'].create({'name': 'Bank', 'type': 'bank', 'code': 'BNK67'}) cls.bank_journal_euro = cls.env['account.journal'].create({'name': 'Bank', 'type': 'bank', 'code': 'BNK67'})
cls.account_euro = cls.bank_journal_euro.default_debit_account_id cls.account_euro = cls.bank_journal_euro.default_account_id
cls.bank_journal_usd = cls.env['account.journal'].create({'name': 'Bank US', 'type': 'bank', 'code': 'BNK68', 'currency_id': cls.currency_usd_id}) cls.bank_journal_usd = cls.env['account.journal'].create({'name': 'Bank US', 'type': 'bank', 'code': 'BNK68', 'currency_id': cls.currency_usd_id})
cls.account_usd = cls.bank_journal_usd.default_debit_account_id cls.account_usd = cls.bank_journal_usd.default_account_id
cls.fx_journal = cls.company.currency_exchange_journal_id cls.fx_journal = cls.company.currency_exchange_journal_id
cls.diff_income_account = cls.company.income_currency_exchange_account_id cls.diff_income_account = cls.company.income_currency_exchange_account_id
@@ -335,7 +335,7 @@ class TestAccountBankStatementLine(TestAccountBankStatementCommon):
'name': cls.statement_line.payment_ref, 'name': cls.statement_line.payment_ref,
'partner_id': cls.statement_line.partner_id.id, 'partner_id': cls.statement_line.partner_id.id,
'currency_id': cls.currency_2.id, 'currency_id': cls.currency_2.id,
'account_id': cls.statement.journal_id.default_debit_account_id.id, 'account_id': cls.statement.journal_id.default_account_id.id,
'debit': 1250.0, 'debit': 1250.0,
'credit': 0.0, 'credit': 0.0,
'amount_currency': 2500.0, 'amount_currency': 2500.0,
@@ -741,7 +741,7 @@ class TestAccountBankStatementLine(TestAccountBankStatementCommon):
{ {
'debit': 1.0, 'debit': 1.0,
'credit': 0, 'credit': 0,
'account_id': self.bank_journal_2.default_debit_account_id.id, 'account_id': self.bank_journal_2.default_account_id.id,
'move_id': st_line.move_id.id, 'move_id': st_line.move_id.id,
}, },
{ {
+2 -3
View File
@@ -16,15 +16,14 @@ class TestAccountJournal(AccountTestInvoicingCommon):
# Try to set a different currency on the 'debit' account. # Try to set a different currency on the 'debit' account.
with self.assertRaises(ValidationError), self.cr.savepoint(): with self.assertRaises(ValidationError), self.cr.savepoint():
journal_bank.default_debit_account_id.currency_id = self.company_data['currency'] journal_bank.default_account_id.currency_id = self.company_data['currency']
def test_constraint_shared_accounts(self): def test_constraint_shared_accounts(self):
''' Ensure the bank/outstanding accounts are not shared between multiple journals. ''' ''' Ensure the bank/outstanding accounts are not shared between multiple journals. '''
journal_bank = self.company_data['default_journal_bank'] journal_bank = self.company_data['default_journal_bank']
account_fields = ( account_fields = (
'default_debit_account_id', 'default_account_id',
'default_credit_account_id',
'payment_debit_account_id', 'payment_debit_account_id',
'payment_credit_account_id', 'payment_credit_account_id',
) )
@@ -421,7 +421,7 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
'credit': 660.0, 'credit': 660.0,
'amount_currency': 0.0, 'amount_currency': 0.0,
'currency_id': currency_id, 'currency_id': currency_id,
'account_id': exchange_diff.journal_id.default_credit_account_id.id, 'account_id': exchange_diff.journal_id.company_id.income_currency_exchange_account_id.id,
}, },
]) ])
@@ -548,7 +548,7 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
'credit': 0.0, 'credit': 0.0,
'amount_currency': 780.0, 'amount_currency': 780.0,
'currency_id': currency1_id, 'currency_id': currency1_id,
'account_id': exchange_diff.journal_id.default_debit_account_id.id, 'account_id': exchange_diff.journal_id.company_id.expense_currency_exchange_account_id.id,
}, },
{ {
'debit': 0.0, 'debit': 0.0,
@@ -563,7 +563,7 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
'credit': 0.0, 'credit': 0.0,
'amount_currency': 480.0, 'amount_currency': 480.0,
'currency_id': currency2_id, 'currency_id': currency2_id,
'account_id': exchange_diff.journal_id.default_debit_account_id.id, 'account_id': exchange_diff.journal_id.company_id.expense_currency_exchange_account_id.id,
}, },
{ {
'debit': 0.0, 'debit': 0.0,
@@ -578,7 +578,7 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
'credit': 0.0, 'credit': 0.0,
'amount_currency': 1440.0, 'amount_currency': 1440.0,
'currency_id': currency2_id, 'currency_id': currency2_id,
'account_id': exchange_diff.journal_id.default_debit_account_id.id, 'account_id': exchange_diff.journal_id.company_id.expense_currency_exchange_account_id.id,
}, },
{ {
'debit': 0.0, 'debit': 0.0,
@@ -593,7 +593,7 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
'credit': 0.0, 'credit': 0.0,
'amount_currency': 2040.0, 'amount_currency': 2040.0,
'currency_id': currency2_id, 'currency_id': currency2_id,
'account_id': exchange_diff.journal_id.default_debit_account_id.id, 'account_id': exchange_diff.journal_id.company_id.expense_currency_exchange_account_id.id,
}, },
{ {
'debit': 0.0, 'debit': 0.0,
@@ -608,7 +608,7 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
'credit': 0.0, 'credit': 0.0,
'amount_currency': 1200.0, 'amount_currency': 1200.0,
'currency_id': currency1_id, 'currency_id': currency1_id,
'account_id': exchange_diff.journal_id.default_debit_account_id.id, 'account_id': exchange_diff.journal_id.company_id.expense_currency_exchange_account_id.id,
}, },
{ {
'debit': 0.0, 'debit': 0.0,
@@ -1345,7 +1345,7 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
'credit': 0.0, 'credit': 0.0,
'amount_currency': 0.0, 'amount_currency': 0.0,
'currency_id': currency_id, 'currency_id': currency_id,
'account_id': transfer_exchange_diff.journal_id.default_debit_account_id.id, 'account_id': transfer_exchange_diff.journal_id.company_id.expense_currency_exchange_account_id.id,
}, },
]) ])
@@ -24,8 +24,8 @@ class TestReconciliationMatchingRules(AccountTestInvoicingCommon):
cls.account_pay = cls.company_data['default_account_payable'] cls.account_pay = cls.company_data['default_account_payable']
cls.account_rcv = cls.company_data['default_account_receivable'] cls.account_rcv = cls.company_data['default_account_receivable']
cls.account_bnk = cls.company_data['default_journal_bank'].default_debit_account_id cls.account_bnk = cls.company_data['default_journal_bank'].default_account_id
cls.account_cash = cls.company_data['default_journal_cash'].default_debit_account_id cls.account_cash = cls.company_data['default_journal_cash'].default_account_id
cls.partner_1 = cls.env['res.partner'].create({'name': 'partner_1', 'company_id': cls.company.id}) cls.partner_1 = cls.env['res.partner'].create({'name': 'partner_1', 'company_id': cls.company.id})
cls.partner_2 = cls.env['res.partner'].create({'name': 'partner_2', 'company_id': cls.company.id}) cls.partner_2 = cls.env['res.partner'].create({'name': 'partner_2', 'company_id': cls.company.id})
@@ -428,8 +428,7 @@ class TestReconciliationMatchingRules(AccountTestInvoicingCommon):
bank_st = self.env['account.bank.statement'].create({ bank_st = self.env['account.bank.statement'].create({
'name': 'test bank journal', 'journal_id': self.bank_journal.id, 'name': 'test bank journal', 'journal_id': self.bank_journal.id,
}) })
bank_st.journal_id.default_credit_account_id = payment_bnk_line.account_id bank_st.journal_id.default_account_id = payment_bnk_line.account_id
bank_st.journal_id.default_debit_account_id = payment_bnk_line.account_id
bank_line_1 = self.env['account.bank.statement.line'].create({ bank_line_1 = self.env['account.bank.statement.line'].create({
'statement_id': bank_st.id, 'statement_id': bank_st.id,
'payment_ref': '8', 'payment_ref': '8',
+1 -1
View File
@@ -149,7 +149,7 @@ class TestTaxCommon(AccountTestInvoicingCommon):
}) })
cls.bank_journal = cls.company_data['default_journal_bank'] cls.bank_journal = cls.company_data['default_journal_bank']
cls.bank_account = cls.bank_journal.default_debit_account_id cls.bank_account = cls.bank_journal.default_account_id
cls.expense_account = cls.company_data['default_account_expense'] cls.expense_account = cls.company_data['default_account_expense']
def _check_compute_all_results(self, total_included, total_excluded, taxes, res): def _check_compute_all_results(self, total_included, total_excluded, taxes, res):
@@ -39,7 +39,7 @@
<field name="tax_ids" widget="many2many_tags" domain="[('company_id','=',company_id)]" attrs="{'invisible': [('internal_group', '=', 'off_balance')]}"/> <field name="tax_ids" widget="many2many_tags" domain="[('company_id','=',company_id)]" attrs="{'invisible': [('internal_group', '=', 'off_balance')]}"/>
<field name="tag_ids" widget="many2many_tags" domain="[('applicability', '!=', 'taxes')]" context="{'default_applicability': 'accounts'}" options="{'no_create_edit': True}"/> <field name="tag_ids" widget="many2many_tags" domain="[('applicability', '!=', 'taxes')]" context="{'default_applicability': 'accounts'}" options="{'no_create_edit': True}"/>
</group> </group>
<group string="Security" name="secutiry_group"> <group string="Security" name="security_group">
<field name="allowed_journal_ids" widget="many2many_tags" domain="[('company_id','=',company_id)]" options="{'no_create_edit': True}"/> <field name="allowed_journal_ids" widget="many2many_tags" domain="[('company_id','=',company_id)]" options="{'no_create_edit': True}"/>
</group> </group>
</group> </group>
+59 -48
View File
@@ -39,78 +39,89 @@
</group> </group>
</group> </group>
<notebook> <notebook>
<page name="bank_account" string="Bank Account" attrs="{'invisible': [('type', '!=', 'bank')]}"> <page name="bank_account" string="Journal Entries">
<group> <group>
<group> <group string="Accounting information">
<field name="company_partner_id" invisible="1"/> <field name="default_account_type" invisible="1"/>
<field name="bank_account_id" context="{'default_partner_id': company_partner_id, 'form_view_ref': 'account.view_company_partner_bank_form'}"/> <!-- Bank -->
<field name="bank_id" attrs="{'invisible': [('bank_account_id', '=', False)]}"/> <field name="default_account_id" options="{'no_create': True}" string="Bank Account"
attrs="{'required': [('id', '!=', False)], 'invisible': [('type', '!=', 'bank')]}"
groups="account.group_account_readonly"/>
<!-- Cash -->
<field name="default_account_id" options="{'no_create': True}" string="Cash Account"
attrs="{'required': [('id', '!=', False)], 'invisible': [('type', '!=', 'cash')]}"
groups="account.group_account_readonly"/>
<field name="suspense_account_id" options="{'no_create': True}"
attrs="{'required': [('id', '!=', False), ('type', 'in', ('bank', 'cash'))], 'invisible': [('type', 'not in', ('bank', 'cash'))]}"
groups="account.group_account_readonly"/>
<field name="profit_account_id" options="{'no_create': True}" attrs="{'invisible': [('type', '!=', 'cash')]}"/>
<field name="loss_account_id" options="{'no_create': True}" attrs="{'invisible': [('type', '!=', 'cash')]}"/>
<!-- Sales -->
<field name="default_account_id" options="{'no_create': True}" string="Default Income Account"
attrs="{'required': [('id', '!=', False)], 'invisible': [('type', '!=', 'sale')]}"
groups="account.group_account_readonly"/>
<!-- Purchase -->
<field name="default_account_id" options="{'no_create': True}" string="Default Expense Account"
attrs="{'required': [('id', '!=', False)], 'invisible': [('type', '!=', 'purchase')]}"
groups="account.group_account_readonly"/>
<field name="refund_sequence" attrs="{'invisible': [('type', 'not in', ['sale', 'purchase'])]}"/>
<field name="code"/>
</group> </group>
<group > <group string="Bank Account Number" attrs="{'invisible': [('type', '!=', 'bank')]}">
<field name="company_partner_id" invisible="1"/>
<field name="bank_account_id" string="Account Number" context="{'default_partner_id': company_partner_id, 'form_view_ref': 'account.view_company_partner_bank_form'}"/>
<field name="bank_id" attrs="{'invisible': [('bank_account_id', '=', False)]}"/>
<field name="bank_statements_source" widget="radio" attrs="{'required': [('type', '=', 'bank')]}" groups="account.group_account_readonly"/> <field name="bank_statements_source" widget="radio" attrs="{'required': [('type', '=', 'bank')]}" groups="account.group_account_readonly"/>
</group> </group>
</group> </group>
</page> </page>
<page name="journal_entries" string="Journal Entries"> <page name="journal_entries" string="Payments Configuration" attrs="{'invisible': [('type', 'in', ['sale', 'purchase', 'general'])]}">
<group> <group>
<group> <group string="Incoming Payments">
<field name="code"/>
<field name="refund_sequence" attrs="{'invisible': [('type', 'not in', ['sale', 'purchase'])]}"/>
</group>
<group>
<field name="id" invisible="1"/>
<field name="default_debit_account_id" options="{'no_create': True}"
attrs="{'required': [('id', '!=', False), ('type', 'in', ('bank', 'cash'))]}"
groups="account.group_account_readonly"/>
<field name="default_credit_account_id" options="{'no_create': True}"
attrs="{'required': [('id', '!=', False), ('type', 'in', ('bank', 'cash'))]}"
groups="account.group_account_readonly"/>
<field name="payment_debit_account_id" options="{'no_create': True}" <field name="payment_debit_account_id" options="{'no_create': True}"
attrs="{'required': [('id', '!=', False), ('type', 'in', ('bank', 'cash'))], 'invisible': [('type', 'not in', ('bank', 'cash'))]}" attrs="{'required': [('id', '!=', False), ('type', 'in', ('bank', 'cash'))], 'invisible': [('type', 'not in', ('bank', 'cash'))]}"
groups="account.group_account_readonly"/> groups="account.group_account_readonly"/>
<field name="inbound_payment_method_ids" string="Methods" widget="many2many_checkboxes" attrs="{'invisible': [('type', 'not in', ['bank', 'cash'])]}"/>
</group>
<group string="Outgoing Payments">
<field name="id" invisible="1"/>
<field name="payment_credit_account_id" options="{'no_create': True}" <field name="payment_credit_account_id" options="{'no_create': True}"
attrs="{'required': [('id', '!=', False), ('type', 'in', ('bank', 'cash'))], 'invisible': [('type', 'not in', ('bank', 'cash'))]}" attrs="{'required': [('id', '!=', False), ('type', 'in', ('bank', 'cash'))], 'invisible': [('type', 'not in', ('bank', 'cash'))]}"
groups="account.group_account_readonly"/> groups="account.group_account_readonly"/>
<field name="suspense_account_id" options="{'no_create': True}"
attrs="{'required': [('id', '!=', False), ('type', 'in', ('bank', 'cash'))], 'invisible': [('type', 'not in', ('bank', 'cash'))]}"
groups="account.group_account_readonly"/>
<field name="currency_id" options="{'no_create': True}" groups="base.group_multi_currency"/> <field name="currency_id" options="{'no_create': True}" groups="base.group_multi_currency"/>
<field name="outbound_payment_method_ids" string="Methods" widget="many2many_checkboxes" attrs="{'invisible': [('type', 'not in', ['bank', 'cash'])]}"/>
</group> </group>
<group name="outgoing_payment" />
</group> </group>
</page> </page>
<page name="advanced_settings" string="Advanced Settings"> <page name="advanced_settings" string="Advanced Settings">
<group> <group>
<group string="Payment References" attrs="{'invisible': [('type', '!=', 'sale')]}">
<field name="invoice_reference_type"/>
<field name="invoice_reference_model" attrs="{'invisible': [('invoice_reference_type', '=', 'none')]}"/>
</group>
<group name="group_alias" string="Email your Invoices/Bills" attrs="{'invisible': [('type', 'not in', ('sale' ,'purchase'))]}">
<label string="Email Alias" attrs="{'invisible': [('alias_domain', '=', False)]}" for="alias_id"/>
<div name="alias_def" attrs="{'invisible': [('alias_domain', '=', False)]}">
<field name="alias_id" class="oe_read_only oe_inline"/>
<div class="oe_edit_only oe_inline" name="edit_alias" style="display: inline;" >
<field name="alias_name" class="oe_inline"/>@<field name="alias_domain" class="oe_inline" readonly="1"/>
</div>
</div>
<div class="content-group" attrs="{'invisible': [('alias_domain', '!=', False)]}">
<a type='action' name='%(action_open_settings)d' class="btn btn-link" role="button"><i class="fa fa-fw o_button_icon fa-arrow-right"/> Configure Email Servers</a>
</div>
</group>
<group string="Posting" name="column_posting" groups="account.group_account_readonly" attrs="{'invisible': [('type', '!=', 'cash')]}">
<field name="profit_account_id" options="{'no_create': True}"/>
<field name="loss_account_id" options="{'no_create': True}"/>
</group>
<group string="Control-Access" groups="account.group_account_manager"> <group string="Control-Access" groups="account.group_account_manager">
<div class="text-muted" colspan="2">Keep empty for no control</div> <div class="text-muted" colspan="2">Keep empty for no control</div>
<field name="type_control_ids" widget="many2many_tags"/> <field name="type_control_ids" widget="many2many_tags"/>
<field name="account_control_ids" widget="many2many_tags"/> <field name="account_control_ids" widget="many2many_tags"/>
<field name="restrict_mode_hash_table" <field name="restrict_mode_hash_table" groups="account.group_account_readonly"/>
attrs="{'invisible': [('type', 'in', ('bank', 'cash'))]}"
groups="account.group_account_readonly"/>
</group> </group>
<group string="Payment Method Types" attrs="{'invisible': [('type', 'not in', ['bank', 'cash'])]}"> <!-- email alias -->
<field name="inbound_payment_method_ids" widget="many2many_checkboxes"/> <group class="oe_read_only" name="group_alias_ro" string="Create Invoices upon Emails" attrs="{'invisible': ['|', ('type', 'not in', ('sale' ,'purchase')), ('alias_domain', '=', False)]}">
<field name="outbound_payment_method_ids" widget="many2many_checkboxes"/> <field name="alias_id"/>
</group>
<group name="group_alias_no_domain" string="Create Invoices upon Emails" attrs="{'invisible': ['|', ('type', 'not in', ('sale' ,'purchase')), ('alias_domain', '!=', False)]}">
<div class="content-group">
<a type='action' name='%(action_open_settings)d' class="btn btn-link" role="button"><i class="fa fa-fw o_button_icon fa-arrow-right"/> Configure Email Servers</a>
</div>
</group>
<group class="oe_edit_only" name="group_alias_edit" string="Create Invoices upon Emails" attrs="{'invisible': ['|', ('type', 'not in', ('sale' ,'purchase')), ('alias_domain', '=', False)]}">
<label string="Email Alias" for="alias_name"/>
<div class="oe_inline" name="edit_alias" style="display: inline;" >
<field name="alias_name" class="oe_inline"/>@<field name="alias_domain" class="oe_inline" readonly="1"/>
</div>
</group>
<!-- email alias end -->
<group string="Payment Communications" attrs="{'invisible': [('type', '!=', 'sale')]}">
<field name="invoice_reference_type"/>
<field name="invoice_reference_model" attrs="{'invisible': [('invoice_reference_type', '=', 'none')]}"/>
</group> </group>
<group string="Follow Customer Payments" attrs="{'invisible': [('type', '!=', 'sale')]}"> <group string="Follow Customer Payments" attrs="{'invisible': [('type', '!=', 'sale')]}">
<field name="sale_activity_type_id"/> <field name="sale_activity_type_id"/>
+1 -1
View File
@@ -10,4 +10,4 @@
</xpath> </xpath>
</field> </field>
</record> </record>
</odoo> </odoo>
@@ -161,10 +161,21 @@
<div class="mt8"> <div class="mt8">
<button name="%(base.action_currency_all_form)d" icon="fa-arrow-right" type="action" string="Activate Other Currencies" class="btn-link"/> <button name="%(base.action_currency_all_form)d" icon="fa-arrow-right" type="action" string="Activate Other Currencies" class="btn-link"/>
</div> </div>
<div class="row mt16"> <div class="mt16">
<label for="currency_exchange_journal_id" class="col-lg-3 o_light_label"/> <b>Post Exchange difference entries in:</b>
</div>
<div class="row mt8">
<label for="currency_exchange_journal_id" class="col-lg-3 o_light_label" string="Journal" />
<field name="currency_exchange_journal_id"/> <field name="currency_exchange_journal_id"/>
</div> </div>
<div class="row mt8">
<label for="income_currency_exchange_account_id" class="col-lg-3 o_light_label"/>
<field name="income_currency_exchange_account_id"/>
</div>
<div class="row mt8">
<label for="expense_currency_exchange_account_id" class="col-lg-3 o_light_label"/>
<field name="expense_currency_exchange_account_id"/>
</div>
</div> </div>
</div> </div>
</div> </div>
+8 -17
View File
@@ -75,27 +75,16 @@ class SetupBarBankConfigWizard(models.TransientModel):
comodel_name='account.journal', inverse='set_linked_journal_id', comodel_name='account.journal', inverse='set_linked_journal_id',
compute="_compute_linked_journal_id", check_company=True, compute="_compute_linked_journal_id", check_company=True,
domain="[('type','=','bank'), ('bank_account_id', '=', False), ('company_id', '=', company_id)]") domain="[('type','=','bank'), ('bank_account_id', '=', False), ('company_id', '=', company_id)]")
new_journal_code = fields.Char(string="Code", required=True, default=lambda self: self._onchange_new_journal_code()) bank_bic = fields.Char(related='bank_id.bic', readonly=False, string="Bic")
num_journals_without_account = fields.Integer(default=lambda self: self._number_unlinked_journal()) num_journals_without_account = fields.Integer(default=lambda self: self._number_unlinked_journal())
# field computing the type of the res.patrner.bank. It's behaves the same as a related res_part_bank_id.acc_type
# except we want to display this information while the record isn't yet saved.
related_acc_type = fields.Selection(string="Account Type", selection=lambda x: x.env['res.partner.bank'].get_supported_account_types(), compute='_compute_related_acc_type')
@api.depends('acc_number')
def _compute_related_acc_type(self):
for record in self:
record.related_acc_type = self.env['res.partner.bank'].retrieve_acc_type(record.acc_number)
def _number_unlinked_journal(self): def _number_unlinked_journal(self):
return self.env['account.journal'].search([('type', '=', 'bank'), ('bank_account_id', '=', False)], count=True) return self.env['account.journal'].search([('type', '=', 'bank'), ('bank_account_id', '=', False)], count=True)
@api.onchange('linked_journal_id') @api.onchange('acc_number')
def _onchange_new_journal_code(self): def _onchange_acc_number(self):
for record in self: for record in self:
if not record.linked_journal_id: record.new_journal_name = record.acc_number
record.new_journal_code = self.env['account.journal'].get_next_bank_cash_default_code('bank', self.env.company)
else:
record.new_journal_code = self.linked_journal_id.code
@api.model @api.model
def create(self, vals): def create(self, vals):
@@ -104,6 +93,7 @@ class SetupBarBankConfigWizard(models.TransientModel):
the model. the model.
""" """
vals['partner_id'] = self.env.company.partner_id.id vals['partner_id'] = self.env.company.partner_id.id
vals['new_journal_name'] = vals['acc_number']
return super(SetupBarBankConfigWizard, self).create(vals) return super(SetupBarBankConfigWizard, self).create(vals)
@api.onchange('linked_journal_id') @api.onchange('linked_journal_id')
@@ -126,11 +116,12 @@ class SetupBarBankConfigWizard(models.TransientModel):
""" """
for record in self: for record in self:
selected_journal = record.linked_journal_id selected_journal = record.linked_journal_id
new_journal_code = self.env['account.journal'].get_next_bank_cash_default_code('bank', self.env.company)
if record.num_journals_without_account == 0: if record.num_journals_without_account == 0:
company = self.env.company company = self.env.company
selected_journal = self.env['account.journal'].create({ selected_journal = self.env['account.journal'].create({
'name': record.new_journal_name, 'name': record.new_journal_name,
'code': record.new_journal_code, 'code': new_journal_code,
'type': 'bank', 'type': 'bank',
'company_id': company.id, 'company_id': company.id,
'bank_account_id': record.res_partner_bank_id.id, 'bank_account_id': record.res_partner_bank_id.id,
@@ -138,7 +129,7 @@ class SetupBarBankConfigWizard(models.TransientModel):
else: else:
selected_journal.bank_account_id = record.res_partner_bank_id.id selected_journal.bank_account_id = record.res_partner_bank_id.id
selected_journal.name = record.new_journal_name selected_journal.name = record.new_journal_name
selected_journal.code = record.new_journal_code selected_journal.code = new_journal_code
def validate(self): def validate(self):
""" Called by the validation button of this wizard. Serves as an """ Called by the validation button of this wizard. Serves as an
+1 -7
View File
@@ -41,17 +41,11 @@
<field name="company_id" invisible="1"/> <field name="company_id" invisible="1"/>
<field name="linked_journal_id" invisible="1"/> <field name="linked_journal_id" invisible="1"/>
<sheet> <sheet>
<div class="oe_title">
<h1><field name="new_journal_name" placeholder="e.g Checking account" class="oe_inline"/></h1>
</div>
<group> <group>
<group> <group>
<field name="acc_number" placeholder="e.g BE15001559627230"/> <field name="acc_number" placeholder="e.g BE15001559627230"/>
<field name="bank_id" placeholder="e.g Bank of America"/> <field name="bank_id" placeholder="e.g Bank of America"/>
<field name="new_journal_code"/> <field name="bank_bic" placeholder="e.g GEBABEBB" string="Bank Identifier Code"/>
</group>
<group>
<field name="related_acc_type" attrs="{'invisible': [('acc_number','=',False)]}"/>
</group> </group>
</group> </group>
<group attrs="{'invisible': [('num_journals_without_account', '&lt;', 2)]}"> <group attrs="{'invisible': [('num_journals_without_account', '&lt;', 2)]}">
@@ -6,6 +6,7 @@
<field name="name">Checks</field> <field name="name">Checks</field>
<field name="code">check_printing</field> <field name="code">check_printing</field>
<field name="payment_type">outbound</field> <field name="payment_type">outbound</field>
<field name="sequence">20</field>
</record> </record>
<function model="account.journal" name="_enable_check_printing_on_bank_journals"/> <function model="account.journal" name="_enable_check_printing_on_bank_journals"/>
@@ -26,12 +26,15 @@
<field name="model">account.journal</field> <field name="model">account.journal</field>
<field name="inherit_id" ref="account.view_account_journal_form" /> <field name="inherit_id" ref="account.view_account_journal_form" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//page[@name='advanced_settings']/group" position="inside"> <xpath expr="//page[@name='journal_entries']//group[@name='outgoing_payment']" position="after">
<group string="Check Printing" attrs="{'invisible': ['|', ('type', '!=', 'bank'), ('check_printing_payment_method_selected', '=', False)]}"> <group string="Check Printing"
attrs="{'invisible': ['|', ('type', '!=', 'bank'), ('check_printing_payment_method_selected', '=', False)]}">
<field name="check_printing_payment_method_selected" invisible="1"/> <field name="check_printing_payment_method_selected" invisible="1"/>
<field name="check_sequence_id" invisible="1"/> <field name="check_sequence_id" invisible="1"/>
<field name="check_manual_sequencing"/> <field name="check_manual_sequencing"
<field name="check_next_number" attrs="{'invisible': [('check_manual_sequencing', '=', False)]}"/> />
<field name="check_next_number"
attrs="{'invisible': [('check_manual_sequencing', '=', False)]}"/>
</group> </group>
</xpath> </xpath>
</field> </field>
@@ -6,8 +6,8 @@
<field name="model">account.journal</field> <field name="model">account.journal</field>
<field name="inherit_id" ref="account.view_account_journal_form" /> <field name="inherit_id" ref="account.view_account_journal_form" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//page[@name='advanced_settings']/group" position="inside"> <xpath expr="//page[@name='advanced_settings']//group[@name='group_alias_edit']" position="after">
<group string="Electronic Data Interchange" > <group string="Electronic Data Interchange" attrs="{'invisible': [('type', '!=', 'sale')]}">
<field name="edi_format_ids" widget="many2many_tags"/> <field name="edi_format_ids" widget="many2many_tags"/>
</group> </group>
</xpath> </xpath>
+2 -1
View File
@@ -13,7 +13,8 @@ with a single statement.
'depends': ['account', 'web'], 'depends': ['account', 'web'],
'data': [ 'data': [
'views/templates.xml', 'views/templates.xml',
'views/partner_view.xml' 'views/partner_view.xml',
'views/setup_wizards_view.xml'
], ],
'demo': ['data/res_partner_bank_demo.xml'], 'demo': ['data/res_partner_bank_demo.xml'],
} }
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="setup_bank_account_iban_wizard" model="ir.ui.view">
<field name="name">account.online.sync.res.partner.bank.setup.form.inherit</field>
<field name="model">account.setup.bank.manual.config</field>
<field name="inherit_id" ref="account.setup_bank_account_wizard"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='acc_number']" position="attributes">
<attribute name="widget">iban</attribute>
</xpath>
</field>
</record>
</odoo>
+5 -5
View File
@@ -386,9 +386,9 @@ class HrExpense(models.Model):
self.ensure_one() self.ensure_one()
account_dest = self.env['account.account'] account_dest = self.env['account.account']
if self.payment_mode == 'company_account': if self.payment_mode == 'company_account':
if not self.sheet_id.bank_journal_id.default_credit_account_id: if not self.sheet_id.bank_journal_id.default_account_id:
raise UserError(_("No credit account found for the %s journal, please configure one.") % (self.sheet_id.bank_journal_id.name)) raise UserError(_("No account found for the %s journal, please configure one.") % (self.sheet_id.bank_journal_id.name))
account_dest = self.sheet_id.bank_journal_id.default_credit_account_id.id account_dest = self.sheet_id.bank_journal_id.default_account_id.id
else: else:
if not self.employee_id.sudo().address_home_id: if not self.employee_id.sudo().address_home_id:
raise UserError(_("No Home Address found for the employee %s, please configure one.") % (self.employee_id.name)) raise UserError(_("No Home Address found for the employee %s, please configure one.") % (self.employee_id.name))
@@ -507,8 +507,8 @@ class HrExpense(models.Model):
# create one more move line, a counterline for the total on payable account # create one more move line, a counterline for the total on payable account
if expense.payment_mode == 'company_account': if expense.payment_mode == 'company_account':
if not expense.sheet_id.bank_journal_id.default_credit_account_id: if not expense.sheet_id.bank_journal_id.default_account_id:
raise UserError(_("No credit account found for the %s journal, please configure one.") % (expense.sheet_id.bank_journal_id.name)) raise UserError(_("No account found for the %s journal, please configure one.") % (expense.sheet_id.bank_journal_id.name))
journal = expense.sheet_id.bank_journal_id journal = expense.sheet_id.bank_journal_id
# create payment # create payment
payment_methods = journal.outbound_payment_method_ids if total_amount < 0 else journal.inbound_payment_method_ids payment_methods = journal.outbound_payment_method_ids if total_amount < 0 else journal.inbound_payment_method_ids
+2 -2
View File
@@ -6,7 +6,7 @@
<field name="model">account.setup.bank.manual.config</field> <field name="model">account.setup.bank.manual.config</field>
<field name="inherit_id" ref="account.setup_bank_account_wizard"/> <field name="inherit_id" ref="account.setup_bank_account_wizard"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="new_journal_code" position="after"> <field name="bank_bic" position="after">
<field name="l10n_ch_show_subscription" invisible="1"/> <field name="l10n_ch_show_subscription" invisible="1"/>
<field name="l10n_ch_isr_subscription_chf" attrs="{'invisible': [('l10n_ch_show_subscription', '=', False)]}"/> <field name="l10n_ch_isr_subscription_chf" attrs="{'invisible': [('l10n_ch_show_subscription', '=', False)]}"/>
<label for="l10n_ch_postal" string="ISR Client Identification Number" attrs="{'invisible': [('l10n_ch_show_subscription', '=', False)]}"/> <label for="l10n_ch_postal" string="ISR Client Identification Number" attrs="{'invisible': [('l10n_ch_show_subscription', '=', False)]}"/>
@@ -15,4 +15,4 @@
</field> </field>
</record> </record>
</data> </data>
</odoo> </odoo>
+1 -2
View File
@@ -34,8 +34,7 @@ class AccountChartTemplate(models.Model):
'name': _('Effectively Paid'), 'name': _('Effectively Paid'),
'code': 'CBMX', 'code': 'CBMX',
'company_id': company.id, 'company_id': company.id,
'default_credit_account_id': account, 'default_account_id': account,
'default_debit_account_id': account,
'show_on_dashboard': True, 'show_on_dashboard': True,
}) })
return res return res
+1 -4
View File
@@ -121,13 +121,10 @@ class TestMembership(TestMembershipCommon):
'membership: after opening the invoice, customer should be in invoiced status') 'membership: after opening the invoice, customer should be in invoiced status')
# the invoice is paid -> customer goes to paid status # the invoice is paid -> customer goes to paid status
bank_journal = self.env['account.journal'].create({'name': 'Bank', 'type': 'bank', 'code': 'BNK67'})
payment = self.env['account.payment.register']\ payment = self.env['account.payment.register']\
.with_context(active_model='account.move', active_ids=invoice.ids)\ .with_context(active_model='account.move', active_ids=invoice.ids)\
.create({ .create({
'amount': 86.25, 'amount': 86.25
'journal_id': bank_journal.id,
})\ })\
._create_payments() ._create_payments()
+1 -2
View File
@@ -267,8 +267,7 @@ class PaymentAcquirer(models.Model):
'sequence': 999, 'sequence': 999,
'type': 'bank', 'type': 'bank',
'company_id': self.company_id.id, 'company_id': self.company_id.id,
'default_debit_account_id': account.id, 'default_account_id': account.id,
'default_credit_account_id': account.id,
# Show the journal on dashboard if the acquirer is published on the website. # Show the journal on dashboard if the acquirer is published on the website.
'show_on_dashboard': self.state == 'enabled', 'show_on_dashboard': self.state == 'enabled',
# Don't show payment methods in the backend. # Don't show payment methods in the backend.
@@ -9,7 +9,7 @@ class AccountBankStatement(models.Model):
_inherit = 'account.bank.statement' _inherit = 'account.bank.statement'
pos_session_id = fields.Many2one('pos.session', string="Session", copy=False) pos_session_id = fields.Many2one('pos.session', string="Session", copy=False)
account_id = fields.Many2one('account.account', related='journal_id.default_debit_account_id', readonly=True) account_id = fields.Many2one('account.account', related='journal_id.default_account_id', readonly=True)
def button_validate_or_action(self): def button_validate_or_action(self):
# OVERRIDE to check the consistency of the statement's state regarding the session's state. # OVERRIDE to check the consistency of the statement's state regarding the session's state.
+1 -1
View File
@@ -78,7 +78,7 @@ class TestPointOfSaleCommon(ValuationReconciliationTestCommon):
# Create POS journal # Create POS journal
cls.pos_config.journal_id = cls.env['account.journal'].create({ cls.pos_config.journal_id = cls.env['account.journal'].create({
'type': 'sale', 'type': 'sale',
'name': 'Point of Sale', 'name': 'Point of Sale - Test',
'code': 'POSS - Test', 'code': 'POSS - Test',
'company_id': cls.env.company.id, 'company_id': cls.env.company.id,
'sequence': 20 'sequence': 20
@@ -56,15 +56,13 @@ class BaseTestUi(odoo.tests.HttpCase):
'name': 'Bank - Test', 'name': 'Bank - Test',
'code': 'TBNK', 'code': 'TBNK',
'type': 'bank', 'type': 'bank',
'default_credit_account_id': bnk.id, 'default_account_id': bnk.id,
'default_debit_account_id': bnk.id,
}) })
self.sales_journal = self.env['account.journal'].create({ self.sales_journal = self.env['account.journal'].create({
'name': 'Customer Invoices - Test', 'name': 'Customer Invoices - Test',
'code': 'TINV', 'code': 'TINV',
'type': 'sale', 'type': 'sale',
'default_credit_account_id': a_sale.id, 'default_account_id': a_sale.id,
'default_debit_account_id': a_sale.id,
'refund_sequence': True, 'refund_sequence': True,
}) })