[FIX]fixed account bank statement import issues

This commit is contained in:
ketul-1997 committed 2021-02-25 13:22:32 +05:30
1 parent dd44b98135
commit 3e0715e48d
5 files changed
+114 -16

No files matched your search

@@ -5,6 +5,8 @@ from flectra import api, fields, models, _
import base64
from flectra.exceptions import UserError, ValidationError
import time
from flectra.tools.misc import formatLang, format_date
class AccountBankStatement(models.Model):
@@ -19,6 +21,66 @@ class AccountBankStatement(models.Model):
" be booked is already closed.",
states={'open': [('readonly', False)]}, readonly=True)
def _balance_check(self):
for stmt in self:
if not stmt.currency_id.is_zero(stmt.difference):
if stmt.journal_type == 'cash':
if stmt.difference < 0.0:
account = stmt.journal_id.loss_account_id
name = _('Loss')
else:
# statement.difference > 0.0
account = stmt.journal_id.profit_account_id
name = _('Profit')
if not account:
raise UserError(_('Please go on the %s journal and define a %s Account. This account will be used to record cash difference.') % (stmt.journal_id.name, name))
values = {
'statement_id': stmt.id,
'account_id': account.id,
'amount': stmt.difference,
'name': _("Cash difference observed during the counting (%s)") % name,
}
self.env['account.bank.statement.line'].create(values)
else:
balance_end_real = formatLang(self.env, stmt.balance_end_real, currency_obj=stmt.currency_id)
balance_end = formatLang(self.env, stmt.balance_end, currency_obj=stmt.currency_id)
raise UserError(_('The ending balance is incorrect !\nThe expected balance (%s) is different from the computed one. (%s)')
% (balance_end_real, balance_end))
return True
def button_confirm_bank(self):
self._balance_check()
statements = self.filtered(lambda r: r.state == 'open')
for statement in statements:
moves = self.env['account.move']
# `line.journal_entry_ids` gets invalidated from the cache during the loop
# because new move lines are being created at each iteration.
# The below dict is to prevent the ORM to permanently refetch `line.journal_entry_ids`
line_journal_entries = {line: line.journal_entry_ids for line in statement.line_ids}
for st_line in statement.line_ids:
#upon bank statement confirmation, look if some lines have the account_id set. It would trigger a journal entry
#creation towards that account, with the wanted side-effect to skip that line in the bank reconciliation widget.
journal_entries = line_journal_entries[st_line]
st_line.fast_counterpart_creation()
if not st_line.account_id and not journal_entries.ids and not st_line.statement_id.currency_id.is_zero(st_line.amount):
raise UserError(_('All the account entries lines must be processed in order to close the statement.'))
moves = statement.mapped('line_ids.journal_entry_ids.move_id')
if moves:
moves.filtered(lambda m: m.state != 'posted').post()
statement.message_post(body=_('Statement %s confirmed, journal items were created.') % (statement.name,))
if statement.journal_id.type == 'bank':
# Attach report to the Bank statement
content, content_type = self.env.ref('account.action_report_account_statement').render_qweb_pdf(statement.id)
self.env['ir.attachment'].create({
'name': statement.name and _("Bank Statement %s.pdf") % statement.name or _("Bank Statement.pdf"),
'type': 'binary',
'datas': base64.encodestring(content),
'res_model': statement._name,
'res_id': statement.id
})
statements.write({'state': 'confirm', 'date_done': time.strftime("%Y-%m-%d %H:%M:%S")})
def action_bank_reconcile_bank_statements(self):
self.ensure_one()
bank_stmt_lines = self.mapped('line_ids')
@@ -20,6 +20,9 @@ class AccountBankStatementLine(models.Model):
default=False, copy=False,
help="Technical field holding the number given to the journal entry, automatically set when the statement line is reconciled then stored to set the same number again if the line is cancelled, set to draft and re-processed again.")
def button_confirm_bank(self):
self.statement_id.button_confirm_bank()
def process_reconciliation(self, counterpart_aml_dicts=None, payment_aml_rec=None, new_aml_dicts=None):
""" Match statement lines with existing payments (eg. checks) and/or payables/receivables (eg. invoices and credit notes) and/or new move lines (eg. write-offs).
If any new journal item needs to be created (via new_aml_dicts or counterpart_aml_dicts), a new journal entry will be created and will contain those
@@ -780,7 +780,7 @@ class AccountReconciliation(models.AbstractModel):
amount = st_line.amount
amount_currency = amount
amount_currency_str = ""
amount_str = formatLang(self.env, abs(amount), currency_obj=st_line.currency_id or statement_currency)
amount_str = formatLang(self.env, abs(amount), currency_obj=st_line.foreign_currency_id or statement_currency)
data = {
'id': st_line.id,
@@ -108,6 +108,7 @@ var StatementModel = BasicModel.extend({
init: function (parent, options) {
this._super.apply(this, arguments);
this.reconcileModels = [];
this.reconcileModelsLine = [];
this.lines = {};
this.valuenow = 0;
this.valuemax = 0;
@@ -444,6 +445,7 @@ var StatementModel = BasicModel.extend({
domainReconcile.push(['match_journal_ids', 'in', self.context.active_ids]);
}
var def_reconcileModel = this._loadReconciliationModel({domainReconcile: domainReconcile});
var def_reconcileModelLine=this._loadreconcileModelLine();
var def_account = this._rpc({
model: 'account.account',
method: 'search_read',
@@ -453,7 +455,7 @@ var StatementModel = BasicModel.extend({
self.accounts = _.object(_.pluck(accounts, 'id'), _.pluck(accounts, 'code'));
});
var def_taxes = self._loadTaxes();
return Promise.all([def_statement, def_reconcileModel, def_account, def_taxes]).then(function () {
return Promise.all([def_statement, def_reconcileModel, def_reconcileModelLine, def_account, def_taxes]).then(function () {
_.each(self.lines, function (line) {
line.reconcileModels = self.reconcileModels;
});
@@ -530,6 +532,17 @@ var StatementModel = BasicModel.extend({
});
});
},
_loadreconcileModelLine: function(){
var self = this;
return this._rpc({
model: 'account.reconcile.model.line',
method: 'search_read',
domain: [],
})
.then(function (reconcileModelsLine) {
self.reconcileModelsLine = reconcileModelsLine;
});
},
_loadTaxes: function(){
var self = this;
self.taxes = {};
@@ -563,7 +576,7 @@ var StatementModel = BasicModel.extend({
var self = this;
var line = this.getLine(handle);
var reconcileModel = _.find(this.reconcileModels, function (r) {return r.id === reconcileModelId;});
var fields = ['account_id', 'amount', 'amount_type', 'analytic_account_id', 'journal_id', 'label', 'force_tax_included', 'tax_ids', 'analytic_tag_ids', 'to_check', 'amount_from_label_regex', 'decimal_separator'];
var fields = ['account_id', 'line_ids', 'amount', 'amount_type', 'analytic_account_id', 'journal_id', 'label', 'force_tax_included', 'tax_ids', 'analytic_tag_ids', 'to_check', 'amount_from_label_regex', 'decimal_separator'];
this._blurProposition(handle);
var focus = this._formatQuickCreate(line, _.pick(reconcileModel, fields));
focus.reconcileModelId = reconcileModelId;
@@ -1103,7 +1116,7 @@ var StatementModel = BasicModel.extend({
_formatMany2ManyTagsTax: function(value) {
var res = [];
for (var i=0; i<value.length; i++) {
res.push({id: value[i], display_name: this.taxes[value[i]] ? this.taxes[value[i]].display_name : ''});
res.push({id: value[i], display_name: this.taxes[value[i]] ? this.taxes[value[i]].display_name : '',});
}
return res;
},
@@ -1293,18 +1306,35 @@ var StatementModel = BasicModel.extend({
default:
amount = values.amount !== undefined ? values.amount : line.balance.amount;
}
var account_id = false;
var tax_ids = false;
var analytic_account_id = false;
if(Array.isArray(values.line_ids)){
if(values.line_ids.length > 0){
account_id = {};
var get_account_id = _.filter( this.reconcileModelsLine, function(value){
return value.id == values.line_ids[0];
});
if(get_account_id[0].account_id.length > 0){
account_id['id'] = get_account_id[0].account_id[0];
}
if(get_account_id[0].tax_ids.length > 0){
tax_ids = get_account_id[0].tax_ids;
}
analytic_account_id = get_account_id[0].analytic_account_id;
}
}
var final_account = values.hasOwnProperty('account_id') ? {'id':values.account_id[0]} : account_id;
var prop = {
'id': _.uniqueId('createLine'),
'label': values.label || line.st_line.name,
'account_id': account,
'account_code': account ? this.accounts[account.id] : '',
'analytic_account_id': this._formatNameGet(values.analytic_account_id),
'line_ids': values.line_ids || [],
'account_id': final_account,
'account_code': final_account ? this.accounts[final_account.hasOwnProperty('id') ? final_account.id : final_account ] : '',
'analytic_account_id': this._formatNameGet(analytic_account_id),
'analytic_tag_ids': this._formatMany2ManyTags(values.analytic_tag_ids || []),
'journal_id': this._formatNameGet(values.journal_id),
'tax_ids': this._formatMany2ManyTagsTax(values.tax_ids || []),
'tag_ids': values.tag_ids,
'tax_ids': this._formatMany2ManyTagsTax(tax_ids || []),
'tax_repartition_line_id': values.tax_repartition_line_id,
'debit': 0,
'credit': 0,
@@ -1315,6 +1345,7 @@ var StatementModel = BasicModel.extend({
'link': values.link,
'display': true,
'invalid': true,
'line_ids': values.line_ids || [],
'to_check': !!values.to_check,
'__tax_to_recompute': true,
'__focus': '__focus' in values ? values.__focus : true,
@@ -1455,7 +1486,7 @@ var StatementModel = BasicModel.extend({
* datas allowing manual reconciliation
*/
var ManualModel = StatementModel.extend({
quickCreateFields: ['account_id', 'journal_id', 'amount', 'analytic_account_id', 'label', 'tax_ids', 'force_tax_included', 'analytic_tag_ids', 'date', 'to_check'],
quickCreateFields: ['line_ids', 'account_id', 'journal_id', 'amount', 'analytic_account_id', 'label', 'tax_ids', 'force_tax_included', 'analytic_tag_ids', 'date', 'to_check'],
modes: ['create', 'match'],
@@ -1514,9 +1545,10 @@ var ManualModel = StatementModel.extend({
domainReconcile.push(['company_id', 'in', company_ids]);
}
var def_reconcileModel = this._loadReconciliationModel({domainReconcile: domainReconcile});
var def_reconcileModelLine = this._loadreconcileModelLine();
var def_taxes = this._loadTaxes();
return Promise.all([def_reconcileModel, def_account, def_taxes]).then(function () {
return Promise.all([def_reconcileModel, def_account, def_reconcileModelLine, def_taxes]).then(function () {
switch(context.mode) {
case 'customers':
case 'suppliers':
@@ -1804,6 +1836,7 @@ var ManualModel = StatementModel.extend({
prop.credit = prop.credit !== 0 ? 0 : tmp_value;
prop.debit = prop.debit !== 0 ? 0 : tmp_value;
prop.amount = -prop.amount;
// prop.line_ids = -prop.line_ids;
prop.journal_id = self._formatNameGet(prop.journal_id || line.journal_id);
prop.to_check = !!prop.to_check;
});
@@ -101,9 +101,9 @@
<tr>
<td class="cell_account_code"><t t-esc="state.st_line.account_code"/></td>
<td class="cell_due_date"><t t-esc="state.st_line.date"/></td>
<td class="cell_label"><t t-if="state.st_line.name" t-esc="state.st_line.name"/> <t t-if="state.st_line.amount_currency_str"> (<t t-esc="state.st_line.amount_currency_str"/>)</t></td>
<td class="cell_left"><t t-if="state.st_line.amount &gt; 0"><t t-raw="state.st_line.amount_str"/></t></td>
<td class="cell_right"><t t-if="state.st_line.amount &lt; 0"><t t-raw="state.st_line.amount_str"/></t></td>
<td class="cell_label"><t t-if="state.st_line.name" t-esc="state.st_line.name"/> <t t-if="state.st_line.amount_str"> (<t t-esc="state.st_line.amount_str"/>)</t></td>
<td class="cell_left"><t t-if="state.st_line.amount &gt; 0"><t t-raw="state.st_line.amount_currency_str"/></t></td>
<td class="cell_right"><t t-if="state.st_line.amount &lt; 0"><t t-raw="state.st_line.amount_currency_str"/></t></td>
<td class="cell_info_popover"></td>
</tr>
</thead>