Skip to content

Commit

Permalink
Merge pull request frappe#27281 from DeeMysterio/party-specific-items
Browse files Browse the repository at this point in the history
feat: link items to supplier / customer
  • Loading branch information
DeeMysterio authored Sep 14, 2021
1 parent 9aa6f52 commit aa82624
Show file tree
Hide file tree
Showing 14 changed files with 189 additions and 135 deletions.
8 changes: 4 additions & 4 deletions erpnext/buying/doctype/supplier/supplier.json
Original file line number Diff line number Diff line change
Expand Up @@ -433,12 +433,12 @@
"image_field": "image",
"links": [
{
"group": "Item Group",
"link_doctype": "Supplier Item Group",
"link_fieldname": "supplier"
"group": "Allowed Items",
"link_doctype": "Party Specific Item",
"link_fieldname": "party"
}
],
"modified": "2021-08-27 18:02:44.314077",
"modified": "2021-09-06 17:37:56.522233",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier",
Expand Down

This file was deleted.

20 changes: 0 additions & 20 deletions erpnext/buying/doctype/supplier_item_group/supplier_item_group.py

This file was deleted.

This file was deleted.

30 changes: 21 additions & 9 deletions erpnext/controllers/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from collections import defaultdict

import frappe
from frappe import scrub
from frappe.desk.reportview import get_filters_cond, get_match_cond
from frappe.utils import nowdate, unique

Expand Down Expand Up @@ -223,18 +224,29 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
if not field in searchfields]
searchfields = " or ".join([field + " like %(txt)s" for field in searchfields])

if filters and isinstance(filters, dict) and filters.get('supplier'):
item_group_list = frappe.get_all('Supplier Item Group',
filters = {'supplier': filters.get('supplier')}, fields = ['item_group'])
if filters and isinstance(filters, dict):
if filters.get('customer') or filters.get('supplier'):
party = filters.get('customer') or filters.get('supplier')
item_rules_list = frappe.get_all('Party Specific Item',
filters = {'party': party}, fields = ['restrict_based_on', 'based_on_value'])

item_groups = []
for i in item_group_list:
item_groups.append(i.item_group)
filters_dict = {}
for rule in item_rules_list:
if rule['restrict_based_on'] == 'Item':
rule['restrict_based_on'] = 'name'
filters_dict[rule.restrict_based_on] = []

del filters['supplier']
for rule in item_rules_list:
filters_dict[rule.restrict_based_on].append(rule.based_on_value)

for filter in filters_dict:
filters[scrub(filter)] = ['in', filters_dict[filter]]

if filters.get('customer'):
del filters['customer']
else:
del filters['supplier']

if item_groups:
filters['item_group'] = ['in', item_groups]

description_cond = ''
if frappe.db.count('Item', cache=True) < 50000:
Expand Down
1 change: 1 addition & 0 deletions erpnext/patches.txt
Original file line number Diff line number Diff line change
Expand Up @@ -304,5 +304,6 @@ erpnext.patches.v13_0.set_operation_time_based_on_operating_cost
erpnext.patches.v13_0.validate_options_for_data_field
erpnext.patches.v13_0.create_gst_payment_entry_fields
erpnext.patches.v14_0.delete_shopify_doctypes
erpnext.patches.v13_0.replace_supplier_item_group_with_party_specific_item
erpnext.patches.v13_0.update_dates_in_tax_withholding_category
erpnext.patches.v14_0.update_opportunity_currency_fields
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright (c) 2019, Frappe and Contributors
# License: GNU General Public License v3. See license.txt

import frappe


def execute():
if frappe.db.table_exists('Supplier Item Group'):
frappe.reload_doc("selling", "doctype", "party_specific_item")
sig = frappe.db.get_all("Supplier Item Group", fields=["name", "supplier", "item_group"])
for item in sig:
psi = frappe.new_doc("Party Specific Item")
psi.party_type = "Supplier"
psi.party = item.supplier
psi.restrict_based_on = "Item Group"
psi.based_on_value = item.item_group
psi.insert()
22 changes: 10 additions & 12 deletions erpnext/selling/doctype/customer/customer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
"tax_withholding_category",
"default_bank_account",
"lead_name",
"prospect",
"opportunity_name",
"image",
"column_break0",
Expand Down Expand Up @@ -214,7 +213,8 @@
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Represents Company",
"options": "Company"
"options": "Company",
"unique": 1
},
{
"depends_on": "represents_company",
Expand Down Expand Up @@ -497,14 +497,6 @@
"label": "Tax Withholding Category",
"options": "Tax Withholding Category"
},
{
"fieldname": "prospect",
"fieldtype": "Link",
"label": "Prospect",
"no_copy": 1,
"options": "Prospect",
"print_hide": 1
},
{
"fieldname": "opportunity_name",
"fieldtype": "Link",
Expand All @@ -518,8 +510,14 @@
"idx": 363,
"image_field": "image",
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-08-25 18:56:09.929905",
"links": [
{
"group": "Allowed Items",
"link_doctype": "Party Specific Item",
"link_fieldname": "party"
}
],
"modified": "2021-09-06 17:38:54.196663",
"modified_by": "Administrator",
"module": "Selling",
"name": "Customer",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt

frappe.ui.form.on('Supplier Item Group', {
frappe.ui.form.on('Party Specific Item', {
// refresh: function(frm) {

// }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
"actions": [],
"creation": "2021-08-27 19:28:07.559978",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"party_type",
"party",
"column_break_3",
"restrict_based_on",
"based_on_value"
],
"fields": [
{
"fieldname": "party_type",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Party Type",
"options": "Customer\nSupplier",
"reqd": 1
},
{
"fieldname": "party",
"fieldtype": "Dynamic Link",
"in_list_view": 1,
"label": "Party Name",
"options": "party_type",
"reqd": 1
},
{
"fieldname": "restrict_based_on",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Restrict Items Based On",
"options": "Item\nItem Group\nBrand",
"reqd": 1
},
{
"fieldname": "column_break_3",
"fieldtype": "Column Break"
},
{
"fieldname": "based_on_value",
"fieldtype": "Dynamic Link",
"in_list_view": 1,
"label": "Based On Value",
"options": "restrict_based_on",
"reqd": 1
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-09-14 13:27:58.612334",
"modified_by": "Administrator",
"module": "Selling",
"name": "Party Specific Item",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "party",
"track_changes": 1
}
19 changes: 19 additions & 0 deletions erpnext/selling/doctype/party_specific_item/party_specific_item.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt

import frappe
from frappe import _
from frappe.model.document import Document


class PartySpecificItem(Document):
def validate(self):
exists = frappe.db.exists({
'doctype': 'Party Specific Item',
'party_type': self.party_type,
'party': self.party,
'restrict_based_on': self.restrict_based_on,
'based_on': self.based_on_value,
})
if exists:
frappe.throw(_("This item filter has already been applied for the {0}").format(self.party_type))
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt

import unittest

import frappe

from erpnext.controllers.queries import item_query

test_dependencies = ['Item', 'Customer', 'Supplier']

def create_party_specific_item(**args):
psi = frappe.new_doc("Party Specific Item")
psi.party_type = args.get('party_type')
psi.party = args.get('party')
psi.restrict_based_on = args.get('restrict_based_on')
psi.based_on_value = args.get('based_on_value')
psi.insert()

class TestPartySpecificItem(unittest.TestCase):
def setUp(self):
self.customer = frappe.get_last_doc("Customer")
self.supplier = frappe.get_last_doc("Supplier")
self.item = frappe.get_last_doc("Item")

def test_item_query_for_customer(self):
create_party_specific_item(party_type='Customer', party=self.customer.name, restrict_based_on='Item', based_on_value=self.item.name)
filters = {'is_sales_item': 1, 'customer': self.customer.name}
items = item_query(doctype= 'Item', txt= '', searchfield= 'name', start= 0, page_len= 20,filters=filters, as_dict= False)
for item in items:
self.assertEqual(item[0], self.item.name)

def test_item_query_for_supplier(self):
create_party_specific_item(party_type='Supplier', party=self.supplier.name, restrict_based_on='Item Group', based_on_value=self.item.item_group)
filters = {'supplier': self.supplier.name, 'is_purchase_item': 1}
items = item_query(doctype= 'Item', txt= '', searchfield= 'name', start= 0, page_len= 20,filters=filters, as_dict= False)
for item in items:
self.assertEqual(item[2], self.item.item_group)
Loading

0 comments on commit aa82624

Please sign in to comment.