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

# -*- 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()