mirror of
https://gitlab.com/flectra-hq/flectra.git
synced 2026-11-02 09:58:50 -06:00
[FIX]fixed account bank statement import issues
This commit is contained in:
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,
|
||||
|
||||
+45
-12
@@ -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 > 0"><t t-raw="state.st_line.amount_str"/></t></td>
|
||||
<td class="cell_right"><t t-if="state.st_line.amount < 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 > 0"><t t-raw="state.st_line.amount_currency_str"/></t></td>
|
||||
<td class="cell_right"><t t-if="state.st_line.amount < 0"><t t-raw="state.st_line.amount_currency_str"/></t></td>
|
||||
<td class="cell_info_popover"></td>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
Reference in new issue
Block a user