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.
 
 
 
 
 

211 lines
9.4 KiB

# -*- coding: utf-8 -*-
################################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Raveena V (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
import io
import json
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
from odoo.tools import json_default
from dateutil.relativedelta import relativedelta
try:
from odoo.tools.misc import xlsxwriter
except ImportError:
import xlsxwriter
class LowSaleReport(models.TransientModel):
"""Its define as the sale low performance product details in pivot view and
the Excel report."""
_name = 'low.sale.report'
_description = 'Low Sale Report'
product_type = fields.Selection(
[('variant', 'By product variant'),
('template', 'By product templates')], string="Report Type",
help='Which sale to take into account: Product templates in general'
' or variants?', required=True)
analysed_period_start = fields.Date(string='Period under analysis',
help='If not chosen, all product sale'
' will be analysed')
analysed_period_end = fields.Date(string='Period under analysis',
help='If not chosen, all product sale'
' will be analysed',
default=fields.Date.today())
absolute_qty = fields.Float(string='Critical Level(Absolute Quantity)',
help='Which sale level are considered to be'
' low(in default unit of measurement) ',
required=True)
category = fields.Many2one('product.category',
string='Product Categories',
help='If not chosen, all product categories '
'wil be analysed')
sale_team = fields.Many2one('crm.team',
help='If not chosen, all the sale team will'
' be analysed', string='Sales Teams')
def action_pivot_low_sale_report(self):
"""Exporting the low sale report as the pivot view format in odoo"""
low_sale_report = {
'product_type': self.product_type,
'analysed_period_start': self.analysed_period_start,
'analysed_period_end': self.analysed_period_end,
'absolute_qty': self.absolute_qty,
'category': self.category,
'sale_team': self.sale_team
}
pivot_data = self.env['low.sale.pivot.view.report'].get_data(
low_sale_report)
if not pivot_data:
raise ValidationError(
_("No data was found for the specified criteria"))
pivot_records = []
for data in pivot_data:
values = {
'price_total': data[2],
'product_uom_qty': data[1]
}
if self.product_type == 'variant':
values['product_id'] = data[0]
view_id = self.env.ref(
'low_sale_report.'
'low_sale_pivot_view_report_view_pivot_variant').id
else:
values['product_tmpl_id'] = data[0]
view_id = self.env.ref(
'low_sale_report.'
'low_sale_pivot_view_report_view_pivot_template').id
pivot_data_records = self.env['low.sale.pivot.view.report'].create(
values)
pivot_records.append(pivot_data_records.id)
return {
'name': 'Low Sale Pivot View Report',
'type': 'ir.actions.act_window',
'res_model': 'low.sale.pivot.view.report',
'view_mode': 'pivot',
'view_id': view_id,
'domain': [('id', 'in', pivot_records)],
}
def action_excel_low_sale_report(self):
"""Exporting the low sale report as the Excel view format in odoo"""
self.ensure_one()
data = {'ids': self.env.context.get('active_ids', []),
'model': self.env.context.get('active_model', 'ir.ui.menu'),
'form': self.read(
['product_type', 'analysed_period_start',
'analysed_period_end', 'absolute_qty',
'category', 'sale_team'])[0]}
return {
'type': 'ir.actions.report',
'data': {'model': 'low.sale.report',
'options': json.dumps(data, default=json_default),
'output_format': 'xlsx',
'report_name': 'Low Sale Report',
},
'report_type': 'low_sale_xlsx_download'
}
def get_low_sale_xlsx_report(self, options, response):
"""Generate the Excel report based on the provided options and write it
to the response."""
output = io.BytesIO()
workbook = xlsxwriter.Workbook(output, {'in_memory': True})
data = {'form': options['form'], 'model': 'ir.ui.menu', 'ids': []}
data['form']['used_context'] = {
'product_type': options['form']['product_type'],
'analysed_period_start': options['form']['analysed_period_start'],
'analysed_period_end': options['form']['analysed_period_end'],
'absolute_qty': options['form']['absolute_qty'],
'active_model': None,
'active_ids': None,
'active_id': None,
'category': options['form']['category'],
'sale_team': options['form']['sale_team'],
}
form_data = data['form']
fetch_datas = self.env['low.sale.pivot.view.report'].get_data(form_data)
if not fetch_datas:
raise ValidationError(
_("No data was found for the specified criteria."))
worksheet = workbook.add_worksheet()
name_formate = workbook.add_format(
{'bold': True, 'align': 'center', 'valign': 'vcenter', 'border': 1,
'bg_color': '#D3D3D3', 'font_size': 16})
format2 = workbook.add_format(
{'font_size': 12, 'bold': True, 'bg_color': '#D3D3D3'})
rows = 0
cols = 0
worksheet.merge_range(rows, cols, rows + 1, cols + 3,
'Low Sale Report', name_formate)
worksheet.set_column('B:B', 35)
worksheet.set_column('C:C', 15)
worksheet.set_column('D:D', 15)
worksheet.write('A4', "ID", format2)
worksheet.write('B4', "Product", format2)
worksheet.write('C4', "Sold Quantity", format2)
worksheet.write('D4', "Revenue", format2)
# Write data to the worksheet
row_num = 5
cols_num = 0
for rec in fetch_datas:
worksheet.write(row_num, cols_num, rec[0])
worksheet.write(row_num, cols_num + 1, rec[3])
worksheet.write(row_num, cols_num + 2, rec[1])
worksheet.write(row_num, cols_num + 3, rec[2])
row_num += 1
# Close the workbook
workbook.close()
# Seek to the beginning of the BytesIO buffer
output.seek(0)
# Stream the Excel file to the response
response.stream.write(output.read())
output.close()
@api.model
def default_get(self, fields):
"""Prefilling the wizard data into the settings field values"""
res = super().default_get(fields)
# Fetch configuration parameters from ResConfigSettings
config_params = self.env['ir.config_parameter'].sudo()
# Prefill the values based on the configuration parameters
res['product_type'] = config_params.get_param(
'low_sale_report.product_type', default='variant')
res['absolute_qty'] = config_params.get_param(
'low_sale_report.absolute_qty', default=0.0)
end_date = res.get('analysed_period_end')
if end_date:
if (config_params.get_param('low_sale_report.analysed_period') ==
'last_month'):
start_date = end_date - relativedelta(days=30)
elif (config_params.get_param('low_sale_report.analysed_period') ==
'last_3'):
start_date = end_date - relativedelta(months=3)
elif (config_params.get_param('low_sale_report.analysed_period') ==
'last_6'):
start_date = end_date - relativedelta(months=6)
elif (config_params.get_param('low_sale_report.analysed_period') ==
'last_12'):
start_date = end_date - relativedelta(months=12)
else:
# Default to last_month if no valid option is selected
start_date = end_date - relativedelta(months=12)
res['analysed_period_start'] = start_date
return res