You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							323 lines
						
					
					
						
							16 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							323 lines
						
					
					
						
							16 KiB
						
					
					
				
								# -*- 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()
							 | 
						|
								
							 |