|
|
@ -6,71 +6,82 @@ from odoo import _, fields, models |
|
|
|
|
|
|
|
|
|
|
|
class BankReconciliationXlsx(models.AbstractModel): |
|
|
|
_name = 'report.bank.reconciliation.xlsx' |
|
|
|
_description = 'Bank Reconciliation XLSX Report' |
|
|
|
_inherit = 'report.report_xlsx.abstract' |
|
|
|
_name = "report.bank.reconciliation.xlsx" |
|
|
|
_description = "Bank Reconciliation XLSX Report" |
|
|
|
_inherit = "report.report_xlsx.abstract" |
|
|
|
|
|
|
|
def _compute_account_balance(self, journal, date): |
|
|
|
bank_account = journal.default_debit_account_id |
|
|
|
amount_field = 'balance' |
|
|
|
# TODO: add support for bank accounts in foreign currency |
|
|
|
# if not o.currency_id else 'amount_currency' |
|
|
|
query = """ |
|
|
|
SELECT sum(%s) FROM account_move_line |
|
|
|
WHERE account_id=%%s AND date <= %%s""" % (amount_field, ) |
|
|
|
SELECT sum(balance) FROM account_move_line |
|
|
|
WHERE account_id=%s AND date <= %s""" |
|
|
|
self.env.cr.execute(query, (bank_account.id, date)) |
|
|
|
query_results = self.env.cr.dictfetchall() |
|
|
|
if query_results: |
|
|
|
account_bal = query_results[0].get('sum') or 0.0 |
|
|
|
account_bal = query_results[0].get("sum") or 0.0 |
|
|
|
else: |
|
|
|
account_bal = 0.0 |
|
|
|
return account_bal |
|
|
|
|
|
|
|
def _prepare_move_lines(self, journal, date): |
|
|
|
bank_account = journal.default_debit_account_id |
|
|
|
mlines = self.env['account.move.line'].search([ |
|
|
|
('account_id', '=', bank_account.id), |
|
|
|
('journal_id', '=', journal.id), # to avoid initial line |
|
|
|
('date', '<=', date), |
|
|
|
'|', ('statement_line_date', '=', False), |
|
|
|
('statement_line_date', '>', date)]) |
|
|
|
mlines = self.env["account.move.line"].search( |
|
|
|
[ |
|
|
|
("account_id", "=", bank_account.id), |
|
|
|
("journal_id", "=", journal.id), # to avoid initial line |
|
|
|
("date", "<=", date), |
|
|
|
"|", |
|
|
|
("statement_line_date", "=", False), |
|
|
|
("statement_line_date", ">", date), |
|
|
|
] |
|
|
|
) |
|
|
|
res = [] |
|
|
|
for mline in mlines: |
|
|
|
move = mline.move_id |
|
|
|
cpart = [] |
|
|
|
for line in move.line_ids: |
|
|
|
if ( |
|
|
|
line.account_id != bank_account and |
|
|
|
line.account_id.code not in cpart): |
|
|
|
line.account_id != bank_account |
|
|
|
and line.account_id.code not in cpart |
|
|
|
): |
|
|
|
cpart.append(line.account_id.code) |
|
|
|
counterpart = ' ,'.join(cpart) |
|
|
|
res.append({ |
|
|
|
'date': mline.date, |
|
|
|
'label': mline.name, |
|
|
|
'ref': mline.ref or '', |
|
|
|
'partner': mline.partner_id.display_name or '', |
|
|
|
'amount': mline.balance, |
|
|
|
'statement_line_date': mline.statement_line_date or '', |
|
|
|
'move_number': move.name, |
|
|
|
'counterpart': counterpart, |
|
|
|
}) |
|
|
|
counterpart = " ,".join(cpart) |
|
|
|
res.append( |
|
|
|
{ |
|
|
|
"date": mline.date, |
|
|
|
"label": mline.name, |
|
|
|
"ref": mline.ref or "", |
|
|
|
"partner": mline.partner_id.display_name or "", |
|
|
|
"amount": mline.balance, |
|
|
|
"statement_line_date": mline.statement_line_date or "", |
|
|
|
"move_number": move.name, |
|
|
|
"counterpart": counterpart, |
|
|
|
} |
|
|
|
) |
|
|
|
return res |
|
|
|
|
|
|
|
def _prepare_draft_statement_lines(self, journal, date): |
|
|
|
blines = self.env['account.bank.statement.line'].search([ |
|
|
|
('journal_entry_ids', '=', False), |
|
|
|
('journal_id', '=', journal.id), |
|
|
|
('date', '<=', date)]) |
|
|
|
blines = self.env["account.bank.statement.line"].search( |
|
|
|
[ |
|
|
|
("journal_entry_ids", "=", False), |
|
|
|
("journal_id", "=", journal.id), |
|
|
|
("date", "<=", date), |
|
|
|
] |
|
|
|
) |
|
|
|
res = [] |
|
|
|
for bline in blines: |
|
|
|
res.append({ |
|
|
|
'date': bline.date, |
|
|
|
'label': bline.name, |
|
|
|
'ref': bline.ref or '', |
|
|
|
'partner': bline.partner_id.display_name or '', |
|
|
|
'amount': bline.amount, |
|
|
|
'statement_ref': bline.statement_id.display_name, |
|
|
|
}) |
|
|
|
res.append( |
|
|
|
{ |
|
|
|
"date": bline.date, |
|
|
|
"label": bline.name, |
|
|
|
"ref": bline.ref or "", |
|
|
|
"partner": bline.partner_id.display_name or "", |
|
|
|
"amount": bline.amount, |
|
|
|
"statement_ref": bline.statement_id.display_name, |
|
|
|
} |
|
|
|
) |
|
|
|
return res |
|
|
|
|
|
|
|
def generate_xlsx_report(self, workbook, data, wizard): |
|
|
@ -83,57 +94,77 @@ class BankReconciliationXlsx(models.AbstractModel): |
|
|
|
lang_code = self.env.user.lang |
|
|
|
lang = False |
|
|
|
if lang_code: |
|
|
|
lang = self.env['res.lang'].search([('code', '=', lang_code)]) |
|
|
|
lang = self.env["res.lang"].search([("code", "=", lang_code)]) |
|
|
|
if not lang: |
|
|
|
lang = self.env['res.lang'].search([], limit=1) |
|
|
|
xls_date_format = lang.date_format.replace('%Y', 'yyyy').\ |
|
|
|
replace('%m', 'mm').replace('%d', 'dd').replace('%y', 'yy') |
|
|
|
lang = self.env["res.lang"].search([], limit=1) |
|
|
|
xls_date_format = ( |
|
|
|
lang.date_format.replace("%Y", "yyyy") |
|
|
|
.replace("%m", "mm") |
|
|
|
.replace("%d", "dd") |
|
|
|
.replace("%y", "yy") |
|
|
|
) |
|
|
|
|
|
|
|
doc_title = workbook.add_format({'bold': True, 'font_size': 16}) |
|
|
|
col_title = workbook.add_format({ |
|
|
|
'bold': True, 'bg_color': '#e2e2fa', |
|
|
|
'text_wrap': True, 'font_size': 10, |
|
|
|
}) |
|
|
|
title_right = workbook.add_format({ |
|
|
|
'bold': True, 'bg_color': '#e6e6fa', |
|
|
|
'font_size': 10, 'align': 'right', |
|
|
|
}) |
|
|
|
title_date = workbook.add_format({ |
|
|
|
'bg_color': '#f6f6ff', 'bold': True, |
|
|
|
'num_format': xls_date_format, |
|
|
|
'font_size': 10, |
|
|
|
'align': 'left'}) |
|
|
|
label_bold = workbook.add_format({ |
|
|
|
'bold': True, 'text_wrap': False, 'font_size': 10}) |
|
|
|
none = workbook.add_format({ |
|
|
|
'bold': True, 'font_size': 10, 'align': 'right'}) |
|
|
|
regular = workbook.add_format({'font_size': 10}) |
|
|
|
if '%' in xls_date_format: |
|
|
|
doc_title = workbook.add_format({"bold": True, "font_size": 16}) |
|
|
|
col_title = workbook.add_format( |
|
|
|
{ |
|
|
|
"bold": True, |
|
|
|
"bg_color": "#e2e2fa", |
|
|
|
"text_wrap": True, |
|
|
|
"font_size": 10, |
|
|
|
} |
|
|
|
) |
|
|
|
title_right = workbook.add_format( |
|
|
|
{ |
|
|
|
"bold": True, |
|
|
|
"bg_color": "#e6e6fa", |
|
|
|
"font_size": 10, |
|
|
|
"align": "right", |
|
|
|
} |
|
|
|
) |
|
|
|
title_date = workbook.add_format( |
|
|
|
{ |
|
|
|
"bg_color": "#f6f6ff", |
|
|
|
"bold": True, |
|
|
|
"num_format": xls_date_format, |
|
|
|
"font_size": 10, |
|
|
|
"align": "left", |
|
|
|
} |
|
|
|
) |
|
|
|
label_bold = workbook.add_format( |
|
|
|
{"bold": True, "text_wrap": False, "font_size": 10} |
|
|
|
) |
|
|
|
none = workbook.add_format( |
|
|
|
{"bold": True, "font_size": 10, "align": "right"} |
|
|
|
) |
|
|
|
regular = workbook.add_format({"font_size": 10}) |
|
|
|
if "%" in xls_date_format: |
|
|
|
# fallback |
|
|
|
xls_date_format = 'yyyy-mm-dd' |
|
|
|
regular_date = workbook.add_format({ |
|
|
|
'num_format': xls_date_format, |
|
|
|
'font_size': 10, |
|
|
|
'align': 'left'}) |
|
|
|
cur_format = u'#,##0.00 %s' % ( |
|
|
|
o.company_id.currency_id.symbol or |
|
|
|
o.company_id.currency_id.name) |
|
|
|
xls_date_format = "yyyy-mm-dd" |
|
|
|
regular_date = workbook.add_format( |
|
|
|
{"num_format": xls_date_format, "font_size": 10, "align": "left"} |
|
|
|
) |
|
|
|
cur_format = u"#,##0.00 %s" % ( |
|
|
|
o.company_id.currency_id.symbol or o.company_id.currency_id.name |
|
|
|
) |
|
|
|
# It seems that Excel replaces automatically the decimal |
|
|
|
# and thousand separator by those of the language under which |
|
|
|
# Excel runs |
|
|
|
regular_currency = workbook.add_format( |
|
|
|
{'num_format': cur_format, 'font_size': 10}) |
|
|
|
regular_currency_bg = workbook.add_format({ |
|
|
|
'num_format': cur_format, 'font_size': 10, |
|
|
|
'bg_color': '#f6f6ff'}) |
|
|
|
{"num_format": cur_format, "font_size": 10} |
|
|
|
) |
|
|
|
regular_currency_bg = workbook.add_format( |
|
|
|
{"num_format": cur_format, "font_size": 10, "bg_color": "#f6f6ff"} |
|
|
|
) |
|
|
|
# End styles |
|
|
|
|
|
|
|
sheet = workbook.add_worksheet(o.code or o.name) |
|
|
|
sheet.write( |
|
|
|
0, 0, |
|
|
|
_('%s - %s - Bank Reconciliation') % ( |
|
|
|
o.company_id.name, o.display_name), |
|
|
|
doc_title) |
|
|
|
0, |
|
|
|
0, |
|
|
|
_("%s - %s - Bank Reconciliation") |
|
|
|
% (o.company_id.name, o.display_name), |
|
|
|
doc_title, |
|
|
|
) |
|
|
|
sheet.set_row(0, 26) |
|
|
|
sheet.set_row(1, 25) |
|
|
|
sheet.set_column(0, 0, 10) |
|
|
@ -151,32 +182,38 @@ class BankReconciliationXlsx(models.AbstractModel): |
|
|
|
row += 2 |
|
|
|
bank_account = o.default_debit_account_id |
|
|
|
for col in range(3): |
|
|
|
sheet.write(row, col, '', title_right) |
|
|
|
sheet.write( |
|
|
|
row, 3, |
|
|
|
_('Balance %s:') % bank_account.code, title_right) |
|
|
|
sheet.write(row, col, "", title_right) |
|
|
|
sheet.write(row, 3, _("Balance %s:") % bank_account.code, title_right) |
|
|
|
account_bal = self._compute_account_balance(o, date) |
|
|
|
|
|
|
|
sheet.write(row, 4, account_bal, regular_currency_bg) |
|
|
|
bank_bal = account_bal |
|
|
|
formula = '=E%d' % (row + 1) |
|
|
|
formula = "=E%d" % (row + 1) |
|
|
|
# 2) Show account move line that are not linked to bank statement |
|
|
|
# line or linked to a statement line after the date |
|
|
|
row += 2 |
|
|
|
sheet.write( |
|
|
|
row, 0, _( |
|
|
|
'Journal items of account %s not linked to a bank ' |
|
|
|
'statement line:') % bank_account.code, |
|
|
|
label_bold) |
|
|
|
row, |
|
|
|
0, |
|
|
|
_("Journal items of account %s not linked to a bank " "statement line:") |
|
|
|
% bank_account.code, |
|
|
|
label_bold, |
|
|
|
) |
|
|
|
mlines = self._prepare_move_lines(o, date) |
|
|
|
if not mlines: |
|
|
|
sheet.write(row, 4, _('NONE'), none) |
|
|
|
sheet.write(row, 4, _("NONE"), none) |
|
|
|
else: |
|
|
|
row += 1 |
|
|
|
col_labels = [ |
|
|
|
_('Date'), _('Label'), _('Ref.'), _('Partner'), |
|
|
|
_('Amount'), _('Statement Line Date'), _('Move Number'), |
|
|
|
_('Counter-part')] |
|
|
|
_("Date"), |
|
|
|
_("Label"), |
|
|
|
_("Ref."), |
|
|
|
_("Partner"), |
|
|
|
_("Amount"), |
|
|
|
_("Statement Line Date"), |
|
|
|
_("Move Number"), |
|
|
|
_("Counter-part"), |
|
|
|
] |
|
|
|
col = 0 |
|
|
|
for col_label in col_labels: |
|
|
|
sheet.write(row, col, col_label, col_title) |
|
|
@ -185,33 +222,36 @@ class BankReconciliationXlsx(models.AbstractModel): |
|
|
|
for mline in mlines: |
|
|
|
row += 1 |
|
|
|
m_end_row = row |
|
|
|
bank_bal -= mline['amount'] |
|
|
|
sheet.write(row, 0, mline['date'], regular_date) |
|
|
|
sheet.write(row, 1, mline['label'], regular) |
|
|
|
sheet.write(row, 2, mline['ref'], regular) |
|
|
|
sheet.write(row, 3, mline['partner'], regular) |
|
|
|
sheet.write(row, 4, mline['amount'], regular_currency) |
|
|
|
sheet.write( |
|
|
|
row, 5, mline['statement_line_date'], regular_date) |
|
|
|
sheet.write(row, 6, mline['move_number'], regular) |
|
|
|
sheet.write(row, 7, mline['counterpart'], regular) |
|
|
|
bank_bal -= mline["amount"] |
|
|
|
sheet.write(row, 0, mline["date"], regular_date) |
|
|
|
sheet.write(row, 1, mline["label"], regular) |
|
|
|
sheet.write(row, 2, mline["ref"], regular) |
|
|
|
sheet.write(row, 3, mline["partner"], regular) |
|
|
|
sheet.write(row, 4, mline["amount"], regular_currency) |
|
|
|
sheet.write(row, 5, mline["statement_line_date"], regular_date) |
|
|
|
sheet.write(row, 6, mline["move_number"], regular) |
|
|
|
sheet.write(row, 7, mline["counterpart"], regular) |
|
|
|
|
|
|
|
formula += '-SUM(E%d:E%d)' % (m_start_row + 1, m_end_row + 1) |
|
|
|
formula += "-SUM(E%d:E%d)" % (m_start_row + 1, m_end_row + 1) |
|
|
|
|
|
|
|
# 3) Add draft bank statement lines |
|
|
|
row += 2 # skip 1 line |
|
|
|
sheet.write( |
|
|
|
row, 0, _( |
|
|
|
'Draft bank statement lines:'), |
|
|
|
label_bold) |
|
|
|
sheet.write(row, 0, _("Draft bank statement lines:"), label_bold) |
|
|
|
blines = self._prepare_draft_statement_lines(o, date) |
|
|
|
if not blines: |
|
|
|
sheet.write(row, 4, _('NONE'), none) |
|
|
|
sheet.write(row, 4, _("NONE"), none) |
|
|
|
else: |
|
|
|
row += 1 |
|
|
|
col_labels = [ |
|
|
|
_('Date'), _('Label'), _('Ref.'), |
|
|
|
_('Partner'), _('Amount'), _('Statement Ref.'), '', ''] |
|
|
|
_("Date"), |
|
|
|
_("Label"), |
|
|
|
_("Ref."), |
|
|
|
_("Partner"), |
|
|
|
_("Amount"), |
|
|
|
_("Statement Ref."), |
|
|
|
"", |
|
|
|
"", |
|
|
|
] |
|
|
|
col = 0 |
|
|
|
for col_label in col_labels: |
|
|
|
sheet.write(row, col, col_label, col_title) |
|
|
@ -220,31 +260,35 @@ class BankReconciliationXlsx(models.AbstractModel): |
|
|
|
for bline in blines: |
|
|
|
row += 1 |
|
|
|
b_end_row = row |
|
|
|
bank_bal += bline['amount'] |
|
|
|
sheet.write(row, 0, bline['date'], regular_date) |
|
|
|
sheet.write(row, 1, bline['label'], regular) |
|
|
|
sheet.write(row, 2, bline['ref'], regular) |
|
|
|
sheet.write(row, 3, bline['partner'], regular) |
|
|
|
sheet.write(row, 4, bline['amount'], regular_currency) |
|
|
|
sheet.write( |
|
|
|
row, 5, bline['statement_ref'], regular_currency) |
|
|
|
formula += '+SUM(E%d:E%d)' % (b_start_row + 1, b_end_row + 1) |
|
|
|
bank_bal += bline["amount"] |
|
|
|
sheet.write(row, 0, bline["date"], regular_date) |
|
|
|
sheet.write(row, 1, bline["label"], regular) |
|
|
|
sheet.write(row, 2, bline["ref"], regular) |
|
|
|
sheet.write(row, 3, bline["partner"], regular) |
|
|
|
sheet.write(row, 4, bline["amount"], regular_currency) |
|
|
|
sheet.write(row, 5, bline["statement_ref"], regular_currency) |
|
|
|
formula += "+SUM(E%d:E%d)" % (b_start_row + 1, b_end_row + 1) |
|
|
|
|
|
|
|
# 4) Theoric bank account balance at the bank |
|
|
|
row += 2 |
|
|
|
for col in range(3): |
|
|
|
sheet.write(row, col, '', title_right) |
|
|
|
sheet.write(row, col, "", title_right) |
|
|
|
sheet.write( |
|
|
|
row, 3, _('Computed Bank Account Balance at the Bank:'), |
|
|
|
title_right) |
|
|
|
sheet.write_formula( |
|
|
|
row, 4, formula, regular_currency_bg, bank_bal) |
|
|
|
row, 3, _("Computed Bank Account Balance at the Bank:"), title_right |
|
|
|
) |
|
|
|
sheet.write_formula(row, 4, formula, regular_currency_bg, bank_bal) |
|
|
|
if no_bank_journal: |
|
|
|
sheet = workbook.add_worksheet(_('No Bank Journal')) |
|
|
|
sheet = workbook.add_worksheet(_("No Bank Journal")) |
|
|
|
sheet.set_row(0, 30) |
|
|
|
warn_msg = workbook.add_format( |
|
|
|
{'bold': True, 'font_size': 16, 'font_color': '#003b6f'}) |
|
|
|
{"bold": True, "font_size": 16, "font_color": "#003b6f"} |
|
|
|
) |
|
|
|
sheet.write( |
|
|
|
0, 0, _( |
|
|
|
0, |
|
|
|
0, |
|
|
|
_( |
|
|
|
"No bank journal selected. " |
|
|
|
"This report is only for bank journals."), warn_msg) |
|
|
|
"This report is only for bank journals." |
|
|
|
), |
|
|
|
warn_msg, |
|
|
|
) |