Skip to content

Commit

Permalink
feat: sales commission
Browse files Browse the repository at this point in the history
  • Loading branch information
fproldan committed Oct 3, 2024
1 parent 876d6ab commit f1790d2
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 33 deletions.
15 changes: 8 additions & 7 deletions erpnext/payroll/doctype/sales_commission/sales_commission.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"commission_against",
"omit_sales_person_transactions",
"column_break_14",
"filtro",
"commission_against_filter",
"section_break_10",
"from_date",
"to_date",
Expand Down Expand Up @@ -245,24 +245,25 @@
"fieldname": "commission_against",
"fieldtype": "Link",
"label": "Comisionar Sobre",
"mandatory_depends_on": "eval:doc.omit_sales_person_transactions == 1;",
"options": "DocType"
},
{
"fieldname": "column_break_14",
"fieldtype": "Column Break"
},
{
"depends_on": "eval:doc.omit_sales_person_transactions == 1;",
"fieldname": "filtro",
"fieldname": "commission_against_filter",
"fieldtype": "Dynamic Link",
"label": "Filtro",
"options": "commission_against"
},
{
"fieldname": "column_break_14",
"fieldtype": "Column Break"
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2024-09-30 13:48:21.649556",
"modified": "2024-09-30 14:33:15.176817",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Sales Commission",
Expand Down
111 changes: 85 additions & 26 deletions erpnext/payroll/doctype/sales_commission/sales_commission.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import frappe
import erpnext
from frappe import _
from frappe.utils import get_link_to_form
from frappe.utils import get_link_to_form, flt, nowdate
from erpnext.accounts.general_ledger import make_gl_entries
from erpnext.controllers.accounts_controller import (
AccountsController,
Expand All @@ -13,14 +13,32 @@
class SalesCommission(AccountsController):
def validate(self):
self.validate_from_to_dates()

self.validate_omit_transaction_duplicates()
self.validate_salary_component()
self.calculate_total_contribution_and_total_commission_amount()
self.create_employee()

def validate_from_to_dates(self):
return super().validate_from_to_dates("from_date", "to_date")

def validate_omit_transaction_duplicates(self):
# TODO chequear por solapamiento de fechas
if not self.omit_sales_person_transactions:
return

previous_contibutions = frappe.get_all(
"Sales Commission",
filters={
"sales_person": self.sales_person,
"docstatus": 1,
"from_date": self.from_date,
"to_date": self.to_date,
},
pluck="name"
)
if previous_contibutions:
frappe.throw(_("Este vendedor ya tiene liquidado ventas en el período seleccionado"))

def validate_amount(self):
if self.total_commission_amount <= 0:
frappe.throw(_("Total Commission Amount should be greater than 0"))
Expand All @@ -46,15 +64,15 @@ def make_gl_entries(self, cancel=False):
def get_gl_entries(self):
gl_entry = []

sales_commission_expense_account = frappe.get_value("Company", self.company, "sales_commission_expense_account") # DEBIT
payment_account_sales_commission = frappe.get_value("Company", self.company, "payment_account_sales_commission") # CREDIT
sales_commission_expense_account = frappe.get_value("Company", self.company, "sales_commission_expense_account")
payment_account_sales_commission = frappe.get_value("Company", self.company, "payment_account_sales_commission")

if not sales_commission_expense_account or not payment_account_sales_commission:
frappe.throw(_("Debe configurar la Cuenta de Pago Comisión Vendedores y la Cuenta de Gastos Comisión Vendedores en la Compañia."))

gl_entry.append(
self.get_gl_dict({
"posting_date": self.creation.date(),
"posting_date": nowdate(),
"account": payment_account_sales_commission,
"credit": self.total_commission_amount,
"credit_in_account_currency": self.total_commission_amount,
Expand All @@ -69,7 +87,7 @@ def get_gl_entries(self):

gl_entry.append(
self.get_gl_dict({
"posting_date": self.creation.date(),
"posting_date": nowdate(),
"account": sales_commission_expense_account,
"debit": self.total_commission_amount,
"debit_in_account_currency": self.total_commission_amount,
Expand All @@ -86,28 +104,69 @@ def add_contributions(self, process_sales_commission):
self.set("contributions", [])
filter_date = "transaction_date" if self.commission_based_on == "Sales Order" else "posting_date"
customer_field = "customer" if self.commission_based_on != "Payment Entry" else "party"
records = [entry.name for entry in frappe.db.get_all(self.commission_based_on, filters={"company": self.company, "docstatus": 1, filter_date: ('between', [self.from_date, self.to_date])})]
sales_persons_details = frappe.get_all(
"Sales Team", filters={"parent": ['in', records], "sales_person": self.sales_person},
fields=["sales_person", "commission_rate", "incentives", "allocated_percentage", "allocated_amount", "parent"])
if sales_persons_details:
for record in sales_persons_details:
if add_record(record, self.sales_person):
record_details = frappe.db.get_value(self.commission_based_on, filters={"name": record["parent"]}, fieldname=[customer_field, filter_date], as_dict=True)
contribution = {
"document_type": self.commission_based_on,
"order_or_invoice": record["parent"],
"customer": record_details.get(customer_field),
"posting_date": record_details[filter_date],
"contribution_percent": record["allocated_percentage"],
"contribution_amount": record["allocated_amount"],
"commission_rate": record["commission_rate"],
"commission_amount": record["incentives"],
"process_sales_commission": process_sales_commission,
}
self.append("contributions", contribution)

if self.omit_sales_person_transactions:
filter_fieldname = self.get_filter_commission_against_field()
filter_value = self.commission_against_filter
commission_rate = frappe.get_value("Sales Person", self.sales_person, "commission_rate")
filter_value_sql = f"AND {filter_fieldname} = '{filter_value}'" if filter_fieldname and filter_value else ""
records = frappe.db.sql(f"""
SELECT {filter_fieldname} AS commission_filter, SUM(total) AS allocated_amount
FROM `tab{self.commission_based_on}`
WHERE docstatus = 1
AND company = '{self.company}'
AND {filter_date} BETWEEN '{self.from_date}' AND '{self.to_date}'
{filter_value_sql}
GROUP BY {filter_fieldname}
""", as_dict=True)

commission_rate = frappe.get_value("Sales Person", self.sales_person, "commission_rate")

for record in records:
record['commission_rate'] = commission_rate
record['incentives'] = flt(record['allocated_amount'] * flt(commission_rate) / 100.0, self.precision("total_contribution"))
record['allocated_percentage'] = 100
contribution = {
"commission_filter": record["commission_filter"],
"contribution_percent": record["allocated_percentage"],
"contribution_amount": record["allocated_amount"],
"commission_rate": record["commission_rate"],
"commission_amount": record["incentives"],
"process_sales_commission": process_sales_commission,
}
self.append("contributions", contribution)
else:
records = [entry.name for entry in frappe.db.get_all(self.commission_based_on, filters={"company": self.company, "docstatus": 1, filter_date: ('between', [self.from_date, self.to_date])})]

sales_persons_details = frappe.get_all(
"Sales Team", filters={"parent": ['in', records], "sales_person": self.sales_person},
fields=["sales_person", "commission_rate", "incentives", "allocated_percentage", "allocated_amount", "parent"])

if sales_persons_details:
for record in sales_persons_details:
if add_record(record, self.sales_person):
record_details = frappe.db.get_value(self.commission_based_on, filters={"name": record["parent"]}, fieldname=[customer_field, filter_date], as_dict=True)
contribution = {
"document_type": self.commission_based_on,
"order_or_invoice": record["parent"],
"customer": record_details.get(customer_field),
"posting_date": record_details[filter_date],
"contribution_percent": record["allocated_percentage"],
"contribution_amount": record["allocated_amount"],
"commission_rate": record["commission_rate"],
"commission_amount": record["incentives"],
"process_sales_commission": process_sales_commission,
}
self.append("contributions", contribution)
self.calculate_total_contribution_and_total_commission_amount()

def get_filter_commission_against_field(self):
commission_based_on_meta = frappe.get_meta(self.commission_based_on)
for field in commission_based_on_meta.fields:
if field.fieldtype == "Link" and field.options == self.commission_against:
return field.fieldname
frappe.throw(f"{self.commission_based_on} no tiene campo {self.commission_against}")

def calculate_total_contribution_and_total_commission_amount(self):
total_contribution, total_commission_amount = 0, 0
for entry in self.contributions:
Expand Down

0 comments on commit f1790d2

Please sign in to comment.