[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:
@@ -123,8 +123,7 @@ class AccountAccount(models.Model):
|
||||
self.env['account.account'].flush(['currency_id'])
|
||||
self.env['account.journal'].flush([
|
||||
'currency_id',
|
||||
'default_debit_account_id',
|
||||
'default_credit_account_id',
|
||||
'default_account_id',
|
||||
'payment_debit_account_id',
|
||||
'payment_credit_account_id',
|
||||
'suspense_account_id',
|
||||
@@ -134,9 +133,7 @@ class AccountAccount(models.Model):
|
||||
FROM account_account account
|
||||
JOIN res_company company ON company.id = account.company_id
|
||||
JOIN account_journal journal ON
|
||||
journal.default_debit_account_id = account.id
|
||||
OR
|
||||
journal.default_credit_account_id = account.id
|
||||
journal.default_account_id = account.id
|
||||
WHERE account.id IN %s
|
||||
AND journal.type IN ('bank', 'cash')
|
||||
AND journal.currency_id IS NOT NULL
|
||||
@@ -179,7 +176,7 @@ class AccountAccount(models.Model):
|
||||
SELECT account.id
|
||||
FROM account_account account
|
||||
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
|
||||
AND acc_type.type IN ('receivable', 'payable')
|
||||
AND journal.type IN ('sale', 'purchase')
|
||||
|
||||
@@ -538,7 +538,7 @@ class AccountBankStatementLine(models.Model):
|
||||
other_lines = self.env['account.move.line']
|
||||
|
||||
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
|
||||
elif line.account_id == self.journal_id.suspense_account_id:
|
||||
suspense_lines += line
|
||||
@@ -590,7 +590,7 @@ class AccountBankStatementLine(models.Model):
|
||||
'move_id': self.move_id.id,
|
||||
'partner_id': self.partner_id.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,
|
||||
'credit': balance < 0 and -balance or 0.0,
|
||||
'amount_currency': amount_currency,
|
||||
|
||||
@@ -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',
|
||||
check_company=True,
|
||||
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]")
|
||||
default_credit_account_id = fields.Many2one('account.account', string='Default Credit Account', copy=False,
|
||||
domain=[('deprecated', '=', False)], help="It acts as a default account for credit amount",
|
||||
check_company=True,
|
||||
ondelete='restrict')
|
||||
default_debit_account_id = fields.Many2one('account.account', string='Default Debit Account', copy=False,
|
||||
check_company=True,
|
||||
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]", help="It acts as a default account for debit amount", ondelete='restrict')
|
||||
payment_debit_account_id = fields.Many2one('account.account', string='Outstanding Receipts Account', copy=False,
|
||||
ondelete='restrict',
|
||||
domain=[('deprecated', '=', False)],
|
||||
default_account_type = fields.Many2one('account.account.type', compute="_compute_default_account_type")
|
||||
default_account_id = fields.Many2one(
|
||||
comodel_name='account.account', check_company=True, copy=False, ondelete='restrict',
|
||||
string='Default Account', help="It acts as a default account",
|
||||
domain="[('deprecated', '=', False), ('company_id', '=', company_id),"
|
||||
"('user_type_id', '=', default_account_type),"
|
||||
"('user_type_id.type', 'not in', ('receivable', 'payable'))]")
|
||||
payment_debit_account_id = fields.Many2one(
|
||||
comodel_name='account.account', check_company=True, copy=False, ondelete='restrict',
|
||||
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 "
|
||||
"transactions will be reconciled with entries on the Outstanding Receipts Account instead of the "
|
||||
"receivable account.")
|
||||
payment_credit_account_id = fields.Many2one('account.account', string='Outstanding Payments Account', copy=False,
|
||||
ondelete='restrict',
|
||||
domain=[('deprecated', '=', False)],
|
||||
"receivable account.", string='Outstanding Receipts 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_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 "
|
||||
"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 "
|
||||
"payable account.")
|
||||
suspense_account_id = fields.Many2one('account.account', string='Bank Suspense Account',
|
||||
ondelete='restrict', readonly=False, store=True,
|
||||
"payable account.", string='Outstanding Payments 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_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',
|
||||
domain=[('deprecated', '=', False), ('reconcile', '=', True)],
|
||||
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",
|
||||
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)
|
||||
@@ -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*?)$")
|
||||
|
||||
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"\
|
||||
"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.")
|
||||
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"\
|
||||
"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.")
|
||||
at_least_one_inbound = 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',
|
||||
domain="[('company_id', '=', company_id)]",
|
||||
check_company=True,
|
||||
help="Used to register a profit when the ending balance of a cash register differs from what the system computes")
|
||||
loss_account_id = fields.Many2one('account.account',
|
||||
domain=lambda self: "[('deprecated', '=', False), ('company_id', '=', company_id), \
|
||||
('user_type_id.type', 'not in', ('receivable', 'payable')), \
|
||||
('user_type_id', 'in', %s)]" % [self.env.ref('account.data_account_type_revenue').id,
|
||||
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',
|
||||
domain="[('company_id', '=', company_id)]",
|
||||
check_company=True,
|
||||
help="Used to register a loss when the ending balance of a cash register differs from what the system computes")
|
||||
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_expenses').id)
|
||||
|
||||
# Bank journals fields
|
||||
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')
|
||||
|
||||
# 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_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',
|
||||
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 !'),
|
||||
]
|
||||
|
||||
@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')
|
||||
def _compute_suspense_account_id(self):
|
||||
for journal in self:
|
||||
@@ -235,10 +263,9 @@ class AccountJournal(models.Model):
|
||||
if self._cr.fetchone():
|
||||
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):
|
||||
accounts = self.default_debit_account_id \
|
||||
+ self.default_credit_account_id \
|
||||
accounts = self.default_account_id \
|
||||
+ self.payment_debit_account_id \
|
||||
+ self.payment_credit_account_id
|
||||
|
||||
@@ -246,8 +273,7 @@ class AccountJournal(models.Model):
|
||||
return
|
||||
|
||||
self.env['account.journal'].flush([
|
||||
'default_debit_account_id',
|
||||
'default_credit_account_id',
|
||||
'default_account_id',
|
||||
'payment_debit_account_id',
|
||||
'payment_credit_account_id',
|
||||
])
|
||||
@@ -257,9 +283,7 @@ class AccountJournal(models.Model):
|
||||
ARRAY_AGG(DISTINCT journal.name) AS journal_names
|
||||
FROM account_account account
|
||||
LEFT JOIN account_journal journal ON
|
||||
journal.default_debit_account_id = account.id
|
||||
OR
|
||||
journal.default_credit_account_id = account.id
|
||||
journal.default_account_id = account.id
|
||||
OR
|
||||
journal.payment_debit_account_id = account.id
|
||||
OR
|
||||
@@ -276,22 +300,11 @@ class AccountJournal(models.Model):
|
||||
journals=', '.join(res[1])
|
||||
))
|
||||
|
||||
@api.constrains('type', 'default_credit_account_id', 'default_debit_account_id')
|
||||
def _check_type_default_credit_account_id_type(self):
|
||||
journals_to_check = self.filtered(lambda journal: journal.type in ('sale', 'purchase'))
|
||||
accounts_to_check = journals_to_check.mapped('default_debit_account_id') + journals_to_check.mapped('default_credit_account_id')
|
||||
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'."))
|
||||
|
||||
@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.constrains('type', 'default_account_id')
|
||||
def _check_type_default_account_id_type(self):
|
||||
for journal in self:
|
||||
if journal.type in ('sale', 'purchase') and journal.default_account_id.user_type_id.type in ('receivable', 'payable'):
|
||||
raise ValidationError(_("The type of the journal's default credit/debit account shouldn't be 'receivable' or 'payable'."))
|
||||
|
||||
@api.onchange('type')
|
||||
def _onchange_type(self):
|
||||
@@ -374,8 +387,7 @@ class AccountJournal(models.Model):
|
||||
|
||||
for journal in self:
|
||||
# Ensure the liquidity accounts are sharing the same foreign currency.
|
||||
accounts = journal.default_debit_account_id + journal.default_credit_account_id
|
||||
accounts.write({'currency_id': journal.currency_id.id})
|
||||
journal.default_account_id.currency_id = journal.currency_id
|
||||
|
||||
# Create the bank_account_id if necessary
|
||||
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')
|
||||
|
||||
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_profit_account = vals.get('profit_account_id')
|
||||
has_loss_account = vals.get('loss_account_id')
|
||||
@@ -447,8 +459,7 @@ class AccountJournal(models.Model):
|
||||
})
|
||||
|
||||
vals.update({
|
||||
'default_debit_account_id': liquidity_account.id,
|
||||
'default_credit_account_id': liquidity_account.id,
|
||||
'default_account_id': liquidity_account.id,
|
||||
})
|
||||
if not has_payment_accounts:
|
||||
vals['payment_debit_account_id'] = self.env['account.account'].create({
|
||||
@@ -474,6 +485,10 @@ class AccountJournal(models.Model):
|
||||
if 'refund_sequence' not in vals:
|
||||
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
|
||||
def create(self, vals):
|
||||
# OVERRIDE
|
||||
@@ -615,12 +630,11 @@ class AccountJournal(models.Model):
|
||||
self.ensure_one()
|
||||
self.env['account.move.line'].check_access_rights('read')
|
||||
|
||||
accounts = self.default_debit_account_id + self.default_credit_account_id
|
||||
if not accounts:
|
||||
if not self.default_account_id:
|
||||
return 0.0
|
||||
|
||||
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')),
|
||||
('move_id.state', '!=', 'cancel'),
|
||||
]
|
||||
|
||||
@@ -1620,12 +1620,7 @@ class AccountMove(models.Model):
|
||||
# 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.
|
||||
if not line._cache.get('account_id') and not line.display_type and not line._origin:
|
||||
line.account_id = line._get_computed_account()
|
||||
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
|
||||
line.account_id = line._get_computed_account() or self.journal_id.default_account_id
|
||||
if line.product_id and not line._cache.get('name'):
|
||||
line.name = line._get_computed_name()
|
||||
|
||||
@@ -3834,20 +3829,12 @@ class AccountMoveLine(models.Model):
|
||||
# OVERRIDE
|
||||
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 not values.get('account_id') \
|
||||
and self._context.get('default_move_type') in self.move_id.get_inbound_types():
|
||||
and self._context.get('default_move_type') in ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt'):
|
||||
# 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_credit_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
|
||||
values['account_id'] = journal.default_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')):
|
||||
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.
|
||||
|
||||
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:
|
||||
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):
|
||||
# amount_residual == 0 and amount_residual_currency has to be fixed.
|
||||
|
||||
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:
|
||||
exchange_line_account = journal.default_credit_account_id
|
||||
|
||||
exchange_line_account = journal.company_id.income_currency_exchange_account_id
|
||||
else:
|
||||
continue
|
||||
|
||||
@@ -4222,9 +4208,9 @@ class AccountMoveLine(models.Model):
|
||||
journal = account.company_id.currency_exchange_journal_id
|
||||
|
||||
if balance > 0.0:
|
||||
exchange_line_account = journal.default_debit_account_id
|
||||
exchange_line_account = journal.company_id.expense_currency_exchange_account_id
|
||||
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'])
|
||||
exchange_diff_move_vals['line_ids'] += [
|
||||
@@ -4253,11 +4239,11 @@ class AccountMoveLine(models.Model):
|
||||
|
||||
# Check the configuration of the exchange difference 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."))
|
||||
if not journal.default_debit_account_id.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."))
|
||||
if not journal.default_credit_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 '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.company_id.expense_currency_exchange_account_id:
|
||||
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.company_id.income_currency_exchange_account_id.id:
|
||||
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 = {
|
||||
'move_type': 'entry',
|
||||
|
||||
@@ -7,10 +7,12 @@ from odoo.exceptions import UserError, ValidationError
|
||||
class AccountPaymentMethod(models.Model):
|
||||
_name = "account.payment.method"
|
||||
_description = "Payment Methods"
|
||||
_order = 'sequence'
|
||||
|
||||
name = fields.Char(required=True, translate=True)
|
||||
code = fields.Char(required=True) # For internal identification
|
||||
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):
|
||||
|
||||
@@ -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),
|
||||
'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),
|
||||
'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:
|
||||
@@ -427,11 +429,7 @@ class AccountChartTemplate(models.Model):
|
||||
default_account = acc_template_ref.get(self.property_account_income_categ_id.id)
|
||||
elif journal['type'] == 'purchase':
|
||||
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
|
||||
|
||||
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'],
|
||||
'code': journal['code'],
|
||||
'company_id': company.id,
|
||||
'default_credit_account_id': _get_default_account(journal, 'credit'),
|
||||
'default_debit_account_id': _get_default_account(journal, 'debit'),
|
||||
'default_account_id': _get_default_account(journal),
|
||||
'show_on_dashboard': journal['favorite'],
|
||||
'color': journal.get('color', False),
|
||||
'sequence': journal['sequence']
|
||||
|
||||
@@ -60,10 +60,17 @@ class ResCompany(models.Model):
|
||||
('round_globally', 'Round Globally'),
|
||||
], 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')])
|
||||
income_currency_exchange_account_id = fields.Many2one('account.account', related='currency_exchange_journal_id.default_credit_account_id', readonly=False,
|
||||
string="Gain Exchange Rate Account", domain="[('internal_type', '=', 'other'), ('deprecated', '=', False), ('company_id', '=', id)]")
|
||||
expense_currency_exchange_account_id = fields.Many2one('account.account', related='currency_exchange_journal_id.default_debit_account_id', readonly=False,
|
||||
string="Loss Exchange Rate Account", domain="[('internal_type', '=', 'other'), ('deprecated', '=', False), ('company_id', '=', id)]")
|
||||
income_currency_exchange_account_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
string="Gain Exchange Rate Account",
|
||||
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")
|
||||
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")
|
||||
|
||||
@@ -11,11 +11,26 @@ class ResConfigSettings(models.TransientModel):
|
||||
currency_id = fields.Many2one('res.currency', related="company_id.currency_id", required=True, readonly=False,
|
||||
string='Currency', help="Main currency of the company.")
|
||||
currency_exchange_journal_id = fields.Many2one(
|
||||
'account.journal',
|
||||
comodel_name='account.journal',
|
||||
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')]",
|
||||
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')
|
||||
chart_template_id = fields.Many2one('account.chart.template', string='Template', default=lambda self: self.env.company.chart_template_id,
|
||||
domain="[('visible','=', True)]")
|
||||
|
||||
@@ -416,10 +416,10 @@ class TestAccountReconciliationCommon(AccountTestInvoicingCommon):
|
||||
})
|
||||
|
||||
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.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.diff_income_account = cls.company.income_currency_exchange_account_id
|
||||
|
||||
@@ -335,7 +335,7 @@ class TestAccountBankStatementLine(TestAccountBankStatementCommon):
|
||||
'name': cls.statement_line.payment_ref,
|
||||
'partner_id': cls.statement_line.partner_id.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,
|
||||
'credit': 0.0,
|
||||
'amount_currency': 2500.0,
|
||||
@@ -741,7 +741,7 @@ class TestAccountBankStatementLine(TestAccountBankStatementCommon):
|
||||
{
|
||||
'debit': 1.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,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -16,15 +16,14 @@ class TestAccountJournal(AccountTestInvoicingCommon):
|
||||
|
||||
# Try to set a different currency on the 'debit' account.
|
||||
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):
|
||||
''' Ensure the bank/outstanding accounts are not shared between multiple journals. '''
|
||||
journal_bank = self.company_data['default_journal_bank']
|
||||
|
||||
account_fields = (
|
||||
'default_debit_account_id',
|
||||
'default_credit_account_id',
|
||||
'default_account_id',
|
||||
'payment_debit_account_id',
|
||||
'payment_credit_account_id',
|
||||
)
|
||||
|
||||
@@ -421,7 +421,7 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
'credit': 660.0,
|
||||
'amount_currency': 0.0,
|
||||
'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,
|
||||
'amount_currency': 780.0,
|
||||
'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,
|
||||
@@ -563,7 +563,7 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
'credit': 0.0,
|
||||
'amount_currency': 480.0,
|
||||
'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,
|
||||
@@ -578,7 +578,7 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
'credit': 0.0,
|
||||
'amount_currency': 1440.0,
|
||||
'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,
|
||||
@@ -593,7 +593,7 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
'credit': 0.0,
|
||||
'amount_currency': 2040.0,
|
||||
'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,
|
||||
@@ -608,7 +608,7 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
'credit': 0.0,
|
||||
'amount_currency': 1200.0,
|
||||
'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,
|
||||
@@ -1345,7 +1345,7 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
'credit': 0.0,
|
||||
'amount_currency': 0.0,
|
||||
'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_rcv = cls.company_data['default_account_receivable']
|
||||
cls.account_bnk = cls.company_data['default_journal_bank'].default_debit_account_id
|
||||
cls.account_cash = cls.company_data['default_journal_cash'].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_account_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})
|
||||
@@ -428,8 +428,7 @@ class TestReconciliationMatchingRules(AccountTestInvoicingCommon):
|
||||
bank_st = self.env['account.bank.statement'].create({
|
||||
'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_debit_account_id = payment_bnk_line.account_id
|
||||
bank_st.journal_id.default_account_id = payment_bnk_line.account_id
|
||||
bank_line_1 = self.env['account.bank.statement.line'].create({
|
||||
'statement_id': bank_st.id,
|
||||
'payment_ref': '8',
|
||||
|
||||
@@ -149,7 +149,7 @@ class TestTaxCommon(AccountTestInvoicingCommon):
|
||||
})
|
||||
|
||||
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']
|
||||
|
||||
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="tag_ids" widget="many2many_tags" domain="[('applicability', '!=', 'taxes')]" context="{'default_applicability': 'accounts'}" options="{'no_create_edit': True}"/>
|
||||
</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}"/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
@@ -39,78 +39,89 @@
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page name="bank_account" string="Bank Account" attrs="{'invisible': [('type', '!=', 'bank')]}">
|
||||
<page name="bank_account" string="Journal Entries">
|
||||
<group>
|
||||
<group>
|
||||
<field name="company_partner_id" invisible="1"/>
|
||||
<field name="bank_account_id" 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)]}"/>
|
||||
<group string="Accounting information">
|
||||
<field name="default_account_type" invisible="1"/>
|
||||
<!-- Bank -->
|
||||
<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 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"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page name="journal_entries" string="Journal Entries">
|
||||
<page name="journal_entries" string="Payments Configuration" attrs="{'invisible': [('type', 'in', ['sale', 'purchase', 'general'])]}">
|
||||
<group>
|
||||
<group>
|
||||
<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"/>
|
||||
<group string="Incoming Payments">
|
||||
<field name="payment_debit_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="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}"
|
||||
attrs="{'required': [('id', '!=', False), ('type', 'in', ('bank', 'cash'))], 'invisible': [('type', 'not in', ('bank', '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="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 name="outgoing_payment" />
|
||||
</group>
|
||||
</page>
|
||||
<page name="advanced_settings" string="Advanced Settings">
|
||||
<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">
|
||||
<div class="text-muted" colspan="2">Keep empty for no control</div>
|
||||
<field name="type_control_ids" widget="many2many_tags"/>
|
||||
<field name="account_control_ids" widget="many2many_tags"/>
|
||||
<field name="restrict_mode_hash_table"
|
||||
attrs="{'invisible': [('type', 'in', ('bank', 'cash'))]}"
|
||||
groups="account.group_account_readonly"/>
|
||||
<field name="restrict_mode_hash_table" groups="account.group_account_readonly"/>
|
||||
</group>
|
||||
<group string="Payment Method Types" attrs="{'invisible': [('type', 'not in', ['bank', 'cash'])]}">
|
||||
<field name="inbound_payment_method_ids" widget="many2many_checkboxes"/>
|
||||
<field name="outbound_payment_method_ids" widget="many2many_checkboxes"/>
|
||||
<!-- email alias -->
|
||||
<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="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 string="Follow Customer Payments" attrs="{'invisible': [('type', '!=', 'sale')]}">
|
||||
<field name="sale_activity_type_id"/>
|
||||
|
||||
@@ -10,4 +10,4 @@
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
</odoo>
|
||||
|
||||
@@ -161,10 +161,21 @@
|
||||
<div class="mt8">
|
||||
<button name="%(base.action_currency_all_form)d" icon="fa-arrow-right" type="action" string="Activate Other Currencies" class="btn-link"/>
|
||||
</div>
|
||||
<div class="row mt16">
|
||||
<label for="currency_exchange_journal_id" class="col-lg-3 o_light_label"/>
|
||||
<div class="mt16">
|
||||
<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"/>
|
||||
</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>
|
||||
|
||||
@@ -75,27 +75,16 @@ class SetupBarBankConfigWizard(models.TransientModel):
|
||||
comodel_name='account.journal', inverse='set_linked_journal_id',
|
||||
compute="_compute_linked_journal_id", check_company=True,
|
||||
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())
|
||||
# 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):
|
||||
return self.env['account.journal'].search([('type', '=', 'bank'), ('bank_account_id', '=', False)], count=True)
|
||||
|
||||
@api.onchange('linked_journal_id')
|
||||
def _onchange_new_journal_code(self):
|
||||
@api.onchange('acc_number')
|
||||
def _onchange_acc_number(self):
|
||||
for record in self:
|
||||
if not record.linked_journal_id:
|
||||
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
|
||||
record.new_journal_name = record.acc_number
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@@ -104,6 +93,7 @@ class SetupBarBankConfigWizard(models.TransientModel):
|
||||
the model.
|
||||
"""
|
||||
vals['partner_id'] = self.env.company.partner_id.id
|
||||
vals['new_journal_name'] = vals['acc_number']
|
||||
return super(SetupBarBankConfigWizard, self).create(vals)
|
||||
|
||||
@api.onchange('linked_journal_id')
|
||||
@@ -126,11 +116,12 @@ class SetupBarBankConfigWizard(models.TransientModel):
|
||||
"""
|
||||
for record in self:
|
||||
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:
|
||||
company = self.env.company
|
||||
selected_journal = self.env['account.journal'].create({
|
||||
'name': record.new_journal_name,
|
||||
'code': record.new_journal_code,
|
||||
'code': new_journal_code,
|
||||
'type': 'bank',
|
||||
'company_id': company.id,
|
||||
'bank_account_id': record.res_partner_bank_id.id,
|
||||
@@ -138,7 +129,7 @@ class SetupBarBankConfigWizard(models.TransientModel):
|
||||
else:
|
||||
selected_journal.bank_account_id = record.res_partner_bank_id.id
|
||||
selected_journal.name = record.new_journal_name
|
||||
selected_journal.code = record.new_journal_code
|
||||
selected_journal.code = new_journal_code
|
||||
|
||||
def validate(self):
|
||||
""" Called by the validation button of this wizard. Serves as an
|
||||
|
||||
@@ -41,17 +41,11 @@
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="linked_journal_id" invisible="1"/>
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1><field name="new_journal_name" placeholder="e.g Checking account" class="oe_inline"/></h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="acc_number" placeholder="e.g BE15001559627230"/>
|
||||
<field name="bank_id" placeholder="e.g Bank of America"/>
|
||||
<field name="new_journal_code"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="related_acc_type" attrs="{'invisible': [('acc_number','=',False)]}"/>
|
||||
<field name="bank_bic" placeholder="e.g GEBABEBB" string="Bank Identifier Code"/>
|
||||
</group>
|
||||
</group>
|
||||
<group attrs="{'invisible': [('num_journals_without_account', '<', 2)]}">
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<field name="name">Checks</field>
|
||||
<field name="code">check_printing</field>
|
||||
<field name="payment_type">outbound</field>
|
||||
<field name="sequence">20</field>
|
||||
</record>
|
||||
|
||||
<function model="account.journal" name="_enable_check_printing_on_bank_journals"/>
|
||||
|
||||
@@ -26,12 +26,15 @@
|
||||
<field name="model">account.journal</field>
|
||||
<field name="inherit_id" ref="account.view_account_journal_form" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//page[@name='advanced_settings']/group" position="inside">
|
||||
<group string="Check Printing" attrs="{'invisible': ['|', ('type', '!=', 'bank'), ('check_printing_payment_method_selected', '=', False)]}">
|
||||
<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)]}">
|
||||
<field name="check_printing_payment_method_selected" invisible="1"/>
|
||||
<field name="check_sequence_id" invisible="1"/>
|
||||
<field name="check_manual_sequencing"/>
|
||||
<field name="check_next_number" attrs="{'invisible': [('check_manual_sequencing', '=', False)]}"/>
|
||||
<field name="check_manual_sequencing"
|
||||
/>
|
||||
<field name="check_next_number"
|
||||
attrs="{'invisible': [('check_manual_sequencing', '=', False)]}"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<field name="model">account.journal</field>
|
||||
<field name="inherit_id" ref="account.view_account_journal_form" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//page[@name='advanced_settings']/group" position="inside">
|
||||
<group string="Electronic Data Interchange" >
|
||||
<xpath expr="//page[@name='advanced_settings']//group[@name='group_alias_edit']" position="after">
|
||||
<group string="Electronic Data Interchange" attrs="{'invisible': [('type', '!=', 'sale')]}">
|
||||
<field name="edi_format_ids" widget="many2many_tags"/>
|
||||
</group>
|
||||
</xpath>
|
||||
|
||||
@@ -13,7 +13,8 @@ with a single statement.
|
||||
'depends': ['account', 'web'],
|
||||
'data': [
|
||||
'views/templates.xml',
|
||||
'views/partner_view.xml'
|
||||
'views/partner_view.xml',
|
||||
'views/setup_wizards_view.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>
|
||||
@@ -386,9 +386,9 @@ class HrExpense(models.Model):
|
||||
self.ensure_one()
|
||||
account_dest = self.env['account.account']
|
||||
if self.payment_mode == 'company_account':
|
||||
if not self.sheet_id.bank_journal_id.default_credit_account_id:
|
||||
raise UserError(_("No credit 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
|
||||
if not self.sheet_id.bank_journal_id.default_account_id:
|
||||
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_account_id.id
|
||||
else:
|
||||
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))
|
||||
@@ -507,8 +507,8 @@ class HrExpense(models.Model):
|
||||
|
||||
# create one more move line, a counterline for the total on payable account
|
||||
if expense.payment_mode == 'company_account':
|
||||
if not expense.sheet_id.bank_journal_id.default_credit_account_id:
|
||||
raise UserError(_("No credit account found for the %s journal, please configure one.") % (expense.sheet_id.bank_journal_id.name))
|
||||
if not expense.sheet_id.bank_journal_id.default_account_id:
|
||||
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
|
||||
# create payment
|
||||
payment_methods = journal.outbound_payment_method_ids if total_amount < 0 else journal.inbound_payment_method_ids
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<field name="model">account.setup.bank.manual.config</field>
|
||||
<field name="inherit_id" ref="account.setup_bank_account_wizard"/>
|
||||
<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_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)]}"/>
|
||||
@@ -15,4 +15,4 @@
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
</odoo>
|
||||
|
||||
@@ -34,8 +34,7 @@ class AccountChartTemplate(models.Model):
|
||||
'name': _('Effectively Paid'),
|
||||
'code': 'CBMX',
|
||||
'company_id': company.id,
|
||||
'default_credit_account_id': account,
|
||||
'default_debit_account_id': account,
|
||||
'default_account_id': account,
|
||||
'show_on_dashboard': True,
|
||||
})
|
||||
return res
|
||||
|
||||
@@ -121,13 +121,10 @@ class TestMembership(TestMembershipCommon):
|
||||
'membership: after opening the invoice, customer should be in invoiced 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']\
|
||||
.with_context(active_model='account.move', active_ids=invoice.ids)\
|
||||
.create({
|
||||
'amount': 86.25,
|
||||
'journal_id': bank_journal.id,
|
||||
'amount': 86.25
|
||||
})\
|
||||
._create_payments()
|
||||
|
||||
|
||||
@@ -267,8 +267,7 @@ class PaymentAcquirer(models.Model):
|
||||
'sequence': 999,
|
||||
'type': 'bank',
|
||||
'company_id': self.company_id.id,
|
||||
'default_debit_account_id': account.id,
|
||||
'default_credit_account_id': account.id,
|
||||
'default_account_id': account.id,
|
||||
# Show the journal on dashboard if the acquirer is published on the website.
|
||||
'show_on_dashboard': self.state == 'enabled',
|
||||
# Don't show payment methods in the backend.
|
||||
|
||||
@@ -9,7 +9,7 @@ class AccountBankStatement(models.Model):
|
||||
_inherit = 'account.bank.statement'
|
||||
|
||||
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):
|
||||
# OVERRIDE to check the consistency of the statement's state regarding the session's state.
|
||||
|
||||
@@ -78,7 +78,7 @@ class TestPointOfSaleCommon(ValuationReconciliationTestCommon):
|
||||
# Create POS journal
|
||||
cls.pos_config.journal_id = cls.env['account.journal'].create({
|
||||
'type': 'sale',
|
||||
'name': 'Point of Sale',
|
||||
'name': 'Point of Sale - Test',
|
||||
'code': 'POSS - Test',
|
||||
'company_id': cls.env.company.id,
|
||||
'sequence': 20
|
||||
|
||||
@@ -56,15 +56,13 @@ class BaseTestUi(odoo.tests.HttpCase):
|
||||
'name': 'Bank - Test',
|
||||
'code': 'TBNK',
|
||||
'type': 'bank',
|
||||
'default_credit_account_id': bnk.id,
|
||||
'default_debit_account_id': bnk.id,
|
||||
'default_account_id': bnk.id,
|
||||
})
|
||||
self.sales_journal = self.env['account.journal'].create({
|
||||
'name': 'Customer Invoices - Test',
|
||||
'code': 'TINV',
|
||||
'type': 'sale',
|
||||
'default_credit_account_id': a_sale.id,
|
||||
'default_debit_account_id': a_sale.id,
|
||||
'default_account_id': a_sale.id,
|
||||
'refund_sequence': True,
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user