diff --git a/pre_commissions/__init__.py b/pre_commissions/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/pre_commissions/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/pre_commissions/__manifest__.py b/pre_commissions/__manifest__.py new file mode 100644 index 00000000000..3c7339935e0 --- /dev/null +++ b/pre_commissions/__manifest__.py @@ -0,0 +1,13 @@ +{ + 'name': "Sale Commission", + 'author': "Kunj Koradiya", + 'description': "This is the description", + 'license': "LGPL-3", + 'depends': ['base', 'account', 'sale'], + 'data': [ + 'security/ir.model.access.csv', + 'views/commision_rule.xml', + 'views/sale_commission.xml', + 'views/menus.xml' + ] +} diff --git a/pre_commissions/models/__init__.py b/pre_commissions/models/__init__.py new file mode 100644 index 00000000000..eb2b588db60 --- /dev/null +++ b/pre_commissions/models/__init__.py @@ -0,0 +1,3 @@ +from . import commission_rule +from . import sale_commission +from . import account_move diff --git a/pre_commissions/models/account_move.py b/pre_commissions/models/account_move.py new file mode 100644 index 00000000000..86d1d49ba80 --- /dev/null +++ b/pre_commissions/models/account_move.py @@ -0,0 +1,21 @@ +from odoo import models + + +class AccountMove(models.Model): + _inherit = 'account.move' + + def action_post(self): + res = super().action_post() + # breakpoint() + for move in self: + if move.move_type != 'out_invoice': + continue + + sale_orders = move.invoice_line_ids.sale_line_ids.order_id + sale_orders = sale_orders.exists() + + if not sale_orders: + continue + + self.env['sale.commission'].sudo().check_commission_rules(sale_orders, move) + return res diff --git a/pre_commissions/models/commission_rule.py b/pre_commissions/models/commission_rule.py new file mode 100644 index 00000000000..04c5ca67aac --- /dev/null +++ b/pre_commissions/models/commission_rule.py @@ -0,0 +1,52 @@ +from odoo import fields, models, api + + +class CommisionRule(models.Model): + _name = 'commission.rule' + _desc = "Commission Rule" + _order = 'sequence' + + sequence = fields.Integer() + active = fields.Boolean(default=True) + commission_rate = fields.Float(required=True) + due_at = fields.Selection([ + ('invoice', "Invoice Posted"), + ('payment', "Payment Received") + ], + default='invoice', + required=True + ) + commission_for = fields.Selection([ + ('salesperson', "Salesperson"), + ('team', "Sales Team") + ]) + product_category_id = fields.Many2one('product.category') + product_id = fields.Many2one('product.product') + product_expired = fields.Selection([ + ('no_impact', 'No Impact'), + ('yes', "Expired Only"), + ('no', 'Not Expired') + ], default='no_impact' + ) + max_discount = fields.Float(string="Max Discount %") + fast_payment = fields.Boolean() + fast_payment_days = fields.Integer() + salesperson_id = fields.Many2one('res.users') + team_id = fields.Many2one('crm.team', string="Sales Team") + condition_display = fields.Char(store=True, compute='_compute_condition_display') + + @api.depends('product_category_id', 'product_id', 'salesperson_id', 'team_id', 'max_discount') + def _compute_condition_display(self): + for rec in self: + parts = [] + if rec.product_category_id: + parts.append(f"Category: {rec.product_category_id.name}") + if rec.product_id: + parts.append(f"Product: {rec.product_id.name}") + if rec.salesperson_id: + parts.append(f"Salesperson: {rec.salesperson_id.name}") + if rec.team_id: + parts.append(f"Team: {rec.team_id.name}") + if rec.max_discount: + parts.append(f"Max Discount: {rec.max_discount}%") + rec.condition_display = " AND ".join(parts) or "All" diff --git a/pre_commissions/models/sale_commission.py b/pre_commissions/models/sale_commission.py new file mode 100644 index 00000000000..e69a18f0d62 --- /dev/null +++ b/pre_commissions/models/sale_commission.py @@ -0,0 +1,56 @@ +from odoo import fields, models, api + + +class SaleCommission(models.Model): + _name = 'sale.commission' + _description = "Sale Commission" + + date = fields.Date(required=True) + user_id = fields.Many2one('res.users', string="Salesperson") + team_id = fields.Many2one('crm.team', string="Sales Team") + invoice_id = fields.Many2one('account.move') + partner_id = fields.Many2one(related='invoice_id.partner_id', store=True) + + amount = fields.Monetary() + currency_id = fields.Many2one( + 'res.currency', + default=lambda self: self.env.company.currency_id.id + ) + + rule_id = fields.Many2one('commission.rule') + sale_order_id = fields.Many2one('sale.order') + + def check_commission_rules(self, sale_orders, invoice): + # breakpoint() + if not sale_orders: + return + rules = self.env['commission.rule'].search([ + ('active', '=', True) + ]) + for order in sale_orders: + for rule in rules: + condition_ok = True + if rule.salesperson_id and order.user_id != rule.salesperson_id: + condition_ok = False + if rule.team_id and order.team_id != rule.team_id: + condition_ok = False + + if not condition_ok: + continue + # existing = self.search([ + # ('invoice_id', '=', invoice.id), + # ('rule_id', '=', rule.id), + # ('sale_order_id', '=', order.id) + # ], limit=1) + # if existing: + # continue + commission_amount = invoice.amount_total * rule.commission_rate + self.create({ + 'date': invoice.invoice_date, + 'invoice_id': invoice.id, + 'user_id': order.user_id.id, + 'team_id': order.team_id.id, + 'amount': commission_amount, + 'rule_id': rule.id, + 'sale_order_id': order.id, + }) diff --git a/pre_commissions/security/ir.model.access.csv b/pre_commissions/security/ir.model.access.csv new file mode 100644 index 00000000000..835acb20bf8 --- /dev/null +++ b/pre_commissions/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink +access_commission_rules,access_commission_rules,model_commission_rule,base.group_user,1,1,1,1 +access_sale_commissions,access_sale_commissions,model_sale_commission,base.group_user,1,1,1,1 diff --git a/pre_commissions/views/commision_rule.xml b/pre_commissions/views/commision_rule.xml new file mode 100644 index 00000000000..a514f77d8b9 --- /dev/null +++ b/pre_commissions/views/commision_rule.xml @@ -0,0 +1,65 @@ + + + + + Commission Rules + commission.rule + list,form + + + + + commission.rule.view.form + commission.rule + +
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + commission.rule.view.list + commission.rule + + + + + + + + + + + +
\ No newline at end of file diff --git a/pre_commissions/views/menus.xml b/pre_commissions/views/menus.xml new file mode 100644 index 00000000000..10b9e753f28 --- /dev/null +++ b/pre_commissions/views/menus.xml @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/pre_commissions/views/sale_commission.xml b/pre_commissions/views/sale_commission.xml new file mode 100644 index 00000000000..3211adcbc51 --- /dev/null +++ b/pre_commissions/views/sale_commission.xml @@ -0,0 +1,53 @@ + + + + + Sale Commission + sale.commission + list,form,pivot,graph + + + + + + sale.commission.view.list + sale.commission + + + + + + + + + + + + + + + sale.commission.view.pivot + sale.commission + + + + + + + + + + + + + sale.commission.view.graph + sale.commission + + + + + + + + +