diff --git a/erpnext/payroll/doctype/process_sales_commission/process_sales_commission.js b/erpnext/payroll/doctype/process_sales_commission/process_sales_commission.js index ea2d22a4fb26..4c75053703a9 100644 --- a/erpnext/payroll/doctype/process_sales_commission/process_sales_commission.js +++ b/erpnext/payroll/doctype/process_sales_commission/process_sales_commission.js @@ -13,5 +13,42 @@ frappe.ui.form.on('Process Sales Commission', { } }; }); + frm.set_query("commission_against", function() { + return { + filters: [ + ['name', 'in', ["Canal de Venta"]] + ] + }; + }); + frm.set_query("sales_persons", function() { + return { + filters: {"enabled": 1} + }; + }); }, -}); \ No newline at end of file + company: function(frm) { + get_sales_persons(frm) + }, + department: function(frm) { + get_sales_persons(frm) + }, + designation: function(frm) { + get_sales_persons(frm) + }, + branch: function(frm) { + get_sales_persons(frm) + } +}); + + +function get_sales_persons(frm) { + frm.clear_table("sales_persons"); + return frappe.call({ + doc: frm.doc, + method: 'get_sales_persons', + callback: function () { + frm.dirty(); + frm.refresh(); + }, + }); +} \ No newline at end of file diff --git a/erpnext/payroll/doctype/process_sales_commission/process_sales_commission.json b/erpnext/payroll/doctype/process_sales_commission/process_sales_commission.json index 167ffc23e12c..95c7f551bd92 100644 --- a/erpnext/payroll/doctype/process_sales_commission/process_sales_commission.json +++ b/erpnext/payroll/doctype/process_sales_commission/process_sales_commission.json @@ -11,11 +11,19 @@ "column_break_3", "designation", "branch", + "sales_persons_break", + "sales_persons", + "comisionar_sobre_section", + "commission_against", + "omit_sales_person_transactions", + "column_break__9", + "commission_against_filter", "section_break_6", "from_date", "to_date", "column_break_9", "commission_based_on", + "submit_sales_commission", "pay_via_salary", "amended_from" ], @@ -31,7 +39,6 @@ { "fieldname": "department", "fieldtype": "Link", - "hidden": 1, "label": "Department", "options": "Department" }, @@ -42,14 +49,12 @@ { "fieldname": "designation", "fieldtype": "Link", - "hidden": 1, "label": "Designation", "options": "Designation" }, { "fieldname": "branch", "fieldtype": "Link", - "hidden": 1, "label": "Branch", "options": "Branch" }, @@ -94,12 +99,59 @@ "options": "Process Sales Commission", "print_hide": 1, "read_only": 1 + }, + { + "fieldname": "comisionar_sobre_section", + "fieldtype": "Section Break" + }, + { + "depends_on": "eval:doc.omit_sales_person_transactions == 1;", + "fieldname": "commission_against", + "fieldtype": "Link", + "label": "Comisionar Sobre", + "mandatory_depends_on": "eval:doc.omit_sales_person_transactions == 1;", + "options": "DocType" + }, + { + "default": "0", + "description": "Si selecciona esta opci\u00f3n, los c\u00e1lculos de comisiones omitir\u00e1n las asignaciones del vendedor incluidas en las transacciones", + "fieldname": "omit_sales_person_transactions", + "fieldtype": "Check", + "label": "Omitir Transacciones del Vendedor" + }, + { + "fieldname": "column_break__9", + "fieldtype": "Column Break" + }, + { + "depends_on": "eval:doc.omit_sales_person_transactions == 1;", + "fieldname": "commission_against_filter", + "fieldtype": "Dynamic Link", + "label": "Filtro", + "options": "commission_against" + }, + { + "default": "0", + "fieldname": "submit_sales_commission", + "fieldtype": "Check", + "label": "Validar Comisiones de Ventas" + }, + { + "fieldname": "sales_persons_break", + "fieldtype": "Section Break" + }, + { + "fieldname": "sales_persons", + "fieldtype": "Table", + "label": "Vendedores", + "options": "Process Sales Commission Sales Person", + "reqd": 1 } ], "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2024-09-02 09:57:58.062144", + "modified": "2024-10-09 17:30:15.732976", "modified_by": "Administrator", "module": "Payroll", "name": "Process Sales Commission", @@ -146,6 +198,7 @@ } ], "restrict_to_domain": "Vendedores y Socios", + "route": "app/doctype/Process%20Sales%20Commission", "sort_field": "modified", "sort_order": "DESC", "track_changes": 1 diff --git a/erpnext/payroll/doctype/process_sales_commission/process_sales_commission.py b/erpnext/payroll/doctype/process_sales_commission/process_sales_commission.py index 16e1dbcc7410..a8b994886ad6 100644 --- a/erpnext/payroll/doctype/process_sales_commission/process_sales_commission.py +++ b/erpnext/payroll/doctype/process_sales_commission/process_sales_commission.py @@ -32,67 +32,94 @@ def process_sales_commission(self): fields=["sales_person", "commission_rate", "incentives", "allocated_percentage", "allocated_amount", "parent"]) if sales_persons_details: sales_persons = {e['sales_person'] for e in sales_persons_details} - sales_persons_list = self.get_sales_persons_list(sales_persons) - # sales_persons_details_map = self.map_sales_persons_details(sales_persons_list, sales_persons_details) - self.make_sales_commission_document(sales_persons_list, filter_date) + sales_persons_list = self.get_sales_persons_list(sales_persons) + self.make_sales_commission_document(sales_persons_list, filter_date) def get_sales_persons_list(self, sales_persons): sales_persons_list = sales_persons - if self.department or self.designation or self.branch: - sales_persons_emp = frappe.get_all("Sales Person", filters={"name": ["in", sales_persons]}, fields=["employee"], as_dict=True)['employee'] - emp_filters = {"name": ["in", sales_persons_emp], "company": self.company} - # for field in ["department", "designation", "branch"]: - if self.department: - emp_filters["department"] = self.department - if self.designation: - emp_filters["designation"] = self.designation - if self.branch: - emp_filters["branch"] = self.branch + if not any([self.department, self.designation, self.branch]): + return sales_persons_list + + sales_persons_emp = frappe.get_all("Sales Person", filters={"name": ["in", sales_persons]}, fields=["employee"], pluck="employee") + emp_filters = {"name": ["in", sales_persons_emp], "company": self.company} + if self.department: + emp_filters["department"] = self.department + if self.designation: + emp_filters["designation"] = self.designation + if self.branch: + emp_filters["branch"] = self.branch - sales_persons_list = frappe.get_all("Employee", filters=emp_filters, as_dict=True) - # for person in sales_persons: - # emp = frappe.db.get_value("Sales Person", filters={"name": person}, fieldname="employee", as_dict=True)['employee'] - # if emp: - # employee_details = frappe.db.get_value("Employee", filters={"name": emp}, as_dict=True) - # if self.company != employee_details["company"]: - # sales_persons_list.remove(person) - # continue - # if self.department and self.department != employee_details["department"]: - # sales_persons_list.remove(person) - # continue - # if self.designation and self.designation != employee_details["designation"]: - # sales_persons_list.remove(person) - # continue - # if self.branch and self.branch != employee_details["branch"]: - # sales_persons_list.remove(person) - # continue + sales_persons_list = frappe.get_all("Employee", filters=emp_filters) + for person in sales_persons: + emp = frappe.db.get_value("Sales Person", filters={"name": person}, fieldname="employee") + if not emp: + continue + employee_details = frappe.db.get_value("Employee", filters={"name": emp}, as_dict=True) + if self.company != employee_details["company"]: + sales_persons_list.remove(person) + continue + if self.department and self.department != employee_details["department"]: + sales_persons_list.remove(person) + continue + if self.designation and self.designation != employee_details["designation"]: + sales_persons_list.remove(person) + continue + if self.branch and self.branch != employee_details["branch"]: + sales_persons_list.remove(person) + continue - return sales_persons_list + def map_sales_persons_details(self, sales_persons, sales_persons_details): + sales_persons_details_map = {} + for person in sales_persons: + sales_persons_details_map[person] = [] + for details in sales_persons_details: + if details['sales_person'] == person: + sales_persons_details_map[person].append(details) - # def map_sales_persons_details(self, sales_persons, sales_persons_details): - # sales_persons_details_map = {} - # for person in sales_persons: - # sales_persons_details_map[person] = [] - # for details in sales_persons_details: - # if details['sales_person'] == person: - # sales_persons_details_map[person].append(details) - - # return sales_persons_details_map + return sales_persons_details_map def make_sales_commission_document(self, sales_persons_details_map, filter_date): for record in sales_persons_details_map: - doc = doc = frappe.new_doc("Sales Commission") + doc = frappe.new_doc("Sales Commission") doc.sales_person = record doc.commission_based_on = self.commission_based_on doc.from_date = self.from_date doc.to_date = self.to_date doc.pay_via_salary = self.pay_via_salary doc.process_sales_commission_reference = self.name + doc.omit_sales_person_transactions = self.omit_sales_person_transactions + doc.commission_against = self.commission_against + doc.commission_against_filter = self.commission_against_filter doc.add_contributions(self.name) doc.insert() + + if self.submit_sales_commission: + try: + doc.submit() + except Exception: + frappe.log_error(title=f"Error al validar Comision De Ventas", message=frappe.get_traceback()) + if not frappe.db.get_single_value("Selling Settings", "approval_required_for_sales_commission_payout"): doc.reload() if self.pay_via_salary and doc.employee: if frappe.db.exists('Salary Structure Assignment', {'employee': doc.employee}): doc.submit() doc.payout_entry() + + @frappe.whitelist() + def get_sales_persons(self): + employee_filters = {"company": self.company} + if self.department: + employee_filters["department"] = self.department + if self.designation: + employee_filters["designation"] = self.designation + if self.branch: + employee_filters["branch"] = self.branch + + employees = frappe.get_all("Employee", filters=employee_filters, pluck="name") + for sales_person in frappe.get_all( + "Sales Person", + filters=[["employee", "in", employees]], + fields="name as sales_person" + ): + self.append("sales_persons", sales_person) \ No newline at end of file diff --git a/erpnext/payroll/doctype/process_sales_commission_sales_person/__init__.py b/erpnext/payroll/doctype/process_sales_commission_sales_person/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/erpnext/payroll/doctype/process_sales_commission_sales_person/process_sales_commission_sales_person.json b/erpnext/payroll/doctype/process_sales_commission_sales_person/process_sales_commission_sales_person.json new file mode 100644 index 000000000000..0bcdd8d8c150 --- /dev/null +++ b/erpnext/payroll/doctype/process_sales_commission_sales_person/process_sales_commission_sales_person.json @@ -0,0 +1,32 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2024-10-09 17:04:37.780469", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "sales_person" + ], + "fields": [ + { + "fieldname": "sales_person", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Sales Person", + "options": "Sales Person" + } + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2024-10-09 17:26:46.461250", + "modified_by": "Administrator", + "module": "Payroll", + "name": "Process Sales Commission Sales Person", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/payroll/doctype/process_sales_commission_sales_person/process_sales_commission_sales_person.py b/erpnext/payroll/doctype/process_sales_commission_sales_person/process_sales_commission_sales_person.py new file mode 100644 index 000000000000..e9cd08ad4f36 --- /dev/null +++ b/erpnext/payroll/doctype/process_sales_commission_sales_person/process_sales_commission_sales_person.py @@ -0,0 +1,8 @@ +# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + +class ProcessSalesCommissionSalesPerson(Document): + pass