You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

323 lines
14 KiB

# © 2016 Julien Coux (Camptocamp)
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import models, api
from odoo.tools import float_is_zero
from datetime import date, datetime
import operator
class OpenItemsReport(models.AbstractModel):
_name = 'report.account_financial_report.open_items'
_description = "Open Items Report"
@api.model
def get_html(self, given_context=None):
return self._get_html()
def _get_html(self):
result = {}
rcontext = {}
context = dict(self.env.context)
rcontext.update(context.get('data'))
active_id = context.get('active_id')
wiz = self.env['open.items.report.wizard'].browse(active_id)
rcontext['o'] = wiz
result['html'] = self.env.ref(
'account_financial_report.report_open_items').render(rcontext)
return result
def _get_account_partial_reconciled(self, company_id, date_at_object):
domain = [('max_date', '>', date_at_object),
('company_id', '=', company_id)]
fields = ['debit_move_id', 'credit_move_id', 'amount']
accounts_partial_reconcile = \
self.env['account.partial.reconcile'].search_read(
domain=domain,
fields=fields
)
debit_amount = {}
credit_amount = {}
for account_partial_reconcile_data in accounts_partial_reconcile:
debit_move_id = account_partial_reconcile_data['debit_move_id'][0]
credit_move_id = account_partial_reconcile_data['credit_move_id'][0]
if debit_move_id not in debit_amount.keys():
debit_amount[debit_move_id] = 0.0
debit_amount[debit_move_id] += \
account_partial_reconcile_data['amount']
if credit_move_id not in credit_amount.keys():
credit_amount[credit_move_id] = 0.0
credit_amount[credit_move_id] += \
account_partial_reconcile_data['amount']
account_partial_reconcile_data.update({
'debit_move_id': debit_move_id,
'credit_move_id': credit_move_id,
})
return accounts_partial_reconcile, debit_amount, credit_amount
@api.model
def _get_new_move_lines_domain(self, new_ml_ids, account_ids, company_id,
partner_ids, target_moves):
domain = [('account_id', 'in', account_ids),
('company_id', '=', company_id),
('id', 'in', new_ml_ids)]
if partner_ids:
domain += [('partner_id', 'in', partner_ids)]
if target_moves == 'posted':
domain += [('move_id.state', '=', 'posted')]
return domain
def _recalculate_move_lines(self, move_lines, debit_ids, credit_ids,
debit_amount, credit_amount, ml_ids,
account_ids, company_id, partner_ids,
target_moves):
debit_ids = set(debit_ids)
credit_ids = set(credit_ids)
in_credit_but_not_in_debit = credit_ids - debit_ids
reconciled_ids = list(debit_ids) + list(in_credit_but_not_in_debit)
reconciled_ids = set(reconciled_ids)
ml_ids = set(ml_ids)
new_ml_ids = reconciled_ids - ml_ids
new_ml_ids = list(new_ml_ids)
new_domain = self._get_new_move_lines_domain(new_ml_ids, account_ids,
company_id, partner_ids,
target_moves)
ml_fields = [
'id', 'name', 'date', 'move_id', 'journal_id', 'account_id',
'partner_id', 'amount_residual', 'date_maturity', 'ref',
'debit', 'credit', 'reconciled', 'currency_id', 'amount_currency',
'amount_residual_currency']
new_move_lines = self.env['account.move.line'].search_read(
domain=new_domain, fields=ml_fields
)
move_lines = move_lines + new_move_lines
for move_line in move_lines:
ml_id = move_line['id']
if ml_id in debit_ids:
move_line['amount_residual'] += debit_amount[ml_id]
if ml_id in credit_ids:
move_line['amount_residual'] -= credit_amount[ml_id]
return move_lines
@api.model
def _get_move_lines_domain(self, company_id, account_ids, partner_ids,
target_move, date_from):
domain = [('account_id', 'in', account_ids),
('company_id', '=', company_id),
('reconciled', '=', False)]
if partner_ids:
domain += [('partner_id', 'in', partner_ids)]
if target_move == 'posted':
domain += [('move_id.state', '=', 'posted')]
if date_from:
domain += [('date', '>', date_from)]
return domain
def _get_accounts_data(self, accounts_ids):
accounts = self.env['account.account'].browse(accounts_ids)
accounts_data = {}
for account in accounts:
accounts_data.update({account.id: {
'id': account.id,
'code': account.code,
'name': account.name,
'hide_account': False,
'currency_id': account.currency_id or False,
'currency_name': account.currency_id.name}
})
return accounts_data
def _get_journals_data(self, journals_ids):
journals = self.env['account.journal'].browse(journals_ids)
journals_data = {}
for journal in journals:
journals_data.update({journal.id: {'id': journal.id,
'code': journal.code}})
return journals_data
def _get_data(
self, account_ids, partner_ids, date_at_object,
target_move, company_id, date_from):
domain = self._get_move_lines_domain(company_id, account_ids,
partner_ids, target_move,
date_from)
ml_fields = [
'id', 'name', 'date', 'move_id', 'journal_id', 'account_id',
'partner_id', 'amount_residual', 'date_maturity', 'ref',
'debit', 'credit', 'reconciled', 'currency_id', 'amount_currency',
'amount_residual_currency']
move_lines = self.env['account.move.line'].search_read(
domain=domain, fields=ml_fields
)
journals_ids = set()
partners_ids = set()
partners_data = {}
if date_at_object < date.today():
acc_partial_rec, debit_amount, credit_amount = \
self._get_account_partial_reconciled(company_id,
date_at_object)
if acc_partial_rec:
ml_ids = list(map(operator.itemgetter('id'), move_lines))
debit_ids = list(map(operator.itemgetter('debit_move_id'),
acc_partial_rec))
credit_ids = list(map(operator.itemgetter('credit_move_id'),
acc_partial_rec))
move_lines = self._recalculate_move_lines(
move_lines, debit_ids, credit_ids,
debit_amount, credit_amount, ml_ids, account_ids,
company_id, partner_ids, target_move
)
move_lines = [move_line for move_line in move_lines if
move_line['date'] <= date_at_object and not
float_is_zero(move_line['amount_residual'],
precision_digits=2)]
open_items_move_lines_data = {}
for move_line in move_lines:
journals_ids.add(move_line['journal_id'][0])
acc_id = move_line['account_id'][0]
# Partners data
if move_line['partner_id']:
prt_id = move_line['partner_id'][0]
prt_name = move_line['partner_id'][1]
else:
prt_id = 0
prt_name = "Missing Partner"
if prt_id not in partners_ids:
partners_data.update({
prt_id: {'id': prt_id, 'name': prt_name}
})
partners_ids.add(prt_id)
# Move line update
original = 0
if not float_is_zero(move_line['credit'], precision_digits=2):
original = move_line['credit']*(-1)
if not float_is_zero(move_line['debit'], precision_digits=2):
original = move_line['debit']
if move_line['ref'] == move_line['name']:
if move_line['ref']:
ref_label = move_line['ref']
else:
ref_label = ''
elif not move_line['ref']:
ref_label = move_line['name']
elif not move_line['name']:
ref_label = move_line['ref']
else:
ref_label = move_line['ref'] + str(' - ') + move_line['name']
move_line.update({
'date': move_line['date'],
'date_maturity': move_line["date_maturity"]
and move_line["date_maturity"].strftime("%d/%m/%Y"),
'original': original,
'partner_id': prt_id,
'partner_name': prt_name,
'ref_label': ref_label,
'journal_id': move_line['journal_id'][0],
'move_name': move_line['move_id'][1],
'currency_id': move_line['currency_id'][0]
if move_line['currency_id'] else False,
'currency_name': move_line['currency_id'][1]
if move_line['currency_id'] else False,
})
# Open Items Move Lines Data
if acc_id not in open_items_move_lines_data.keys():
open_items_move_lines_data[acc_id] = {prt_id: [move_line]}
else:
if prt_id not in open_items_move_lines_data[acc_id].keys():
open_items_move_lines_data[acc_id][prt_id] = [move_line]
else:
open_items_move_lines_data[acc_id][prt_id].append(move_line)
journals_data = self._get_journals_data(list(journals_ids))
accounts_data = self._get_accounts_data(
open_items_move_lines_data.keys())
return move_lines, partners_data, journals_data, accounts_data, \
open_items_move_lines_data
@api.model
def _calculate_amounts(self, open_items_move_lines_data):
total_amount = {}
for account_id in open_items_move_lines_data.keys():
total_amount[account_id] = {}
total_amount[account_id]['residual'] = 0.0
for partner_id in open_items_move_lines_data[account_id].keys():
total_amount[account_id][partner_id] = {}
total_amount[account_id][partner_id]['residual'] = 0.0
for move_line in open_items_move_lines_data[account_id][
partner_id]:
total_amount[account_id][partner_id]['residual'] += \
move_line['amount_residual']
total_amount[account_id]['residual'] += move_line[
'amount_residual']
return total_amount
@api.model
def _order_open_items_by_date(
self, open_items_move_lines_data, show_partner_details):
new_open_items = {}
if not show_partner_details:
for acc_id in open_items_move_lines_data.keys():
new_open_items[acc_id] = {}
move_lines = []
for prt_id in open_items_move_lines_data[acc_id]:
for move_line in open_items_move_lines_data[acc_id][prt_id]:
move_lines += [move_line]
move_lines = sorted(move_lines, key=lambda k: (k['date']))
new_open_items[acc_id] = move_lines
else:
for acc_id in open_items_move_lines_data.keys():
new_open_items[acc_id] = {}
for prt_id in open_items_move_lines_data[acc_id]:
new_open_items[acc_id][prt_id] = {}
move_lines = []
for move_line in open_items_move_lines_data[acc_id][prt_id]:
move_lines += [move_line]
move_lines = sorted(move_lines, key=lambda k: (k['date']))
new_open_items[acc_id][prt_id] = move_lines
return new_open_items
@api.multi
def _get_report_values(self, docids, data):
wizard_id = data['wizard_id']
company = self.env['res.company'].browse(data['company_id'])
company_id = data['company_id']
account_ids = data['account_ids']
partner_ids = data['partner_ids']
date_at = data['date_at']
date_at_object = datetime.strptime(date_at, '%Y-%m-%d').date()
date_from = data['date_from']
target_move = data['target_move']
show_partner_details = data['show_partner_details']
move_lines_data, partners_data, journals_data, accounts_data, \
open_items_move_lines_data = self._get_data(
account_ids, partner_ids, date_at_object,
target_move, company_id, date_from)
total_amount = self._calculate_amounts(open_items_move_lines_data)
open_items_move_lines_data = self._order_open_items_by_date(
open_items_move_lines_data, show_partner_details
)
return{
'doc_ids': [wizard_id],
'doc_model': 'open.items.report.wizard',
'docs': self.env['open.items.report.wizard'].browse(wizard_id),
'foreign_currency': data['foreign_currency'],
'show_partner_details': data['show_partner_details'],
'company_name': company.display_name,
'currency_name': company.currency_id.name,
'date_at': date_at_object.strftime("%d/%m/%Y"),
'hide_account_at_0': data['hide_account_at_0'],
'target_move': data['target_move'],
'journals_data': journals_data,
'partners_data': partners_data,
'accounts_data': accounts_data,
'total_amount': total_amount,
'Open_Items': open_items_move_lines_data,
}