You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							370 lines
						
					
					
						
							18 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							370 lines
						
					
					
						
							18 KiB
						
					
					
				| # -*- coding: utf-8 -*- | |
| ################################################################################ | |
| # | |
| #    Cybrosys Technologies Pvt. Ltd. | |
| # | |
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | |
| #    Author: Ammu Raj (odoo@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 | |
|         """ | |
|         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: | |
|             move_line_id = move_line_ids.filtered( | |
|                 lambda x: x.partner_id == partner) | |
|             move_line_list = [] | |
|             for move_line in move_line_id: | |
|                 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, | |
|                 'partner_id': partner.id} | |
|             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 | |
|         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) | |
|                 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) | |
|                 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)]) | |
|                 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) | |
|                 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) | |
|                 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)]) | |
|                 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)]) | |
|                 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)]) | |
|                 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)]) | |
|             else: | |
|                 move_line_ids = self.env['account.move.line'].search( | |
|                     [('partner_id', '=', partners), ( | |
|                         'account_type', 'in', | |
|                         account_type_domain), | |
|                      ('parent_state', 'in', option_domain)]) | |
|             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) | |
|             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} | |
|             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}) | |
|         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) | |
|                     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()
 | |
| 
 |