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
17 KiB

"""Report Wizard for Commission Plan"""
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2021-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<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 odoo import models, fields, api
from odoo.tools import date_utils
from odoo.exceptions import ValidationError
try:
from odoo.tools.misc import xlsxwriter
except ImportError:
import xlsxwriter
class CommissionReportWizard(models.TransientModel):
_name = 'commission.wizard'
_description = 'Commission Report Wizard'
date_from = fields.Date(string="From Date")
date_to = fields.Date(string="To Date")
salesperson_ids = fields.Many2many('res.users', string='Salesperson',
domain="[('share','=',False)]")
sales_team_ids = fields.Many2many('crm.team', string='Sales Team')
date = fields.Date(string='Date', default=fields.Date.context_today)
is_sales_person = fields.Boolean(default=False, string="Is sales person")
is_sales_team = fields.Boolean(default=False, string="Is sales team")
@api.onchange('salesperson_ids')
def onchange_salesperson_ids(self):
"""Function for hide a field base on values"""
self.is_sales_person = True if self.salesperson_ids else False
@api.onchange('sales_team_ids')
def onchange_sales_team_ids(self):
self.is_sales_team = True if self.sales_team_ids else False
@api.constrains('sales_team_ids', 'salesperson_ids')
def sales_team_constrains(self):
"""Function for showing validation error"""
for rec in self:
if self.sales_team_ids:
if not rec.sales_team_ids.member_ids:
raise ValidationError(
"Selected Sales Team haven't any Salespersons")
if not self.sales_team_ids.member_ids.commission_id and \
not self.sales_team_ids.commission_id:
raise ValidationError(
"Selected Sales Team haven't any Commission Plan")
elif self.salesperson_ids and not rec.salesperson_ids.commission_id:
raise ValidationError(
"Selected Salesperson haven't any Commission Plan")
def print_xls_report(self):
"""Function for printing xlsx report"""
# sales person's condition starts here #
user_sale_orders = self.env['sale.order'].search([
('user_id', 'in', self.salesperson_ids.ids)])
user_sale_orders_dict = {}
total_list = []
commission_list = []
user_commission_name = []
user_commission_salesperson = []
user_obj = user_sale_orders.mapped('user_id').sorted(key=lambda d: d.id)
for user in user_obj:
user_sale_orders_dict.update({
user: user_sale_orders.filtered(lambda l: l.user_id == user)
})
for user, user_sale_orders in user_sale_orders_dict.items():
commission_id = user.commission_id
if not commission_id:
continue
filtered_order_lines = user_sale_orders.filtered(
lambda l: self.date_from <= l.date_order.date(
) <= self.date_to and l.date_order.date() >= commission_id.date_from
).mapped('order_line')
filtered_order_lines_commission_total = sum(
filtered_order_lines.mapped('price_subtotal'))
if commission_id.type == 'product':
commission_products = commission_id.product_comm_ids.product_id
prod_commission = filtered_order_lines.filtered(
lambda l: l.product_id in commission_products)
for rule in commission_id.product_comm_ids.filtered(
lambda l: l.product_id in prod_commission.mapped(
'product_id')):
product_order_line = prod_commission.filtered(
lambda l: l.product_id == rule.product_id)
total_price = sum(
product_order_line.mapped('price_subtotal'))
product_commission = (total_price * rule.percentage) / 100
total_list.append(total_price)
user_commission_name.append(commission_id.name)
user_commission_salesperson.append(user.name)
commission_list.append(rule.amount) if (
product_commission > rule.amount) \
else commission_list.append(product_commission)
if commission_id.type == 'revenue' and (
commission_id.revenue_type == 'graduated'):
for rule in commission_id.revenue_grd_comm_ids:
if rule.amount_from <= filtered_order_lines_commission_total < rule.amount_to:
graduated_commission = (filtered_order_lines_commission_total
* rule.graduated_commission_rate) / 100
commission_list.append(graduated_commission)
user_commission_name.append(commission_id.name)
user_commission_salesperson.append(user.name)
total_list.append(filtered_order_lines_commission_total)
if commission_id.type == 'revenue' and (
commission_id.revenue_type == 'straight'):
straight_commission = (filtered_order_lines_commission_total
* commission_id.straight_commission_rate) / 100
commission_list.append(straight_commission)
user_commission_name.append(commission_id.name)
user_commission_salesperson.append(user.name)
total_list.append(filtered_order_lines_commission_total)
# sales person's condition ends here #
if not self.sales_team_ids and not self.salesperson_ids:
self.sales_team_ids = self.env['crm.team'].search([])
# sales team's condition starts here #
team_wizard_persons = self.sales_team_ids.member_ids
team_sale_orders = self.env['sale.order'].search(
[('user_id', 'in', team_wizard_persons.ids)])
team_sale_orders_dict = {}
commission_total = []
commission = []
commission_name = []
commission_salesperson = []
commission_sales_team = []
team_obj = team_sale_orders.mapped('user_id').sorted(key=lambda d: d.id)
for team_user in team_obj:
team_sale_orders_dict.update({
team_user: team_sale_orders.filtered(
lambda l: l.user_id == team_user)
})
for team_user, team_sale_orders in team_sale_orders_dict.items():
commissions_id = team_user.commission_id if team_user.commission_id \
else team_user.sale_team_id.commission_id
if commissions_id:
filtered_order_lines = team_sale_orders.filtered(
lambda l: self.date_from <= l.date_order.date(
) <= self.date_to and l.date_order.date() >= commissions_id.date_from
).mapped('order_line')
filtered_order_lines_commission_total = sum(
filtered_order_lines.mapped('price_subtotal'))
if commissions_id.type == 'product':
commission_products = commissions_id.product_comm_ids.product_id
prod_commission = filtered_order_lines.filtered(
lambda l: l.product_id in commission_products)
for rules in commissions_id.product_comm_ids.filtered(
lambda l: l.product_id in prod_commission.mapped(
'product_id')):
product_order_line = prod_commission.filtered(
lambda l: l.product_id == rules.product_id)
total_price = sum(
product_order_line.mapped('price_subtotal'))
product_commission = (total_price * rules.percentage) / 100
commission_total.append(total_price)
commission_name.append(commissions_id.name)
commission_salesperson.append(team_user.name)
commission_sales_team.append(
team_user.sale_team_id.name)
commission.append(rules.amount) if (
product_commission > rules.amount) \
else commission.append(product_commission)
if commissions_id.type == 'revenue' and (
commissions_id.revenue_type == 'graduated'):
for rules in commissions_id.revenue_grd_comm_ids:
if rules.amount_from <= filtered_order_lines_commission_total \
< rules.amount_to:
graduated_commission = (filtered_order_lines_commission_total
* rules.graduated_commission_rate) / 100
commission.append(graduated_commission)
commission_name.append(commissions_id.name)
commission_salesperson.append(team_user.name)
commission_sales_team.append(
team_user.sale_team_id.name)
commission_total.append(
filtered_order_lines_commission_total)
if commissions_id.type == 'revenue' and (
commissions_id.revenue_type == 'straight'):
straight_commission = (filtered_order_lines_commission_total
* commissions_id.straight_commission_rate) / 100
commission.append(straight_commission)
commission_name.append(commissions_id.name)
commission_salesperson.append(team_user.name)
commission_sales_team.append(team_user.sale_team_id.name)
commission_total.append(
filtered_order_lines_commission_total)
# sales team's condition ends here #
data = {
'model_id': self.id,
'date': self.date,
'date_from': self.date_from,
'date_to': self.date_to,
'sales_team_ids': self.sales_team_ids.ids,
'salesperson_ids': self.salesperson_ids.ids,
'commission_list': commission_list,
'total_list': total_list,
'commission': commission,
'commission_total': commission_total,
'commission_name': commission_name,
'commission_salesperson': commission_salesperson,
'commission_sales_team': commission_sales_team,
'user_commission_name': user_commission_name,
'user_commission_salesperson': user_commission_salesperson,
}
return {
'type': 'ir.actions.report',
'data': {
'model': 'commission.wizard',
'options': json.dumps(data, default=date_utils.json_default),
'output_format': 'xlsx',
'report_name': 'Commission Plan xlsx report'},
'report_type': 'xlsx'
}
def get_xlsx_report(self, data, response):
"""get_xlsx_report function"""
date = data['date']
team = data['sales_team_ids']
user = data['salesperson_ids']
commission_list = data['commission_list']
total_list = data['total_list']
commission = data['commission']
commission_total = data['commission_total']
commission_name = data['commission_name']
commission_salesperson = data['commission_salesperson']
commission_sales_team = data['commission_sales_team']
user_commission_name = data['user_commission_name']
user_commission_salesperson = data['user_commission_salesperson']
output = io.BytesIO()
workbook = xlsxwriter.Workbook(output, {'in_memory': True})
sheet = workbook.add_worksheet()
head = workbook.add_format({'align': 'center', 'bold': True,
'font_size': '15px', 'valign': 'vcenter'})
format1 = workbook.add_format({'align': 'left', 'font_size': '12px'})
format2 = workbook.add_format({'align': 'right', 'font_size': '12x'})
format3 = workbook.add_format(
{'align': 'right', 'font_size': '12x', 'bold': True})
heading = workbook.add_format({'align': 'left', 'bold': True,
'font_size': '12px',
'valign': 'vcenter'})
date_format = workbook.add_format(
{'num_format': 'dd/mm/yy', 'align': 'left', 'font_size': '10px'})
sheet.merge_range('A2:B2', "Printed Date: " + date, date_format)
sheet.write('A4', 'No.', heading)
sheet.set_column(5, 1, 25)
sheet.set_row(0, 25)
row = 5
col = 0
index = 1
if user:
sheet.merge_range('A1:E1', 'COMMISSION PLAN REPORT', head)
sheet.write('D2', 'Date From: ' + data['date_from'], date_format)
sheet.write('E2', 'Date To: ' + data['date_to'], date_format)
sheet.write('B4', 'Sale Persons', heading)
sheet.write('C4', 'Commission Plan Name', heading)
sheet.write('D4', 'Total Revenue', heading)
sheet.write('E4', 'Commission Amount', heading)
for j in user_commission_name:
sheet.write(row, col + 0, index, format2)
sheet.write(row, col + 1, j, format1)
row += 1
index += 1
row = 5
col = 0
for j in user_commission_salesperson:
sheet.write(row, col + 2, j, format1)
row += 1
row = 5
col = 0
for j in total_list:
sheet.write(row, col + 3, round(j, 2), format2)
row += 1
row = 5
col = 0
for i in commission_list:
sheet.write(row, col + 4, round(i, 2), format2)
row += 1
sheet.write(row + 1, col + 2, 'Total', format3)
sheet.write(row + 1, col + 3, round(sum(total_list), 2), format2)
sheet.write(row + 1, col + 4, round(sum(commission_list), 2),
format2)
elif team:
sheet.merge_range('A1:F1', 'COMMISSION PLAN REPORT', head)
sheet.write('E2', 'Date From: ' + data['date_from'], date_format)
sheet.write('F2', 'Date To: ' + data['date_to'], date_format)
sheet.write('B4', 'Sales Teams', heading)
sheet.write('C4', 'Sales Person', heading)
sheet.write('D4', 'Commission Plan Name', heading)
sheet.write('E4', 'Total Revenue', heading)
sheet.write('F4', 'Commission Amount', heading)
for j in commission_sales_team:
sheet.write(row, col + 0, index, format2)
sheet.write(row, col + 1, j, format1)
row += 1
index += 1
row = 5
col = 0
for j in commission_salesperson:
sheet.write(row, col + 2, j, format1)
row += 1
row = 5
col = 0
for j in commission_name:
sheet.write(row, col + 3, j, format1)
row += 1
row = 5
col = 0
for j in commission_total:
sheet.write(row, col + 4, round(j, 2), format2)
row += 1
row = 5
col = 0
for i in commission:
sheet.write(row, col + 5, round(i, 2), format2)
row += 1
sheet.write(row + 1, col + 3, 'Total:', format3)
sheet.write(row + 1, col + 4, round(sum(commission_total), 2),
format2)
sheet.write(row + 1, col + 5, round(sum(commission), 2), format2)
workbook.close()
output.seek(0)
response.stream.write(output.read())
output.close()