@ -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 |