Add module commission_simple and commission_simple_sale

Improve view inheritance in account_usability
This commit is contained in:
Alexis de Lattre
2019-12-09 22:52:33 +01:00
parent 9020ab18f6
commit edb93dda3d
23 changed files with 834 additions and 2 deletions

View File

@@ -374,8 +374,9 @@ module -->
<field name="model">account.move.line</field>
<field name="inherit_id" ref="account.view_move_line_tree"/>
<field name="arch" type="xml">
<!-- Move reconcile_id to a better position -->
<field name="full_reconcile_id" position="replace"/>
<field name="full_reconcile_id" position="attributes">
<attribute name="invisible">1</attribute>
</field>
<field name="credit" position="after">
<field name="balance" sum="Total Balance"/>
<field name="reconcile_string"/>

View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
from . import models
from . import wizard

View File

@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
# Copyright 2019 Akretion France (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Commission Simple',
'version': '10.0.1.0.0',
'category': 'Sales',
'license': 'AGPL-3',
'summary': 'Compute commissions for salesman',
'description': """
Commission Simple
=================
This module is a **simple** module to compute commission for salesman. From my experience, companies often use very specific methods to compute commissions and it's impossible to develop a module that can support all of them. So the goal of this module is just to have a simple base to build the company-specific commissionning system by inheriting this simple module.
Here is a short description of this module:
* create commission profiles using rules (per product category, per product, per product and customer, etc.),
* the commission rules can have a start and end date (optional),
* commissionning can happen on invoicing or on payment,
* each invoice line can only be commissionned to one salesman,
* commission reports are stored in Odoo.
This module has been written by Alexis de Lattre from Akretion
<alexis.delattre@akretion.com>.
""",
'author': 'Akretion',
'website': 'http://www.akretion.com',
'depends': [
'account',
'date_range',
# this uses some related fields on account.invoice.line
'account_usability',
],
'data': [
'data/decimal_precision.xml',
'views/commission.xml',
'views/res_users.xml',
'views/account_config_settings.xml',
'wizard/commission_compute_view.xml',
'security/ir.model.access.csv',
'security/rule.xml',
],
'installable': True,
}

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<record forcecreate="True" id="commission_rate" model="decimal.precision">
<field name="name">Commission Rate</field>
<field name="digits">2</field>
</record>
</odoo>

View File

@@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
from . import commission
from . import res_users
from . import res_company
from . import account_config_settings
from . import account_invoice_line

View File

@@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
# Copyright 2019 Akretion France (http://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class AccountConfigSettings(models.TransientModel):
_inherit = 'account.config.settings'
commission_date_range_type_id = fields.Many2one(
related='company_id.commission_date_range_type_id', readonly=False)

View File

@@ -0,0 +1,108 @@
# -*- coding: utf-8 -*-
# Copyright 2019 Akretion France (http://www.akretion.com/)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
import odoo.addons.decimal_precision as dp
class AccountInvoiceLine(models.Model):
_inherit = 'account.invoice.line'
user_id = fields.Many2one(
related='invoice_id.user_id', store=True, readonly=True)
product_categ_id = fields.Many2one(
related='product_id.categ_id', store=True, readonly=True)
commission_result_id = fields.Many2one(
'commission.result', string='Commission Result')
commission_rule_id = fields.Many2one(
'commission.rule', 'Matched Commission Rule', ondelete='restrict')
commission_base = fields.Monetary('Commission Base', currency_field='company_currency_id')
commission_rate = fields.Float('Commission Rate', digits=dp.get_precision('Commission Rate'))
commission_amount = fields.Monetary(
string='Commission Amount', currency_field='company_currency_id',
readonly=True, compute='_compute_commission_amount', store=True)
@api.depends('commission_rate', 'commission_base')
def _compute_amount(self):
for line in self:
line.commission_amount = line.commission_rate * line.commission_base / 100.0
def compute_commission_for_one_user(self, user, date_range, rules):
profile = user.commission_profile_id
assert profile
domain = [
('invoice_type', 'in', ('out_invoice', 'out_refund')),
('date_invoice', '<=', date_range.date_end),
('company_id', '=', self.env.user.company_id.id),
('user_id', '=', user.id),
('commission_result_id', '=', False),
]
if profile.trigger_type == 'invoice':
domain.append(('state', 'in', ('open', 'paid')))
elif profile.trigger_type == 'payment':
# TODO : for this trigger, we would need to filter
# out the invoices paid after the end date of the period compute
domain.append(('state', '=', 'paid'))
else:
raise
ilines = self.search(domain, order='date_invoice, invoice_id, sequence')
com_result = self.env['commission.result'].create({
'user_id': user.id,
'profile_id': profile.id,
'date_range_id': date_range.id,
})
total = 0.0
for iline in ilines:
rule = iline._match_commission_rule(rules[profile.id])
if rule:
lvals = iline._prepare_commission_data(rule, com_result)
if lvals:
iline.write(lvals)
total += lvals['commission_amount']
com_result.amount_total = total
return com_result
def _match_commission_rule(self, rules):
# commission rules are already in the right order
self.ensure_one()
for rule in rules:
if rule['date_start'] and rule['date_start'] > self.date_invoice:
continue
if rule['date_end'] and rule['date_end'] < self.date_invoice:
continue
if rule['applied_on'] == '0_customer_product':
if (
self.commercial_partner_id.id in
rule['partner_ids'] and
self.product_id.id in rule['product_ids']):
return rule
elif rule['applied_on'] == '1_customer_product_category':
if (
self.commercial_partner_id.id in
rule['partner_ids'] and
self.product_categ_id.id in rule['product_categ_ids']):
return rule
elif rule['applied_on'] == '2_product':
if self.product_id.id in rule['product_ids']:
return rule
elif rule['applied_on'] == '3_product_category':
if self.product_categ_id.id in rule['product_categ_ids']:
return rule
elif rule['applied_on'] == '4_global':
return rule
return False
def _prepare_commission_data(self, rule, commission_result):
self.ensure_one()
lvals = {
'commission_result_id': commission_result.id,
'commission_rule_id': rule['id'],
# company currency
'commission_base': self.price_subtotal_signed,
'commission_rate': rule['rate'],
'commission_amount': rule['rate'] * self.price_subtotal_signed,
}
return lvals

View File

@@ -0,0 +1,120 @@
# -*- coding: utf-8 -*-
# Copyright Akretion France (http://www.akretion.com/)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models, api
import odoo.addons.decimal_precision as dp
class CommissionProfile(models.Model):
_name = 'commission.profile'
_description = 'Commission Profile'
name = fields.Char(string='Name of the Profile', required=True)
active = fields.Boolean(string='Active', default=True)
company_id = fields.Many2one(
'res.company', string='Company',
required=True,
default=lambda self: self.env['res.company']._company_default_get())
line_ids = fields.One2many(
'commission.rule', 'profile_id', string='Commission Rules')
trigger_type = fields.Selection([
('invoice', 'Invoicing'),
('payment', 'Payment'),
], default='invoice', string='Trigger', required=True)
class CommissionRule(models.Model):
_name = 'commission.rule'
_description = 'Commission Rule'
_order = 'profile_id, applied_on'
partner_ids = fields.Many2many(
'res.partner', string='Customers',
domain=[('parent_id', '=', False), ('customer', '=', True)])
product_categ_ids = fields.Many2many(
'product.category', string="Product Categories",
domain=[('type', '=', 'normal')])
product_ids = fields.Many2many('product.product', string='Products')
date_start = fields.Date('Start Date')
date_end = fields.Date('End Date')
profile_id = fields.Many2one(
'commission.profile', string='Profile', ondelete='cascade')
company_id = fields.Many2one(
related='profile_id.company_id', store=True, readonly=True)
rate = fields.Float(
'Commission Rate', digits=dp.get_precision('Commission Rate'),
copy=False)
applied_on = fields.Selection([
('0_customer_product', 'Products and Customers'),
('1_customer_product_category', "Product Categories and Customers"),
('2_product', "Products"),
('3_product_category', "Product Categories"),
('4_global', u'Global')],
string='Apply On', default='4_global', required=True)
active = fields.Boolean(string='Active', default=True)
@api.model
def load_all_rules(self):
rules = self.search_read()
res = {} # key = profile, value = [rule1 recordset, rule2]
for rule in rules:
if rule['profile_id']:
if rule['profile_id'][0] not in res:
res[rule['profile_id'][0]] = [rule]
else:
res[rule['profile_id'][0]].append(rule)
return res
_sql_constraints = [(
'rate_positive',
'CHECK(rate >= 0)',
'Rate must be positive !')]
class CommissionResult(models.Model):
_name = 'commission.result'
_description = "Commission Result"
_order = 'date_start desc'
user_id = fields.Many2one(
'res.users', 'Salesman', required=True, ondelete='restrict',
readonly=True)
profile_id = fields.Many2one(
'commission.profile', string='Commission Profile',
readonly=True)
company_id = fields.Many2one(
'res.company', string='Company',
required=True, readonly=True,
default=lambda self: self.env['res.company']._company_default_get())
company_currency_id = fields.Many2one(
related='company_id.currency_id', string='Company Currency',
readonly=True, store=True)
date_range_id = fields.Many2one(
'date.range', required=True, string='Period', readonly=True)
date_start = fields.Date(
related='date_range_id.date_start', readonly=True, store=True)
date_end = fields.Date(
related='date_range_id.date_end', readonly=True, store=True)
line_ids = fields.One2many(
'account.invoice.line', 'commission_result_id', 'Commission Lines',
readonly=True)
amount_total = fields.Monetary(
string='Commission Total', currency_field='company_currency_id',
help='This is the total amount at the date of the computation of the commission',
readonly=True)
def name_get(self):
res = []
for result in self:
name = '%s (%s)' % (result.user_id.name, result.date_range_id.name)
res.append((result.id, name))
return res
_sql_constraints = [(
'salesman_period_company_unique',
'unique(company_id, commission_partner_id, date_range_id)',
'A commission result already exists for this salesman for '
'the same period')]

View File

@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
# Copyright 2019 Akretion France (http://www.akretion.com/)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ResCompany(models.Model):
_inherit = 'res.company'
commission_date_range_type_id = fields.Many2one(
'date.range.type', string='Commission Periodicity')

View File

@@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
# Copyright 2019 Akretion France (http://www.akretion.com/)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ResUsers(models.Model):
_inherit = 'res.users'
commission_profile_id = fields.Many2one(
'commission.profile', string='Commission Profile',
company_dependant=True)

View File

@@ -0,0 +1,7 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_commission_profile_read,Read access on commission.profile for employees,model_commission_profile,base.group_user,1,0,0,0
access_commission_profile_full,Full access on commission.profile for financial manager,model_commission_profile,account.group_account_manager,1,1,1,1
access_commission_rule_full,Full access on commission.rule for financial manager,model_commission_rule,account.group_account_manager,1,1,1,1
access_commission_rule_read,Read access on commission.rule for invoicing group,model_commission_rule,account.group_account_invoice,1,0,0,0
access_commission_result_full,Full access on commission.result to accountant,model_commission_result,account.group_account_user,1,1,1,1
access_commission_result_read,Read access on commission.result to invoicing grp,model_commission_result,account.group_account_invoice,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_commission_profile_read Read access on commission.profile for employees model_commission_profile base.group_user 1 0 0 0
3 access_commission_profile_full Full access on commission.profile for financial manager model_commission_profile account.group_account_manager 1 1 1 1
4 access_commission_rule_full Full access on commission.rule for financial manager model_commission_rule account.group_account_manager 1 1 1 1
5 access_commission_rule_read Read access on commission.rule for invoicing group model_commission_rule account.group_account_invoice 1 0 0 0
6 access_commission_result_full Full access on commission.result to accountant model_commission_result account.group_account_user 1 1 1 1
7 access_commission_result_read Read access on commission.result to invoicing grp model_commission_result account.group_account_invoice 1 0 0 0

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 Akretion France (http://www.akretion.com)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-->
<odoo noupdate="1">
<record id="commission_profile_rule" model="ir.rule">
<field name="name">Commission Profile multi-company</field>
<field name="model_id" ref="model_commission_profile"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
</record>
<record id="commission_rule_rule" model="ir.rule">
<field name="name">Commission Rule multi-company</field>
<field name="model_id" ref="model_commission_rule"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
</record>
<record id="commission_result_rule" model="ir.rule">
<field name="name">Commission Result multi-company</field>
<field name="model_id" ref="model_commission_result"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
</record>
</odoo>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 Akretion France
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<record id="view_account_config_settings" model="ir.ui.view">
<field name="name">commission.account.config.settings.form</field>
<field name="model">account.config.settings</field>
<field name="inherit_id" ref="account.view_account_config_settings" />
<field name="arch" type="xml">
<xpath expr="//div[@name='invoice_taxes']/.." position="after">
<group name="commission">
<label for="id" string="Commission"/>
<div name="commission">
<div name="commission_date_range_type">
<label for="commission_date_range_type_id"/>
<field name="commission_date_range_type_id" class="oe_inline"/>
</div>
</div>
</group>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,211 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 Akretion France (http://www.akretion.com)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-->
<odoo>
<menuitem id="commission_root" name="Commissions" parent="account.menu_finance" sequence="11"/>
<menuitem id="commission_config_root" name="Commissions" parent="account.menu_finance_configuration" sequence="110"/>
<!-- PROFILE -->
<record id="commission_profile_form" model="ir.ui.view">
<field name="name">commission.profile.form</field>
<field name="model">commission.profile</field>
<field name="arch" type="xml">
<form string="Commission Profile">
<sheet>
<div class="oe_button_box" name="button_box">
<button name="toggle_active" type="object"
class="oe_stat_button" icon="fa-archive">
<field name="active" widget="boolean_button"
options='{"terminology": "archive"}'/>
</button>
</div>
<group name="main">
<field name="name"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="trigger_type"/>
</group>
<group name="lines" string="Rules">
<field name="line_ids" nolabel="1"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="commission_profile_tree" model="ir.ui.view">
<field name="name">commission.profile.tree</field>
<field name="model">commission.profile</field>
<field name="arch" type="xml">
<tree string="Commission Profiles">
<field name="name"/>
<field name="trigger_type"/>
<field name="company_id" groups="base.group_multi_company"/>
</tree>
</field>
</record>
<record id="commission_profile_action" model="ir.actions.act_window">
<field name="name">Commission Profiles</field>
<field name="res_model">commission.profile</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="commission_profile_menu" action="commission_profile_action" parent="commission_config_root" sequence="18"/>
<!-- RULE -->
<record id="commission_rule_form" model="ir.ui.view">
<field name="name">commission.rule.form</field>
<field name="model">commission.rule</field>
<field name="arch" type="xml">
<form string="Commission Rules">
<sheet>
<group name="main">
<field name="profile_id" invisible="not context.get('commission_rule_main_view')"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="applied_on" widget="radio"/>
</group>
<group name="match" string="Match">
<field name="partner_ids" attrs="{'invisible': [('applied_on', 'not in', ('0_customer_product', '1_customer_product_category'))], 'required': [('applied_on', 'in', ('0_customer_product', '1_customer_product_category'))]}"/>
<field name="product_categ_ids" attrs="{'invisible': [('applied_on', 'not in', ('1_customer_product_category', '3_product_category'))], 'required': [('applied_on', 'in', ('1_customer_product_category', '3_product_category'))]}"/>
<field name="product_ids" attrs="{'invisible': [('applied_on', 'not in', ('0_customer_product', '2_product'))], 'required': [('applied_on', 'in', ('0_customer_product', '2_product'))]}"/>
<field name="date_start"/>
<field name="date_end"/>
</group>
<group name="compute" string="Compute">
<field name="rate"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="commission_rule_tree" model="ir.ui.view">
<field name="name">commission.rule.tree</field>
<field name="model">commission.rule</field>
<field name="arch" type="xml">
<tree string="Règles de commission">
<field name="profile_id" invisible="not context.get('commission_rule_main_view')"/>
<field name="applied_on"/>
<field name="date_start"/>
<field name="date_end"/>
<field name="rate"/>
</tree>
</field>
</record>
<record id="commission_rule_search" model="ir.ui.view">
<field name="name">commission.rule.search</field>
<field name="model">commission.rule</field>
<field name="arch" type="xml">
<search string="Search in Commission Rules">
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
<group name="groupby">
<filter name="profile_groupby" string="Profile" context="{'group_by': 'profile_id'}"/>
</group>
</search>
</field>
</record>
<record id="commission_rule_action" model="ir.actions.act_window">
<field name="name">Commission Rules</field>
<field name="res_model">commission.rule</field>
<field name="view_mode">tree,form</field>
<field name="context">{'commission_rule_main_view': True}</field>
</record>
<menuitem id="commission_rule_menu" action="commission_rule_action" parent="commission_config_root" sequence="20"/>
<!-- RESULT -->
<record id="commission_result_form" model="ir.ui.view">
<field name="name">commission.result.form</field>
<field name="model">commission.result</field>
<field name="arch" type="xml">
<form string="Commission Result">
<group name="main">
<group name="main-left">
<field name="user_id"/>
<field name="profile_id" groups="account.group_account_manager"/>
<field name="company_currency_id" invisible="1"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="amount_total"/>
</group>
<group name="main-right">
<field name="date_range_id"/>
<field name="date_start"/>
<field name="date_end"/>
</group>
</group>
<group name="lines" string="Invoice Lines">
<field nolabel="1" name="line_ids">
<tree>
<field name="invoice_number"/>
<field name="date_invoice"/>
<field name="commercial_partner_id" string="Customer"/>
<field name="name"/>
<field name="quantity"/>
<field name="uom_id"/>
<field name="price_unit"/>
<field name="currency_id"/>
<field name="discount"/>
<field name="price_subtotal_signed" string="Amount w/o tax in company cur."/>
<field name="state"/>
<field name="commission_base"/>
<field name="commission_rate" string="Rate (%)"/>
<field name="commission_amount" sum="1"/>
<field name="commission_rule_id" string="Commission Rule"/>
<field name="company_currency_id" invisible="1"/>
</tree>
</field>
</group>
</form>
</field>
</record>
<record id="commission_result_tree" model="ir.ui.view">
<field name="name">commission.result.tree</field>
<field name="model">commission.result</field>
<field name="arch" type="xml">
<tree string="Commission Results">
<field name="date_range_id"/>
<field name="user_id"/>
<field name="profile_id" groups="account.group_account_manager"/>
<field name="company_currency_id" invisible="1"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="amount_total" sum="Total"/>
</tree>
</field>
</record>
<record id="commission_result_search" model="ir.ui.view">
<field name="name">commission.result.search</field>
<field name="model">commission.result</field>
<field name="arch" type="xml">
<search string="Search Commission Results">
<field name="user_id"/>
<field name="date_range_id"/>
<group name="groupby">
<filter name="user_groupby" string="Salesman" context="{'group_by': 'user_id'}"/>
<filter name="date_range_groupby" string="Period" context="{'group_by': 'date_range_id'}"/>
</group>
</search>
</field>
</record>
<record id="commission_result_action" model="ir.actions.act_window">
<field name="name">Commissions</field>
<field name="res_model">commission.result</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="commission_result_menu" action="commission_result_action" parent="commission_root" sequence="10"/>
</odoo>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 Akretion France (http://www.akretion.com)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-->
<odoo>
<record id="view_users_form" model="ir.ui.view">
<field name="name">commission.res.users.form</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='action_id']/.." position="after">
<group name="commission" string="Commission">
<field name="commission_profile_id"/>
</group>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import commission_compute

View File

@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
# Copyright 2019 Akretion France (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models, _
from dateutil.relativedelta import relativedelta
from odoo.exceptions import UserError
import logging
logger = logging.getLogger(__name__)
class CommissionCompute(models.TransientModel):
_name = 'commission.compute'
_description = 'Compute Commissoins'
@api.model
def _default_date_range(self):
drange_type = self.env.user.company_id.commission_date_range_type_id
if not drange_type:
return False
today = fields.Date.from_string(fields.Date.context_today(self))
first_day_last_month = today + relativedelta(months=-1, day=1)
dranges = self.env['date.range'].search([
('company_id', '=', self.env.user.company_id.id),
('type_id', '=', drange_type.id),
('date_start', '=', fields.Date.to_string(first_day_last_month))
])
return dranges and dranges[0] or dranges
date_range_id = fields.Many2one(
'date.range', required=True, string='Period',
default=lambda self: self._default_date_range())
date_start = fields.Date(related='date_range_id.date_start', readonly=True)
date_end = fields.Date(related='date_range_id.date_end', readonly=True)
def run(self):
self.ensure_one()
creso = self.env['commission.result']
ruo = self.env['res.users']
date_range = self.date_range_id
existing_res = creso.search([('date_range_id', '=', date_range.id)])
if existing_res:
raise UserError(
u'Il existe déjà des commissions pour cette période.')
com_result_ids = self.core_compute()
if not com_result_ids:
raise UserError(_('No commission generated.'))
action = self.env['ir.actions.act_window'].for_xml_id(
'commission_simple', 'commission_result_action')
action.update({
'views': False,
'domain': "[('id', 'in', %s)]" % com_result_ids,
})
return action
def core_compute(self):
rules = self.env['commission.rule'].load_all_rules()
ailo = self.env['account.invoice.line']
ruo = self.env['res.users']
com_result_ids = []
for user in ruo.with_context(active_test=False).search([]):
if user.commission_profile_id:
if user.commission_profile_id.id not in rules:
raise UserError(_(
"The commission profile '%s' doesn't have any rules.")
% user.commission_profile_id.name)
com_result = ailo.compute_commission_for_one_user(user, self.date_range_id, rules)
if com_result:
com_result_ids.append(com_result.id)
else:
logger.debug(
"Commission computation: salesman '%s' "
"doesn't have a commission profile",
user.name)
return com_result_ids

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 Akretion France (http://www.akretion.com)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<record id="commission_compute_form" model="ir.ui.view">
<field name="name">commission.compute.form</field>
<field name="model">commission.compute</field>
<field name="arch" type="xml">
<form string="Compute Commissions">
<group name="main">
<field name="date_range_id"/>
<field name="date_start"/>
<field name="date_end"/>
</group>
<footer>
<button name="run" type="object" string="Compute"
class="btn-primary"/>
<button special="cancel" string="Cancel"/>
</footer>
</form>
</field>
</record>
<record id="commission_compute_action" model="ir.actions.act_window">
<field name="name">Compute Commissions</field>
<field name="res_model">commission.compute</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<menuitem id="commission_compute_menu" action="commission_compute_action" parent="commission_root" sequence="15" groups="account.group_account_user"/>
</odoo>

View File

View File

@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
# Copyright 2019 Akretion France (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Commission Simple Sale',
'version': '10.0.1.0.0',
'category': 'Sales',
'license': 'AGPL-3',
'summary': 'Give access to commission results to Salesman',
'description': """
Commission Simple Sale
======================
This module allows salesman to see their commissions in Odoo, under the Sales menu.
This module has been written by Alexis de Lattre from Akretion
<alexis.delattre@akretion.com>.
""",
'author': 'Akretion',
'website': 'http://www.akretion.com',
'depends': [
'sale',
'commission_simple',
],
'data': [
'views/commission.xml',
'security/rule.xml',
'security/ir.model.access.csv',
],
'installable': True,
}

View File

@@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_commission_result_salesman_read,Read access on commission.result to salesman,commission_simple.model_commission_result,sales_team.group_sale_salesman,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_commission_result_salesman_read Read access on commission.result to salesman commission_simple.model_commission_result sales_team.group_sale_salesman 1 0 0 0

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 Akretion France (http://www.akretion.com)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-->
<odoo noupdate="1">
<record id="commission_result_salesman_rule" model="ir.rule">
<field name="name">Commission Result for Salesman</field>
<field name="model_id" ref="commission_simple.model_commission_result"/>
<field name="groups" eval="[(4, ref('sales_team.group_sale_salesman'))]"/>
<field name="domain_force">[('user_id', '=', user.id)]</field>
</record>
</odoo>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 Akretion France (http://www.akretion.com)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-->
<odoo>
<menuitem id="commission_sale_root" name="Commissions" parent="sales_team.menu_base_partner" sequence="50"/>
<menuitem id="commission_result_sale_menu" action="commission_simple.commission_result_action" parent="commission_sale_root" sequence="10" groups="sales_team.group_sale_salesman"/>
</odoo>