@ -0,0 +1,51 @@ |
|||
.. image:: https://img.shields.io/badge/licence-LGPL--3-green.svg |
|||
:target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html |
|||
:alt: License: LGPL-3 |
|||
|
|||
Dynamic Financial Reports |
|||
========================= |
|||
* Dynamic financial reports for Odoo 18 community editions |
|||
|
|||
Configuration |
|||
============= |
|||
* No need of additional configuration. |
|||
|
|||
License |
|||
------- |
|||
Lesser General Public License, Version 3 (LGPL-3). |
|||
(https://www.gnu.org/licenses/lgpl-3.0.en.html) |
|||
|
|||
Company |
|||
------- |
|||
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
|||
|
|||
Credits |
|||
======= |
|||
* Developer: (v15) Jibin @ Cybrosys, |
|||
(v15) Mehjabin @ Cybrosys, |
|||
(v15) Mily @ Cybrosys, |
|||
(v16) Aneesh @ Cybrosys, |
|||
(v17) Ammu Raj @ Cybrosys, |
|||
(v18) Bhagyadev @ Cybrosys, Contact: odoo@cybrosys.com |
|||
|
|||
Contacts |
|||
-------- |
|||
* Mail Contact : odoo@cybrosys.com |
|||
* Website : https://cybrosys.com |
|||
|
|||
Bug Tracker |
|||
----------- |
|||
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. |
|||
|
|||
Maintainer |
|||
========== |
|||
.. image:: https://cybrosys.com/images/logo.png |
|||
:target: https://cybrosys.com |
|||
|
|||
This module is maintained by Cybrosys Technologies. |
|||
|
|||
For support and more information, please visit `Our Website <https://cybrosys.com/>`__ |
|||
|
|||
Further information |
|||
=================== |
|||
HTML Description: `<static/description/index.html>`__ |
@ -0,0 +1,23 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Bhagyadev KP (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
from . import controllers |
|||
from . import models |
@ -0,0 +1,81 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Bhagyadev KP (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
{ |
|||
'name': 'Odoo18 Dynamic Accounting Reports', |
|||
'version': '18.0.1.0.0', |
|||
'category': 'Accounting', |
|||
'summary': "Odoo 18 Accounting Financial Reports,Dynamic Accounting Reports, Dynamic Financial Reports,Dynamic Report Odoo18, Odoo18,Financial Reports, Odoo18 Accounting,Accounting, Odoo Apps", |
|||
'description': "This module creates dynamic Accounting General Ledger, Trial" |
|||
"Balance, Balance Sheet, Profit and Loss, Cash Book, Partner" |
|||
"Ledger, Aged Payable, Aged Receivable, Bank book and Tax" |
|||
"Reports in Odoo 18 community edition, Reporting, Odoo18 Accounting, odoo18 reporting, odoo18, odoo18 accounts reports", |
|||
'author': 'Cybrosys Techno Solutions', |
|||
'company': 'Cybrosys Techno Solutions', |
|||
'maintainer': 'Cybrosys Techno Solutions', |
|||
'website': "https://www.cybrosys.com", |
|||
'depends': ['base_accounting_kit'], |
|||
'data': [ |
|||
'security/ir.model.access.csv', |
|||
'views/accounting_report_views.xml', |
|||
'report/trial_balance.xml', |
|||
'report/general_ledger_templates.xml', |
|||
'report/financial_report_template.xml', |
|||
'report/partner_ledger_templates.xml', |
|||
'report/financial_reports_views.xml', |
|||
'report/balance_sheet_report_templates.xml', |
|||
'report/bank_book_templates.xml', |
|||
'report/aged_payable_templates.xml', |
|||
'report/aged_receivable_templates.xml', |
|||
'report/tax_report_templates.xml', |
|||
], |
|||
'assets': { |
|||
'web.assets_backend': [ |
|||
'dynamic_accounts_report/static/src/xml/general_ledger_view.xml', |
|||
'dynamic_accounts_report/static/src/xml/trial_balance_view.xml', |
|||
'dynamic_accounts_report/static/src/xml/cash_flow_templates.xml', |
|||
'dynamic_accounts_report/static/src/xml/bank_flow_templates.xml', |
|||
'dynamic_accounts_report/static/src/xml/profit_and_loss_templates.xml', |
|||
'dynamic_accounts_report/static/src/xml/balance_sheet_template.xml', |
|||
'dynamic_accounts_report/static/src/xml/partner_ledger_view.xml', |
|||
'dynamic_accounts_report/static/src/xml/aged_payable_report_views.xml', |
|||
'dynamic_accounts_report/static/src/xml/aged_receivable_report_views.xml', |
|||
'dynamic_accounts_report/static/src/xml/tax_report_views.xml', |
|||
'dynamic_accounts_report/static/src/css/accounts_report.css', |
|||
'dynamic_accounts_report/static/src/js/general_ledger.js', |
|||
'dynamic_accounts_report/static/src/js/trial_balance.js', |
|||
'dynamic_accounts_report/static/src/js/cash_flow.js', |
|||
'dynamic_accounts_report/static/src/js/bank_flow.js', |
|||
'dynamic_accounts_report/static/src/js/profit_and_loss.js', |
|||
'dynamic_accounts_report/static/src/js/balance_sheet.js', |
|||
'dynamic_accounts_report/static/src/js/partner_ledger.js', |
|||
'dynamic_accounts_report/static/src/js/aged_payable_report.js', |
|||
'dynamic_accounts_report/static/src/js/aged_receivable_report.js', |
|||
'dynamic_accounts_report/static/src/js/tax_report.js', |
|||
'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js' |
|||
], |
|||
}, |
|||
'images': ['static/description/banner.png'], |
|||
'license': 'LGPL-3', |
|||
'installable': True, |
|||
'auto_install': False, |
|||
'application': False, |
|||
} |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Bhagyadev KP (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
from . import controllers |
@ -0,0 +1,71 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Bhagyadev KP (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
import json |
|||
from odoo import http |
|||
from odoo.http import content_disposition, request |
|||
from odoo.tools import html_escape |
|||
|
|||
|
|||
class XLSXReportController(http.Controller): |
|||
@http.route('/xlsx_report', type='http', auth='user', methods=['POST'], |
|||
csrf=False) |
|||
def get_report_xlsx(self, model, data, output_format, report_name, |
|||
report_action): |
|||
"""Generate an XLSX report based on the provided data and return it as |
|||
a response. |
|||
Args: |
|||
model (str): The name of the model on which the report is based. |
|||
data (str): The data required for generating the report. |
|||
output_format (str): The desired output format for the report |
|||
(e.g., 'xlsx'). |
|||
report_name (str): The name to be given to the generated report |
|||
file. |
|||
Returns: |
|||
Response: The generated report file as a response. |
|||
Raises: |
|||
Exception: If an error occurs during report generation. |
|||
""" |
|||
uid = request.session.uid |
|||
report_obj = request.env[model].with_user(uid) |
|||
token = 'dummy-because-api-expects-one' |
|||
try: |
|||
if output_format == 'xlsx': |
|||
response = request.make_response( |
|||
None, |
|||
headers=[ |
|||
('Content-Type', 'application/vnd.ms-excel'), |
|||
('Content-Disposition', |
|||
content_disposition(report_name + '.xlsx')) |
|||
] |
|||
) |
|||
report_obj.get_xlsx_report(data, response, report_name, |
|||
report_action) |
|||
response.set_cookie('fileToken', token) |
|||
return response |
|||
except Exception as e: |
|||
se = http.serialize_exception(e) |
|||
error = { |
|||
'code': 200, |
|||
'message': 'Odoo Server Error', |
|||
'data': se |
|||
} |
|||
return request.make_response(html_escape(json.dumps(error))) |
@ -0,0 +1,6 @@ |
|||
## Module <dynamic_accounts_report> |
|||
|
|||
#### 18.10.2024 |
|||
#### Version 18.0.1.0.0 |
|||
#### ADD |
|||
- Initial commit for Dynamic Accounts Reports |
@ -0,0 +1,30 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Bhagyadev KP (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
from . import account_general_ledger |
|||
from . import account_partner_ledger |
|||
from . import account_trial_balance |
|||
from . import aged_payable_report |
|||
from . import aged_receivable_report |
|||
from . import bank_book_report |
|||
from . import cash_book_report |
|||
from . import dynamic_balance_sheet_report |
|||
from . import tax_report |
@ -0,0 +1,329 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Bhagyadev KP (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
import io |
|||
import json |
|||
import calendar |
|||
from dateutil.relativedelta import relativedelta |
|||
import xlsxwriter |
|||
from odoo import api, fields, models |
|||
from datetime import datetime |
|||
from odoo.tools import date_utils |
|||
|
|||
|
|||
class AccountGeneralLedger(models.TransientModel): |
|||
"""For creating General Ledger report""" |
|||
_name = 'account.general.ledger' |
|||
_description = 'General Ledger Report' |
|||
|
|||
@api.model |
|||
def view_report(self, option, tag): |
|||
""" |
|||
Retrieve partner ledger report data based on options and tags. |
|||
|
|||
:param option: The options to filter the report data. |
|||
:type option: str |
|||
|
|||
:param tag: The tag to filter the report data. |
|||
:type tag: str |
|||
|
|||
:return: A dictionary containing the partner ledger report data. |
|||
:rtype: dict |
|||
""" |
|||
account_dict = {} |
|||
account_totals = {} |
|||
move_line_ids = self.env['account.move.line'].search( |
|||
[('parent_state', '=', 'posted')]) |
|||
account_ids = move_line_ids.mapped('account_id') |
|||
account_dict['journal_ids'] = self.env['account.journal'].search_read( |
|||
[], ['name']) |
|||
account_dict['analytic_ids'] = self.env[ |
|||
'account.analytic.account'].search_read( |
|||
[], ['name']) |
|||
for account in account_ids: |
|||
move_line_id = move_line_ids.filtered( |
|||
lambda x: x.account_id == account) |
|||
move_line_list = [] |
|||
for move_line in move_line_id: |
|||
move_line_data = move_line.read( |
|||
['date', 'name', 'move_name', 'debit', 'credit', |
|||
'partner_id', 'account_id', 'journal_id', 'move_id', |
|||
'analytic_line_ids']) |
|||
move_line_list.append(move_line_data) |
|||
account_dict[account.display_name] = move_line_list |
|||
currency_id = self.env.company.currency_id.symbol |
|||
account_totals[account.display_name] = { |
|||
'total_debit': round(sum(move_line_id.mapped('debit')), 2), |
|||
'total_credit': round(sum(move_line_id.mapped('credit')), 2), |
|||
'currency_id': currency_id, |
|||
'account_id': account.id} |
|||
account_dict['account_totals'] = account_totals |
|||
return account_dict |
|||
|
|||
@api.model |
|||
def get_filter_values(self, journal_id, date_range, options, analytic, |
|||
method): |
|||
""" |
|||
Retrieve filtered values for the partner ledger report. |
|||
|
|||
:param journal_id: The journal IDs to filter the report data. |
|||
:type journal_id: list |
|||
|
|||
:param date_range: The date range option to filter the report data. |
|||
:type date_range: str or dict |
|||
|
|||
:param options: The additional options to filter the report data. |
|||
:type options: dict |
|||
|
|||
:param method: Find the method |
|||
:type options: dict |
|||
|
|||
:param analytic: The analytic IDs to filter the report data. |
|||
:type analytic: list |
|||
|
|||
:return: A dictionary containing the filtered values for the partner |
|||
ledger report. |
|||
:rtype: dict |
|||
""" |
|||
account_dict = {} |
|||
account_totals = {} |
|||
today = fields.Date.today() |
|||
quarter_start, quarter_end = date_utils.get_quarter(today) |
|||
previous_quarter_start = quarter_start - relativedelta(months=3) |
|||
previous_quarter_end = quarter_start - relativedelta(days=1) |
|||
if options == {}: |
|||
options = None |
|||
if options is None: |
|||
option_domain = ['posted'] |
|||
elif 'draft' in options: |
|||
option_domain = ['posted', 'draft'] |
|||
domain = [('journal_id', 'in', journal_id), |
|||
('parent_state', 'in', option_domain), ] if journal_id else [ |
|||
('parent_state', 'in', option_domain), ] |
|||
if method == {}: |
|||
method = None |
|||
if method is not None and 'cash' in method: |
|||
domain += [('journal_id', 'in', |
|||
self.env.company.tax_cash_basis_journal_id.ids), ] |
|||
if analytic: |
|||
analytic_line = self.env['account.analytic.line'].search( |
|||
[('account_id', 'in', analytic)]).mapped('id') |
|||
domain += [('analytic_line_ids', 'in', analytic_line)] |
|||
if date_range: |
|||
if date_range == 'month': |
|||
domain += [('date', '>=', today.replace(day=1)), |
|||
('date', '<=', today)] |
|||
elif date_range == 'year': |
|||
domain += [('date', '>=', today.replace(month=1, day=1)), |
|||
('date', '<=', today)] |
|||
elif date_range == 'quarter': |
|||
domain += [('date', '>=', quarter_start), |
|||
('date', '<=', quarter_end)] |
|||
elif date_range == 'last-month': |
|||
last_month_start = today.replace(day=1) - relativedelta( |
|||
months=1) |
|||
last_month_end = last_month_start + relativedelta( |
|||
day=calendar.monthrange(last_month_start.year, |
|||
last_month_start.month)[ |
|||
1]) |
|||
domain += [('date', '>=', last_month_start), |
|||
('date', '<=', last_month_end)] |
|||
elif date_range == 'last-year': |
|||
last_year_start = today.replace(month=1, |
|||
day=1) - relativedelta(years=1) |
|||
last_year_end = last_year_start.replace(month=12, day=31) |
|||
domain += [('date', '>=', last_year_start), |
|||
('date', '<=', last_year_end)] |
|||
elif date_range == 'last-quarter': |
|||
domain += [('date', '>=', previous_quarter_start), |
|||
('date', '<=', previous_quarter_end)] |
|||
elif 'start_date' in date_range and 'end_date' in date_range: |
|||
start_date = datetime.strptime(date_range['start_date'], |
|||
'%Y-%m-%d').date() |
|||
end_date = datetime.strptime(date_range['end_date'], |
|||
'%Y-%m-%d').date() |
|||
domain += [('date', '>=', start_date), |
|||
('date', '<=', end_date)] |
|||
elif 'start_date' in date_range: |
|||
start_date = datetime.strptime(date_range['start_date'], |
|||
'%Y-%m-%d').date() |
|||
domain += [('date', '>=', start_date)] |
|||
elif 'end_date' in date_range: |
|||
end_date = datetime.strptime(date_range['end_date'], |
|||
'%Y-%m-%d').date() |
|||
domain += [('date', '<=', end_date)] |
|||
move_line_ids = self.env['account.move.line'].search(domain) |
|||
account_ids = move_line_ids.mapped('account_id') |
|||
account_dict['journal_ids'] = self.env['account.journal'].search_read( |
|||
[], ['name']) |
|||
account_dict['analytic_ids'] = self.env[ |
|||
'account.analytic.account'].search_read( |
|||
[], ['name']) |
|||
for account in account_ids: |
|||
move_line_id = move_line_ids.filtered( |
|||
lambda x: x.account_id == account) |
|||
move_line_list = [] |
|||
for move_line in move_line_id: |
|||
move_line_data = move_line.read( |
|||
['date', 'name', 'move_name', 'debit', 'credit', |
|||
'partner_id', 'account_id', 'journal_id', 'move_id', |
|||
'analytic_line_ids']) |
|||
move_line_list.append(move_line_data) |
|||
account_dict[account.display_name] = move_line_list |
|||
currency_id = self.env.company.currency_id.symbol |
|||
account_totals[account.display_name] = { |
|||
'total_debit': round(sum(move_line_id.mapped('debit')), 2), |
|||
'total_credit': round(sum(move_line_id.mapped('credit')), 2), |
|||
'currency_id': currency_id, |
|||
'account_id': account.id} |
|||
account_dict['account_totals'] = account_totals |
|||
return account_dict |
|||
|
|||
@api.model |
|||
def get_xlsx_report(self, data, response, report_name, report_action): |
|||
""" |
|||
Generate an XLSX report based on the provided data and write it to the |
|||
response stream. |
|||
|
|||
:param data: The data used to generate the report. |
|||
:type data: str (JSON format) |
|||
|
|||
:param response: The response object to write the generated report to. |
|||
:type response: werkzeug.wrappers.Response |
|||
|
|||
:param report_name: The name of the report. |
|||
:type report_name: str |
|||
""" |
|||
data = json.loads(data) |
|||
output = io.BytesIO() |
|||
workbook = xlsxwriter.Workbook(output, {'in_memory': True}) |
|||
start_date = data['filters']['start_date'] if \ |
|||
data['filters']['start_date'] else '' |
|||
end_date = data['filters']['end_date'] if \ |
|||
data['filters']['end_date'] else '' |
|||
sheet = workbook.add_worksheet() |
|||
head = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '15px'}) |
|||
sub_heading = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px', |
|||
'border': 1, 'bg_color': '#D3D3D3', |
|||
'border_color': 'black'}) |
|||
filter_head = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px', |
|||
'border': 1, 'bg_color': '#D3D3D3', |
|||
'border_color': 'black'}) |
|||
filter_body = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px'}) |
|||
side_heading_sub = workbook.add_format( |
|||
{'align': 'left', 'bold': True, 'font_size': '10px', |
|||
'border': 1, |
|||
'border_color': 'black'}) |
|||
side_heading_sub.set_indent(1) |
|||
txt_name = workbook.add_format({'font_size': '10px', 'border': 1}) |
|||
txt_name.set_indent(2) |
|||
sheet.set_column(0, 0, 30) |
|||
sheet.set_column(1, 1, 20) |
|||
sheet.set_column(2, 2, 15) |
|||
sheet.set_column(3, 3, 15) |
|||
col = 0 |
|||
sheet.write('A1:b1', report_name, head) |
|||
sheet.write('B3:b4', 'Date Range', filter_head) |
|||
sheet.write('B4:b4', 'Journals', filter_head) |
|||
sheet.write('B5:b4', 'Analytic', filter_head) |
|||
sheet.write('B6:b4', 'Options', filter_head) |
|||
if start_date or end_date: |
|||
sheet.merge_range('C3:G3', f"{start_date} to {end_date}", |
|||
filter_body) |
|||
if data['filters']['journal']: |
|||
display_names = [journal for |
|||
journal in data['filters']['journal']] |
|||
display_names_str = ', '.join(display_names) |
|||
sheet.merge_range('C4:G4', display_names_str, filter_body) |
|||
if data['filters']['analytic']: |
|||
display_names = [analytic for |
|||
analytic in data['filters']['analytic']] |
|||
account_keys_str = ', '.join(display_names) |
|||
sheet.merge_range('C5:G5', account_keys_str, filter_body) |
|||
if data['filters']['options']: |
|||
option_keys = list(data['filters']['options'].keys()) |
|||
option_keys_str = ', '.join(option_keys) |
|||
sheet.merge_range('C6:G6', option_keys_str, filter_body) |
|||
if data: |
|||
if report_action == 'dynamic_accounts_report.action_general_ledger': |
|||
sheet.write(8, col, ' ', sub_heading) |
|||
sheet.write(8, col + 1, 'Date', sub_heading) |
|||
sheet.merge_range('C9:E9', 'Communication', sub_heading) |
|||
sheet.merge_range('F9:G9', 'Partner', sub_heading) |
|||
sheet.merge_range('H9:I9', 'Debit', sub_heading) |
|||
sheet.merge_range('J9:K9', 'Credit', sub_heading) |
|||
sheet.merge_range('L9:M9', 'Balance', sub_heading) |
|||
row = 8 |
|||
for account in data['account']: |
|||
row += 1 |
|||
sheet.write(row, col, account, txt_name) |
|||
sheet.write(row, col + 1, ' ', txt_name) |
|||
sheet.merge_range(row, col + 2, row, col + 4, ' ', txt_name) |
|||
sheet.merge_range(row, col + 5, row, col + 6, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row, col + 7, row, col + 8, |
|||
data['total'][account]['total_debit'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 9, row, col + 10, |
|||
data['total'][account]['total_credit'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 11, row, col + 12, |
|||
data['total'][account]['total_debit'] - |
|||
data['total'][account]['total_credit'], |
|||
txt_name) |
|||
for rec in data['data'][account]: |
|||
row += 1 |
|||
partner = rec[0]['partner_id'] |
|||
name = partner[1] if partner else None |
|||
sheet.write(row, col, rec[0]['move_name'], txt_name) |
|||
sheet.write(row, col + 1, rec[0]['date'], txt_name) |
|||
sheet.merge_range(row, col + 2, row, col + 4, |
|||
rec[0]['name'], txt_name) |
|||
sheet.merge_range(row, col + 5, row, col + 6, name, |
|||
txt_name) |
|||
sheet.merge_range(row, col + 7, row, col + 8, |
|||
rec[0]['debit'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 9, row, col + 10, |
|||
rec[0]['credit'], txt_name) |
|||
sheet.merge_range(row, col + 11, row, col + 12, ' ', |
|||
txt_name) |
|||
row += 1 |
|||
sheet.merge_range(row, col, row, col + 6, 'Total', |
|||
filter_head) |
|||
sheet.merge_range(row, col + 7, row, col + 8, |
|||
data['grand_total']['total_debit'], |
|||
filter_head) |
|||
sheet.merge_range(row, col + 9, row, col + 10, |
|||
data['grand_total']['total_credit'], |
|||
filter_head) |
|||
sheet.merge_range(row, col + 11, row, col + 12, |
|||
float(data['grand_total']['total_debit']) - |
|||
float(data['grand_total']['total_credit']), |
|||
filter_head) |
|||
workbook.close() |
|||
output.seek(0) |
|||
response.stream.write(output.read()) |
|||
output.close() |
@ -0,0 +1,496 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Bhagyadev KP (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
import io |
|||
import json |
|||
from dateutil.relativedelta import relativedelta |
|||
import xlsxwriter |
|||
from odoo import api, fields, models |
|||
from datetime import datetime |
|||
from odoo.tools import date_utils |
|||
|
|||
|
|||
class AccountPartnerLedger(models.TransientModel): |
|||
"""For creating Partner Ledger report""" |
|||
_name = 'account.partner.ledger' |
|||
_description = 'Partner Ledger Report' |
|||
|
|||
@api.model |
|||
def view_report(self, option, tag): |
|||
""" |
|||
Retrieve partner-related data for generating a report. |
|||
|
|||
:param option: The option for filtering the data. |
|||
:type option: str |
|||
|
|||
:param tag: The tag used for filtering the data. |
|||
:type tag: str |
|||
|
|||
:return: A dictionary containing the partner data for the report. |
|||
:rtype: dict |
|||
""" |
|||
fiscal_year = self.env['res.company'].search([]).mapped('account_opening_date')[0].strftime('%Y-%m-%d') |
|||
fiscal_year_start = datetime.strptime(fiscal_year, |
|||
'%Y-%m-%d').date() |
|||
partner_dict = {} |
|||
partner_totals = {} |
|||
move_line_ids = self.env['account.move.line'].search( |
|||
[('account_type', 'in', |
|||
['liability_payable', 'asset_receivable']), |
|||
('parent_state', '=', 'posted')]) |
|||
partner_ids = move_line_ids.mapped('partner_id') |
|||
for partner in partner_ids: |
|||
total_debit_balance = 0 |
|||
total_credit_balance = 0 |
|||
balance = 0 |
|||
move_line_id = move_line_ids.filtered( |
|||
lambda x: x.partner_id == partner) |
|||
move_line_list = [] |
|||
for move_line in move_line_id: |
|||
if move_line.invoice_date: |
|||
if move_line.invoice_date < fiscal_year_start: |
|||
total_debit_balance += move_line.debit |
|||
total_credit_balance += move_line.credit |
|||
balance = total_debit_balance - total_credit_balance |
|||
move_line_data = move_line.read( |
|||
['date', 'move_name', 'account_type', 'debit', 'credit', |
|||
'date_maturity', 'account_id', 'journal_id', 'move_id', |
|||
'matching_number', 'amount_currency']) |
|||
account_code = self.env['account.account'].browse( |
|||
move_line.account_id.id).code |
|||
journal_code = self.env['account.journal'].browse( |
|||
move_line.journal_id.id).code |
|||
if account_code: |
|||
move_line_data[0]['jrnl'] = journal_code |
|||
move_line_data[0]['code'] = account_code |
|||
move_line_list.append(move_line_data) |
|||
partner_dict[partner.name] = move_line_list |
|||
currency_id = self.env.company.currency_id.symbol |
|||
partner_totals[partner.name] = { |
|||
'total_debit': round(sum(move_line_id.mapped('debit')), 2), |
|||
'total_credit': round(sum(move_line_id.mapped('credit')), 2), |
|||
'currency_id': currency_id, |
|||
'initial_balance': balance, |
|||
'partner_id': partner.id, |
|||
'move_name': 'Initial Balance', |
|||
'initial_debit': total_debit_balance, |
|||
'initial_credit': total_credit_balance, |
|||
} |
|||
partner_dict['partner_totals'] = partner_totals |
|||
return partner_dict |
|||
|
|||
@api.model |
|||
def get_filter_values(self, partner_id, data_range, account, options): |
|||
""" |
|||
Retrieve filtered partner-related data for generating a report. |
|||
|
|||
:param partner_id: The ID(s) of the partner(s) to filter by. |
|||
:type partner_id: list or int |
|||
|
|||
:param data_range: The date range option for filtering the data. |
|||
:type data_range: str |
|||
|
|||
:param account: The account type(s) to filter by. |
|||
:type account: list or str |
|||
|
|||
:param options: Additional options for filtering the data. |
|||
:type options: dict |
|||
|
|||
:return: A dictionary containing the filtered partner data. |
|||
:rtype: dict |
|||
""" |
|||
if options == {}: |
|||
options = None |
|||
if account == {}: |
|||
account = None |
|||
account_type_domain = [] |
|||
if options is None: |
|||
option_domain = ['posted'] |
|||
elif 'draft' in options: |
|||
option_domain = ['posted', 'draft'] |
|||
if account is None or ( |
|||
'Receivable' in account and 'Payable' in account): |
|||
account_type_domain.append('liability_payable') |
|||
account_type_domain.append('asset_receivable') |
|||
elif 'Receivable' in account: |
|||
account_type_domain.append('asset_receivable') |
|||
elif 'Payable' in account: |
|||
account_type_domain.append('liability_payable') |
|||
partner_dict = {} |
|||
partner_totals = {} |
|||
today = fields.Date.today() |
|||
quarter_start, quarter_end = date_utils.get_quarter(today) |
|||
previous_quarter_start = quarter_start - relativedelta(months=3) |
|||
previous_quarter_end = quarter_start - relativedelta(days=1) |
|||
if not partner_id: |
|||
partner_id = self.env['account.move.line'].search([( |
|||
'account_type', 'in', account_type_domain), |
|||
('parent_state', 'in', option_domain)]).mapped( |
|||
'partner_id').ids |
|||
balance_move_line_ids = [] |
|||
for partners in partner_id: |
|||
partner = self.env['res.partner'].browse(partners).name |
|||
if data_range: |
|||
if data_range == 'month': |
|||
move_line_ids = self.env['account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('parent_state', 'in', option_domain)]).filtered( |
|||
lambda x: x.date.month == fields.Date.today().month) |
|||
date_start = fields.Date.today().replace(day=1) |
|||
balance_move_line_ids = self.env[ |
|||
'account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('parent_state', 'in', option_domain), |
|||
('invoice_date', '<', date_start)]) |
|||
elif data_range == 'year': |
|||
move_line_ids = self.env['account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('parent_state', 'in', option_domain)]).filtered( |
|||
lambda x: x.date.year == fields.Date.today().year) |
|||
date_start = fields.Date.today().replace(month=1, day=1) |
|||
balance_move_line_ids = self.env[ |
|||
'account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('parent_state', 'in', option_domain), |
|||
('invoice_date', '<', date_start)]) |
|||
elif data_range == 'quarter': |
|||
move_line_ids = self.env['account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('date', '>=', quarter_start), |
|||
('date', '<=', quarter_end), |
|||
('parent_state', 'in', option_domain)]) |
|||
date_start = quarter_start |
|||
balance_move_line_ids = self.env[ |
|||
'account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('parent_state', 'in', option_domain), |
|||
('invoice_date', '<', date_start)]) |
|||
elif data_range == 'last-month': |
|||
move_line_ids = self.env['account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('parent_state', 'in', option_domain)]).filtered( |
|||
lambda x: x.date.month == fields.Date.today().month - 1) |
|||
date_start = fields.Date.today().replace(day=1,month=fields.Date.today().month - 1) |
|||
balance_move_line_ids = self.env[ |
|||
'account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('parent_state', 'in', option_domain), |
|||
('invoice_date', '<', date_start)]) |
|||
elif data_range == 'last-year': |
|||
move_line_ids = self.env['account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('parent_state', 'in', option_domain)]).filtered( |
|||
lambda x: x.date.year == fields.Date.today().year - 1) |
|||
date_start = fields.Date.today().replace(day=1,month=1,) |
|||
balance_move_line_ids = self.env[ |
|||
'account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('parent_state', 'in', option_domain), |
|||
('invoice_date', '<', date_start)]) |
|||
elif data_range == 'last-quarter': |
|||
move_line_ids = self.env['account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('date', '>=', previous_quarter_start), |
|||
('date', '<=', previous_quarter_end), |
|||
('parent_state', 'in', option_domain)]) |
|||
date_start = previous_quarter_start |
|||
balance_move_line_ids = self.env[ |
|||
'account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('parent_state', 'in', option_domain), |
|||
('invoice_date', '<', date_start)]) |
|||
elif 'start_date' in data_range and 'end_date' in data_range: |
|||
start_date = datetime.strptime(data_range['start_date'], |
|||
'%Y-%m-%d').date() |
|||
end_date = datetime.strptime(data_range['end_date'], |
|||
'%Y-%m-%d').date() |
|||
move_line_ids = self.env['account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('date', '>=', start_date), |
|||
('date', '<=', end_date), |
|||
('parent_state', 'in', option_domain)]) |
|||
date_start = start_date |
|||
balance_move_line_ids = self.env[ |
|||
'account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('parent_state', 'in', option_domain), |
|||
('invoice_date', '<', date_start)]) |
|||
elif 'start_date' in data_range: |
|||
start_date = datetime.strptime(data_range['start_date'], |
|||
'%Y-%m-%d').date() |
|||
move_line_ids = self.env['account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('date', '>=', start_date), |
|||
('parent_state', 'in', option_domain)]) |
|||
date_start = start_date |
|||
balance_move_line_ids = self.env[ |
|||
'account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('parent_state', 'in', option_domain), |
|||
('invoice_date', '<', date_start)]) |
|||
elif 'end_date' in data_range: |
|||
end_date = datetime.strptime(data_range['end_date'], |
|||
'%Y-%m-%d').date() |
|||
move_line_ids = self.env['account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('date', '<=', end_date), |
|||
('parent_state', 'in', option_domain)]) |
|||
fiscal_year = self.env['res.company'].search([]).mapped( |
|||
'account_opening_date')[0].strftime('%Y-%m-%d') |
|||
date_start = datetime.strptime(fiscal_year, |
|||
'%Y-%m-%d').date() |
|||
balance_move_line_ids = self.env[ |
|||
'account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('parent_state', 'in', option_domain), |
|||
('invoice_date', '<', date_start)]) |
|||
else: |
|||
move_line_ids = self.env['account.move.line'].search( |
|||
[('partner_id', '=', partners), ( |
|||
'account_type', 'in', |
|||
account_type_domain), |
|||
('parent_state', 'in', option_domain)]) |
|||
total_debit_balance = 0 |
|||
total_credit_balance = 0 |
|||
balance = 0 |
|||
move_line_list = [] |
|||
for move_line in move_line_ids: |
|||
move_line_data = move_line.read( |
|||
['date', 'move_name', 'account_type', 'debit', 'credit', |
|||
'date_maturity', 'account_id', 'journal_id', 'move_id', |
|||
'matching_number', 'amount_currency']) |
|||
account_code = self.env['account.account'].browse( |
|||
move_line.account_id.id).code |
|||
journal_code = self.env['account.journal'].browse( |
|||
move_line.journal_id.id).code |
|||
if account_code: |
|||
move_line_data[0]['jrnl'] = journal_code |
|||
move_line_data[0]['code'] = account_code |
|||
move_line_list.append(move_line_data) |
|||
for remaining_move in balance_move_line_ids: |
|||
if remaining_move.invoice_date: |
|||
if remaining_move.invoice_date < date_start: |
|||
total_debit_balance += remaining_move.debit |
|||
total_credit_balance += remaining_move.credit |
|||
balance = total_debit_balance - total_credit_balance |
|||
partner_dict[partner] = move_line_list |
|||
currency_id = self.env.company.currency_id.symbol |
|||
partner_totals[partner] = { |
|||
'total_debit': round(sum(move_line_ids.mapped('debit')), 2), |
|||
'total_credit': round(sum(move_line_ids.mapped('credit')), 2), |
|||
'currency_id': currency_id, |
|||
'partner_id': partners, |
|||
'initial_balance': balance, |
|||
'move_name': 'Initial Balance', |
|||
'initial_debit': total_debit_balance, |
|||
'initial_credit': total_credit_balance, |
|||
} |
|||
partner_dict['partner_totals'] = partner_totals |
|||
return partner_dict |
|||
|
|||
@api.model |
|||
def get_xlsx_report(self, data, response, report_name, report_action): |
|||
""" |
|||
Generate an Excel report based on the provided data. |
|||
|
|||
:param data: The data used to generate the report. |
|||
:type data: str (JSON format) |
|||
|
|||
:param response: The response object to write the report to. |
|||
:type response: object |
|||
|
|||
:param report_name: The name of the report. |
|||
:type report_name: str |
|||
|
|||
:return: None |
|||
""" |
|||
data = json.loads(data) |
|||
output = io.BytesIO() |
|||
workbook = xlsxwriter.Workbook(output, {'in_memory': True}) |
|||
start_date = data['filters']['start_date'] if \ |
|||
data['filters']['start_date'] else '' |
|||
end_date = data['filters']['end_date'] if \ |
|||
data['filters']['end_date'] else '' |
|||
sheet = workbook.add_worksheet() |
|||
head = workbook.add_format( |
|||
{'font_size': 15, 'align': 'center', 'bold': True}) |
|||
head_highlight = workbook.add_format( |
|||
{'font_size': 10, 'align': 'center', 'bold': True}) |
|||
sub_heading = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px', |
|||
'border': 1, 'bg_color': '#D3D3D3', |
|||
'border_color': 'black'}) |
|||
filter_head = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px', |
|||
'border': 1, 'bg_color': '#D3D3D3', |
|||
'border_color': 'black'}) |
|||
filter_body = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px'}) |
|||
side_heading_sub = workbook.add_format( |
|||
{'align': 'left', 'bold': True, 'font_size': '10px', |
|||
'border': 1, |
|||
'border_color': 'black'}) |
|||
side_heading_sub.set_indent(1) |
|||
txt_name = workbook.add_format({'font_size': '10px', 'border': 1}) |
|||
txt_name.set_indent(2) |
|||
sheet.set_column(0, 0, 30) |
|||
sheet.set_column(1, 1, 20) |
|||
sheet.set_column(2, 2, 15) |
|||
sheet.set_column(3, 3, 15) |
|||
col = 0 |
|||
sheet.write('A1:b1', report_name, head) |
|||
sheet.write('B3:b4', 'Date Range', filter_head) |
|||
sheet.write('B4:b4', 'Partners', filter_head) |
|||
sheet.write('B5:b4', 'Accounts', filter_head) |
|||
sheet.write('B6:b4', 'Options', filter_head) |
|||
if start_date or end_date: |
|||
sheet.merge_range('C3:G3', f"{start_date} to {end_date}", |
|||
filter_body) |
|||
if data['filters']['partner']: |
|||
display_names = [partner.get('display_name', 'undefined') for |
|||
partner in data['filters']['partner']] |
|||
display_names_str = ', '.join(display_names) |
|||
sheet.merge_range('C4:G4', display_names_str, filter_body) |
|||
if data['filters']['account']: |
|||
account_keys = list(data['filters']['account'].keys()) |
|||
account_keys_str = ', '.join(account_keys) |
|||
sheet.merge_range('C5:G5', account_keys_str, filter_body) |
|||
if data['filters']['options']: |
|||
option_keys = list(data['filters']['options'].keys()) |
|||
option_keys_str = ', '.join(option_keys) |
|||
sheet.merge_range('C6:G6', option_keys_str, filter_body) |
|||
if data: |
|||
if report_action == 'dynamic_accounts_report.action_partner_ledger': |
|||
sheet.write(8, col, ' ', sub_heading) |
|||
sheet.write(8, col + 1, 'JNRL', sub_heading) |
|||
sheet.write(8, col + 2, 'Account', sub_heading) |
|||
sheet.merge_range('D9:E9', 'Ref', sub_heading) |
|||
sheet.merge_range('F9:G9', 'Due Date', sub_heading) |
|||
sheet.merge_range('H9:I9', 'Debit', sub_heading) |
|||
sheet.merge_range('J9:K9', 'Credit', sub_heading) |
|||
sheet.merge_range('L9:M9', 'Balance', sub_heading) |
|||
row = 8 |
|||
for partner in data['partners']: |
|||
row += 1 |
|||
sheet.write(row, col, partner, txt_name) |
|||
sheet.write(row, col + 1, ' ', txt_name) |
|||
sheet.write(row, col + 2, ' ', txt_name) |
|||
sheet.merge_range(row, col + 3, row, col + 4, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row, col + 5, row, col + 6, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row, col + 7, row, col + 8, |
|||
data['total'][partner]['total_debit'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 9, row, col + 10, |
|||
data['total'][partner]['total_credit'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 11, row, col + 12, |
|||
data['total'][partner]['total_debit'] - |
|||
data['total'][partner]['total_credit'], |
|||
txt_name) |
|||
if data['total'][partner]['initial_balance'] != 0: |
|||
row += 1 |
|||
sheet.write(row, col, '', txt_name) |
|||
sheet.write(row, col + 1, ' ', txt_name) |
|||
sheet.write(row, col + 2, ' ', txt_name) |
|||
sheet.merge_range(row, col + 3, row, col + 4, 'Initial Balance ', |
|||
head_highlight) |
|||
sheet.merge_range(row, col + 5, row, col + 6, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row, col + 7, row, col + 8, |
|||
data['total'][partner]['initial_debit'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 9, row, col + 10, |
|||
data['total'][partner]['initial_credit'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 11, row, col + 12, |
|||
data['total'][partner]['initial_balance'], |
|||
txt_name) |
|||
for rec in data['data'][partner]: |
|||
row += 1 |
|||
sheet.write(row, col, rec[0]['date'], txt_name) |
|||
sheet.write(row, col + 1, rec[0]['jrnl'], txt_name) |
|||
sheet.write(row, col + 2, rec[0]['code'], txt_name) |
|||
sheet.merge_range(row, col + 3, row, col + 4, |
|||
rec[0]['move_name'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 5, row, col + 6, |
|||
rec[0]['date_maturity'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 7, row, col + 8, |
|||
rec[0]['debit'], txt_name) |
|||
sheet.merge_range(row, col + 9, row, col + 10, |
|||
rec[0]['credit'], txt_name) |
|||
sheet.merge_range(row, col + 11, row, col + 12, ' ', |
|||
txt_name) |
|||
row += 1 |
|||
sheet.merge_range(row, col, row, col + 6, 'Total', filter_head) |
|||
sheet.merge_range(row, col + 7, row, col + 8, |
|||
data['grand_total']['total_debit'], |
|||
filter_head) |
|||
sheet.merge_range(row, col + 9, row, col + 10, |
|||
data['grand_total']['total_credit'], |
|||
filter_head) |
|||
sheet.merge_range(row, col + 11, row, col + 12, |
|||
data['grand_total']['total_debit'] - |
|||
data['grand_total']['total_credit'], |
|||
filter_head) |
|||
workbook.close() |
|||
output.seek(0) |
|||
response.stream.write(output.read()) |
|||
output.close() |
@ -0,0 +1,449 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Bhagyadev KP (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
import calendar |
|||
import io |
|||
import json |
|||
from datetime import datetime |
|||
import xlsxwriter |
|||
from odoo import api, fields, models |
|||
from odoo.tools.date_utils import get_month, get_fiscal_year, \ |
|||
get_quarter_number, subtract |
|||
|
|||
|
|||
class AccountTrialBalance(models.TransientModel): |
|||
"""For creating Trial Balance report""" |
|||
_name = 'account.trial.balance' |
|||
_description = 'Trial Balance Report' |
|||
|
|||
@api.model |
|||
def view_report(self): |
|||
""" |
|||
Generates a trial balance report for multiple accounts. |
|||
Retrieves account information and calculates total debit and credit |
|||
amounts for each account within the specified date range. Returns a list |
|||
of dictionaries containing account details and transaction totals. |
|||
|
|||
:return: List of dictionaries representing the trial balance report. |
|||
:rtype: list |
|||
""" |
|||
account_ids = self.env['account.move.line'].search([]).mapped( |
|||
'account_id') |
|||
today = fields.Date.today() |
|||
move_line_list = [] |
|||
for account_id in account_ids: |
|||
initial_move_line_ids = self.env['account.move.line'].search( |
|||
[('date', '<', get_month(today)[0]), |
|||
('account_id', '=', account_id.id), |
|||
('parent_state', '=', 'posted')]) |
|||
initial_total_debit = round( |
|||
sum(initial_move_line_ids.mapped('debit')), 2) |
|||
initial_total_credit = round( |
|||
sum(initial_move_line_ids.mapped('credit')), 2) |
|||
move_line_ids = self.env['account.move.line'].search( |
|||
[('date', '>=', get_month(today)[0]), |
|||
('account_id', '=', account_id.id), |
|||
('date', '<=', get_month(today)[1]), |
|||
('parent_state', '=', 'posted')]) |
|||
total_debit = round(sum(move_line_ids.mapped('debit')), 2) |
|||
total_credit = round(sum(move_line_ids.mapped('credit')), 2) |
|||
sum_debit = initial_total_debit + total_debit |
|||
sum_credit = initial_total_credit + total_credit |
|||
diff_credit_debit = sum_debit - sum_credit |
|||
if diff_credit_debit > 0: |
|||
end_total_debit = diff_credit_debit |
|||
end_total_credit = 0.0 |
|||
else: |
|||
end_total_debit = 0.0 |
|||
end_total_credit = abs(diff_credit_debit) |
|||
data = { |
|||
'account': account_id.display_name, |
|||
'account_id': account_id.id, |
|||
'journal_ids': self.env['account.journal'].search_read([], [ |
|||
'name']), |
|||
'initial_total_debit': initial_total_debit, |
|||
'initial_total_credit': initial_total_credit, |
|||
'total_debit': total_debit, |
|||
'total_credit': total_credit, |
|||
'end_total_debit': end_total_debit, |
|||
'end_total_credit': end_total_credit |
|||
} |
|||
move_line_list.append(data) |
|||
return move_line_list |
|||
|
|||
@api.model |
|||
def get_filter_values(self, start_date, end_date, comparison_number, |
|||
comparison_type, journal_list, analytic, options, |
|||
method): |
|||
""" |
|||
Retrieves and calculates filtered values for generating a financial |
|||
report. |
|||
Retrieves and processes account movement data based on the provided |
|||
filters. Calculates initial, dynamic, and end total debit and credit |
|||
amounts for each account,considering date range, comparison type, and |
|||
other filter criteria. |
|||
|
|||
:param str start_date: Start date of the reporting period. |
|||
:param str end_date: End date of the reporting period. |
|||
:param int comparison_number: Number of periods for comparison. |
|||
:param str comparison_type: Type of comparison (month, year, quarter). |
|||
:param list[int] journal_list: List of selected journal IDs. |
|||
:param list[int] analytic: List of selected analytic line IDs. |
|||
:param dict options: Additional filtering options (e.g., 'draft'). |
|||
:param dict method: Find the method. |
|||
:return: List of dictionaries representing the financial report. |
|||
:rtype: list |
|||
""" |
|||
if options == {}: |
|||
options = None |
|||
if options is None: |
|||
option_domain = ['posted'] |
|||
elif 'draft' in options: |
|||
option_domain = ['posted', 'draft'] |
|||
if method == {}: |
|||
method = None |
|||
dynamic_total_debit = {} |
|||
dynamic_date_num = {} |
|||
dynamic_total_credit = {} |
|||
account_ids = self.env['account.move.line'].search([]).mapped( |
|||
'account_id') |
|||
move_line_list = [] |
|||
start_date_first = \ |
|||
get_fiscal_year(datetime.strptime(start_date, "%Y-%m-%d").date())[ |
|||
0] if comparison_type == 'year' else datetime.strptime( |
|||
start_date, "%Y-%m-%d").date() |
|||
end_date_first = \ |
|||
get_fiscal_year(datetime.strptime(end_date, "%Y-%m-%d").date())[ |
|||
1] if comparison_type == 'year' else datetime.strptime(end_date, |
|||
"%Y-%m-%d").date() |
|||
for account_id in account_ids: |
|||
start_date = start_date_first |
|||
end_date = end_date_first |
|||
if comparison_number: |
|||
if comparison_type == 'month': |
|||
initial_start_date = subtract(start_date, months=eval( |
|||
comparison_number)) |
|||
elif comparison_type == 'year': |
|||
initial_start_date = subtract(start_date, years=eval( |
|||
comparison_number)) |
|||
else: |
|||
initial_start_date = subtract(start_date, months=eval( |
|||
comparison_number) * 3) |
|||
else: |
|||
initial_start_date = start_date |
|||
domain = [('date', '<', initial_start_date), |
|||
('account_id', '=', account_id.id), |
|||
('parent_state', 'in', option_domain), ] |
|||
if journal_list: |
|||
domain.append( |
|||
('journal_id', 'in', journal_list), ) |
|||
if analytic: |
|||
domain.append( |
|||
('analytic_line_ids', 'in', analytic)) |
|||
if method is not None and 'cash' in method: |
|||
domain.append(('journal_id', 'in', |
|||
self.env.company.tax_cash_basis_journal_id.ids)) |
|||
initial_move_line_ids = self.env['account.move.line'].search( |
|||
domain) |
|||
initial_total_debit = round( |
|||
sum(initial_move_line_ids.mapped('debit')), 2) |
|||
initial_total_credit = round( |
|||
sum(initial_move_line_ids.mapped('credit')), 2) |
|||
if comparison_number: |
|||
if comparison_type == 'year': |
|||
for i in range(1, eval(comparison_number) + 1): |
|||
com_start_date = subtract(start_date, years=i) |
|||
com_end_date = subtract(end_date, years=i) |
|||
domain = [('date', '>=', com_start_date), |
|||
('account_id', '=', account_id.id), |
|||
('date', '<=', com_end_date), |
|||
('parent_state', 'in', option_domain), ] |
|||
if journal_list: |
|||
domain.append( |
|||
('journal_id', 'in', journal_list), ) |
|||
if analytic: |
|||
domain.append( |
|||
('analytic_line_ids', 'in', analytic)) |
|||
if method is not None and 'cash' in method: |
|||
domain.append(('journal_id', 'in', |
|||
self.env.company.tax_cash_basis_journal_id.ids)) |
|||
move_lines = self.env['account.move.line'].search( |
|||
domain) |
|||
dynamic_total_debit[ |
|||
f"dynamic_total_debit_{i}"] = round( |
|||
sum(move_lines.mapped('debit')), 2) |
|||
dynamic_total_credit[ |
|||
f"dynamic_total_credit_{i}"] = round( |
|||
sum(move_lines.mapped('credit')), 2) |
|||
if comparison_type == 'month': |
|||
dynamic_date_num[ |
|||
f"dynamic_date_num{0}"] = self.get_month_name( |
|||
start_date) + ' ' + str( |
|||
start_date.year) |
|||
for i in range(1, eval(comparison_number) + 1): |
|||
com_start_date = subtract(start_date, months=i) |
|||
com_end_date = subtract(end_date, months=i) |
|||
domain = [('date', '>=', com_start_date), |
|||
('account_id', '=', account_id.id), |
|||
('date', '<=', com_end_date), |
|||
('parent_state', 'in', option_domain), ] |
|||
if journal_list: |
|||
domain.append( |
|||
('journal_id', 'in', journal_list), ) |
|||
if analytic: |
|||
domain.append( |
|||
('analytic_line_ids', 'in', analytic)) |
|||
if method is not None and 'cash' in method: |
|||
domain.append(('journal_id', 'in', |
|||
self.env.company.tax_cash_basis_journal_id.ids), ) |
|||
move_lines = self.env['account.move.line'].search( |
|||
domain) |
|||
dynamic_date_num[ |
|||
f"dynamic_date_num{i}"] = self.get_month_name( |
|||
com_start_date) + ' ' + str( |
|||
com_start_date.year) |
|||
dynamic_total_debit[ |
|||
f"dynamic_total_debit_{i}"] = round( |
|||
sum(move_lines.mapped('debit')), 2) |
|||
dynamic_total_credit[ |
|||
f"dynamic_total_credit_{i}"] = round( |
|||
sum(move_lines.mapped('credit')), 2) |
|||
if comparison_type == 'quarter': |
|||
dynamic_date_num[ |
|||
f"dynamic_date_num{0}"] = 'Q' + ' ' + str( |
|||
get_quarter_number(start_date)) + ' ' + str( |
|||
start_date.year) |
|||
for i in range(1, eval(comparison_number) + 1): |
|||
com_start_date = subtract(start_date, months=i * 3) |
|||
com_end_date = subtract(end_date, months=i * 3) |
|||
domain = [('date', '>=', com_start_date), |
|||
('account_id', '=', account_id.id), |
|||
('date', '<=', com_end_date), |
|||
('parent_state', 'in', option_domain), ] |
|||
if journal_list: |
|||
domain.append( |
|||
('journal_id', 'in', journal_list), ) |
|||
if analytic: |
|||
domain.append( |
|||
('analytic_line_ids', 'in', analytic)) |
|||
if method is not None and 'cash' in method: |
|||
domain.append(('journal_id', 'in', |
|||
self.env.company.tax_cash_basis_journal_id.ids)) |
|||
move_lines = self.env['account.move.line'].search( |
|||
domain) |
|||
dynamic_date_num[ |
|||
f"dynamic_date_num{i}"] = 'Q' + ' ' + str( |
|||
get_quarter_number(com_start_date)) + ' ' + str( |
|||
com_start_date.year) |
|||
dynamic_total_debit[ |
|||
f"dynamic_total_debit_{i}"] = round( |
|||
sum(move_lines.mapped('debit')), 2) |
|||
dynamic_total_credit[ |
|||
f"dynamic_total_credit_{i}"] = round( |
|||
sum(move_lines.mapped('credit')), 2) |
|||
domain = [('date', '>=', start_date), |
|||
('account_id', '=', account_id.id), |
|||
('date', '<=', end_date), |
|||
('parent_state', 'in', option_domain), ] |
|||
if journal_list: |
|||
domain.append( |
|||
('journal_id', 'in', journal_list), ) |
|||
if analytic: |
|||
domain.append( |
|||
('analytic_line_ids', 'in', analytic)) |
|||
if method is not None and 'cash' in method: |
|||
domain.append(('journal_id', 'in', |
|||
self.env.company.tax_cash_basis_journal_id.ids)) |
|||
move_line_ids = self.env['account.move.line'].search(domain) |
|||
total_debit = round(sum(move_line_ids.mapped('debit')), 2) |
|||
total_credit = round(sum(move_line_ids.mapped('credit')), 2) |
|||
sum_debit = initial_total_debit + sum( |
|||
dynamic_total_debit.values()) + total_debit |
|||
sum_credit = initial_total_credit + sum( |
|||
dynamic_total_credit.values()) + total_credit |
|||
diff_credit_debit = sum_debit - sum_credit |
|||
if diff_credit_debit > 0: |
|||
end_total_debit = diff_credit_debit |
|||
end_total_credit = 0.0 |
|||
else: |
|||
end_total_debit = 0.0 |
|||
end_total_credit = abs(diff_credit_debit) |
|||
data = { |
|||
'account': account_id.display_name, |
|||
'account_id': account_id.id, |
|||
'journal_ids': self.env['account.journal'].search_read([], [ |
|||
'name']), |
|||
'initial_total_debit': initial_total_debit, |
|||
'initial_total_credit': initial_total_credit, |
|||
'total_debit': total_debit, |
|||
'total_credit': total_credit, |
|||
'end_total_debit': end_total_debit, |
|||
'end_total_credit': end_total_credit |
|||
} |
|||
if comparison_number: |
|||
if dynamic_date_num: |
|||
data['dynamic_date_num'] = dynamic_date_num |
|||
for i in range(1, eval(comparison_number) + 1): |
|||
data[f'dynamic_total_debit_{i}'] = dynamic_total_debit.get( |
|||
f"dynamic_total_debit_{eval(comparison_number) + 1 - i}", |
|||
0.0) |
|||
data[ |
|||
f'dynamic_total_credit_{i}'] = dynamic_total_credit.get( |
|||
f"dynamic_total_credit_{eval(comparison_number) + 1 - i}", |
|||
0.0) |
|||
move_line_list.append(data) |
|||
return move_line_list |
|||
|
|||
@api.model |
|||
def get_month_name(self, date): |
|||
""" |
|||
Retrieve the abbreviated name of the month for a given date. |
|||
:param date: The date for which to retrieve the month's abbreviated name. |
|||
:type date: datetime.date |
|||
:return: Abbreviated name of the month (e.g., 'Jan', 'Feb', ..., 'Dec'). |
|||
:rtype: str |
|||
""" |
|||
month_names = calendar.month_abbr |
|||
return month_names[date.month] |
|||
|
|||
@api.model |
|||
def get_xlsx_report(self, data, response, report_name, report_action): |
|||
""" |
|||
Generate an XLSX report based on provided data and response stream. |
|||
Generates an Excel workbook with specified report format, including |
|||
subheadings,column headers, and row data for the given financial report |
|||
data. |
|||
:param str data: JSON-encoded data for the report. |
|||
:param response: Response object to stream the generated report. |
|||
:param str report_name: Name of the financial report. |
|||
""" |
|||
data = json.loads(data) |
|||
output = io.BytesIO() |
|||
workbook = xlsxwriter.Workbook(output, {'in_memory': True}) |
|||
start_date = data['filters']['start_date'] if \ |
|||
data['filters']['start_date'] else '' |
|||
end_date = data['filters']['end_date'] if \ |
|||
data['filters']['end_date'] else '' |
|||
head = workbook.add_format( |
|||
{'font_size': 15, 'align': 'center', 'bold': True}) |
|||
sheet = workbook.add_worksheet() |
|||
sub_heading = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px', |
|||
'border': 1, 'bg_color': '#D3D3D3', |
|||
'border_color': 'black'}) |
|||
filter_head = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px', |
|||
'border': 1, 'bg_color': '#D3D3D3', |
|||
'border_color': 'black'}) |
|||
filter_body = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px'}) |
|||
side_heading_sub = workbook.add_format( |
|||
{'align': 'left', 'bold': True, 'font_size': '10px', |
|||
'border': 1, |
|||
'border_color': 'black'}) |
|||
side_heading_sub.set_indent(1) |
|||
txt_name = workbook.add_format({'font_size': '10px', 'border': 1}) |
|||
txt_name.set_indent(2) |
|||
sheet.set_column(0, 0, 30) |
|||
sheet.set_column(1, 1, 20) |
|||
sheet.set_column(2, 2, 15) |
|||
sheet.set_column(3, 3, 15) |
|||
col = 0 |
|||
sheet.write('A1:b1', report_name, head) |
|||
sheet.write('B3:b4', 'Date Range', filter_head) |
|||
sheet.write('B4:b4', 'Comparison', filter_head) |
|||
sheet.write('B5:b4', 'Journal', filter_head) |
|||
sheet.write('B6:b4', 'Account', filter_head) |
|||
sheet.write('B7:b4', 'Option', filter_head) |
|||
if start_date or end_date: |
|||
sheet.merge_range('C3:G3', f"{start_date} to {end_date}", |
|||
filter_body) |
|||
if data['filters']['comparison_number_range']: |
|||
sheet.merge_range('C4:G4', |
|||
f"{data['filters']['comparison_type']} : {data['filters']['comparison_number_range']}", |
|||
filter_body) |
|||
if data['filters']['journal']: |
|||
display_names = [journal for |
|||
journal in data['filters']['journal']] |
|||
display_names_str = ', '.join(display_names) |
|||
sheet.merge_range('C5:G5', display_names_str, filter_body) |
|||
if data['filters']['account']: |
|||
account_keys = [account.get('display_name', 'undefined') for |
|||
account in data['filters']['account']] |
|||
account_keys_str = ', '.join(account_keys) |
|||
sheet.merge_range('C6:G6', account_keys_str, filter_body) |
|||
if data['filters']['options']: |
|||
option_keys = list(data['filters']['options'].keys()) |
|||
option_keys_str = ', '.join(option_keys) |
|||
sheet.merge_range('C7:G7', option_keys_str, filter_body) |
|||
sheet.write(9, col, '', sub_heading) |
|||
sheet.merge_range(9, col + 1, 9, col + 2, 'Initial Balance', |
|||
sub_heading) |
|||
i = 3 |
|||
for date_view in data['date_viewed']: |
|||
sheet.merge_range(9, col + i, 9, col + i + 1, date_view, |
|||
sub_heading) |
|||
i += 2 |
|||
sheet.merge_range(9, col + i, 9, col + i + 1, 'End Balance', |
|||
sub_heading) |
|||
sheet.write(10, col, '', sub_heading) |
|||
sheet.write(10, col + 1, 'Debit', sub_heading) |
|||
sheet.write(10, col + 2, 'Credit', sub_heading) |
|||
i = 3 |
|||
for date_views in data['date_viewed']: |
|||
sheet.write(10, col + i, 'Debit', sub_heading) |
|||
i += 1 |
|||
sheet.write(10, col + i, 'Credit', sub_heading) |
|||
i += 1 |
|||
sheet.write(10, col + i, 'Debit', sub_heading) |
|||
sheet.write(10, col + (i + 1), 'Credit', sub_heading) |
|||
if data: |
|||
if report_action == 'dynamic_accounts_report.action_trial_balance': |
|||
row = 11 |
|||
for move_line in data['data']: |
|||
sheet.write(row, col, move_line['account'], |
|||
side_heading_sub) |
|||
sheet.write(row, col + 1, move_line['initial_total_debit'], |
|||
txt_name) |
|||
sheet.write(row, col + 2, |
|||
move_line['initial_total_credit'], txt_name) |
|||
j = 3 |
|||
if data['apply_comparison']: |
|||
number_of_periods = data['comparison_number_range'] |
|||
for num in number_of_periods: |
|||
sheet.write(row, col + j, move_line[ |
|||
'dynamic_total_debit_' + str(num)], txt_name) |
|||
sheet.write(row, col + j + 1, move_line[ |
|||
'dynamic_total_credit_' + str(num)], txt_name) |
|||
j += 2 |
|||
sheet.write(row, col + j, move_line['total_debit'], |
|||
txt_name) |
|||
sheet.write(row, col + j + 1, move_line['total_credit'], |
|||
txt_name) |
|||
sheet.write(row, col + j + 2, move_line['end_total_debit'], |
|||
txt_name) |
|||
sheet.write(row, col + j + 3, |
|||
move_line['end_total_credit'], txt_name) |
|||
row += 1 |
|||
workbook.close() |
|||
output.seek(0) |
|||
response.stream.write(output.read()) |
|||
output.close() |
@ -0,0 +1,305 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Bhagyadev KP (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
import io |
|||
import json |
|||
import xlsxwriter |
|||
from odoo import api, fields, models |
|||
|
|||
|
|||
class AgePayableReport(models.TransientModel): |
|||
"""For creating Age Payable report""" |
|||
_name = 'age.payable.report' |
|||
_description = 'Aged Payable Report' |
|||
|
|||
@api.model |
|||
def view_report(self): |
|||
""" |
|||
Generate a report with move line data categorized by partner and credit |
|||
difference. |
|||
Returns: |
|||
dict: Dictionary containing move line data categorized by partner |
|||
names. Each partner's data includes credit amounts and credit |
|||
differences based on days between maturity date and today. The |
|||
'partner_totals' key contains summary data for each partner. |
|||
""" |
|||
partner_total = {} |
|||
move_line_list = {} |
|||
paid = self.env['account.move.line'].search( |
|||
[('parent_state', '=', 'posted'), |
|||
('account_type', '=', 'liability_payable'), |
|||
('reconciled', '=', False)]) |
|||
currency_id = self.env.company.currency_id.symbol |
|||
partner_ids = paid.mapped('partner_id') |
|||
today = fields.Date.today() |
|||
for partner_id in partner_ids: |
|||
move_line_ids = paid.filtered( |
|||
lambda rec: rec.partner_id in partner_id) |
|||
move_line_data = move_line_ids.read( |
|||
['name', 'move_name', 'date', 'amount_currency', 'account_id', |
|||
'date_maturity', 'currency_id', 'credit', 'move_id']) |
|||
for val in move_line_data: |
|||
diffrence = (today - val['date_maturity']).days |
|||
val['diff0'] = val['credit'] if diffrence <= 0 else 0.0 |
|||
val['diff1'] = val['credit'] if 0 < diffrence <= 30 else 0.0 |
|||
val['diff2'] = val['credit'] if 30 < diffrence <= 60 else 0.0 |
|||
val['diff3'] = val['credit'] if 60 < diffrence <= 90 else 0.0 |
|||
val['diff4'] = val['credit'] if 90 < diffrence <= 120 else 0.0 |
|||
val['diff5'] = val['credit'] if diffrence > 120 else 0.0 |
|||
move_line_list[partner_id.name] = move_line_data |
|||
partner_total[partner_id.name] = { |
|||
'credit_sum': sum(val['credit'] for val in move_line_data), |
|||
'diff0_sum': round(sum(val['diff0'] for val in move_line_data), |
|||
2), |
|||
'diff1_sum': round(sum(val['diff1'] for val in move_line_data), |
|||
2), |
|||
'diff2_sum': round(sum(val['diff2'] for val in move_line_data), |
|||
2), |
|||
'diff3_sum': round(sum(val['diff3'] for val in move_line_data), |
|||
2), |
|||
'diff4_sum': round(sum(val['diff4'] for val in move_line_data), |
|||
2), |
|||
'diff5_sum': round(sum(val['diff5'] for val in move_line_data), |
|||
2), |
|||
'currency_id': currency_id, |
|||
'partner_id': partner_id.id |
|||
} |
|||
move_line_list['partner_totals'] = partner_total |
|||
return move_line_list |
|||
|
|||
@api.model |
|||
def get_filter_values(self, date, partner): |
|||
""" |
|||
Retrieve filtered move line data based on date and partner(s). |
|||
Parameters: |
|||
date (str): Date for filtering move lines (format: 'YYYY-MM-DD'). |
|||
partner (list): List of partner IDs to filter move lines for. |
|||
Returns: |
|||
dict: Dictionary with filtered move line data organized by partner |
|||
names. Includes credit amount categorization based on days |
|||
difference. Contains partner-wise summary under |
|||
'partner_totals' key. |
|||
""" |
|||
partner_total = {} |
|||
move_line_list = {} |
|||
if date: |
|||
paid = self.env['account.move.line'].search( |
|||
[('parent_state', '=', 'posted'), |
|||
('account_type', '=', 'liability_payable'), |
|||
('reconciled', '=', False), ('date', '<=', date)]) |
|||
else: |
|||
paid = self.env['account.move.line'].search( |
|||
[('parent_state', '=', 'posted'), |
|||
('account_type', '=', 'liability_payable'), |
|||
('reconciled', '=', False)]) |
|||
currency_id = self.env.company.currency_id.symbol |
|||
if partner: |
|||
partner_ids = self.env['res.partner'].search( |
|||
[('id', 'in', partner)]) |
|||
else: |
|||
partner_ids = paid.mapped('partner_id') |
|||
today = fields.Date.today() |
|||
for partner_id in partner_ids: |
|||
move_line_ids = paid.filtered( |
|||
lambda rec: rec.partner_id in partner_id) |
|||
move_line_data = move_line_ids.read( |
|||
['name', 'move_name', 'date', 'amount_currency', 'account_id', |
|||
'date_maturity', 'currency_id', 'credit', 'move_id']) |
|||
for val in move_line_data: |
|||
diffrence = (today - val['date_maturity']).days |
|||
val['diff0'] = val['credit'] if diffrence <= 0 else 0.0 |
|||
val['diff1'] = val['credit'] if 0 < diffrence <= 30 else 0.0 |
|||
val['diff2'] = val['credit'] if 30 < diffrence <= 60 else 0.0 |
|||
val['diff3'] = val['credit'] if 60 < diffrence <= 90 else 0.0 |
|||
val['diff4'] = val['credit'] if 90 < diffrence <= 120 else 0.0 |
|||
val['diff5'] = val['credit'] if diffrence > 120 else 0.0 |
|||
move_line_list[partner_id.name] = move_line_data |
|||
partner_total[partner_id.name] = { |
|||
'credit_sum': sum(val['credit'] for val in move_line_data), |
|||
'diff0_sum': round(sum(val['diff0'] for val in move_line_data), |
|||
2), |
|||
'diff1_sum': round(sum(val['diff1'] for val in move_line_data), |
|||
2), |
|||
'diff2_sum': round(sum(val['diff2'] for val in move_line_data), |
|||
2), |
|||
'diff3_sum': round(sum(val['diff3'] for val in move_line_data), |
|||
2), |
|||
'diff4_sum': round(sum(val['diff4'] for val in move_line_data), |
|||
2), |
|||
'diff5_sum': round(sum(val['diff5'] for val in move_line_data), |
|||
2), |
|||
'currency_id': currency_id, |
|||
'partner_id': partner_id.id |
|||
} |
|||
move_line_list['partner_totals'] = partner_total |
|||
return move_line_list |
|||
|
|||
@api.model |
|||
def get_xlsx_report(self, data, response, report_name, report_action): |
|||
""" |
|||
Generate an Excel report based on the provided data. |
|||
:param data: The data used to generate the report. |
|||
:type data: str (JSON format) |
|||
:param response: The response object to write the report to. |
|||
:type response: object |
|||
:param report_name: The name of the report. |
|||
:type report_name: str |
|||
:return: None |
|||
""" |
|||
data = json.loads(data) |
|||
output = io.BytesIO() |
|||
workbook = xlsxwriter.Workbook(output, {'in_memory': True}) |
|||
end_date = data['filters']['end_date'] if \ |
|||
data['filters']['end_date'] else '' |
|||
sheet = workbook.add_worksheet() |
|||
head = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '15px'}) |
|||
sub_heading = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px', |
|||
'border': 1, 'bg_color': '#D3D3D3', |
|||
'border_color': 'black'}) |
|||
filter_head = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px', |
|||
'border': 1, 'bg_color': '#D3D3D3', |
|||
'border_color': 'black'}) |
|||
filter_body = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px'}) |
|||
side_heading_sub = workbook.add_format( |
|||
{'align': 'left', 'bold': True, 'font_size': '10px', |
|||
'border': 1, |
|||
'border_color': 'black'}) |
|||
side_heading_sub.set_indent(1) |
|||
txt_name = workbook.add_format({'font_size': '10px', 'border': 1}) |
|||
txt_name.set_indent(2) |
|||
sheet.set_column(0, 0, 30) |
|||
sheet.set_column(1, 1, 20) |
|||
sheet.set_column(2, 2, 15) |
|||
sheet.set_column(3, 3, 15) |
|||
col = 0 |
|||
sheet.write('A1:b1', report_name, head) |
|||
sheet.write('B3:b4', 'Date Range', filter_head) |
|||
sheet.write('B4:b4', 'Partners', filter_head) |
|||
if end_date: |
|||
sheet.merge_range('C3:G3', f"{end_date}", filter_body) |
|||
if data['filters']['partner']: |
|||
display_names = [partner.get('display_name', 'undefined') for |
|||
partner in data['filters']['partner']] |
|||
display_names_str = ', '.join(display_names) |
|||
sheet.merge_range('C4:G4', display_names_str, filter_body) |
|||
if data: |
|||
if report_action == 'dynamic_accounts_report.action_aged_payable': |
|||
sheet.write(6, col, ' ', sub_heading) |
|||
sheet.write(6, col + 1, 'Invoice Date', sub_heading) |
|||
sheet.write(6, col + 2, 'Amount Currency', sub_heading) |
|||
sheet.write(6, col + 3, 'Currency', sub_heading) |
|||
sheet.merge_range(6, col + 4, 6, col + 5, 'Account', |
|||
sub_heading) |
|||
sheet.merge_range(6, col + 6, 6, col + 7, 'Expected Date', |
|||
sub_heading) |
|||
sheet.write(6, col + 8, 'At Date', sub_heading) |
|||
sheet.write(6, col + 9, '1-30', sub_heading) |
|||
sheet.write(6, col + 10, '31-60', sub_heading) |
|||
sheet.write(6, col + 11, '61-90', sub_heading) |
|||
sheet.write(6, col + 12, '91-120', sub_heading) |
|||
sheet.write(6, col + 13, 'Older', sub_heading) |
|||
sheet.write(6, col + 14, 'Total', sub_heading) |
|||
row = 6 |
|||
for move_line in data['move_lines']: |
|||
row += 1 |
|||
sheet.write(row, col, move_line, txt_name) |
|||
sheet.write(row, col + 1, ' ', txt_name) |
|||
sheet.write(row, col + 2, ' ', txt_name) |
|||
sheet.write(row, col + 3, ' ', txt_name) |
|||
sheet.merge_range(row, col + 4, row, col + 5, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row, col + 6, row, col + 7, ' ', |
|||
txt_name) |
|||
sheet.write(row, col + 8, |
|||
data['total'][move_line]['diff0_sum'], |
|||
txt_name) |
|||
sheet.write(row, col + 9, |
|||
data['total'][move_line]['diff1_sum'], |
|||
txt_name) |
|||
sheet.write(row, col + 10, |
|||
data['total'][move_line]['diff2_sum'], |
|||
txt_name) |
|||
sheet.write(row, col + 11, |
|||
data['total'][move_line]['diff3_sum'], |
|||
txt_name) |
|||
sheet.write(row, col + 12, |
|||
data['total'][move_line]['diff4_sum'], |
|||
txt_name) |
|||
sheet.write(row, col + 13, |
|||
data['total'][move_line]['diff5_sum'], |
|||
txt_name) |
|||
sheet.write(row, col + 14, |
|||
data['total'][move_line]['credit_sum'], |
|||
txt_name) |
|||
for rec in data['data'][move_line]: |
|||
row += 1 |
|||
sheet.write(row, col, rec['move_name'] + rec['name'], |
|||
txt_name) |
|||
sheet.write(row, col + 1, rec['date'], |
|||
txt_name) |
|||
sheet.write(row, col + 2, rec['amount_currency'], |
|||
txt_name) |
|||
sheet.write(row, col + 3, rec['currency_id'][1], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 4, row, col + 5, |
|||
rec['account_id'][1], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 6, row, col + 7, |
|||
rec['date_maturity'], |
|||
txt_name) |
|||
sheet.write(row, col + 8, rec['diff0'], txt_name) |
|||
sheet.write(row, col + 9, rec['diff1'], txt_name) |
|||
sheet.write(row, col + 10, rec['diff2'], txt_name) |
|||
sheet.write(row, col + 11, rec['diff3'], txt_name) |
|||
sheet.write(row, col + 12, rec['diff4'], txt_name) |
|||
sheet.write(row, col + 13, rec['diff5'], txt_name) |
|||
sheet.write(row, col + 14, ' ', txt_name) |
|||
sheet.merge_range(row + 1, col, row + 1, col + 7, 'Total', |
|||
filter_head) |
|||
sheet.write(row + 1, col + 8, |
|||
data['grand_total']['diff0_sum'], |
|||
filter_head) |
|||
sheet.write(row + 1, col + 9, |
|||
data['grand_total']['diff1_sum'], |
|||
filter_head) |
|||
sheet.write(row + 1, col + 10, |
|||
data['grand_total']['diff2_sum'], |
|||
filter_head) |
|||
sheet.write(row + 1, col + 11, |
|||
data['grand_total']['diff3_sum'], |
|||
filter_head) |
|||
sheet.write(row + 1, col + 12, |
|||
data['grand_total']['diff4_sum'], |
|||
filter_head) |
|||
sheet.write(row + 1, col + 13, |
|||
data['grand_total']['diff5_sum'], |
|||
filter_head) |
|||
sheet.write(row + 1, col + 14, |
|||
data['grand_total']['total_credit'], |
|||
filter_head) |
|||
workbook.close() |
|||
output.seek(0) |
|||
response.stream.write(output.read()) |
|||
output.close() |
@ -0,0 +1,323 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Bhagyadev KP (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
import io |
|||
import json |
|||
|
|||
import xlsxwriter |
|||
from odoo import models, fields, api |
|||
|
|||
|
|||
class AgeReceivableReport(models.TransientModel): |
|||
"""For creating Age Receivable report""" |
|||
_name = 'age.receivable.report' |
|||
_description = 'Aged Receivable Report' |
|||
|
|||
@api.model |
|||
def view_report(self): |
|||
""" |
|||
Generate a report with move line data categorized by partner and debit |
|||
difference.This method retrieves move line data from the |
|||
'account.move.line' model, filters the records based on specific |
|||
criteria (parent_state, account_type, reconciled),and categorizes the |
|||
data by each partner's name. For each move line, it calculates the debit |
|||
difference based on the number of days between today's date and the |
|||
maturity date of the move line. |
|||
Returns: |
|||
dict: Dictionary containing move line data categorized by partner names. |
|||
Each partner's data includes debit amounts and debit differences |
|||
based on days between maturity date and today. |
|||
The 'partner_totals' key contains summary data for each partner. |
|||
""" |
|||
partner_total = {} |
|||
move_line_list = {} |
|||
paid = self.env['account.move.line'].search( |
|||
[('parent_state', '=', 'posted'), |
|||
('account_type', '=', 'asset_receivable'), |
|||
('reconciled', '=', False)]) |
|||
currency_id = self.env.company.currency_id.symbol |
|||
partner_ids = paid.mapped('partner_id') |
|||
today = fields.Date.today() |
|||
for partner_id in partner_ids: |
|||
move_line_ids = paid.filtered( |
|||
lambda rec: rec.partner_id in partner_id) |
|||
move_line_data = move_line_ids.read( |
|||
['name', 'move_name', 'date', 'amount_currency', 'account_id', |
|||
'date_maturity', 'currency_id', 'debit', 'move_id']) |
|||
for val in move_line_data: |
|||
if val['date_maturity']: |
|||
diffrence = (today - val['date_maturity']).days |
|||
val['diff0'] = val['debit'] if diffrence <= 0 else 0.0 |
|||
val['diff1'] = val['debit'] if 0 < diffrence <= 30 else 0.0 |
|||
val['diff2'] = val['debit'] if 30 < diffrence <= 60 else 0.0 |
|||
val['diff3'] = val['debit'] if 60 < diffrence <= 90 else 0.0 |
|||
val['diff4'] = val['debit'] if 90 < diffrence <= 120 else 0.0 |
|||
val['diff5'] = val['debit'] if diffrence > 120 else 0.0 |
|||
move_line_list[partner_id.name] = move_line_data |
|||
partner_total[partner_id.name] = { |
|||
'debit_sum': sum(val['debit'] for val in move_line_data), |
|||
'diff0_sum': round(sum(val['diff0'] for val in move_line_data), |
|||
2), |
|||
'diff1_sum': round(sum(val['diff1'] for val in move_line_data), |
|||
2), |
|||
'diff2_sum': round(sum(val['diff2'] for val in move_line_data), |
|||
2), |
|||
'diff3_sum': round(sum(val['diff3'] for val in move_line_data), |
|||
2), |
|||
'diff4_sum': round(sum(val['diff4'] for val in move_line_data), |
|||
2), |
|||
'diff5_sum': round(sum(val['diff5'] for val in move_line_data), |
|||
2), |
|||
'currency_id': currency_id, |
|||
'partner_id': partner_id.id |
|||
} |
|||
move_line_list['partner_totals'] = partner_total |
|||
return move_line_list |
|||
|
|||
@api.model |
|||
def get_filter_values(self, date, partner): |
|||
""" |
|||
Retrieve move line data categorized by partner and debit difference. |
|||
|
|||
Parameters: |
|||
date (str): Date for filtering move lines (format: 'YYYY-MM-DD'). |
|||
partner (list): List of partner IDs to filter move lines for. |
|||
|
|||
Returns: |
|||
dict: Dictionary containing move line data categorized by partner |
|||
names.Includes debit amount categorization based on days |
|||
difference.Contains partner-wise summary under |
|||
'partner_totals' key. |
|||
""" |
|||
partner_total = {} |
|||
move_line_list = {} |
|||
if date: |
|||
paid = self.env['account.move.line'].search( |
|||
[('parent_state', '=', 'posted'), |
|||
('account_type', '=', 'asset_receivable'), |
|||
('reconciled', '=', False), ('date', '<=', date)]) |
|||
else: |
|||
paid = self.env['account.move.line'].search( |
|||
[('parent_state', '=', 'posted'), |
|||
('account_type', '=', 'asset_receivable'), |
|||
('reconciled', '=', False)]) |
|||
currency_id = self.env.company.currency_id.symbol |
|||
if partner: |
|||
partner_ids = self.env['res.partner'].search( |
|||
[('id', 'in', partner)]) |
|||
else: |
|||
partner_ids = paid.mapped('partner_id') |
|||
today = fields.Date.today() |
|||
for partner_id in partner_ids: |
|||
move_line_ids = paid.filtered( |
|||
lambda rec: rec.partner_id in partner_id) |
|||
move_line_data = move_line_ids.read( |
|||
['name', 'move_name', 'date', 'amount_currency', 'account_id', |
|||
'date_maturity', 'currency_id', 'debit', 'move_id']) |
|||
for val in move_line_data: |
|||
diffrence = 0 |
|||
if val['date_maturity']: |
|||
diffrence = (today - val['date_maturity']).days |
|||
val['diff0'] = val['debit'] if diffrence <= 0 else 0.0 |
|||
val['diff1'] = val['debit'] if 0 < diffrence <= 30 else 0.0 |
|||
val['diff2'] = val['debit'] if 30 < diffrence <= 60 else 0.0 |
|||
val['diff3'] = val['debit'] if 60 < diffrence <= 90 else 0.0 |
|||
val['diff4'] = val['debit'] if 90 < diffrence <= 120 else 0.0 |
|||
val['diff5'] = val['debit'] if diffrence > 120 else 0.0 |
|||
move_line_list[partner_id.name] = move_line_data |
|||
partner_total[partner_id.name] = { |
|||
'debit_sum': sum(val['debit'] for val in move_line_data), |
|||
'diff0_sum': round(sum(val['diff0'] for val in move_line_data), |
|||
2), |
|||
'diff1_sum': round(sum(val['diff1'] for val in move_line_data), |
|||
2), |
|||
'diff2_sum': round(sum(val['diff2'] for val in move_line_data), |
|||
2), |
|||
'diff3_sum': round(sum(val['diff3'] for val in move_line_data), |
|||
2), |
|||
'diff4_sum': round(sum(val['diff4'] for val in move_line_data), |
|||
2), |
|||
'diff5_sum': round(sum(val['diff5'] for val in move_line_data), |
|||
2), |
|||
'currency_id': currency_id, |
|||
'partner_id': partner_id.id |
|||
} |
|||
move_line_list['partner_totals'] = partner_total |
|||
return move_line_list |
|||
|
|||
@api.model |
|||
def get_xlsx_report(self, data, response, report_name, report_action): |
|||
""" |
|||
Generate an Excel report based on the provided data. |
|||
|
|||
:param data: The data used to generate the report. |
|||
:type data: str (JSON format) |
|||
|
|||
:param response: The response object to write the report to. |
|||
:type response: object |
|||
|
|||
:param report_name: The name of the report. |
|||
:type report_name: str |
|||
|
|||
:return: None |
|||
""" |
|||
data = json.loads(data) |
|||
output = io.BytesIO() |
|||
workbook = xlsxwriter.Workbook(output, {'in_memory': True}) |
|||
end_date = data['filters']['end_date'] if \ |
|||
data['filters']['end_date'] else '' |
|||
sheet = workbook.add_worksheet() |
|||
head = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '15px'}) |
|||
sub_heading = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px', |
|||
'border': 1, 'bg_color': '#D3D3D3', |
|||
'border_color': 'black'}) |
|||
filter_head = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px', |
|||
'border': 1, 'bg_color': '#D3D3D3', |
|||
'border_color': 'black'}) |
|||
filter_body = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px'}) |
|||
side_heading_sub = workbook.add_format( |
|||
{'align': 'left', 'bold': True, 'font_size': '10px', |
|||
'border': 1, |
|||
'border_color': 'black'}) |
|||
side_heading_sub.set_indent(1) |
|||
txt_name = workbook.add_format({'font_size': '10px', 'border': 1}) |
|||
txt_name.set_indent(2) |
|||
sheet.set_column(0, 0, 30) |
|||
sheet.set_column(1, 1, 20) |
|||
sheet.set_column(2, 2, 15) |
|||
sheet.set_column(3, 3, 15) |
|||
col = 0 |
|||
sheet.write('A1:b1', report_name, head) |
|||
sheet.write('B3:b4', 'Date Range', filter_head) |
|||
sheet.write('B4:b4', 'Partners', filter_head) |
|||
if end_date: |
|||
sheet.merge_range('C3:G3', f"{end_date}", filter_body) |
|||
if data['filters']['partner']: |
|||
display_names = [partner.get('display_name', 'undefined') for |
|||
partner in data['filters']['partner']] |
|||
display_names_str = ', '.join(display_names) |
|||
sheet.merge_range('C4:G4', display_names_str, filter_body) |
|||
if data: |
|||
if report_action == 'dynamic_accounts_report.action_aged_receivable': |
|||
sheet.write(6, col, ' ', sub_heading) |
|||
sheet.write(6, col + 1, 'Invoice Date', sub_heading) |
|||
sheet.write(6, col + 2, 'Amount Currency', sub_heading) |
|||
sheet.write(6, col + 3, 'Currency', sub_heading) |
|||
sheet.merge_range(6, col + 4, 6, col + 5, 'Account', |
|||
sub_heading) |
|||
sheet.merge_range(6, col + 6, 6, col + 7, 'Expected Date', |
|||
sub_heading) |
|||
sheet.write(6, col + 8, 'At Date', sub_heading) |
|||
sheet.write(6, col + 9, '1-30', sub_heading) |
|||
sheet.write(6, col + 10, '31-60', sub_heading) |
|||
sheet.write(6, col + 11, '61-90', sub_heading) |
|||
sheet.write(6, col + 12, '91-120', sub_heading) |
|||
sheet.write(6, col + 13, 'Older', sub_heading) |
|||
sheet.write(6, col + 14, 'Total', sub_heading) |
|||
row = 6 |
|||
for move_line in data['move_lines']: |
|||
row += 1 |
|||
sheet.write(row, col, move_line, txt_name) |
|||
sheet.write(row, col + 1, ' ', txt_name) |
|||
sheet.write(row, col + 2, ' ', txt_name) |
|||
sheet.write(row, col + 3, ' ', txt_name) |
|||
sheet.merge_range(row, col + 4, row, col + 5, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row, col + 6, row, col + 7, ' ', |
|||
txt_name) |
|||
sheet.write(row, col + 8, |
|||
data['total'][move_line]['diff0_sum'], |
|||
txt_name) |
|||
sheet.write(row, col + 9, |
|||
data['total'][move_line]['diff1_sum'], |
|||
txt_name) |
|||
sheet.write(row, col + 10, |
|||
data['total'][move_line]['diff2_sum'], |
|||
txt_name) |
|||
sheet.write(row, col + 11, |
|||
data['total'][move_line]['diff3_sum'], |
|||
txt_name) |
|||
sheet.write(row, col + 12, |
|||
data['total'][move_line]['diff4_sum'], |
|||
txt_name) |
|||
sheet.write(row, col + 13, |
|||
data['total'][move_line]['diff5_sum'], |
|||
txt_name) |
|||
sheet.write(row, col + 14, |
|||
data['total'][move_line]['debit_sum'], |
|||
txt_name) |
|||
for rec in data['data'][move_line]: |
|||
row += 1 |
|||
if not rec['name']: |
|||
rec['name'] = ' ' |
|||
sheet.write(row, col, rec['move_name'] + rec['name'], |
|||
txt_name) |
|||
sheet.write(row, col + 1, rec['date'], |
|||
txt_name) |
|||
sheet.write(row, col + 2, rec['amount_currency'], |
|||
txt_name) |
|||
sheet.write(row, col + 3, rec['currency_id'][1], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 4, row, col + 5, |
|||
rec['account_id'][1], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 6, row, col + 7, |
|||
rec['date_maturity'], |
|||
txt_name) |
|||
sheet.write(row, col + 8, rec['diff0'], txt_name) |
|||
sheet.write(row, col + 9, rec['diff1'], txt_name) |
|||
sheet.write(row, col + 10, rec['diff2'], txt_name) |
|||
sheet.write(row, col + 11, rec['diff3'], txt_name) |
|||
sheet.write(row, col + 12, rec['diff4'], txt_name) |
|||
sheet.write(row, col + 13, rec['diff5'], txt_name) |
|||
sheet.write(row, col + 14, ' ', txt_name) |
|||
sheet.merge_range(row + 1, col, row + 1, col + 7, 'Total', |
|||
filter_head) |
|||
sheet.write(row + 1, col + 8, |
|||
data['grand_total']['diff0_sum'], |
|||
filter_head) |
|||
sheet.write(row + 1, col + 9, |
|||
data['grand_total']['diff1_sum'], |
|||
filter_head) |
|||
sheet.write(row + 1, col + 10, |
|||
data['grand_total']['diff2_sum'], |
|||
filter_head) |
|||
sheet.write(row + 1, col + 11, |
|||
data['grand_total']['diff3_sum'], |
|||
filter_head) |
|||
sheet.write(row + 1, col + 12, |
|||
data['grand_total']['diff4_sum'], |
|||
filter_head) |
|||
sheet.write(row + 1, col + 13, |
|||
data['grand_total']['diff5_sum'], |
|||
filter_head) |
|||
sheet.write(row + 1, col + 14, |
|||
data['grand_total']['total_debit'], |
|||
filter_head) |
|||
|
|||
workbook.close() |
|||
output.seek(0) |
|||
response.stream.write(output.read()) |
|||
output.close() |
@ -0,0 +1,321 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Bhagyadev KP (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
import io |
|||
import json |
|||
from dateutil.relativedelta import relativedelta |
|||
import xlsxwriter |
|||
from datetime import datetime |
|||
from odoo.tools import date_utils |
|||
from odoo import api, fields, models |
|||
|
|||
|
|||
class BankBookReport(models.TransientModel): |
|||
"""For creating Bank Book report""" |
|||
_name = 'bank.book.report' |
|||
_description = 'Account Bank Book Report' |
|||
|
|||
@api.model |
|||
def view_report(self): |
|||
""" |
|||
This method retrieves and returns the necessary data for the partner |
|||
ledger report.It fetches account move lines, grouped by accounts, and |
|||
calculates total debit and credit amounts.The resulting data includes |
|||
move lines for each account and the total debit and credit amounts for |
|||
each account. |
|||
""" |
|||
data = {} |
|||
move_lines_total = {} |
|||
journals = self.env['account.journal'].search( |
|||
[('type', '=', 'bank')]) |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
[('parent_state', '=', 'posted'), |
|||
('journal_id', 'in', journals.ids)]) |
|||
accounts = account_move_lines.mapped('account_id').read( |
|||
['display_name', 'name']) |
|||
for account in accounts: |
|||
move_lines = account_move_lines.filtered( |
|||
lambda x: x.account_id.id == account['id']) |
|||
move_line_data = move_lines.read( |
|||
['date', 'journal_id', 'partner_id', 'move_name', 'debit', |
|||
'move_id', |
|||
'credit', 'name', 'ref']) |
|||
data[move_lines.mapped('account_id').display_name] = move_line_data |
|||
currency_id = self.env.company.currency_id.symbol |
|||
move_lines_total[move_lines.mapped('account_id').display_name] = { |
|||
'total_debit': round(sum(move_lines.mapped('debit')), 2), |
|||
'total_credit': round(sum(move_lines.mapped('credit')), 2), |
|||
'currency_id': currency_id} |
|||
data['move_lines_total'] = move_lines_total |
|||
data['accounts'] = accounts |
|||
return data |
|||
|
|||
@api.model |
|||
def get_filter_values(self, partner_id, data_range, account_list, options): |
|||
""" |
|||
Retrieve filtered data for the partner ledger report. |
|||
Args: |
|||
partner_id (list or None): List of partner IDs for filtering by |
|||
partner. If None, all partners will be |
|||
included. |
|||
data_range (str or dict): Range of data to filter the account move |
|||
lines. Can be a string ('month', 'year', |
|||
'quarter','last-month', 'last-year', |
|||
'last-quarter') or a dictionary with |
|||
'start_date' and 'end_date'. |
|||
account_list (list or None): List of account IDs for filtering by |
|||
account. If None, all accounts will be |
|||
included. |
|||
options (dict or None): Additional filtering options with 'draft' |
|||
key (boolean) to include draft moves if |
|||
True. |
|||
Returns: |
|||
dict: Filtered data for the partner ledger report, grouped by |
|||
accounts and summary of total debit and credit amounts. |
|||
""" |
|||
data = {} |
|||
move_lines_total = {} |
|||
today = fields.Date.today() |
|||
quarter_start, quarter_end = date_utils.get_quarter(today) |
|||
previous_quarter_start = quarter_start - relativedelta(months=3) |
|||
previous_quarter_end = quarter_start - relativedelta(days=1) |
|||
journals = self.env['account.journal'].search([('type', '=', 'bank')]) |
|||
option_domain = ['posted'] |
|||
if options is not None: |
|||
if 'draft' in options: |
|||
option_domain = ['posted', 'draft'] |
|||
if partner_id: |
|||
domain = [('parent_state', 'in', option_domain), |
|||
('journal_id', 'in', journals.ids), |
|||
('partner_id', 'in', partner_id), ] |
|||
else: |
|||
domain = [('parent_state', 'in', option_domain), |
|||
('journal_id', 'in', journals.ids), ] |
|||
if account_list: |
|||
domain += ('account_id', 'in', account_list), |
|||
if data_range: |
|||
if data_range == 'month': |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain).filtered( |
|||
lambda x: x.date.month == fields.Date.today().month) |
|||
elif data_range == 'year': |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain).filtered( |
|||
lambda x: x.date.year == fields.Date.today().year) |
|||
elif data_range == 'quarter': |
|||
domain += ('date', '>=', quarter_start), ( |
|||
'date', '<=', quarter_end) |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain) |
|||
elif data_range == 'last-month': |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain).filtered( |
|||
lambda x: x.date.month == fields.Date.today().month - 1) |
|||
elif data_range == 'last-year': |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain).filtered( |
|||
lambda x: x.date.year == fields.Date.today().year - 1) |
|||
elif data_range == 'last-quarter': |
|||
domain += ('date', '>=', previous_quarter_start), ( |
|||
'date', '<=', previous_quarter_end) |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain) |
|||
elif 'start_date' in data_range and 'end_date' in data_range: |
|||
start_date = datetime.strptime(data_range['start_date'], |
|||
'%Y-%m-%d').date() |
|||
end_date = datetime.strptime(data_range['end_date'], |
|||
'%Y-%m-%d').date() |
|||
domain += ('date', '>=', start_date), ('date', '<=', end_date), |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain) |
|||
elif 'start_date' in data_range: |
|||
start_date = datetime.strptime(data_range['start_date'], |
|||
'%Y-%m-%d').date() |
|||
domain.append(('date', '>=', start_date)) |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain) |
|||
elif 'end_date' in data_range: |
|||
end_date = datetime.strptime(data_range['end_date'], |
|||
'%Y-%m-%d').date() |
|||
domain.append(('date', '<=', end_date)) |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain) |
|||
else: |
|||
account_move_lines = self.env['account.move.line'].search(domain) |
|||
accounts = account_move_lines.mapped('account_id').read( |
|||
['display_name']) |
|||
for account in accounts: |
|||
move_lines = account_move_lines.filtered( |
|||
lambda x: x.account_id.id == account['id']) |
|||
move_line_data = move_lines.read( |
|||
['date', 'journal_id', 'partner_id', 'move_name', 'debit', |
|||
'move_id', |
|||
'credit', 'name', 'ref']) |
|||
data[move_lines.mapped('account_id').display_name] = move_line_data |
|||
currency_id = self.env.company.currency_id.symbol |
|||
move_lines_total[move_lines.mapped('account_id').display_name] = { |
|||
'total_debit': round(sum(move_lines.mapped('debit')), 2), |
|||
'total_credit': round(sum(move_lines.mapped('credit')), 2), |
|||
'currency_id': currency_id} |
|||
data['move_lines_total'] = move_lines_total |
|||
return data |
|||
|
|||
@api.model |
|||
def get_xlsx_report(self, data, response, report_name, report_action): |
|||
""" |
|||
Generate an Excel report based on the provided data. |
|||
:param data: The data used to generate the report. |
|||
:type data: str (JSON format) |
|||
:param response: The response object to write the report to. |
|||
:type response: object |
|||
:param report_name: The name of the report. |
|||
:type report_name: str |
|||
:return: None |
|||
""" |
|||
data = json.loads(data) |
|||
output = io.BytesIO() |
|||
workbook = xlsxwriter.Workbook(output, {'in_memory': True}) |
|||
start_date = data['filters']['start_date'] if \ |
|||
data['filters']['start_date'] else '' |
|||
end_date = data['filters']['end_date'] if \ |
|||
data['filters']['end_date'] else '' |
|||
sheet = workbook.add_worksheet() |
|||
head = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '15px'}) |
|||
sub_heading = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px', |
|||
'border': 1, 'bg_color': '#D3D3D3', |
|||
'border_color': 'black'}) |
|||
filter_head = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px', |
|||
'border': 1, 'bg_color': '#D3D3D3', |
|||
'border_color': 'black'}) |
|||
filter_body = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px'}) |
|||
side_heading_sub = workbook.add_format( |
|||
{'align': 'left', 'bold': True, 'font_size': '10px', |
|||
'border': 1, |
|||
'border_color': 'black'}) |
|||
side_heading_sub.set_indent(1) |
|||
txt_name = workbook.add_format({'font_size': '10px', 'border': 1}) |
|||
txt_name.set_indent(2) |
|||
sheet.set_column(0, 0, 30) |
|||
sheet.set_column(1, 1, 20) |
|||
sheet.set_column(2, 2, 15) |
|||
sheet.set_column(3, 3, 15) |
|||
col = 0 |
|||
sheet.write('A1:b1', report_name, head) |
|||
sheet.write('B3:b4', 'Date Range', filter_head) |
|||
sheet.write('B4:b4', 'Partners', filter_head) |
|||
sheet.write('B5:b4', 'Accounts', filter_head) |
|||
sheet.write('B6:b4', 'Options', filter_head) |
|||
if start_date or end_date: |
|||
sheet.merge_range('C3:G3', f"{start_date} to {end_date}", |
|||
filter_body) |
|||
if data['filters']['partner']: |
|||
display_names = [partner.get('display_name', 'undefined') for |
|||
partner in data['filters']['partner']] |
|||
display_names_str = ', '.join(display_names) |
|||
sheet.merge_range('C4:G4', display_names_str, filter_body) |
|||
if data['filters']['account']: |
|||
account_keys_str = ', '.join(data['filters']['account']) |
|||
sheet.merge_range('C5:G5', account_keys_str, filter_body) |
|||
if data['filters']['options']: |
|||
option_keys = list(data['filters']['options'].keys()) |
|||
option_keys_str = ', '.join(option_keys) |
|||
sheet.merge_range('C6:G6', option_keys_str, filter_body) |
|||
if data: |
|||
if report_action == 'dynamic_accounts_report.action_bank_book': |
|||
sheet.write(8, col, ' ', sub_heading) |
|||
sheet.merge_range('B9:C9', 'Journal', sub_heading) |
|||
sheet.merge_range('D9:E9', 'Partner', sub_heading) |
|||
sheet.merge_range('F9:G9', 'Ref', sub_heading) |
|||
sheet.merge_range('H9:I9', 'Move', sub_heading) |
|||
sheet.merge_range('J9:K9', 'Entry Label', sub_heading) |
|||
sheet.merge_range('L9:M9', 'Debit', sub_heading) |
|||
sheet.merge_range('N9:O9', 'Credit', sub_heading) |
|||
sheet.merge_range('P9:Q9', 'Balance', sub_heading) |
|||
row = 8 |
|||
for move_line in data['move_lines']: |
|||
row += 1 |
|||
sheet.write(row, col, move_line, txt_name) |
|||
sheet.merge_range(row, col + 1, row, col + 2, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row, col + 3, row, col + 4, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row, col + 5, row, col + 6, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row, col + 7, row, col + 8, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row, col + 9, row, col + 10, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row, col + 11, row, col + 12, |
|||
data['total'][move_line]['total_debit'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 13, row, col + 14, |
|||
data['total'][move_line]['total_credit'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 15, row, col + 16, |
|||
data['total'][move_line]['total_debit'] - |
|||
data['total'][move_line]['total_credit'], |
|||
txt_name) |
|||
for rec in data['data'][move_line]: |
|||
row += 1 |
|||
if rec['partner_id']: |
|||
partner = rec['partner_id'][1] |
|||
else: |
|||
partner = ' ' |
|||
sheet.write(row, col, rec['date'], txt_name) |
|||
sheet.merge_range(row, col + 1, row, col + 2, |
|||
rec['journal_id'][1], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 3, row, col + 4, partner, |
|||
txt_name) |
|||
sheet.merge_range(row, col + 5, row, col + 6, |
|||
rec['ref'], txt_name) |
|||
sheet.merge_range(row, col + 7, row, col + 8, |
|||
rec['move_name'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 9, row, col + 10, |
|||
rec['name'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 11, row, col + 12, |
|||
rec['debit'], txt_name) |
|||
sheet.merge_range(row, col + 13, row, col + 14, |
|||
rec['credit'], txt_name) |
|||
sheet.merge_range(row, col + 15, row, col + 16, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row + 1, col, row + 1, col + 10, 'Total', |
|||
filter_head) |
|||
sheet.merge_range(row + 1, col + 11, row + 1, col + 12, |
|||
data['grand_total']['total_debit'], |
|||
filter_head) |
|||
sheet.merge_range(row + 1, col + 13, row + 1, col + 14, |
|||
data['grand_total']['total_credit'], |
|||
filter_head) |
|||
sheet.merge_range(row + 1, col + 15, row + 1, col + 16, |
|||
float(data['grand_total']['total_debit']) - |
|||
float(data['grand_total']['total_credit']), |
|||
filter_head) |
|||
workbook.close() |
|||
output.seek(0) |
|||
response.stream.write(output.read()) |
|||
output.close() |
@ -0,0 +1,345 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Bhagyadev KP (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
import io |
|||
import json |
|||
from dateutil.relativedelta import relativedelta |
|||
import xlsxwriter |
|||
from datetime import datetime |
|||
from odoo.tools import date_utils |
|||
from odoo import api, fields, models |
|||
|
|||
|
|||
class CashBookReport(models.TransientModel): |
|||
"""For creating Cash Book report""" |
|||
_name = 'cash.book.report' |
|||
_description = 'Account Cash Book Report' |
|||
|
|||
@api.model |
|||
def view_report(self): |
|||
""" |
|||
Retrieves and formats data for the cash book report. |
|||
|
|||
Returns a dictionary containing the following data: |
|||
- 'move_lines_total': A dictionary containing the total debit, total |
|||
credit, and currency symbol for each account in |
|||
the cash journal. |
|||
- 'accounts': A list of dictionaries, each representing an account |
|||
in the cash journal. Each dictionary contains the |
|||
'display_name' and 'name' of the account. |
|||
- Additional data for each account: The key is the 'display_name' of the |
|||
account, and the value is a list of |
|||
dictionaries, each representing a |
|||
move line for that account. Each |
|||
move line dictionary contains the |
|||
following |
|||
data: 'date', 'journal_id', 'partner_id', 'move_name', 'debit', |
|||
'move_id', 'credit', 'name', and 'ref'. |
|||
""" |
|||
data = {} |
|||
move_lines_total = {} |
|||
journals = self.env['account.journal'].search( |
|||
[('type', '=', 'cash')]) |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
[('parent_state', '=', 'posted'), |
|||
('journal_id', 'in', journals.ids)]) |
|||
accounts = account_move_lines.mapped('account_id').read( |
|||
['display_name', 'name']) |
|||
for account in accounts: |
|||
move_lines = account_move_lines.filtered( |
|||
lambda x: x.account_id.id == account['id']) |
|||
move_line_data = move_lines.read( |
|||
['date', 'journal_id', 'partner_id', 'move_name', 'debit', |
|||
'move_id', |
|||
'credit', 'name', 'ref']) |
|||
data[move_lines.mapped('account_id').display_name] = move_line_data |
|||
currency_id = self.env.company.currency_id.symbol |
|||
move_lines_total[move_lines.mapped('account_id').display_name] = { |
|||
'total_debit': round(sum(move_lines.mapped('debit')), 2), |
|||
'total_credit': round(sum(move_lines.mapped('credit')), 2), |
|||
'currency_id': currency_id} |
|||
data['move_lines_total'] = move_lines_total |
|||
data['accounts'] = accounts |
|||
return data |
|||
|
|||
@api.model |
|||
def get_filter_values(self, partner_id, data_range, account_list, options): |
|||
""" |
|||
Retrieves and formats filtered data for the cash book report based on |
|||
the provided filter criteria. |
|||
:param partner_id: List of partner IDs to filter the data by. |
|||
:type partner_id: list |
|||
:param data_range: Specifies the date range filter. Possible values are |
|||
'month', 'year', 'quarter', 'last-month', |
|||
'last-year', 'last-quarter', or a dictionary |
|||
containing 'start_date' and/or 'end_date' fields. |
|||
:type data_range: str or dict |
|||
:param account_list: List of account IDs to filter the data by. |
|||
:type account_list: list |
|||
:param options: Dictionary containing additional options for filtering |
|||
the data. The 'draft' option indicates |
|||
whether to include draft journal entries in the data. |
|||
:type options: dict |
|||
|
|||
:return: A dictionary containing the following data: |
|||
- 'move_lines_total': A dictionary containing the total debit, |
|||
total credit, and currency symbol |
|||
for each account in the cash journal. |
|||
- Additional data for each account: The key is the |
|||
'display_name' of account, |
|||
and the value is a list of |
|||
dictionaries, each |
|||
representing a move line for |
|||
that account. Each move line |
|||
dictionary contains the |
|||
following |
|||
data: 'date', 'journal_id', 'partner_id', 'move_name', |
|||
debit', 'move_id', 'credit', 'name', and 'ref'. |
|||
:rtype: dict |
|||
""" |
|||
data = {} |
|||
move_lines_total = {} |
|||
today = fields.Date.today() |
|||
quarter_start, quarter_end = date_utils.get_quarter(today) |
|||
previous_quarter_start = quarter_start - relativedelta(months=3) |
|||
previous_quarter_end = quarter_start - relativedelta(days=1) |
|||
journals = self.env['account.journal'].search([('type', '=', 'cash')]) |
|||
option_domain = ['posted'] |
|||
if options is not None: |
|||
if 'draft' in options: |
|||
option_domain = ['posted', 'draft'] |
|||
if partner_id: |
|||
domain = [('parent_state', 'in', option_domain), |
|||
('journal_id', 'in', journals.ids), |
|||
('partner_id', 'in', partner_id), ] |
|||
else: |
|||
domain = [('parent_state', 'in', option_domain), |
|||
('journal_id', 'in', journals.ids), ] |
|||
if account_list: |
|||
domain += ('account_id', 'in', account_list), |
|||
if data_range: |
|||
if data_range == 'month': |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain).filtered( |
|||
lambda x: x.date.month == fields.Date.today().month) |
|||
elif data_range == 'year': |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain).filtered( |
|||
lambda x: x.date.year == fields.Date.today().year) |
|||
elif data_range == 'quarter': |
|||
domain += ('date', '>=', quarter_start), ( |
|||
'date', '<=', quarter_end) |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain) |
|||
elif data_range == 'last-month': |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain).filtered( |
|||
lambda x: x.date.month == fields.Date.today().month - 1) |
|||
elif data_range == 'last-year': |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain).filtered( |
|||
lambda x: x.date.year == fields.Date.today().year - 1) |
|||
elif data_range == 'last-quarter': |
|||
domain += ('date', '>=', previous_quarter_start), ( |
|||
'date', '<=', previous_quarter_end) |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain) |
|||
elif 'start_date' in data_range and 'end_date' in data_range: |
|||
start_date = datetime.strptime(data_range['start_date'], |
|||
'%Y-%m-%d').date() |
|||
end_date = datetime.strptime(data_range['end_date'], |
|||
'%Y-%m-%d').date() |
|||
domain += ('date', '>=', start_date), ('date', '<=', end_date), |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain) |
|||
elif 'start_date' in data_range: |
|||
start_date = datetime.strptime(data_range['start_date'], |
|||
'%Y-%m-%d').date() |
|||
domain.append(('date', '>=', start_date)) |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain) |
|||
elif 'end_date' in data_range: |
|||
end_date = datetime.strptime(data_range['end_date'], |
|||
'%Y-%m-%d').date() |
|||
domain.append(('date', '<=', end_date)) |
|||
account_move_lines = self.env['account.move.line'].search( |
|||
domain) |
|||
else: |
|||
account_move_lines = self.env['account.move.line'].search(domain) |
|||
accounts = account_move_lines.mapped('account_id').read( |
|||
['display_name']) |
|||
for account in accounts: |
|||
move_lines = account_move_lines.filtered( |
|||
lambda x: x.account_id.id == account['id']) |
|||
move_line_data = move_lines.read( |
|||
['date', 'journal_id', 'partner_id', 'move_name', 'debit', |
|||
'move_id', |
|||
'credit', 'name', 'ref']) |
|||
data[move_lines.mapped('account_id').display_name] = move_line_data |
|||
currency_id = self.env.company.currency_id.symbol |
|||
move_lines_total[move_lines.mapped('account_id').display_name] = { |
|||
'total_debit': round(sum(move_lines.mapped('debit')), 2), |
|||
'total_credit': round(sum(move_lines.mapped('credit')), 2), |
|||
'currency_id': currency_id} |
|||
data['move_lines_total'] = move_lines_total |
|||
return data |
|||
|
|||
@api.model |
|||
def get_xlsx_report(self, data, response, report_name, report_action): |
|||
""" |
|||
Generate an Excel report based on the provided data. |
|||
:param data: The data used to generate the report. |
|||
:type data: str (JSON format) |
|||
:param response: The response object to write the report to. |
|||
:type response: object |
|||
:param report_name: The name of the report. |
|||
:type report_name: str |
|||
:return: None |
|||
""" |
|||
data = json.loads(data) |
|||
output = io.BytesIO() |
|||
workbook = xlsxwriter.Workbook(output, {'in_memory': True}) |
|||
start_date = data['filters']['start_date'] if \ |
|||
data['filters']['start_date'] else '' |
|||
end_date = data['filters']['end_date'] if \ |
|||
data['filters']['end_date'] else '' |
|||
sheet = workbook.add_worksheet() |
|||
head = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '15px'}) |
|||
sub_heading = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px', |
|||
'border': 1, 'bg_color': '#D3D3D3', |
|||
'border_color': 'black'}) |
|||
filter_head = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px', |
|||
'border': 1, 'bg_color': '#D3D3D3', |
|||
'border_color': 'black'}) |
|||
filter_body = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px'}) |
|||
side_heading_sub = workbook.add_format( |
|||
{'align': 'left', 'bold': True, 'font_size': '10px', |
|||
'border': 1, |
|||
'border_color': 'black'}) |
|||
side_heading_sub.set_indent(1) |
|||
txt_name = workbook.add_format({'font_size': '10px', 'border': 1}) |
|||
txt_name.set_indent(2) |
|||
sheet.set_column(0, 0, 30) |
|||
sheet.set_column(1, 1, 20) |
|||
sheet.set_column(2, 2, 15) |
|||
sheet.set_column(3, 3, 15) |
|||
col = 0 |
|||
sheet.write('A1:b1', report_name, head) |
|||
sheet.write('B3:b4', 'Date Range', filter_head) |
|||
sheet.write('B4:b4', 'Partners', filter_head) |
|||
sheet.write('B5:b4', 'Accounts', filter_head) |
|||
sheet.write('B6:b4', 'Options', filter_head) |
|||
if start_date or end_date: |
|||
sheet.merge_range('C3:G3', f"{start_date} to {end_date}", |
|||
filter_body) |
|||
if data['filters']['partner']: |
|||
display_names = [partner.get('display_name', 'undefined') for |
|||
partner in data['filters']['partner']] |
|||
display_names_str = ', '.join(display_names) |
|||
sheet.merge_range('C4:G4', display_names_str, filter_body) |
|||
if data['filters']['account']: |
|||
account_keys_str = ', '.join(data['filters']['account']) |
|||
sheet.merge_range('C5:G5', account_keys_str, filter_body) |
|||
if data['filters']['options']: |
|||
option_keys = list(data['filters']['options'].keys()) |
|||
option_keys_str = ', '.join(option_keys) |
|||
sheet.merge_range('C6:G6', option_keys_str, filter_body) |
|||
if data: |
|||
if report_action == 'dynamic_accounts_report.action_cash_book': |
|||
sheet.write(8, col, ' ', sub_heading) |
|||
sheet.merge_range('B9:C9', 'Journal', sub_heading) |
|||
sheet.merge_range('D9:E9', 'Partner', sub_heading) |
|||
sheet.merge_range('F9:G9', 'Ref', sub_heading) |
|||
sheet.merge_range('H9:I9', 'Move', sub_heading) |
|||
sheet.merge_range('J9:K9', 'Entry Label', sub_heading) |
|||
sheet.merge_range('L9:M9', 'Debit', sub_heading) |
|||
sheet.merge_range('N9:O9', 'Credit', sub_heading) |
|||
sheet.merge_range('P9:Q9', 'Balance', sub_heading) |
|||
row = 8 |
|||
for move_line in data['move_lines']: |
|||
row += 1 |
|||
sheet.write(row, col, move_line, txt_name) |
|||
sheet.merge_range(row, col + 1, row, col + 2, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row, col + 3, row, col + 4, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row, col + 5, row, col + 6, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row, col + 7, row, col + 8, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row, col + 9, row, col + 10, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row, col + 11, row, col + 12, |
|||
data['total'][move_line]['total_debit'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 13, row, col + 14, |
|||
data['total'][move_line]['total_credit'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 15, row, col + 16, |
|||
data['total'][move_line]['total_debit'] - |
|||
data['total'][move_line]['total_credit'], |
|||
txt_name) |
|||
for rec in data['data'][move_line]: |
|||
row += 1 |
|||
if rec['partner_id']: |
|||
partner = rec['partner_id'][1] |
|||
else: |
|||
partner = ' ' |
|||
sheet.write(row, col, rec['date'], txt_name) |
|||
sheet.merge_range(row, col + 1, row, col + 2, |
|||
rec['journal_id'][1], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 3, row, col + 4, partner, |
|||
txt_name) |
|||
sheet.merge_range(row, col + 5, row, col + 6, |
|||
rec['ref'], txt_name) |
|||
sheet.merge_range(row, col + 7, row, col + 8, |
|||
rec['move_name'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 9, row, col + 10, |
|||
rec['name'], |
|||
txt_name) |
|||
sheet.merge_range(row, col + 11, row, col + 12, |
|||
rec['debit'], txt_name) |
|||
sheet.merge_range(row, col + 13, row, col + 14, |
|||
rec['credit'], txt_name) |
|||
sheet.merge_range(row, col + 15, row, col + 16, ' ', |
|||
txt_name) |
|||
sheet.merge_range(row + 1, col, row + 1, col + 10, 'Total', |
|||
filter_head) |
|||
sheet.merge_range(row + 1, col + 11, row + 1, col + 12, |
|||
data['grand_total']['total_debit'], |
|||
filter_head) |
|||
sheet.merge_range(row + 1, col + 13, row + 1, col + 14, |
|||
data['grand_total']['total_credit'], |
|||
filter_head) |
|||
sheet.merge_range(row + 1, col + 15, row + 1, col + 16, |
|||
float(data['grand_total']['total_debit']) - |
|||
float(data['grand_total']['total_credit']), |
|||
filter_head) |
|||
workbook.close() |
|||
output.seek(0) |
|||
response.stream.write(output.read()) |
|||
output.close() |
@ -0,0 +1,760 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Bhagyadev KP (<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
import calendar |
|||
import io |
|||
import json |
|||
from datetime import datetime |
|||
import xlsxwriter |
|||
from odoo import models, fields, api |
|||
from odoo.tools.date_utils import get_month, get_fiscal_year, \ |
|||
get_quarter_number, subtract |
|||
|
|||
|
|||
class TaxReport(models.TransientModel): |
|||
"""For creating Tax report.""" |
|||
_name = 'tax.report' |
|||
_description = 'Tax Report' |
|||
|
|||
@api.model |
|||
def view_report(self): |
|||
""" |
|||
View a tax report for the current month. This function retrieves |
|||
tax-related information for the current month. It calculates the net |
|||
amount and tax amount for both sales and purchases based on the tax |
|||
information associated with account move lines. |
|||
:return: Dictionary containing sale and purchase data for the |
|||
current month. |
|||
""" |
|||
sale = [] |
|||
purchase = [] |
|||
tax_ids = self.env['account.move.line'].search([]).mapped( |
|||
'tax_ids') |
|||
today = fields.Date.today() |
|||
for tax in tax_ids: |
|||
tax_id = self.env['account.move.line'].search( |
|||
[('tax_ids', '=', tax.id), ('parent_state', '=', 'posted'), |
|||
('date', '>=', get_month(today)[0]), |
|||
('date', '<=', get_month(today)[1])]).read( |
|||
['debit', 'credit']) |
|||
tax_debit_sums = sum(record['debit'] for record in tax_id) |
|||
tax_credit_sums = sum(record['credit'] for record in tax_id) |
|||
if tax.type_tax_use == 'sale': |
|||
sale.append({ |
|||
'name': tax.name, |
|||
'amount': tax.amount, |
|||
'net': round(tax_debit_sums + tax_credit_sums, 2), |
|||
'tax': round((tax_debit_sums + tax_credit_sums) * ( |
|||
tax.amount / 100), 2) |
|||
}) |
|||
elif tax.type_tax_use == 'purchase': |
|||
purchase.append({ |
|||
'name': tax.name, |
|||
'amount': tax.amount, |
|||
'net': round(tax_debit_sums + tax_credit_sums, 2), |
|||
'tax': round((tax_debit_sums + tax_credit_sums) * ( |
|||
tax.amount / 100), 2) |
|||
}) |
|||
return { |
|||
'sale': sale, |
|||
'purchase': purchase |
|||
} |
|||
|
|||
@api.model |
|||
def get_filter_values(self, start_date, end_date, comparison_number, |
|||
comparison_type, options, report_type): |
|||
""" |
|||
Get filtered tax values based on various criteria. |
|||
|
|||
:param start_date: Start date of the filter period. |
|||
:param end_date: End date of the filter period. |
|||
:param comparison_number: Number of comparison periods. |
|||
:param comparison_type: Type of comparison (year, month, quarter). |
|||
:param options: Filter options. |
|||
:param report_type: Type of report (account, tax). |
|||
:return: Dictionary containing dynamic_date_num, sale, and purchase |
|||
data. |
|||
""" |
|||
sale = [] |
|||
purchase = [] |
|||
dynamic_date_num = {} |
|||
if options == {}: |
|||
options = None |
|||
if options is None: |
|||
option_domain = ['posted'] |
|||
elif 'draft' in options: |
|||
option_domain = ['posted', 'draft'] |
|||
tax_ids = self.env['account.move.line'].search([]).mapped( |
|||
'tax_ids') |
|||
start_date_first = \ |
|||
get_fiscal_year(datetime.strptime(start_date, "%Y-%m-%d").date())[ |
|||
0] if comparison_type == 'year' else datetime.strptime( |
|||
start_date, "%Y-%m-%d").date() |
|||
end_date_first = \ |
|||
get_fiscal_year(datetime.strptime(end_date, "%Y-%m-%d").date())[ |
|||
1] if comparison_type == 'year' else datetime.strptime( |
|||
end_date, "%Y-%m-%d").date() |
|||
if report_type is not None and 'account' in report_type: |
|||
start_date = start_date_first |
|||
end_date = end_date_first |
|||
account_ids = self.env['account.move.line'].search([]).mapped( |
|||
'account_id') |
|||
for account in account_ids: |
|||
tax_ids = self.env['account.move.line'].search( |
|||
[('account_id', '=', account.id)]).mapped('tax_ids') |
|||
if tax_ids: |
|||
for tax in tax_ids: |
|||
dynamic_total_tax_sum = {} |
|||
dynamic_total_net_sum = {} |
|||
if comparison_number: |
|||
if comparison_type == 'year': |
|||
start_date = start_date_first |
|||
end_date = end_date_first |
|||
for i in range(1, eval(comparison_number) + 1): |
|||
com_start_date = subtract(start_date, |
|||
years=i) |
|||
com_end_date = subtract(end_date, years=i) |
|||
tax_id = self.env[ |
|||
'account.move.line'].search( |
|||
[('tax_ids', '=', tax.id), |
|||
('date', '>=', com_start_date), |
|||
('date', '<=', com_end_date), |
|||
('account_id', '=', account.id), |
|||
('parent_state', 'in', |
|||
option_domain)]).read( |
|||
['debit', 'credit']) |
|||
tax_debit_sums = sum( |
|||
record['debit'] for record in tax_id) |
|||
tax_credit_sums = sum( |
|||
record['credit'] for record in tax_id) |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] = tax_debit_sums + tax_credit_sums |
|||
dynamic_total_tax_sum[ |
|||
f"dynamic_total_tax_sum{i}"] = \ |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] * ( |
|||
tax.amount / 100) |
|||
elif comparison_type == 'month': |
|||
dynamic_date_num[ |
|||
f"dynamic_date_num{0}"] = self.get_month_name( |
|||
start_date) + ' ' + str(start_date.year) |
|||
for i in range(1, eval(comparison_number) + 1): |
|||
com_start_date = subtract(start_date, |
|||
months=i) |
|||
com_end_date = subtract(end_date, months=i) |
|||
tax_id = self.env[ |
|||
'account.move.line'].search( |
|||
[('tax_ids', '=', tax.id), |
|||
('date', '>=', com_start_date), |
|||
('account_id', '=', account.id), |
|||
('date', '<=', com_end_date), |
|||
('parent_state', 'in', |
|||
option_domain)]).read( |
|||
['debit', 'credit']) |
|||
tax_debit_sums = sum( |
|||
record['debit'] for record in tax_id) |
|||
tax_credit_sums = sum( |
|||
record['credit'] for record in tax_id) |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] = tax_debit_sums + tax_credit_sums |
|||
dynamic_total_tax_sum[ |
|||
f"dynamic_total_tax_sum{i}"] = \ |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] * ( |
|||
tax.amount / 100) |
|||
dynamic_date_num[ |
|||
f"dynamic_date_num{i}"] = self.get_month_name( |
|||
com_start_date) + ' ' + str( |
|||
com_start_date.year) |
|||
elif comparison_type == 'quarter': |
|||
dynamic_date_num[ |
|||
f"dynamic_date_num{0}"] = 'Q' + ' ' + str( |
|||
get_quarter_number( |
|||
start_date)) + ' ' + str( |
|||
start_date.year) |
|||
for i in range(1, eval(comparison_number) + 1): |
|||
com_start_date = subtract(start_date, |
|||
months=i * 3) |
|||
com_end_date = subtract(end_date, |
|||
months=i * 3) |
|||
tax_id = self.env[ |
|||
'account.move.line'].search( |
|||
[('tax_ids', '=', tax.id), |
|||
('date', '>=', com_start_date), |
|||
('account_id', '=', account.id), |
|||
('date', '<=', com_end_date), |
|||
('parent_state', 'in', |
|||
option_domain)]).read( |
|||
['debit', 'credit']) |
|||
tax_debit_sums = sum( |
|||
record['debit'] for record in tax_id) |
|||
tax_credit_sums = sum( |
|||
record['credit'] for record in tax_id) |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] = tax_debit_sums + tax_credit_sums |
|||
dynamic_total_tax_sum[ |
|||
f"dynamic_total_tax_sum{i}"] = \ |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] * ( |
|||
tax.amount / 100) |
|||
dynamic_date_num[ |
|||
f"dynamic_date_num{i}"] = 'Q' + ' ' + str( |
|||
get_quarter_number( |
|||
com_start_date)) + ' ' + str( |
|||
com_start_date.year) |
|||
tax_id = self.env['account.move.line'].search( |
|||
[('tax_ids', '=', tax.id), |
|||
('date', '>=', start_date_first), |
|||
('date', '<=', end_date_first), |
|||
('parent_state', 'in', option_domain), |
|||
('account_id', '=', account.id)]).read( |
|||
['debit', 'credit']) |
|||
tax_debit_sums = sum( |
|||
record['debit'] for record in tax_id) |
|||
tax_credit_sums = sum( |
|||
record['credit'] for record in tax_id) |
|||
if tax_id and tax.type_tax_use == 'sale': |
|||
if comparison_number: |
|||
sale.append({ |
|||
'name': tax.name, |
|||
'amount': tax.amount, |
|||
'net': round( |
|||
tax_debit_sums + tax_credit_sums, |
|||
2), |
|||
'tax': round( |
|||
(tax_debit_sums + tax_credit_sums) * ( |
|||
tax.amount / 100), 2), |
|||
'dynamic net': dynamic_total_net_sum, |
|||
'dynamic tax': dynamic_total_tax_sum, |
|||
'account': account.display_name, |
|||
}) |
|||
else: |
|||
sale.append({ |
|||
'name': tax.name, |
|||
'amount': tax.amount, |
|||
'net': round( |
|||
tax_debit_sums + tax_credit_sums, |
|||
2), |
|||
'tax': round( |
|||
(tax_debit_sums + tax_credit_sums) * ( |
|||
tax.amount / 100), 2), |
|||
'account': account.display_name, |
|||
}) |
|||
elif tax_id and tax.type_tax_use == 'purchase': |
|||
if comparison_number: |
|||
purchase.append({ |
|||
'name': tax.name, |
|||
'amount': tax.amount, |
|||
'net': round( |
|||
tax_debit_sums + tax_credit_sums, |
|||
2), |
|||
'tax': round( |
|||
(tax_debit_sums + tax_credit_sums) * ( |
|||
tax.amount / 100), 2), |
|||
'dynamic net': dynamic_total_net_sum, |
|||
'dynamic tax': dynamic_total_tax_sum, |
|||
'account': account.display_name, |
|||
}) |
|||
else: |
|||
purchase.append({ |
|||
'name': tax.name, |
|||
'amount': tax.amount, |
|||
'net': round( |
|||
tax_debit_sums + tax_credit_sums, |
|||
2), |
|||
'tax': round( |
|||
(tax_debit_sums + tax_credit_sums) * ( |
|||
tax.amount / 100), 2), |
|||
'account': account.display_name, |
|||
}) |
|||
elif report_type is not None and 'tax' in report_type: |
|||
start_date = start_date_first |
|||
end_date = end_date_first |
|||
for tax in tax_ids: |
|||
account_ids = self.env['account.move.line'].search( |
|||
[('tax_ids', '=', tax.id)]).mapped('account_id') |
|||
for account in account_ids: |
|||
dynamic_total_tax_sum = {} |
|||
dynamic_total_net_sum = {} |
|||
if comparison_number: |
|||
if comparison_type == 'year': |
|||
start_date = start_date_first |
|||
end_date = end_date_first |
|||
for i in range(1, eval(comparison_number) + 1): |
|||
com_start_date = subtract(start_date, |
|||
years=i) |
|||
com_end_date = subtract(end_date, years=i) |
|||
tax_id = self.env[ |
|||
'account.move.line'].search( |
|||
[('tax_ids', '=', tax.id), |
|||
('date', '>=', com_start_date), |
|||
('date', '<=', com_end_date), |
|||
('account_id', '=', account.id), |
|||
('parent_state', 'in', |
|||
option_domain)]).read( |
|||
['debit', 'credit']) |
|||
tax_debit_sums = sum( |
|||
record['debit'] for record in tax_id) |
|||
tax_credit_sums = sum( |
|||
record['credit'] for record in tax_id) |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] = tax_debit_sums + tax_credit_sums |
|||
dynamic_total_tax_sum[ |
|||
f"dynamic_total_tax_sum{i}"] = \ |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] * ( |
|||
tax.amount / 100) |
|||
elif comparison_type == 'month': |
|||
dynamic_date_num[ |
|||
f"dynamic_date_num{0}"] = self.get_month_name( |
|||
start_date) + ' ' + str(start_date.year) |
|||
for i in range(1, eval(comparison_number) + 1): |
|||
com_start_date = subtract(start_date, months=i) |
|||
com_end_date = subtract(end_date, months=i) |
|||
tax_id = self.env[ |
|||
'account.move.line'].search( |
|||
[('tax_ids', '=', tax.id), |
|||
('date', '>=', com_start_date), |
|||
('date', '<=', com_end_date), |
|||
('account_id', '=', account.id), |
|||
('parent_state', 'in', |
|||
option_domain)]).read( |
|||
['debit', 'credit']) |
|||
tax_debit_sums = sum( |
|||
record['debit'] for record in tax_id) |
|||
tax_credit_sums = sum( |
|||
record['credit'] for record in tax_id) |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] = tax_debit_sums + tax_credit_sums |
|||
dynamic_total_tax_sum[ |
|||
f"dynamic_total_tax_sum{i}"] = \ |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] * ( |
|||
tax.amount / 100) |
|||
dynamic_date_num[ |
|||
f"dynamic_date_num{i}"] = self.get_month_name( |
|||
com_start_date) + ' ' + str( |
|||
com_start_date.year) |
|||
elif comparison_type == 'quarter': |
|||
dynamic_date_num[ |
|||
f"dynamic_date_num{0}"] = 'Q' + ' ' + str( |
|||
get_quarter_number(start_date)) + ' ' + str( |
|||
start_date.year) |
|||
for i in range(1, eval(comparison_number) + 1): |
|||
com_start_date = subtract(start_date, |
|||
months=i * 3) |
|||
com_end_date = subtract(end_date, |
|||
months=i * 3) |
|||
tax_id = self.env[ |
|||
'account.move.line'].search( |
|||
[('tax_ids', '=', tax.id), |
|||
('date', '>=', com_start_date), |
|||
('date', '<=', com_end_date), |
|||
('account_id', '=', account.id), |
|||
('parent_state', 'in', |
|||
option_domain)]).read( |
|||
['debit', 'credit']) |
|||
tax_debit_sums = sum( |
|||
record['debit'] for record in tax_id) |
|||
tax_credit_sums = sum( |
|||
record['credit'] for record in tax_id) |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] = tax_debit_sums + tax_credit_sums |
|||
dynamic_total_tax_sum[ |
|||
f"dynamic_total_tax_sum{i}"] = \ |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] * ( |
|||
tax.amount / 100) |
|||
dynamic_date_num[ |
|||
f"dynamic_date_num{i}"] = 'Q' + ' ' + str( |
|||
get_quarter_number( |
|||
com_start_date)) + ' ' + str( |
|||
com_start_date.year) |
|||
tax_id = self.env['account.move.line'].search( |
|||
[('tax_ids', '=', tax.id), |
|||
('parent_state', 'in', option_domain), |
|||
('date', '>=', start_date_first), |
|||
('date', '<=', end_date_first), |
|||
('account_id', '=', account.id)]).read( |
|||
['debit', 'credit']) |
|||
tax_debit_sums = sum( |
|||
record['debit'] for record in tax_id) |
|||
tax_credit_sums = sum( |
|||
record['credit'] for record in tax_id) |
|||
if tax_id and tax.type_tax_use == 'sale': |
|||
if comparison_number: |
|||
sale.append({ |
|||
'name': tax.name, |
|||
'amount': tax.amount, |
|||
'net': round(tax_debit_sums + tax_credit_sums, |
|||
2), |
|||
'tax': round( |
|||
(tax_debit_sums + tax_credit_sums) * ( |
|||
tax.amount / 100), 2), |
|||
'dynamic net': dynamic_total_net_sum, |
|||
'dynamic tax': dynamic_total_tax_sum, |
|||
'account': account.display_name, |
|||
}) |
|||
else: |
|||
sale.append({ |
|||
'name': tax.name, |
|||
'amount': tax.amount, |
|||
'net': round(tax_debit_sums + tax_credit_sums, |
|||
2), |
|||
'tax': round( |
|||
(tax_debit_sums + tax_credit_sums) * ( |
|||
tax.amount / 100), 2), |
|||
'account': account.display_name, |
|||
}) |
|||
elif tax_id and tax.type_tax_use == 'purchase': |
|||
if comparison_number: |
|||
purchase.append({ |
|||
'name': tax.name, |
|||
'amount': tax.amount, |
|||
'net': round(tax_debit_sums + tax_credit_sums, |
|||
2), |
|||
'tax': round( |
|||
(tax_debit_sums + tax_credit_sums) * ( |
|||
tax.amount / 100), 2), |
|||
'dynamic net': dynamic_total_net_sum, |
|||
'dynamic tax': dynamic_total_tax_sum, |
|||
'account': account.display_name, |
|||
}) |
|||
else: |
|||
purchase.append({ |
|||
'name': tax.name, |
|||
'amount': tax.amount, |
|||
'net': round(tax_debit_sums + tax_credit_sums, |
|||
2), |
|||
'tax': round( |
|||
(tax_debit_sums + tax_credit_sums) * ( |
|||
tax.amount / 100), 2), |
|||
'account': account.display_name, |
|||
}) |
|||
else: |
|||
start_date = start_date_first |
|||
end_date = end_date_first |
|||
for tax in tax_ids: |
|||
dynamic_total_tax_sum = {} |
|||
dynamic_total_net_sum = {} |
|||
if comparison_number: |
|||
if comparison_type == 'year': |
|||
start_date = start_date_first |
|||
end_date = end_date_first |
|||
for i in range(1, eval(comparison_number) + 1): |
|||
com_start_date = subtract(start_date, |
|||
years=i) |
|||
com_end_date = subtract(end_date, years=i) |
|||
tax_id = self.env[ |
|||
'account.move.line'].search( |
|||
[('tax_ids', '=', tax.id), |
|||
('date', '>=', com_start_date), |
|||
('date', '<=', com_end_date), |
|||
('parent_state', 'in', option_domain)]).read( |
|||
['debit', 'credit']) |
|||
tax_debit_sums = sum( |
|||
record['debit'] for record in tax_id) |
|||
tax_credit_sums = sum( |
|||
record['credit'] for record in tax_id) |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] = tax_debit_sums + tax_credit_sums |
|||
dynamic_total_tax_sum[ |
|||
f"dynamic_total_tax_sum{i}"] = \ |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] * ( |
|||
tax.amount / 100) |
|||
elif comparison_type == 'month': |
|||
dynamic_date_num[ |
|||
f"dynamic_date_num{0}"] = self.get_month_name( |
|||
start_date) + ' ' + str(start_date.year) |
|||
for i in range(1, eval(comparison_number) + 1): |
|||
com_start_date = subtract(start_date, months=i) |
|||
com_end_date = subtract(end_date, months=i) |
|||
tax_id = self.env[ |
|||
'account.move.line'].search( |
|||
[('tax_ids', '=', tax.id), |
|||
('date', '>=', com_start_date), |
|||
('date', '<=', com_end_date), |
|||
('parent_state', 'in', option_domain)]).read( |
|||
['debit', 'credit']) |
|||
tax_debit_sums = sum( |
|||
record['debit'] for record in tax_id) |
|||
tax_credit_sums = sum( |
|||
record['credit'] for record in tax_id) |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] = tax_debit_sums + tax_credit_sums |
|||
dynamic_total_tax_sum[ |
|||
f"dynamic_total_tax_sum{i}"] = \ |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] * ( |
|||
tax.amount / 100) |
|||
dynamic_date_num[ |
|||
f"dynamic_date_num{i}"] = self.get_month_name( |
|||
com_start_date) + ' ' + str( |
|||
com_start_date.year) |
|||
elif comparison_type == 'quarter': |
|||
dynamic_date_num[ |
|||
f"dynamic_date_num{0}"] = 'Q' + ' ' + str( |
|||
get_quarter_number(start_date)) + ' ' + str( |
|||
start_date.year) |
|||
for i in range(1, eval(comparison_number) + 1): |
|||
com_start_date = subtract(start_date, |
|||
months=i * 3) |
|||
com_end_date = subtract(end_date, |
|||
months=i * 3) |
|||
tax_id = self.env[ |
|||
'account.move.line'].search( |
|||
[('tax_ids', '=', tax.id), |
|||
('date', '>=', com_start_date), |
|||
('date', '<=', com_end_date), |
|||
('parent_state', 'in', option_domain)]).read( |
|||
['debit', 'credit']) |
|||
tax_debit_sums = sum( |
|||
record['debit'] for record in tax_id) |
|||
tax_credit_sums = sum( |
|||
record['credit'] for record in tax_id) |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] = tax_debit_sums + tax_credit_sums |
|||
dynamic_total_tax_sum[ |
|||
f"dynamic_total_tax_sum{i}"] = \ |
|||
dynamic_total_net_sum[ |
|||
f"dynamic_total_net_sum{i}"] * ( |
|||
tax.amount / 100) |
|||
dynamic_date_num[ |
|||
f"dynamic_date_num{i}"] = 'Q' + ' ' + str( |
|||
get_quarter_number( |
|||
com_start_date)) + ' ' + str( |
|||
com_start_date.year) |
|||
tax_id = self.env['account.move.line'].search( |
|||
[('tax_ids', '=', tax.id), |
|||
('parent_state', 'in', option_domain), |
|||
('date', '>=', start_date_first), |
|||
('date', '<=', end_date_first)]).read(['debit', 'credit']) |
|||
tax_debit_sums = sum(record['debit'] for record in tax_id) |
|||
tax_credit_sums = sum(record['credit'] for record in tax_id) |
|||
if tax.type_tax_use == 'sale': |
|||
if comparison_number: |
|||
sale.append({ |
|||
'name': tax.name, |
|||
'amount': tax.amount, |
|||
'net': round(tax_debit_sums + tax_credit_sums, 2), |
|||
'tax': round((tax_debit_sums + tax_credit_sums) * ( |
|||
tax.amount / 100), 2), |
|||
'dynamic net': dynamic_total_net_sum, |
|||
'dynamic tax': dynamic_total_tax_sum, |
|||
}) |
|||
else: |
|||
sale.append({ |
|||
'name': tax.name, |
|||
'amount': tax.amount, |
|||
'net': round(tax_debit_sums + tax_credit_sums, 2), |
|||
'tax': round((tax_debit_sums + tax_credit_sums) * ( |
|||
tax.amount / 100), 2), |
|||
}) |
|||
elif tax.type_tax_use == 'purchase': |
|||
if comparison_number: |
|||
purchase.append({ |
|||
'name': tax.name, |
|||
'amount': tax.amount, |
|||
'net': round(tax_debit_sums + tax_credit_sums, 2), |
|||
'tax': round((tax_debit_sums + tax_credit_sums) * ( |
|||
tax.amount / 100), 2), |
|||
'dynamic net': dynamic_total_net_sum, |
|||
'dynamic tax': dynamic_total_tax_sum, |
|||
}) |
|||
else: |
|||
purchase.append({ |
|||
'name': tax.name, |
|||
'amount': tax.amount, |
|||
'net': round(tax_debit_sums + tax_credit_sums, 2), |
|||
'tax': round((tax_debit_sums + tax_credit_sums) * ( |
|||
tax.amount / 100), 2), |
|||
}) |
|||
return { |
|||
'dynamic_date_num': dynamic_date_num, |
|||
'sale': sale, |
|||
'purchase': purchase |
|||
} |
|||
|
|||
@api.model |
|||
def get_month_name(self, date): |
|||
""" |
|||
Retrieve the abbreviated name of the month for a given date. |
|||
|
|||
:param date: The date for which to retrieve the month's abbreviated |
|||
name. |
|||
:type date: datetime.date |
|||
:return: Abbreviated name of the month (e.g., 'Jan', 'Feb', ..., 'Dec'). |
|||
:rtype: str |
|||
""" |
|||
month_names = calendar.month_abbr |
|||
return month_names[date.month] |
|||
|
|||
@api.model |
|||
def get_xlsx_report(self, data, response, report_name, report_action): |
|||
""" |
|||
Generate an XLSX report based on provided data and response stream. |
|||
|
|||
Generates an Excel workbook with specified report format, including |
|||
subheadings,column headers, and row data for the given financial report |
|||
data. |
|||
|
|||
:param str data: JSON-encoded data for the report. |
|||
:param response: Response object to stream the generated report. |
|||
:param str report_name: Name of the financial report. |
|||
""" |
|||
data = json.loads(data) |
|||
output = io.BytesIO() |
|||
workbook = xlsxwriter.Workbook(output, {'in_memory': True}) |
|||
sheet = workbook.add_worksheet() |
|||
sub_heading = workbook.add_format( |
|||
{'align': 'center', 'bold': True, 'font_size': '10px', |
|||
'border': 1, |
|||
'border_color': 'black'}) |
|||
side_heading_sub = workbook.add_format( |
|||
{'align': 'left', 'bold': True, 'font_size': '10px', |
|||
'border': 1, |
|||
'border_color': 'black'}) |
|||
side_heading_sub.set_indent(1) |
|||
txt_name = workbook.add_format({'font_size': '10px', 'border': 1}) |
|||
txt_name.set_indent(2) |
|||
sheet.set_column(0, 0, 30) |
|||
sheet.set_column(1, 1, 20) |
|||
sheet.set_column(2, 2, 15) |
|||
sheet.set_column(3, 3, 15) |
|||
col = 0 |
|||
sheet.write('A3:b4', report_name, sub_heading) |
|||
sheet.write(5, col, '', sub_heading) |
|||
i = 1 |
|||
for date_view in data['date_viewed']: |
|||
sheet.merge_range(5, col + i, 5, col + i + 1, date_view, |
|||
sub_heading) |
|||
i += 2 |
|||
j = 1 |
|||
prev_account = None |
|||
prev_tax = None |
|||
sheet.write(6, col, '', sub_heading) |
|||
for date in data['date_viewed']: |
|||
sheet.write(6, col + j, 'NET', sub_heading) |
|||
sheet.write(6, col + j + 1, 'TAX', sub_heading) |
|||
j += 1 |
|||
sheet.write(7, col, 'Sales', sub_heading) |
|||
sheet.write(7, col + 1, ' ', sub_heading) |
|||
sheet.write(7, col + 2, data['sale_total'], sub_heading) |
|||
row = 8 |
|||
for sale in data['data']['sale']: |
|||
if data['report_type']: |
|||
if list(data['report_type'].keys())[0] == 'account': |
|||
if prev_account != sale['account']: |
|||
prev_account = sale['account'] |
|||
sheet.write(row, col, sale['account'], txt_name) |
|||
sheet.write(row, col + 1, '', txt_name) |
|||
sheet.write(row, col + 2, '', txt_name) |
|||
elif list(data['report_type'].keys())[0] == 'tax': |
|||
if prev_tax != sale['name']: |
|||
prev_tax = sale['name'] |
|||
sheet.write(row, col, sale['name'] + '(' + str( |
|||
sale['amount']) + '%)', txt_name) |
|||
sheet.write(row, col + 1, '', txt_name) |
|||
sheet.write(row, col + 2, '', txt_name) |
|||
row += 1 |
|||
if data['apply_comparison']: |
|||
if sale['dynamic net']: |
|||
periods = data['comparison_number_range'] |
|||
for num in periods: |
|||
if sale['dynamic net'][ |
|||
'dynamic_total_net_sum' + str(num)]: |
|||
sheet.write(row, col + j, sale['dynamic net'][ |
|||
'dynamic_total_net_sum' + str(num)], |
|||
txt_name) |
|||
if sale['dynamic tax'][ |
|||
'dynamic_total_tax_sum' + str(num)]: |
|||
sheet.write(row, col, sale['dynamic tax'][ |
|||
'dynamic_total_tax_sum' + str(num)], |
|||
txt_name) |
|||
j += 1 |
|||
j = 0 |
|||
sheet.write(row, col + j, sale['name'], txt_name) |
|||
sheet.write(row, col + j + 1, sale['net'], txt_name) |
|||
sheet.write(row, col + j + 2, sale['tax'], txt_name) |
|||
else: |
|||
j = 0 |
|||
sheet.write(row, col + j, sale['name'], txt_name) |
|||
sheet.write(row, col + j + 1, sale['net'], txt_name) |
|||
sheet.write(row, col + j + 2, sale['tax'], txt_name) |
|||
row += 1 |
|||
row += 1 |
|||
sheet.write(row, col, 'Purchase', sub_heading) |
|||
sheet.write(row, col + 1, ' ', sub_heading) |
|||
sheet.write(row, col + 2, data['purchase_total'], sub_heading) |
|||
row += 1 |
|||
for purchase in data['data']['purchase']: |
|||
if data['report_type']: |
|||
if list(data['report_type'].keys())[0] == 'account': |
|||
if prev_account != purchase['account']: |
|||
prev_account = purchase['account'] |
|||
sheet.write(row, col, purchase['account'], txt_name) |
|||
sheet.write(row, col + 1, '', txt_name) |
|||
sheet.write(row, col + 2, '', txt_name) |
|||
elif list(data['report_type'].keys())[0] == 'tax': |
|||
if prev_tax != purchase['name']: |
|||
prev_tax = purchase['name'] |
|||
sheet.write(row, col, purchase['name'] + '(' + str( |
|||
purchase['amount']) + '%)', txt_name) |
|||
sheet.write(row, col + 1, '', txt_name) |
|||
sheet.write(row, col + 2, '', txt_name) |
|||
row += 1 |
|||
if data['apply_comparison']: |
|||
if purchase['dynamic net']: |
|||
periods = data['comparison_number_range'] |
|||
for num in periods: |
|||
if purchase['dynamic net'][ |
|||
'dynamic_total_net_sum' + str(num)]: |
|||
sheet.write(row, col + j, |
|||
purchase['dynamic net'][ |
|||
'dynamic_total_net_sum' + str( |
|||
num)], |
|||
txt_name) |
|||
if purchase['dynamic tax'][ |
|||
'dynamic_total_tax_sum' + str(num)]: |
|||
sheet.write(row, col, purchase['dynamic tax'][ |
|||
'dynamic_total_tax_sum' + str(num)], |
|||
txt_name) |
|||
j += 1 |
|||
j = 0 |
|||
sheet.write(row, col + j, purchase['name'], txt_name) |
|||
sheet.write(row, col + j + 1, purchase['net'], txt_name) |
|||
sheet.write(row, col + j + 2, purchase['tax'], txt_name) |
|||
else: |
|||
j = 0 |
|||
sheet.write(row, col + j, purchase['name'], txt_name) |
|||
sheet.write(row, col + j + 1, purchase['net'], txt_name) |
|||
sheet.write(row, col + j + 2, purchase['tax'], txt_name) |
|||
row += 1 |
|||
row += 1 |
|||
sheet.write(row, col, 'Purchase', sub_heading) |
|||
sheet.write(row, col + 1, ' ', sub_heading) |
|||
sheet.write(row, col + 2, data['purchase_total'], sub_heading) |
|||
row += 1 |
|||
workbook.close() |
|||
output.seek(0) |
|||
response.stream.write(output.read()) |
|||
output.close() |
@ -0,0 +1,278 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Report template for Aged Payable Report.--> |
|||
<template id="aged_payable"> |
|||
<t t-call="web.html_container"> |
|||
<t t-call="web.external_layout"> |
|||
<t t-set="data_report_margin_top" t-value="12"/> |
|||
<t t-set="data_report_header_spacing" t-value="9"/> |
|||
<t t-set="data_report_dpi" t-value="110"/> |
|||
<div class="page"> |
|||
<h3> |
|||
<center> |
|||
<b> |
|||
<span t-esc="report_name"/> |
|||
</b> |
|||
</center> |
|||
</h3> |
|||
<br/> |
|||
<br/> |
|||
<div class="filters"> |
|||
<table class="table table-sm table-reports"> |
|||
<thead class="filter_table" |
|||
style="background:#808080;"> |
|||
<tr> |
|||
<th>Date Range</th> |
|||
<th>Partner</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody style="font-size:11px;font-weight:100;"> |
|||
<tr> |
|||
<th> |
|||
<t t-if="filters['end_date']"> |
|||
<t t-out="filters['end_date']"/> |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-foreach="filters['partner']" |
|||
t-as="selected_partner" |
|||
t-key="partner_index"> |
|||
<t t-out="selected_partner['display_name']"/> |
|||
, |
|||
</t> |
|||
</th> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
<br/> |
|||
<br/> |
|||
<br/> |
|||
<t t-if="move_lines"> |
|||
<t t-foreach="move_lines" |
|||
t-as="move_line" |
|||
t-key="partner_index"> |
|||
<table class="table table-sm table-reports"> |
|||
<thead style="background:#808080;"> |
|||
<tr> |
|||
<th style="width:10%" colspan="6"/> |
|||
<th style="width:10%">Invoice Date</th> |
|||
<th style="width:10%">Amount Currency |
|||
</th> |
|||
<th style="width:10%">Currency</th> |
|||
<th style="width:10%">Account</th> |
|||
<th style="width:10%">Expected Date</th> |
|||
<th style="width:10%">At Date</th> |
|||
<th style="width:10%">1-30</th> |
|||
<th style="width:10%">31-60</th> |
|||
<th style="width:10%">61-90</th> |
|||
<th style="width:10%">91-120</th> |
|||
<th style="width:10%">Older</th> |
|||
<th style="width:10%">Total</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr class="border-bottom" |
|||
style="background:#D3D3D3;"> |
|||
<th colspan="6" |
|||
style="border:0px solid transparent;border-left: thin solid #dee2e6;"> |
|||
<div> |
|||
<span class="fw-bolder"> |
|||
<t t-esc="move_line"/> |
|||
</span> |
|||
</div> |
|||
</th> |
|||
<th style="border:0px solid transparent;"/> |
|||
<th style="border:0px solid transparent;"/> |
|||
<th style="border:0px solid transparent;"/> |
|||
<th style="border:0px solid transparent;"/> |
|||
<th style="border:0px solid transparent;"/> |
|||
<th style="border:0px solid transparent;font-size:11px;font-weight:100;"> |
|||
<span> |
|||
<t t-if="total[move_line]['diff0_sum']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="total[move_line]['diff0_sum']" |
|||
t-esc="total[move_line]['diff0_sum']"/> |
|||
</span> |
|||
</th> |
|||
<th style="border:0px solid transparent;font-size:11px;font-weight:100;"> |
|||
<span> |
|||
<t t-if="total[move_line]['diff1_sum']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="total[move_line]['diff1_sum']" |
|||
t-esc="total[move_line]['diff1_sum']"/> |
|||
</span> |
|||
</th> |
|||
<th style="border:0px solid transparent;font-size:11px;font-weight:100;"> |
|||
<span> |
|||
<t t-if="total[move_line]['diff2_sum']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="total[move_line]['diff2_sum']" |
|||
t-esc="total[move_line]['diff2_sum']"/> |
|||
</span> |
|||
</th> |
|||
<th style="border:0px solid transparent;font-size:11px;font-weight:100;"> |
|||
<span> |
|||
<t t-if="total[move_line]['diff3_sum']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="total[move_line]['diff3_sum']" |
|||
t-esc="total[move_line]['diff3_sum']"/> |
|||
</span> |
|||
</th> |
|||
<th style="border:0px solid transparent;font-size:11px;font-weight:100;"> |
|||
<span> |
|||
<t t-if="total[move_line]['diff4_sum']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="total[move_line]['diff4_sum']" |
|||
t-esc="total[move_line]['diff4_sum']"/> |
|||
</span> |
|||
</th> |
|||
<th style="border:0px solid transparent;font-size:11px;font-weight:100;"> |
|||
<span> |
|||
<t t-if="total[move_line]['diff5_sum']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="total[move_line]['diff5_sum']" |
|||
t-esc="total[move_line]['diff5_sum']"/> |
|||
</span> |
|||
</th> |
|||
<th style="border:0px solid transparent;border-right: thin solid #dee2e6;font-size:11px;font-weight:100;"> |
|||
<span class="fw-bolder"> |
|||
<t t-if="total[move_line]['credit_sum']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="total[move_line]['credit_sum']" |
|||
t-esc="total[move_line]['credit_sum']"/> |
|||
</span> |
|||
</th> |
|||
</tr> |
|||
<t t-foreach="data[move_line]" |
|||
t-as="valuelist" |
|||
t-key="valuelist_index"> |
|||
<tr class="border-bottom" |
|||
style="font-size:11px;font-weight:100;"> |
|||
<th colspan="6"> |
|||
<span> |
|||
<t t-esc="valuelist['move_name']"/> |
|||
<t t-esc="valuelist['name']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-esc="valuelist['date']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-esc="valuelist['amount_currency']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-esc="valuelist['currency_id'][1]"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-esc="valuelist['account_id'][1]"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-if="valuelist['date_maturity']" |
|||
t-esc="valuelist['date_maturity']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-if="valuelist['diff0']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="valuelist['diff0']" |
|||
t-esc="valuelist['diff0']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-if="valuelist['diff1']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="valuelist['diff1']" |
|||
t-esc="valuelist['diff1']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-if="valuelist['diff2']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="valuelist['diff2']" |
|||
t-esc="valuelist['diff2']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-if="valuelist['diff3']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="valuelist['diff3']" |
|||
t-esc="valuelist['diff3']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-if="valuelist['diff4']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="valuelist['diff4']" |
|||
t-esc="valuelist['diff4']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-if="valuelist['diff5']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="valuelist['diff5']" |
|||
t-esc="valuelist['diff5']"/> |
|||
</span> |
|||
</th> |
|||
<th/> |
|||
</tr> |
|||
</t> |
|||
</tbody> |
|||
</table> |
|||
</t> |
|||
</t> |
|||
<table class="table table-sm table-reports"> |
|||
<tbody> |
|||
<tr> |
|||
<th style="width:60%;">Total</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['diff0_sum']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['diff1_sum']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['diff2_sum']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['diff3_sum']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['diff4_sum']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['diff5_sum']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['total_credit']"/> |
|||
</th> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</template> |
|||
</odoo> |
@ -0,0 +1,279 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Report template for Aged Receivable Report.--> |
|||
<template id="aged_receivable"> |
|||
<t t-call="web.html_container"> |
|||
<t t-call="web.external_layout"> |
|||
<t t-set="data_report_margin_top" t-value="12"/> |
|||
<t t-set="data_report_header_spacing" t-value="9"/> |
|||
<t t-set="data_report_dpi" t-value="110"/> |
|||
<div class="page"> |
|||
<h3> |
|||
<center> |
|||
<b> |
|||
<span t-esc="report_name"/> |
|||
</b> |
|||
</center> |
|||
</h3> |
|||
<br/> |
|||
<br/> |
|||
<div class="filters"> |
|||
<table class="table table-sm table-reports"> |
|||
<thead class="filter_table" |
|||
style="background:#808080;"> |
|||
<tr> |
|||
<th>Date Range</th> |
|||
<th>Partner</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody style="font-size:11px;font-weight:100;"> |
|||
<tr> |
|||
<th> |
|||
<t t-if="filters['end_date']"> |
|||
<t t-out="filters['end_date']"/> |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-foreach="filters['partner']" |
|||
t-as="selected_partner" |
|||
t-key="partner_index"> |
|||
<t t-out="selected_partner['display_name']"/> |
|||
, |
|||
</t> |
|||
</th> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
<br/> |
|||
<br/> |
|||
<br/> |
|||
<t t-if="move_lines"> |
|||
<t t-foreach="move_lines" |
|||
t-as="move_line" |
|||
t-key="partner_index"> |
|||
<table class="table table-sm table-reports"> |
|||
<thead style="background:#808080;"> |
|||
<tr> |
|||
<th style="width:10%" colspan="6"/> |
|||
<th style="width:10%">Invoice Date</th> |
|||
<th style="width:10%">Amount Currency |
|||
</th> |
|||
<th style="width:10%">Currency</th> |
|||
<th style="width:10%">Account</th> |
|||
<th style="width:10%">Expected Date |
|||
</th> |
|||
<th style="width:10%">At Date</th> |
|||
<th style="width:10%">1-30</th> |
|||
<th style="width:10%">31-60</th> |
|||
<th style="width:10%">61-90</th> |
|||
<th style="width:10%">91-120</th> |
|||
<th style="width:10%">Older</th> |
|||
<th style="width:10%">Total</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr class="border-bottom" |
|||
style="background:#D3D3D3;"> |
|||
<th colspan="6" |
|||
style="border:0px solid transparent;border-left: thin solid #dee2e6;"> |
|||
<div> |
|||
<span class="fw-bolder"> |
|||
<t t-esc="move_line"/> |
|||
</span> |
|||
</div> |
|||
</th> |
|||
<th style="border:0px solid transparent;"/> |
|||
<th style="border:0px solid transparent;"/> |
|||
<th style="border:0px solid transparent;"/> |
|||
<th style="border:0px solid transparent;"/> |
|||
<th style="border:0px solid transparent;"/> |
|||
<th style="border:0px solid transparent;font-size:11px;font-weight:100;"> |
|||
<span> |
|||
<t t-if="total[move_line]['diff0_sum']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="total[move_line]['diff0_sum']" |
|||
t-esc="total[move_line]['diff0_sum']"/> |
|||
</span> |
|||
</th> |
|||
<th style="border:0px solid transparent;font-size:11px;font-weight:100;"> |
|||
<span> |
|||
<t t-if="total[move_line]['diff1_sum']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="total[move_line]['diff1_sum']" |
|||
t-esc="total[move_line]['diff1_sum']"/> |
|||
</span> |
|||
</th> |
|||
<th style="border:0px solid transparent;font-size:11px;font-weight:100;"> |
|||
<span> |
|||
<t t-if="total[move_line]['diff2_sum']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="total[move_line]['diff2_sum']" |
|||
t-esc="total[move_line]['diff2_sum']"/> |
|||
</span> |
|||
</th> |
|||
<th style="border:0px solid transparent;font-size:11px;font-weight:100;"> |
|||
<span> |
|||
<t t-if="total[move_line]['diff3_sum']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="total[move_line]['diff3_sum']" |
|||
t-esc="total[move_line]['diff3_sum']"/> |
|||
</span> |
|||
</th> |
|||
<th style="border:0px solid transparent;font-size:11px;font-weight:100;"> |
|||
<span> |
|||
<t t-if="total[move_line]['diff4_sum']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="total[move_line]['diff4_sum']" |
|||
t-esc="total[move_line]['diff4_sum']"/> |
|||
</span> |
|||
</th> |
|||
<th style="border:0px solid transparent;font-size:11px;font-weight:100;"> |
|||
<span> |
|||
<t t-if="total[move_line]['diff5_sum']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="total[move_line]['diff5_sum']" |
|||
t-esc="total[move_line]['diff5_sum']"/> |
|||
</span> |
|||
</th> |
|||
<th style="border:0px solid transparent;border-right: thin solid #dee2e6;font-size:11px;font-weight:100;"> |
|||
<span class="fw-bolder"> |
|||
<t t-if="total[move_line]['debit_sum']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="total[move_line]['debit_sum']" |
|||
t-esc="total[move_line]['debit_sum']"/> |
|||
</span> |
|||
</th> |
|||
</tr> |
|||
<t t-foreach="data[move_line]" |
|||
t-as="valuelist" |
|||
t-key="valuelist_index"> |
|||
<tr class="border-bottom" |
|||
style="font-size:11px;font-weight:100;"> |
|||
<th colspan="6"> |
|||
<span> |
|||
<t t-esc="valuelist['move_name']"/> |
|||
<t t-esc="valuelist['name']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-esc="valuelist['date']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-esc="valuelist['amount_currency']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-esc="valuelist['currency_id'][1]"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-esc="valuelist['account_id'][1]"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-if="valuelist['date_maturity']" |
|||
t-esc="valuelist['date_maturity']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-if="valuelist['diff0']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="valuelist['diff0']" |
|||
t-esc="valuelist['diff0']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-if="valuelist['diff1']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="valuelist['diff1']" |
|||
t-esc="valuelist['diff1']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-if="valuelist['diff2']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="valuelist['diff2']" |
|||
t-esc="valuelist['diff2']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-if="valuelist['diff3']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="valuelist['diff3']" |
|||
t-esc="valuelist['diff3']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-if="valuelist['diff4']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="valuelist['diff4']" |
|||
t-esc="valuelist['diff4']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-if="valuelist['diff5']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="valuelist['diff5']" |
|||
t-esc="valuelist['diff5']"/> |
|||
</span> |
|||
</th> |
|||
<th/> |
|||
</tr> |
|||
</t> |
|||
</tbody> |
|||
</table> |
|||
</t> |
|||
</t> |
|||
<table class="table table-sm table-reports"> |
|||
<tbody> |
|||
<tr> |
|||
<th style="width:60%;">Total</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['diff0_sum']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['diff1_sum']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['diff2_sum']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['diff3_sum']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['diff4_sum']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['diff5_sum']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['total_debit']"/> |
|||
</th> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</template> |
|||
</odoo> |
@ -0,0 +1,922 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Balance Sheet Template --> |
|||
<!-- This template defines the structure and layout of a balance sheet |
|||
report --> |
|||
<template id="dynamic_accounts_report.balance_sheet"> |
|||
<t t-call="web.html_container"> |
|||
<t t-call="web.external_layout"> |
|||
|
|||
<t t-set="data_report_dpi" t-value="110"/> |
|||
<div class="page"> |
|||
<h3> |
|||
<span t-esc="report_name"/><!-- Report title --> |
|||
</h3> |
|||
<br/> |
|||
<table cellspacing="0" width="100%" |
|||
style="border: 1px solid white; text-align: left;"> |
|||
<thead> |
|||
<!-- Table header --> |
|||
<tr class="o_heading"> |
|||
<th colspan="6"/> |
|||
<t t-if="data['year']"> |
|||
<t t-foreach="data['year']" |
|||
t-as="periodData" |
|||
t-key="periodData_index"> |
|||
<th class="text-end"> |
|||
<t t-esc="periodData"/> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
<tr class="o_heading"> |
|||
<th colspan="6"/> |
|||
<t t-if="data['year']"> |
|||
<t t-foreach="data['year']" |
|||
t-as="periodData" |
|||
t-key="periodData_index"> |
|||
<th class="text-end">Balance</th> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<!-- Table body --> |
|||
<tr style="border-bottom: 1.5px solid black;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="font-weight: bolder; margin-left: 2%;"> |
|||
ASSETS |
|||
</span> |
|||
</th> |
|||
<th colspan="3"/> |
|||
</tr> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
Current Assets |
|||
</span> |
|||
</th> |
|||
<th colspan="3"/> |
|||
</tr> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="margin-left: 6%;">Bank and Cash |
|||
Accounts |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['asset_cash'][1]"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<t t-foreach="data['datas'][0]['asset_cash'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-if="datas['amount'] != '0.00'"> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" |
|||
style="font-weight: normal;"> |
|||
<span style="margin-left: 8%;"> |
|||
<t t-esc="datas['name']"/> |
|||
</span> |
|||
</th> |
|||
<!-- Assuming you want to iterate over all values to display --> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" t-key="values_index"> |
|||
<t t-foreach="values['asset_cash'][0]" |
|||
t-as="account" |
|||
t-key="account_index"> |
|||
<t t-if="account['name'] == datas['name']"> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="account['amount']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="margin-left: 6%;">Receivables |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['asset_receivable'][1]"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<t t-foreach="data['datas']" t-as="value" |
|||
t-key="value_index"> |
|||
<t t-if="value_index == 0"> |
|||
<t t-foreach="value['asset_receivable'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-set="account_name" |
|||
t-value="datas['name']"/> |
|||
<t t-set="account_value" t-value="0"/> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['asset_receivable'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<t t-if="datas['amount'] != '0.00'"> |
|||
<t t-set="account_value" |
|||
t-value="1"/> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<t t-if="account_value == 1"> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['asset_receivable'][0]" |
|||
t-as="datas" |
|||
t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<th colspan="6" |
|||
style="font-weight: normal;"> |
|||
<span style="margin-left: 8%;"> |
|||
<t t-esc="datas['name']"/> |
|||
</span> |
|||
</th> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['amount']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="margin-left: 6%;">Current |
|||
Assets |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['asset_current'][1]"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<t t-foreach="data['datas']" t-as="value" |
|||
t-key="value_index"> |
|||
<t t-if="value_index == 0"> |
|||
<t t-foreach="value['asset_current'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-set="account_name" |
|||
t-value="datas['name']"/> |
|||
<t t-set="account_value" t-value="0"/> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['asset_current'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<t t-if="datas['amount'] != '0.00'"> |
|||
<t t-set="account_value" |
|||
t-value="1"/> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<t t-if="account_value == 1"> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['asset_current'][0]" |
|||
t-as="datas" |
|||
t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<th colspan="6" |
|||
style="font-weight: normal;"> |
|||
<span style="margin-left: 8%;"> |
|||
<t t-esc="datas['name']"/> |
|||
</span> |
|||
</th> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['amount']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="margin-left: 6%;">Prepayments |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['asset_prepayments'][1]"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<t t-foreach="data['datas']" t-as="value" |
|||
t-key="value_index"> |
|||
<t t-if="value_index == 0"> |
|||
<t t-foreach="value['asset_prepayments'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-set="account_name" |
|||
t-value="datas['name']"/> |
|||
<t t-set="account_value" t-value="0"/> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['asset_prepayments'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<t t-if="datas['amount'] != '0.00'"> |
|||
<t t-set="account_value" |
|||
t-value="1"/> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<t t-if="account_value == 1"> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['asset_prepayments'][0]" |
|||
t-as="datas" |
|||
t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<th colspan="6" |
|||
style="font-weight: normal;"> |
|||
<span style="margin-left: 8%;"> |
|||
<t t-esc="datas['name']"/> |
|||
</span> |
|||
</th> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['amount']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
Total Current Assets |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
<t t-esc="datas['total_current_asset']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="margin-left: 6%;">Plus Fixed |
|||
Assets |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['asset_fixed'][1]"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<t t-foreach="data['datas']" t-as="value" |
|||
t-key="value_index"> |
|||
<t t-if="value_index == 0"> |
|||
<t t-foreach="value['asset_fixed'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-set="account_name" |
|||
t-value="datas['name']"/> |
|||
<t t-set="account_value" t-value="0"/> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['asset_fixed'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<t t-if="datas['amount'] != '0.00'"> |
|||
<t t-set="account_value" |
|||
t-value="1"/> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<t t-if="account_value == 1"> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['asset_fixed'][0]" |
|||
t-as="datas" |
|||
t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<th colspan="6" |
|||
style="font-weight: normal;"> |
|||
<span style="margin-left: 8%;"> |
|||
<t t-esc="datas['name']"/> |
|||
</span> |
|||
</th> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['amount']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="margin-left: 6%;">Plus |
|||
Non-current Assets |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['asset_non_current'][1]"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<t t-foreach="data['datas']" t-as="value" |
|||
t-key="value_index"> |
|||
<t t-if="value_index == 0"> |
|||
<t t-foreach="value['asset_non_current'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-set="account_name" |
|||
t-value="datas['name']"/> |
|||
<t t-set="account_value" t-value="0"/> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['asset_non_current'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<t t-if="datas['amount'] != '0.00'"> |
|||
<t t-set="account_value" |
|||
t-value="1"/> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<t t-if="account_value == 1"> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['asset_non_current'][0]" |
|||
t-as="datas" |
|||
t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<th colspan="6" |
|||
style="font-weight: normal;"> |
|||
<span style="margin-left: 8%;"> |
|||
<t t-esc="datas['name']"/> |
|||
</span> |
|||
</th> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['amount']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<tr style="border-bottom: 1px solid black;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
Total Assets |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
<t t-esc="datas['total_assets']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<tr style="border-bottom: 1.5px solid black;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="font-weight: bolder; margin-left: 2%;"> |
|||
LIABILITIES |
|||
</span> |
|||
</th> |
|||
<th colspan="3"/> |
|||
</tr> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
Current Liabilities |
|||
</span> |
|||
</th> |
|||
<th colspan="3"/> |
|||
</tr> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="margin-left: 6%;">Current |
|||
Liabilities |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['liability_current'][1]"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<t t-foreach="data['datas']" t-as="value" |
|||
t-key="value_index"> |
|||
<t t-if="value_index == 0"> |
|||
<t t-foreach="value['liability_current'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-set="account_name" |
|||
t-value="datas['name']"/> |
|||
<t t-set="account_value" t-value="0"/> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['liability_current'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<t t-if="datas['amount'] != '0.00'"> |
|||
<t t-set="account_value" |
|||
t-value="1"/> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<t t-if="account_value == 1"> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['liability_current'][0]" |
|||
t-as="datas" |
|||
t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<th colspan="6" |
|||
style="font-weight: normal;"> |
|||
<span style="margin-left: 8%;"> |
|||
<t t-esc="datas['name']"/> |
|||
</span> |
|||
</th> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['amount']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="margin-left: 6%;">Payables |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['liability_payable'][1]"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<t t-foreach="data['datas']" t-as="value" |
|||
t-key="value_index"> |
|||
<t t-if="value_index == 0"> |
|||
<t t-foreach="value['liability_payable'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-set="account_name" |
|||
t-value="datas['name']"/> |
|||
<t t-set="account_value" t-value="0"/> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['liability_payable'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<t t-if="datas['amount'] != '0.00'"> |
|||
<t t-set="account_value" |
|||
t-value="1"/> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<t t-if="account_value == 1"> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['liability_payable'][0]" |
|||
t-as="datas" |
|||
t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<th colspan="6" |
|||
style="font-weight: normal;"> |
|||
<span style="margin-left: 8%;"> |
|||
<t t-esc="datas['name']"/> |
|||
</span> |
|||
</th> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['amount']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
Total Current Liabilities |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
<t t-esc="datas['total_current_liability']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="margin-left: 6%;">Plus |
|||
Non-current Liabilities |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['liability_non_current'][1]"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<t t-foreach="data['datas']" t-as="value" |
|||
t-key="value_index"> |
|||
<t t-if="value_index == 0"> |
|||
<t t-foreach="value['liability_non_current'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-set="account_name" |
|||
t-value="datas['name']"/> |
|||
<t t-set="account_value" t-value="0"/> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['liability_non_current'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<t t-if="datas['amount'] != '0.00'"> |
|||
<t t-set="account_value" |
|||
t-value="1"/> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<t t-if="account_value == 1"> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['liability_non_current'][0]" |
|||
t-as="datas" |
|||
t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<th colspan="6" |
|||
style="font-weight: normal;"> |
|||
<span style="margin-left: 8%;"> |
|||
<t t-esc="datas['name']"/> |
|||
</span> |
|||
</th> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['amount']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<tr style="border-bottom: 1px solid black;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
Total LIABILITIES |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
<t t-esc="datas['total_liability']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<tr style="border-bottom: 1.5px solid black;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="font-weight: bolder; margin-left: 2%;"> |
|||
EQUITY |
|||
</span> |
|||
</th> |
|||
<th colspan="3"/> |
|||
</tr> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
Unallocated Earnings |
|||
</span> |
|||
</th> |
|||
<th colspan="3"/> |
|||
</tr> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="margin-left: 6%;">Current |
|||
Earnings |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['total_earnings']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="margin-left: 6%;">Current |
|||
Allocated Earnings |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['equity_unaffected'][1]"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<t t-foreach="data['datas']" t-as="value" |
|||
t-key="value_index"> |
|||
<t t-if="value_index == 0"> |
|||
<t t-foreach="value['equity_unaffected'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-set="account_name" |
|||
t-value="datas['name']"/> |
|||
<t t-set="account_value" t-value="0"/> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['equity_unaffected'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<t t-if="datas['amount'] != '0.00'"> |
|||
<t t-set="account_value" |
|||
t-value="1"/> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<t t-if="account_value == 1"> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['equity_unaffected'][0]" |
|||
t-as="datas" |
|||
t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<th colspan="6" |
|||
style="font-weight: normal;"> |
|||
<span style="margin-left: 8%;"> |
|||
<t t-esc="datas['name']"/> |
|||
</span> |
|||
</th> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['amount']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
Total Unallocated Earnings |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
<t t-esc="datas['total_unallocated_earning']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="margin-left: 6%;">Retained |
|||
Earnings |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['equity'][1]"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<t t-foreach="data['datas']" t-as="value" |
|||
t-key="value_index"> |
|||
<t t-if="value_index == 0"> |
|||
<t t-foreach="value['equity'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-set="account_name" |
|||
t-value="datas['name']"/> |
|||
<t t-set="account_value" t-value="0"/> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['equity'][0]" |
|||
t-as="datas" t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<t t-if="datas['amount'] != '0.00'"> |
|||
<t t-set="account_value" |
|||
t-value="1"/> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<t t-if="account_value == 1"> |
|||
<tr style="border-bottom: 1px solid gainsboro;"> |
|||
<t t-foreach="data['datas']" |
|||
t-as="values" |
|||
t-key="values_index"> |
|||
<t t-foreach="values['equity'][0]" |
|||
t-as="datas" |
|||
t-key="datas_index"> |
|||
<t t-if="account_name == datas['name']"> |
|||
<th colspan="6" |
|||
style="font-weight: normal;"> |
|||
<span style="margin-left: 8%;"> |
|||
<t t-esc="datas['name']"/> |
|||
</span> |
|||
</th> |
|||
<th class="text-end" |
|||
style="font-weight: normal;"> |
|||
<span> |
|||
<t t-esc="datas['amount']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<tr style="border-bottom: 1px solid black;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
Total EQUITY |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
<t t-esc="datas['total_equity']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<tr style="border-bottom: 1px solid black;"> |
|||
<th colspan="6" style="font-weight: normal;"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
LIABILITIES + EQUITY |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="datas" |
|||
t-key="datas_index"> |
|||
<th class="text-end"> |
|||
<span style="font-weight: bolder; margin-left: 4%;"> |
|||
<t t-esc="datas['total_balance']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</template> |
|||
</odoo> |
@ -0,0 +1,231 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Report Template for Bank Book.--> |
|||
<template id="bank_book"> |
|||
<t t-call="web.html_container"> |
|||
<t t-call="web.external_layout"> |
|||
<t t-set="data_report_margin_top" t-value="12"/> |
|||
<t t-set="data_report_header_spacing" t-value="9"/> |
|||
<t t-set="data_report_dpi" t-value="110"/> |
|||
<div class="page"> |
|||
<h3> |
|||
<center> |
|||
<b> |
|||
<span t-esc="report_name"/> |
|||
</b> |
|||
</center> |
|||
</h3> |
|||
<br/> |
|||
<br/> |
|||
<div class="filters"> |
|||
<table class="table table-sm table-reports"> |
|||
<thead class="filter_table" |
|||
style="background:#808080;"> |
|||
<tr> |
|||
<th>Date Range</th> |
|||
<th>Partner</th> |
|||
<th>Account</th> |
|||
<th>Options</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody style="font-size:11px;font-weight:100;"> |
|||
<tr> |
|||
<th> |
|||
<t t-if="filters['start_date']" |
|||
t-out="filters['start_date']"/> |
|||
<t t-if="filters['end_date']"> |
|||
to |
|||
<t t-out="filters['end_date']"/> |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-foreach="filters['partner']" |
|||
t-as="selected_partner" |
|||
t-key="partner_index"> |
|||
<t t-out="selected_partner['display_name']"/> |
|||
, |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-set="first_account" t-value="True"/> |
|||
<t t-foreach="filters['account']" t-as="selected_account"> |
|||
<t t-if="not first_account">,</t> |
|||
<t t-out="selected_account"/> |
|||
<t t-set="first_account" t-value="False"/> |
|||
</t> |
|||
</th> |
|||
<th> |
|||
Posted, |
|||
<t t-foreach="filters['options']" |
|||
t-as="selected_options" |
|||
t-key="options_index"> |
|||
<t t-out="selected_options"/>, |
|||
</t> |
|||
</th> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
<br/> |
|||
<br/> |
|||
<br/> |
|||
<t t-if="move_lines"> |
|||
<t t-foreach="move_lines" |
|||
t-as="move_line" |
|||
t-key="move_lines_index"> |
|||
<table class="table table-sm table-reports"> |
|||
<thead style="background:#808080;"> |
|||
<tr> |
|||
<th style="width:10%" colspan="6"/> |
|||
<th style="width:10%">Journal</th> |
|||
<th style="width:10%">Partner</th> |
|||
<th style="width:10%">Reference</th> |
|||
<th style="width:10%">Move</th> |
|||
<th style="width:10%">Entry label</th> |
|||
<th class="text-right" |
|||
style="padding-right:6px;width:10%;"> |
|||
Debit |
|||
</th> |
|||
<th class="text-right" |
|||
style="padding-right:6px;width:10%;"> |
|||
Credit |
|||
</th> |
|||
<th class="text-right" |
|||
style="padding-right:6px;width:10%;"> |
|||
Balance |
|||
</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody style="font-size:11px;font-weight:100;"> |
|||
<tr class="border-bottom" |
|||
style="background:#D3D3D3;"> |
|||
<th colspan="8" |
|||
style="border:0px solid transparent;"> |
|||
<div class="ms-3"> |
|||
<span class="fw-bolder"> |
|||
<strong> |
|||
<b> |
|||
<t t-esc="move_line"/> |
|||
</b> |
|||
</strong> |
|||
</span> |
|||
</div> |
|||
</th> |
|||
<th style="width:10% border:0px solid transparent;"/> |
|||
<th style="width:10% border:0px solid transparent;"/> |
|||
<th style="width:10% border:0px solid transparent;"/> |
|||
<th style="width:10% border:0px solid transparent;"> |
|||
<strong> |
|||
<span> |
|||
<t t-if="total[move_line]['total_debit']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="total[move_line]['total_debit']" |
|||
t-esc="total[move_line]['total_debit']"/> |
|||
</span> |
|||
</strong> |
|||
</th> |
|||
<th style="width:10% border:0px solid transparent;"> |
|||
<strong> |
|||
<span> |
|||
<t t-if="total[move_line]['total_credit']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="total[move_line]['total_credit']" |
|||
t-esc="total[move_line]['total_credit']"/> |
|||
</span> |
|||
</strong> |
|||
</th> |
|||
<th style="width:10% border:0px solid transparent;"> |
|||
<strong> |
|||
<span class="fw-bolder"> |
|||
<t t-esc="total[move_line]['currency_id']"/> |
|||
<t t-esc="total[move_line]['total_debit'] - total[move_line]['total_credit']"/> |
|||
</span> |
|||
</strong> |
|||
</th> |
|||
</tr> |
|||
<t t-foreach="data[move_line]" |
|||
t-as="valuelist" |
|||
t-key="valuelist_index"> |
|||
<tr class="border-bottom"> |
|||
<th colspan="6" style="width:10%"> |
|||
<span> |
|||
<t t-esc="valuelist['date']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-esc="valuelist['journal_id'][1]"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-if="valuelist['partner_id']"> |
|||
<t t-esc="valuelist['partner_id'][1]"/> |
|||
</t> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-if="valuelist['ref']" |
|||
t-esc="valuelist['ref']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-if="valuelist['move_name']" |
|||
t-esc="valuelist['move_name']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-if="valuelist['name']" |
|||
t-esc="valuelist['name']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-if="valuelist['debit']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="valuelist['debit']" |
|||
t-esc="valuelist['debit']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-if="valuelist['credit']" |
|||
t-esc="total[move_line]['currency_id']"/> |
|||
<t t-if="valuelist['credit']" |
|||
t-esc="valuelist['credit']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"/> |
|||
</tr> |
|||
</t> |
|||
</tbody> |
|||
</table> |
|||
</t> |
|||
</t> |
|||
<table class="table table-sm table-reports"> |
|||
<tbody> |
|||
<tr> |
|||
<th style="width:60%;">Total</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['total_debit']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['total_credit']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="float(grand_total['total_debit']) - float(grand_total['total_credit'])"/> |
|||
</th> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</template> |
|||
</odoo> |
@ -0,0 +1,209 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Report Template for Profit and Book.--> |
|||
<template id="profit_loss"> |
|||
<t t-call="web.html_container"> |
|||
<t t-call="web.external_layout"> |
|||
<t t-set="data_report_margin_top" t-value="12"/> |
|||
<t t-set="data_report_header_spacing" t-value="9"/> |
|||
<t t-set="data_report_dpi" t-value="110"/> |
|||
<div class="page"> |
|||
<h3> |
|||
<center> |
|||
<b> |
|||
<span t-esc="report_name"/> |
|||
</b> |
|||
</center> |
|||
</h3> |
|||
<br/> |
|||
<br/> |
|||
<div class="filters"> |
|||
<table class="table table-sm table-reports"> |
|||
<thead class="filter_table" |
|||
style="background:#808080;"> |
|||
<tr> |
|||
<th>Date Range</th> |
|||
<th>Comparison</th> |
|||
<th>Account</th> |
|||
<th>Journal</th> |
|||
<th>Analytic Account</th> |
|||
<th>Target move</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody style="font-size:11px;font-weight:100;"> |
|||
<tr> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
<br/> |
|||
<br/> |
|||
<br/> |
|||
<table cellspacing="0" width="100%" style="border: 1px solid white; text-align: left;"> |
|||
<thead> |
|||
<tr class="o_heading"> |
|||
<th colspan="6"/> |
|||
<t t-if="data['year']"> |
|||
<t t-foreach="data['year']" |
|||
t-as="periodData" |
|||
t-key="periodData_index"> |
|||
<th class="text-end"> |
|||
<t t-esc="periodData"/> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
<tr class="o_heading"> |
|||
<th colspan="6"/> |
|||
<t t-if="data['year']"> |
|||
<t t-foreach="data['year']" |
|||
t-as="periodData" |
|||
t-key="periodData_index"> |
|||
<th class="text-end">Balance</th> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr> |
|||
<th colspan="6"> |
|||
<span class="fw-bolder"> |
|||
Net Profit |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="total" |
|||
t-key="total_index"> |
|||
<th class="text-end"> |
|||
<span class="fw-bolder"> |
|||
<t t-if="total['total']" |
|||
t-esc="total['total']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<tr class="border-bottom border-dark" style="border-right:0px solid transparent;"> |
|||
<th colspan="9"> |
|||
<span class="fw-bolder ms-2"> |
|||
Income |
|||
</span> |
|||
</th> |
|||
</tr> |
|||
<tr class="border-bottom border-gainsboro"> |
|||
<th colspan="9"> |
|||
<span class="fw-bolder ms-3"> |
|||
Gross Profit |
|||
</span> |
|||
</th> |
|||
</tr> |
|||
<tr class="border-bottom border-gainsboro"> |
|||
<th colspan="6"> |
|||
<span class="ms-3">Operating Income</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="total" |
|||
t-key="total_index"> |
|||
<th class="text-end"> |
|||
<span> |
|||
<t t-esc="total['income'][1]"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<tr class="border-bottom border-gainsboro"> |
|||
<th colspan="6"> |
|||
<span class="ms-3">Cost of |
|||
Revenue |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="total" |
|||
t-key="total_index"> |
|||
<th class="text-end"> |
|||
<span> |
|||
<t t-esc="total['expense_direct_cost'][1]"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<tr class="border-bottom"> |
|||
<th colspan="6"> |
|||
<span class="ms-3">Other Income |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="total" |
|||
t-key="total_index"> |
|||
<th class="text-end"> |
|||
<span> |
|||
<t t-esc="total['income_other'][1]"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<tr class="border-bottom"> |
|||
<th colspan="6"> |
|||
<span class="fw-bolder ms-2"> |
|||
Total Income |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="total" |
|||
t-key="total_index"> |
|||
<th class="text-end"> |
|||
<span class="fw-bolder"> |
|||
<t t-esc="total['total_income']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<tr class="border-bottom border-dark" style="border-right:0px solid transparent;"> |
|||
<th colspan="9"> |
|||
<span class="fw-bolder ms-1"> |
|||
Expenses |
|||
</span> |
|||
</th> |
|||
</tr> |
|||
<tr class="border-bottom" style="border-right:0px solid transparent;"> |
|||
<th colspan="6"> |
|||
<span class="ms-3">Expenses</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="total" |
|||
t-key="total_index"> |
|||
<th class="text-end"> |
|||
<span> |
|||
<t t-esc="total['expense'][1]"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<tr class="border-bottom border-gainsboro"> |
|||
<th colspan="6"> |
|||
<span class="ms-3">Depreciation |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="total" |
|||
t-key="total_index"> |
|||
<th class="text-end"> |
|||
<span> |
|||
<t t-esc="total['expense_depreciation'][1]"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<tr class="border-bottom"> |
|||
<th colspan="6"> |
|||
<span class="fw-bolder ms-2">Total Expenses |
|||
</span> |
|||
</th> |
|||
<t t-foreach="data['datas']" t-as="total" |
|||
t-key="total_index"> |
|||
<th class="text-end"> |
|||
<span class="fw-bolder"> |
|||
<t t-esc="total['total_expense']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</template> |
|||
</odoo> |
@ -0,0 +1,74 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Action record for Profit and Loss report --> |
|||
<record id="action_print_profit_loss" model="ir.actions.report"> |
|||
<field name="name">Profit And Loss</field> |
|||
<field name="model">dynamic.balance.sheet.report</field> |
|||
<field name="report_type">qweb-pdf</field> |
|||
<field name="report_name">dynamic_accounts_report.profit_loss</field> |
|||
<field name="report_file">dynamic_accounts_report.profit_loss</field> |
|||
</record> |
|||
<!-- Action record for Balance Sheet report --> |
|||
<record id="action_print_balance_sheet" model="ir.actions.report"> |
|||
<field name="name">Balance Sheet</field> |
|||
<field name="model">dynamic.balance.sheet.report</field> |
|||
<field name="report_type">qweb-pdf</field> |
|||
<field name="report_name">dynamic_accounts_report.balance_sheet</field> |
|||
<field name="report_file">dynamic_accounts_report.balance_sheet</field> |
|||
</record> |
|||
<!-- Action record for Partner Ledger report --> |
|||
<record id="action_print_partner_ledger" model="ir.actions.report"> |
|||
<field name="name">Partner Ledger</field> |
|||
<field name="model">account.partner.ledger</field> |
|||
<field name="report_type">qweb-pdf</field> |
|||
<field name="report_name">dynamic_accounts_report.partner_ledger</field> |
|||
<field name="report_file">dynamic_accounts_report.partner_ledger</field> |
|||
</record> |
|||
<!-- Action record for General Ledger report --> |
|||
<record id="action_print_general_ledger" model="ir.actions.report"> |
|||
<field name="name">General Ledger</field> |
|||
<field name="model">account.general.ledger</field> |
|||
<field name="report_type">qweb-pdf</field> |
|||
<field name="report_name">dynamic_accounts_report.general_ledger</field> |
|||
<field name="report_file">dynamic_accounts_report.general_ledger</field> |
|||
</record> |
|||
<!-- Action record for Bank Book report --> |
|||
<record id="action_print_bank_book" model="ir.actions.report"> |
|||
<field name="name">Bank Book</field> |
|||
<field name="model">bank.book.report</field> |
|||
<field name="report_type">qweb-pdf</field> |
|||
<field name="report_name">dynamic_accounts_report.bank_book</field> |
|||
<field name="report_file">dynamic_accounts_report.bank_book</field> |
|||
</record> |
|||
<!-- Action record for Age Receivable report --> |
|||
<record id="action_print_aged_receivable" model="ir.actions.report"> |
|||
<field name="name">Age Receivable</field> |
|||
<field name="model">age.receivable.report</field> |
|||
<field name="report_type">qweb-pdf</field> |
|||
<field name="report_name">dynamic_accounts_report.aged_receivable</field> |
|||
<field name="report_file">dynamic_accounts_report.aged_receivable</field> |
|||
</record> |
|||
<!-- Action record for Age Payable report --> |
|||
<record id="action_print_aged_payable" model="ir.actions.report"> |
|||
<field name="name">Age Payable</field> |
|||
<field name="model">age.payable.report</field> |
|||
<field name="report_type">qweb-pdf</field> |
|||
<field name="report_name">dynamic_accounts_report.aged_payable</field> |
|||
<field name="report_file">dynamic_accounts_report.aged_payable</field> |
|||
</record> |
|||
<!-- Action record for Age Payable report --> |
|||
<record id="action_print_trial_balance" model="ir.actions.report"> |
|||
<field name="name">Trial Balance</field> |
|||
<field name="model">account.trial.balance</field> |
|||
<field name="report_type">qweb-pdf</field> |
|||
<field name="report_name">dynamic_accounts_report.trial_balance</field> |
|||
<field name="report_file">dynamic_accounts_report.trial_balance</field> |
|||
</record> |
|||
<record id="action_print_tax_report" model="ir.actions.report"> |
|||
<field name="name">Tax Report</field> |
|||
<field name="model">tax.report</field> |
|||
<field name="report_type">qweb-pdf</field> |
|||
<field name="report_name">dynamic_accounts_report.tax_report</field> |
|||
<field name="report_file">dynamic_accounts_report.tax_report</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,219 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Report Template for General Ledger--> |
|||
<template id="general_ledger"> |
|||
<t t-call="web.html_container"> |
|||
<t t-call="web.external_layout"> |
|||
<t t-set="data_report_margin_top" t-value="12"/> |
|||
<t t-set="data_report_header_spacing" t-value="9"/> |
|||
<t t-set="data_report_dpi" t-value="110"/> |
|||
<div class="page"> |
|||
<h3> |
|||
<center> |
|||
<b> |
|||
<span t-esc="report_name"/> |
|||
</b> |
|||
</center> |
|||
</h3> |
|||
<br/> |
|||
<br/> |
|||
<div class="filters"> |
|||
<table class="table table-sm table-reports"> |
|||
<thead class="filter_table" |
|||
style="background:#808080;"> |
|||
<tr> |
|||
<th>Date Range</th> |
|||
<th>Journal</th> |
|||
<th>Analytic</th> |
|||
<th>Options</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody style="font-size:11px;font-weight:100;"> |
|||
<tr> |
|||
<th> |
|||
<t t-if="filters['start_date']" |
|||
t-out="filters['start_date']"/> |
|||
<t t-if="filters['end_date']"> |
|||
to |
|||
<t t-out="filters['end_date']"/> |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-set="first_journal" t-value="True"/> |
|||
<t t-foreach="filters['journal']" t-as="selected_journal"> |
|||
<t t-if="not first_journal">,</t> |
|||
<t t-out="selected_journal"/> |
|||
<t t-set="first_journal" t-value="False"/> |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-set="first_account" t-value="True"/> |
|||
<t t-foreach="filters['analytic']" t-as="selected_analytic_account"> |
|||
<t t-if="not first_account">,</t> |
|||
<t t-out="selected_analytic_account"/> |
|||
<t t-set="first_account" t-value="False"/> |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-if="filters['options']"> |
|||
Posted , |
|||
</t> |
|||
<t t-else=""> |
|||
Posted |
|||
</t> |
|||
<t t-set="first_option" t-value="True"/> |
|||
<t t-foreach="filters['options']" t-as="selected_options"> |
|||
<t t-if="not first_option">,</t> |
|||
<t t-out="selected_options"/> |
|||
<t t-set="first_option" t-value="False"/> |
|||
</t> |
|||
</th> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
<br/> |
|||
<br/> |
|||
<br/> |
|||
<t t-if="account"> |
|||
<t t-foreach="account" |
|||
t-as="accounts" |
|||
t-key="accounts_index"> |
|||
<table class="table table-sm table-reports"> |
|||
<thead style="background:#808080;"> |
|||
<tr> |
|||
<th style="width:10%" colspan="6"/> |
|||
<th style="width:10%">Date</th> |
|||
<th style="width:10%">Communication |
|||
</th> |
|||
<th style="width:10%">Partner</th> |
|||
<th style="width:10%">Debit</th> |
|||
<th style="width:10%">Credit</th> |
|||
<th style="width:10%">Balance</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody style="font-size:11px;font-weight:100;"> |
|||
<tr class="border-bottom" |
|||
style="background:#D3D3D3;"> |
|||
<th colspan="6"> |
|||
<div class="ms-3"> |
|||
<span class="fw-bolder"> |
|||
<t t-if="accounts != 'false'"> |
|||
<strong> |
|||
<b> |
|||
<t t-esc="accounts"/> |
|||
</b> |
|||
</strong> |
|||
</t> |
|||
<t t-else=""> |
|||
<span>Unknown |
|||
Account |
|||
</span> |
|||
</t> |
|||
</span> |
|||
</div> |
|||
</th> |
|||
<th style="width:10% border:0px solid transparent;"/> |
|||
<th style="width:10% border:0px solid transparent;"/> |
|||
<th style="width:10% border:0px solid transparent;"/> |
|||
<th style="width:10% border:0px solid transparent;"> |
|||
<strong> |
|||
<span> |
|||
<t t-if="total[accounts]['total_debit']" |
|||
t-esc="total[accounts]['currency_id']"/> |
|||
<t t-if="total[accounts]['total_debit']" |
|||
t-esc="total[accounts]['total_debit']"/> |
|||
</span> |
|||
</strong> |
|||
</th> |
|||
<th style="width:10% border:0px solid transparent;"> |
|||
<strong> |
|||
<span> |
|||
<t t-if="total[accounts]['total_credit']" |
|||
t-esc="total[accounts]['currency_id']"/> |
|||
<t t-if="total[accounts]['total_credit']" |
|||
t-esc="total[accounts]['total_credit']"/> |
|||
</span> |
|||
</strong> |
|||
</th> |
|||
<th style="width:10% border:0px solid transparent;border-right: thin solid #dee2e6;"> |
|||
<strong> |
|||
<span class="fw-bolder"> |
|||
<t t-esc="total[accounts]['currency_id']"/> |
|||
<t t-esc="total[accounts]['total_debit'] - total[accounts]['total_credit']"/> |
|||
</span> |
|||
</strong> |
|||
</th> |
|||
</tr> |
|||
<t t-foreach="data[accounts]" |
|||
t-as="valuelist" |
|||
t-key="valuelist_index"> |
|||
<tr class="border-bottom"> |
|||
<th colspan="6" style="width:10%"> |
|||
<span> |
|||
<t t-esc="valuelist[0]['move_name']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-esc="valuelist[0]['date']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-esc="valuelist[0]['name']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-if="valuelist[0]['partner_id']" |
|||
t-esc="valuelist[0]['partner_id'][1]"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-if="valuelist[0]['debit']" |
|||
t-esc="total[accounts]['currency_id']"/> |
|||
<t t-if="valuelist[0]['debit']" |
|||
t-esc="valuelist[0]['debit']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-if="valuelist[0]['credit']" |
|||
t-esc="total[accounts]['currency_id']"/> |
|||
<t t-if="valuelist[0]['credit']" |
|||
t-esc="valuelist[0]['credit']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"/> |
|||
</tr> |
|||
</t> |
|||
</tbody> |
|||
</table> |
|||
</t> |
|||
</t> |
|||
<table class="table table-sm table-reports"> |
|||
<tbody> |
|||
<tr> |
|||
<th style="width:45%;">Total</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['total_debit']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['total_credit']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="float(grand_total['total_debit']) - float(grand_total['total_credit'])"/> |
|||
</th> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</template> |
|||
</odoo> |
@ -0,0 +1,281 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Report Template for Partner Ledger.--> |
|||
<template id="partner_ledger"> |
|||
<t t-call="web.html_container"> |
|||
<t t-call="web.external_layout"> |
|||
<t t-set="data_report_margin_top" t-value="12"/> |
|||
<t t-set="data_report_header_spacing" t-value="9"/> |
|||
<t t-set="data_report_dpi" t-value="110"/> |
|||
<div class="page"> |
|||
<h3> |
|||
<center> |
|||
<b> |
|||
<span t-esc="report_name"/> |
|||
</b> |
|||
</center> |
|||
</h3> |
|||
<br/> |
|||
<br/> |
|||
<div class="filters"> |
|||
<table class="table table-sm table-reports"> |
|||
<thead class="filter_table" |
|||
style="background:#808080;"> |
|||
<tr> |
|||
<th>Date Range</th> |
|||
<th>Partner</th> |
|||
<th>Account</th> |
|||
<th>Options</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody style="font-size:11px;font-weight:100;"> |
|||
<tr> |
|||
<th> |
|||
<t t-if="filters['start_date']" |
|||
t-out="filters['start_date']"/> |
|||
<t t-if="filters['end_date']"> |
|||
to |
|||
<t t-out="filters['end_date']"/> |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-foreach="filters['partner']" |
|||
t-as="selected_partner" |
|||
t-key="partner_index"> |
|||
<t t-out="selected_partner['display_name']"/> |
|||
, |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-foreach="filters['account']" |
|||
t-as="selected_account" |
|||
t-key="account_index"> |
|||
<t t-out="selected_account"/>, |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-foreach="filters['options']" |
|||
t-as="selected_options" |
|||
t-key="options_index"> |
|||
<t t-out="selected_options"/>, |
|||
</t> |
|||
</th> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
<br/> |
|||
<br/> |
|||
<br/> |
|||
<t t-if="partners"> |
|||
<t t-foreach="partners" |
|||
t-as="partner" |
|||
t-key="partner_index"> |
|||
<table class="table table-sm table-reports"> |
|||
<thead style="background:#808080;"> |
|||
<tr> |
|||
<th style="width:10%" colspan="6"/> |
|||
<th style="width:10%">JRNL</th> |
|||
<th style="width:10%">Account</th> |
|||
<th style="width:10%">Ref</th> |
|||
<th style="width:10%">Due Date</th> |
|||
<th style="width:10%">Matching Number |
|||
</th> |
|||
<th style="width:10%">Debit</th> |
|||
<th style="width:10%">Credit</th> |
|||
<th style="width:10%">Amount Currency |
|||
</th> |
|||
<th style="width:10%">Balance</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody style="font-size:11px;font-weight:100;"> |
|||
<tr class="border-bottom" |
|||
style="background:#D3D3D3;"> |
|||
<th colspan="9" |
|||
style="border:0px solid transparent;border-left: thin solid #dee2e6;"> |
|||
<div class="ms-3"> |
|||
<span class="fw-bolder"> |
|||
<t t-if="partner != 'false'"> |
|||
<strong> |
|||
<b> |
|||
<t t-esc="partner"/> |
|||
</b> |
|||
</strong> |
|||
</t> |
|||
<t t-else=""> |
|||
<span>Unknown |
|||
Partner |
|||
</span> |
|||
</t> |
|||
</span> |
|||
</div> |
|||
</th> |
|||
<th style="width:10% border:0px solid transparent;"/> |
|||
<th style="width:10% border:0px solid transparent;"/> |
|||
<th style="width:10% border:0px solid transparent;"> |
|||
<strong> |
|||
<span> |
|||
<t t-if="total[partner]['total_debit']" |
|||
t-esc="total[partner]['currency_id']"/> |
|||
<t t-if="total[partner]['total_debit']" |
|||
t-esc="total[partner]['total_debit']"/> |
|||
</span> |
|||
</strong> |
|||
</th> |
|||
<th style="width:10% border:0px solid transparent;"> |
|||
<strong> |
|||
<span> |
|||
<t t-if="total[partner]['total_credit']" |
|||
t-esc="total[partner]['currency_id']"/> |
|||
<t t-if="total[partner]['total_credit']" |
|||
t-esc="total[partner]['total_credit']"/> |
|||
</span> |
|||
</strong> |
|||
</th> |
|||
<th style="width:10% border:0px solid transparent;"/> |
|||
<th style="width:10% border:0px solid transparent;border-right: thin solid #dee2e6;"> |
|||
<strong> |
|||
<span class="fw-bolder"> |
|||
<t t-esc="total[partner]['currency_id']"/> |
|||
<t t-esc="total[partner]['total_debit'] - total[partner]['total_credit']"/> |
|||
</span> |
|||
</strong> |
|||
</th> |
|||
</tr> |
|||
<!-- Iterate over partner's initial balance --> |
|||
<t t-set="j" t-value="0"/> |
|||
<t t-foreach="partners" |
|||
t-as="partner_initial" |
|||
t-key="partner_initial_index"> |
|||
<t t-set="j" t-value="j + 1"/> |
|||
<t t-if="j == 1 and total[partner]['initial_balance'] != 0"> |
|||
<th colspan="6"> |
|||
<span style="gap: 12px;display: flex;"> |
|||
|
|||
</span> |
|||
</th> |
|||
<th> |
|||
</th> |
|||
<th> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-esc="total[partner]['move_name']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
</th> |
|||
<th> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-esc="total[partner]['initial_debit']"/> |
|||
</span> |
|||
</th> |
|||
<th> |
|||
<span> |
|||
<t t-esc="total[partner]['initial_credit']"/> |
|||
</span> |
|||
</th> |
|||
<th/> |
|||
<th> |
|||
<span> |
|||
<t t-esc="total[partner]['initial_balance']"/> |
|||
</span> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
<!-- Iterate over partner's value list --> |
|||
<t t-foreach="data[partner]" |
|||
t-as="valuelist" |
|||
t-key="valuelist_index"> |
|||
<tr class="border-bottom"> |
|||
<th colspan="6" style="width:10%"> |
|||
<span> |
|||
<t t-esc="valuelist[0]['date']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-esc="valuelist[0]['jrnl']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-esc="valuelist[0]['code']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-if="valuelist[0]['move_name']" |
|||
t-esc="valuelist[0]['move_name']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-if="valuelist[0]['date_maturity']" |
|||
t-esc="valuelist[0]['date_maturity']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-if="valuelist[0]['matching_number']" |
|||
t-esc="valuelist[0]['matching_number']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-if="valuelist[0]['debit']" |
|||
t-esc="total[partner]['currency_id']"/> |
|||
<t t-if="valuelist[0]['debit']" |
|||
t-esc="valuelist[0]['debit']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-if="valuelist[0]['credit']" |
|||
t-esc="total[partner]['currency_id']"/> |
|||
<t t-if="valuelist[0]['credit']" |
|||
t-esc="valuelist[0]['credit']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<span> |
|||
<t t-if="valuelist[0]['amount_currency']" |
|||
t-esc="total[partner]['currency_id']"/> |
|||
<t t-if="valuelist[0]['amount_currency']" |
|||
t-esc="valuelist[0]['amount_currency']"/> |
|||
</span> |
|||
</th> |
|||
<th style="width:10%"/> |
|||
</tr> |
|||
</t> |
|||
</tbody> |
|||
</table> |
|||
</t> |
|||
</t> |
|||
<table class="table table-sm table-reports"> |
|||
<tbody> |
|||
<tr> |
|||
<th style="width:60%;">Total</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['total_debit']"/> |
|||
</th> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['total_credit']"/> |
|||
</th> |
|||
<th style="width:10%"/> |
|||
<th style="width:10%"> |
|||
<t t-out="grand_total['currency']"/> |
|||
<t t-out="grand_total['total_debit'] - grand_total['total_credit']"/> |
|||
</th> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</template> |
|||
</odoo> |
@ -0,0 +1,308 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Report Template for Tax--> |
|||
<template id="tax_report"> |
|||
<t t-call="web.html_container"> |
|||
<t t-call="web.external_layout"> |
|||
<t t-set="data_report_margin_top" t-value="12"/> |
|||
<t t-set="data_report_header_spacing" t-value="9"/> |
|||
<t t-set="data_report_dpi" t-value="110"/> |
|||
<div class="page"> |
|||
<h3> |
|||
<center> |
|||
<b> |
|||
<span t-esc="report_name"/> |
|||
</b> |
|||
</center> |
|||
</h3> |
|||
<br/> |
|||
<br/> |
|||
<div class="filters"> |
|||
<table class="table table-sm table-reports"> |
|||
<thead class="filter_table" |
|||
style="background:#808080;"> |
|||
<tr> |
|||
<th>Date Range</th> |
|||
<th>Comparison</th> |
|||
<th>Options</th> |
|||
<th>Report</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody style="font-size:11px;font-weight:100;"> |
|||
<tr> |
|||
<th> |
|||
<t t-if="filters['start_date']" |
|||
t-out="filters['start_date']"/> |
|||
<t t-if="filters['end_date']"> |
|||
to |
|||
<t t-out="filters['end_date']"/> |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-if="filters['comparison_number_range']"> |
|||
<t t-out="filters['comparison_type']"/> |
|||
: |
|||
<t t-out="filters['comparison_number_range']"/> |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-foreach="filters['options']" |
|||
t-as="selected_options" |
|||
t-key="options_index"> |
|||
<t t-out="selected_options"/>, |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-if="report_type and list(report_type.keys())[0] == 'account'"> |
|||
<span>Account</span> |
|||
</t> |
|||
<t t-elif="report_type and list(report_type.keys())[0] == 'tax'"> |
|||
<span>Tax</span> |
|||
</t> |
|||
<t t-else=""> |
|||
<t t-out="report_type"/> |
|||
</t> |
|||
</th> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
<br/> |
|||
<br/> |
|||
<br/> |
|||
<table class="table table-sm table-reports" |
|||
style="width: fit-content;"> |
|||
<thead style="background:#808080;"> |
|||
<tr> |
|||
<th colspan="6"/> |
|||
<t t-foreach="date_viewed" t-as="date_view"> |
|||
<th colspan="2"> |
|||
<t t-esc="date_view"/> |
|||
</th> |
|||
</t> |
|||
</tr> |
|||
<tr class="o_heading" style="text-align:center;"> |
|||
<th colspan="6"/> |
|||
<th>NET</th> |
|||
<th>TAX</th> |
|||
<t t-if="apply_comparison == true"> |
|||
<t t-set="number_of_periods" |
|||
t-value="comparison_number_range"/> |
|||
<t t-foreach="number_of_periods" |
|||
t-as="number"> |
|||
<th>NET</th> |
|||
<th>TAX</th> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<t t-if="data"> |
|||
<t t-set="prev_account" t-value="None"/> |
|||
<t t-set="prev_tax" t-value="None"/> |
|||
<tr class="border-bottom" |
|||
style="border-spacing: 0 10px;background:#dfdfdf;"> |
|||
<th colspan="6"> |
|||
<span style="font-weight: 700;">Sales |
|||
</span> |
|||
</th> |
|||
<th/> |
|||
<t t-if="apply_comparison == true"> |
|||
<t t-set="number_of_periods" |
|||
t-value="comparison_number_range"/> |
|||
<t t-foreach="number_of_periods" |
|||
t-as="no"> |
|||
<th/> |
|||
<th/> |
|||
</t> |
|||
</t> |
|||
<th style="text-align:center;font-weight: 700;"> |
|||
<t t-esc="sale_total"/> |
|||
</th> |
|||
</tr> |
|||
<t t-set="i" t-value="0"/> |
|||
<t t-foreach="data['sale']" |
|||
t-as="sale_tax_line"> |
|||
<t t-set="i" t-value="i + 1"/> |
|||
<t t-if="report_type"> |
|||
<t t-if="report_type == 'account'"> |
|||
<t t-if="prev_account != sale_tax_line['account']"> |
|||
<t t-set="prev_account" |
|||
t-value="sale_tax_line['account']"/> |
|||
<tr class="border-bottom" |
|||
style="border-spacing: 0 10px;"> |
|||
<th colspan="12"> |
|||
<span> |
|||
<t t-esc="sale_tax_line['account']"/> |
|||
</span> |
|||
</th> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
<t t-else="list(report_type.keys())[0] == 'tax'"> |
|||
<t t-if="prev_tax != sale_tax_line['name']"> |
|||
<t t-set="prev_tax" |
|||
t-value=" sale_tax_line['name']"/> |
|||
<tr class="border-bottom" |
|||
style="border-spacing: 0 10px;"> |
|||
<th colspan="12"> |
|||
<span> |
|||
<t t-esc="sale_tax_line['name']"/> |
|||
( |
|||
<t t-esc="sale_tax_line['amount']"/> |
|||
%) |
|||
</span> |
|||
</th> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<tr class="border-bottom" |
|||
style="border-spacing: 0 10px;font-weight: 400;"> |
|||
<th colspan="6"> |
|||
<span style="font-weight: 400;"> |
|||
<t t-if="report_type and list(report_type.keys())[0] == 'tax'"> |
|||
<t t-esc="sale_tax_line['account']"/> |
|||
</t> |
|||
<t t-else=""> |
|||
<t t-esc="sale_tax_line['name']"/> |
|||
( |
|||
<t t-esc="sale_tax_line['amount']"/> |
|||
%) |
|||
</t> |
|||
</span> |
|||
</th> |
|||
<t t-if="apply_comparison == true"> |
|||
<t t-if="sale_tax_line['dynamic net']"> |
|||
<t t-set="number_of_periods" |
|||
t-value="comparison_number_range"/> |
|||
<t t-foreach="number_of_periods" |
|||
t-as="num"> |
|||
<th style="text-align:center;font-weight: 400;"> |
|||
<t t-if="sale_tax_line['dynamic net']['dynamic_total_net_sum' + str(num)]" |
|||
t-esc="sale_tax_line['dynamic net']['dynamic_total_net_sum' + str(num)]"/> |
|||
</th> |
|||
<th style="text-align:center;font-weight: 400;"> |
|||
<t t-if="sale_tax_line['dynamic tax']['dynamic_total_tax_sum' + str(num)]" |
|||
t-esc="sale_tax_line['dynamic tax']['dynamic_total_tax_sum' + str(num)]"/> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<th style="text-align:center;"> |
|||
<span style="font-weight: 400;"> |
|||
<t t-esc="sale_tax_line['net']"/> |
|||
</span> |
|||
</th> |
|||
<th style="text-align:center;"> |
|||
<span style="font-weight: 400;"> |
|||
<t t-esc="sale_tax_line['tax']"/> |
|||
</span> |
|||
</th> |
|||
</tr> |
|||
</t> |
|||
<tr style="height: 2rem;"/> |
|||
<tr class="border-bottom" |
|||
style="border-spacing: 0 10px;background:#dfdfdf;"> |
|||
<th colspan="6"> |
|||
<span style="font-weight: 700;"> |
|||
Purchase |
|||
</span> |
|||
</th> |
|||
<th/> |
|||
<t t-if="apply_comparison == true"> |
|||
<t t-set="number_of_periods" |
|||
t-value="comparison_number_range"/> |
|||
<t t-foreach="number_of_periods" |
|||
t-as="numb"> |
|||
<th/> |
|||
<th/> |
|||
</t> |
|||
</t> |
|||
<th style="text-align:center;font-weight: 700;"> |
|||
<t t-esc="purchase_total"/> |
|||
</th> |
|||
</tr> |
|||
<t t-set="i" t-value="0"/> |
|||
<t t-foreach="data['purchase']" |
|||
t-as="purchase_tax_line"> |
|||
<t t-set="i" t-value="i + 1"/> |
|||
<t t-if="report_type"> |
|||
<t t-if="list(report_type.keys())[0] == 'account'"> |
|||
<tr class="border-bottom" |
|||
style="border-spacing: 0 10px;"> |
|||
<th colspan="12"> |
|||
<span> |
|||
<t t-esc="purchase_tax_line['account']"/> |
|||
</span> |
|||
</th> |
|||
</tr> |
|||
</t> |
|||
<t t-else="list(report_type.keys())[0] == 'tax'"> |
|||
<t t-set="prev_account" |
|||
t-value="purchase_tax_line['name']"/> |
|||
<tr class="border-bottom" |
|||
style="border-spacing: 0 10px;"> |
|||
<th colspan="12"> |
|||
<span> |
|||
<t t-esc="purchase_tax_line['name']"/> |
|||
( |
|||
<t t-esc="purchase_tax_line['amount']"/> |
|||
%) |
|||
</span> |
|||
</th> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
<tr class="border-bottom" |
|||
style="border-spacing: 0 10px;"> |
|||
<th colspan="6"> |
|||
<span style="font-weight: 400;"> |
|||
<t t-if="report_type and list(report_type.keys())[0] == 'tax'"> |
|||
<t t-esc="purchase_tax_line['account']"/> |
|||
</t> |
|||
<t t-else=""> |
|||
<t t-esc="purchase_tax_line['name']"/> |
|||
( |
|||
<t t-esc="purchase_tax_line['amount']"/> |
|||
%) |
|||
</t> |
|||
</span> |
|||
</th> |
|||
<t t-if="apply_comparison == true"> |
|||
<t t-if="purchase_tax_line['dynamic net']"> |
|||
<t t-set="number_of_periods" |
|||
t-value="comparison_number_range"/> |
|||
<t t-foreach="number_of_periods" |
|||
t-as="period"> |
|||
<th style="text-align:center;font-weight: 400;"> |
|||
<t t-if="purchase_tax_line['dynamic net']['dynamic_total_net_sum' + str(period)]" |
|||
t-esc="purchase_tax_line['dynamic net']['dynamic_total_net_sum' + str(period)]"/> |
|||
</th> |
|||
<th style="text-align:center;font-weight: 400;"> |
|||
<t t-if="purchase_tax_line['dynamic net']['dynamic_total_net_sum' + str(period)]" |
|||
t-esc="purchase_tax_line['dynamic net']['dynamic_total_net_sum' + str(period)]"/> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<th style="text-align:center;"> |
|||
<span style="font-weight: 400;"> |
|||
<t t-esc="purchase_tax_line['net']"/> |
|||
</span> |
|||
</th> |
|||
<th style="text-align:center;"> |
|||
<span style="font-weight: 400;"> |
|||
<t t-esc="purchase_tax_line['tax']"/> |
|||
</span> |
|||
</th> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</template> |
|||
</odoo> |
@ -0,0 +1,172 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Report Template for trial balance--> |
|||
<template id="trial_balance"> |
|||
<t t-call="web.html_container"> |
|||
<t t-call="web.external_layout"> |
|||
<t t-set="data_report_margin_top" t-value="12"/> |
|||
<t t-set="data_report_header_spacing" t-value="9"/> |
|||
<t t-set="data_report_dpi" t-value="110"/> |
|||
<div class="page"> |
|||
<h3> |
|||
<center> |
|||
<b> |
|||
<span t-esc="report_name"/> |
|||
</b> |
|||
</center> |
|||
</h3> |
|||
<br/> |
|||
<br/> |
|||
<div class="filters"> |
|||
<table class="table table-sm table-reports"> |
|||
<thead class="filter_table" |
|||
style="background:#808080;"> |
|||
<tr> |
|||
<th>Date Range</th> |
|||
<th>Comparison</th> |
|||
<th>Account</th> |
|||
<th>Journal</th> |
|||
<th>Options</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody style="font-size:11px;font-weight:100;"> |
|||
<tr> |
|||
<th> |
|||
<t t-if="filters['start_date']" |
|||
t-out="filters['start_date']"/> |
|||
<t t-if="filters['end_date']"> |
|||
to |
|||
<t t-out="filters['end_date']"/> |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-if="filters['comparison_number_range']"> |
|||
<t t-out="filters['comparison_type']"/> |
|||
: |
|||
<t t-out="filters['comparison_number_range']"/> |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-foreach="filters['journal']" |
|||
t-as="selected_journal" |
|||
t-key="journal_index"> |
|||
<t t-out="selected_journal"/> |
|||
, |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-foreach="filters['account']" |
|||
t-as="selected_account" |
|||
t-key="account_index"> |
|||
<t t-out="selected_account['display_name']"/> |
|||
, |
|||
</t> |
|||
</th> |
|||
<th> |
|||
<t t-foreach="filters['options']" |
|||
t-as="selected_options" |
|||
t-key="options_index"> |
|||
<t t-out="selected_options"/>, |
|||
</t> |
|||
</th> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
<br/> |
|||
<br/> |
|||
<br/> |
|||
<table class="table table-sm table-reports" |
|||
style="width: fit-content;"> |
|||
<thead style="background:#808080;"> |
|||
<tr> |
|||
<th colspan="6"/> |
|||
<th colspan="2">Initial Balance</th> |
|||
<t t-foreach="date_viewed" t-as="date_view" |
|||
t-key="date_view_index"> |
|||
<th colspan="2"> |
|||
<t t-esc="date_view"/> |
|||
</th> |
|||
</t> |
|||
<th colspan="2">End Balance</th> |
|||
</tr> |
|||
<tr class="o_heading" style="text-align:center;background:#D3D3D3;"> |
|||
<th colspan="6"/> |
|||
<th>Debit</th> |
|||
<th>Credit</th> |
|||
<th>Debit</th> |
|||
<th>Credit</th> |
|||
<th>Debit</th> |
|||
<th>Credit</th> |
|||
<t t-if="apply_comparison == true"> |
|||
<t t-set="number_of_periods" |
|||
t-value="comparison_number_range"/> |
|||
<t t-foreach="number_of_periods" |
|||
t-as="number" t-key="number"> |
|||
<th>Debit</th> |
|||
<th>Credit</th> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<t t-if="data"> |
|||
<t t-set="i" t-value="0"/> |
|||
<t t-foreach="data" |
|||
t-as="move_line" |
|||
t-key="move_line_index"> |
|||
<t t-set="i" t-value="i + 1"/> |
|||
<tr class="border-bottom" |
|||
style="border-spacing: 0 10px;"> |
|||
<th colspan="6"> |
|||
<t t-esc="move_line['account']"/> |
|||
</th> |
|||
<th style="text-align:center;"> |
|||
<t t-if="move_line['initial_total_debit']" |
|||
t-esc="move_line['initial_total_debit']"/> |
|||
</th> |
|||
<th style="text-align:center;"> |
|||
<t t-if="move_line['initial_total_credit']" |
|||
t-esc="move_line['initial_total_credit']"/> |
|||
</th> |
|||
<t t-if="apply_comparison == true"> |
|||
<t t-set="number_of_periods" |
|||
t-value="comparison_number_range"/> |
|||
<t t-foreach="number_of_periods" |
|||
t-as="num" t-key="num"> |
|||
<th style="text-align:center;"> |
|||
<t t-if="move_line['dynamic_total_debit_' + str(num)]" |
|||
t-esc="move_line['dynamic_total_debit_' + str(num)]"/> |
|||
</th> |
|||
<th style="text-align:center;"> |
|||
<t t-if="move_line['dynamic_total_credit_' + str(num)]" |
|||
t-esc="move_line['dynamic_total_credit_' + str(num)]"/> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
<th style="text-align:center;"> |
|||
<t t-if="move_line['total_debit']" |
|||
t-esc="move_line['total_debit']"/> |
|||
</th> |
|||
<th style="text-align:center;"> |
|||
<t t-if="move_line['total_credit']" |
|||
t-esc="move_line['total_credit']"/> |
|||
</th> |
|||
<th style="text-align:center;"> |
|||
<t t-if="move_line['end_total_debit']" |
|||
t-esc="move_line['end_total_debit']"/> |
|||
</th> |
|||
<th style="text-align:center;"> |
|||
<t t-if="move_line['end_total_credit']" |
|||
t-esc="move_line['end_total_credit']"/> |
|||
</th> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</template> |
|||
</odoo> |
|
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 628 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 210 KiB |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 109 KiB |
After Width: | Height: | Size: 495 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 624 B |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 214 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 929 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 542 B |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 738 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 600 B |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 462 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 926 B |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 800 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 189 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 875 B |