commit
						c027563b13
					
				| @ -61,4 +61,31 @@ frappe.ui.form.on("Pricing Rule", "refresh", function(frm) { | ||||
| 	'</table>'].join("\n"); | ||||
| 
 | ||||
| 	set_field_options("pricing_rule_help", help_content); | ||||
| 
 | ||||
| 	cur_frm.cscript.set_options_for_applicable_for(); | ||||
| }); | ||||
| 
 | ||||
| cur_frm.cscript.set_options_for_applicable_for = function() { | ||||
| 	var options = [""]; | ||||
| 	var applicable_for = cur_frm.doc.applicable_for; | ||||
| 
 | ||||
| 	if(cur_frm.doc.selling) { | ||||
| 		options = $.merge(options, ["Customer", "Customer Group", "Territory", "Sales Partner", "Campaign"]); | ||||
| 	} | ||||
| 	if(cur_frm.doc.buying) { | ||||
| 		$.merge(options, ["Supplier", "Supplier Type"]); | ||||
| 	} | ||||
| 
 | ||||
| 	set_field_options("applicable_for", options.join("\n")); | ||||
| 
 | ||||
| 	if(!in_list(options, applicable_for)) applicable_for = null; | ||||
| 	cur_frm.set_value("applicable_for", applicable_for) | ||||
| } | ||||
| 
 | ||||
| cur_frm.cscript.selling = function() { | ||||
| 	cur_frm.cscript.set_options_for_applicable_for(); | ||||
| } | ||||
| 
 | ||||
| cur_frm.cscript.buying = function() { | ||||
| 	cur_frm.cscript.set_options_for_applicable_for(); | ||||
| } | ||||
|  | ||||
| @ -1,288 +1,299 @@ | ||||
| { | ||||
|  "allow_import": 1, | ||||
|  "autoname": "PRULE.#####", | ||||
|  "creation": "2014-02-21 15:02:51", | ||||
|  "docstatus": 0, | ||||
|  "doctype": "DocType", | ||||
|  "document_type": "Master", | ||||
|  "allow_import": 1,  | ||||
|  "autoname": "PRULE.#####",  | ||||
|  "creation": "2014-02-21 15:02:51",  | ||||
|  "docstatus": 0,  | ||||
|  "doctype": "DocType",  | ||||
|  "document_type": "Master",  | ||||
|  "fields": [ | ||||
|   { | ||||
|    "fieldname": "applicability_section", | ||||
|    "fieldtype": "Section Break", | ||||
|    "in_list_view": 0, | ||||
|    "label": "Applicability", | ||||
|    "fieldname": "applicability_section",  | ||||
|    "fieldtype": "Section Break",  | ||||
|    "in_list_view": 0,  | ||||
|    "label": "Applicability",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "default": "Item Code", | ||||
|    "fieldname": "apply_on", | ||||
|    "fieldtype": "Select", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Apply On", | ||||
|    "options": "\nItem Code\nItem Group\nBrand", | ||||
|    "permlevel": 0, | ||||
|    "default": "Item Code",  | ||||
|    "fieldname": "apply_on",  | ||||
|    "fieldtype": "Select",  | ||||
|    "in_list_view": 1,  | ||||
|    "label": "Apply On",  | ||||
|    "options": "\nItem Code\nItem Group\nBrand",  | ||||
|    "permlevel": 0,  | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "depends_on": "eval:doc.apply_on==\"Item Code\"", | ||||
|    "fieldname": "item_code", | ||||
|    "fieldtype": "Link", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Item Code", | ||||
|    "options": "Item", | ||||
|    "permlevel": 0, | ||||
|    "depends_on": "eval:doc.apply_on==\"Item Code\"",  | ||||
|    "fieldname": "item_code",  | ||||
|    "fieldtype": "Link",  | ||||
|    "in_list_view": 1,  | ||||
|    "label": "Item Code",  | ||||
|    "options": "Item",  | ||||
|    "permlevel": 0,  | ||||
|    "reqd": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "depends_on": "eval:doc.apply_on==\"Item Group\"", | ||||
|    "fieldname": "item_group", | ||||
|    "fieldtype": "Link", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Item Group", | ||||
|    "options": "Item Group", | ||||
|    "depends_on": "eval:doc.apply_on==\"Item Group\"",  | ||||
|    "fieldname": "item_group",  | ||||
|    "fieldtype": "Link",  | ||||
|    "in_list_view": 1,  | ||||
|    "label": "Item Group",  | ||||
|    "options": "Item Group",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "depends_on": "eval:doc.apply_on==\"Brand\"", | ||||
|    "fieldname": "brand", | ||||
|    "fieldtype": "Link", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Brand", | ||||
|    "options": "Brand", | ||||
|    "depends_on": "eval:doc.apply_on==\"Brand\"",  | ||||
|    "fieldname": "brand",  | ||||
|    "fieldtype": "Link",  | ||||
|    "in_list_view": 1,  | ||||
|    "label": "Brand",  | ||||
|    "options": "Brand",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "applicable_for", | ||||
|    "fieldtype": "Select", | ||||
|    "label": "Applicable For", | ||||
|    "options": "\nCustomer\nCustomer Group\nTerritory\nSales Partner\nCampaign\nSupplier\nSupplier Type", | ||||
|    "fieldname": "selling",  | ||||
|    "fieldtype": "Check",  | ||||
|    "label": "Selling",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "depends_on": "eval:doc.applicable_for==\"Customer\"", | ||||
|    "fieldname": "customer", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Customer", | ||||
|    "options": "Customer", | ||||
|    "fieldname": "buying",  | ||||
|    "fieldtype": "Check",  | ||||
|    "label": "Buying",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "depends_on": "eval:doc.applicable_for==\"Customer Group\"", | ||||
|    "fieldname": "customer_group", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Customer Group", | ||||
|    "options": "Customer Group", | ||||
|    "fieldname": "applicable_for",  | ||||
|    "fieldtype": "Select",  | ||||
|    "label": "Applicable For",  | ||||
|    "options": "\nCustomer\nCustomer Group\nTerritory\nSales Partner\nCampaign\nSupplier\nSupplier Type",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "depends_on": "eval:doc.applicable_for==\"Territory\"", | ||||
|    "fieldname": "territory", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Territory", | ||||
|    "options": "Territory", | ||||
|    "depends_on": "eval:doc.applicable_for==\"Customer\"",  | ||||
|    "fieldname": "customer",  | ||||
|    "fieldtype": "Link",  | ||||
|    "label": "Customer",  | ||||
|    "options": "Customer",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "depends_on": "eval:doc.applicable_for==\"Sales Partner\"", | ||||
|    "fieldname": "sales_partner", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Sales Partner", | ||||
|    "options": "Sales Partner", | ||||
|    "depends_on": "eval:doc.applicable_for==\"Customer Group\"",  | ||||
|    "fieldname": "customer_group",  | ||||
|    "fieldtype": "Link",  | ||||
|    "label": "Customer Group",  | ||||
|    "options": "Customer Group",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "depends_on": "eval:doc.applicable_for==\"Campaign\"", | ||||
|    "fieldname": "campaign", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Campaign", | ||||
|    "options": "Campaign", | ||||
|    "depends_on": "eval:doc.applicable_for==\"Territory\"",  | ||||
|    "fieldname": "territory",  | ||||
|    "fieldtype": "Link",  | ||||
|    "label": "Territory",  | ||||
|    "options": "Territory",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "depends_on": "eval:doc.applicable_for==\"Supplier\"", | ||||
|    "fieldname": "supplier", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Supplier", | ||||
|    "options": "Supplier", | ||||
|    "depends_on": "eval:doc.applicable_for==\"Sales Partner\"",  | ||||
|    "fieldname": "sales_partner",  | ||||
|    "fieldtype": "Link",  | ||||
|    "label": "Sales Partner",  | ||||
|    "options": "Sales Partner",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "depends_on": "eval:doc.applicable_for==\"Supplier Type\"", | ||||
|    "fieldname": "supplier_type", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Supplier Type", | ||||
|    "options": "Supplier Type", | ||||
|    "depends_on": "eval:doc.applicable_for==\"Campaign\"",  | ||||
|    "fieldname": "campaign",  | ||||
|    "fieldtype": "Link",  | ||||
|    "label": "Campaign",  | ||||
|    "options": "Campaign",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "min_qty", | ||||
|    "fieldtype": "Float", | ||||
|    "label": "Min Qty", | ||||
|    "depends_on": "eval:doc.applicable_for==\"Supplier\"",  | ||||
|    "fieldname": "supplier",  | ||||
|    "fieldtype": "Link",  | ||||
|    "label": "Supplier",  | ||||
|    "options": "Supplier",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "max_qty", | ||||
|    "fieldtype": "Float", | ||||
|    "label": "Max Qty", | ||||
|    "depends_on": "eval:doc.applicable_for==\"Supplier Type\"",  | ||||
|    "fieldname": "supplier_type",  | ||||
|    "fieldtype": "Link",  | ||||
|    "label": "Supplier Type",  | ||||
|    "options": "Supplier Type",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "col_break1", | ||||
|    "fieldtype": "Column Break", | ||||
|    "fieldname": "min_qty",  | ||||
|    "fieldtype": "Float",  | ||||
|    "label": "Min Qty",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "company", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Company", | ||||
|    "options": "Company", | ||||
|    "fieldname": "max_qty",  | ||||
|    "fieldtype": "Float",  | ||||
|    "label": "Max Qty",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "default": "Today", | ||||
|    "fieldname": "valid_from", | ||||
|    "fieldtype": "Date", | ||||
|    "label": "Valid From", | ||||
|    "fieldname": "col_break1",  | ||||
|    "fieldtype": "Column Break",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "valid_upto", | ||||
|    "fieldtype": "Date", | ||||
|    "label": "Valid Upto", | ||||
|    "fieldname": "company",  | ||||
|    "fieldtype": "Link",  | ||||
|    "label": "Company",  | ||||
|    "options": "Company",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "priority", | ||||
|    "fieldtype": "Select", | ||||
|    "label": "Priority", | ||||
|    "options": "\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20", | ||||
|    "default": "Today",  | ||||
|    "fieldname": "valid_from",  | ||||
|    "fieldtype": "Date",  | ||||
|    "label": "Valid From",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "disable", | ||||
|    "fieldtype": "Check", | ||||
|    "label": "Disable", | ||||
|    "fieldname": "valid_upto",  | ||||
|    "fieldtype": "Date",  | ||||
|    "label": "Valid Upto",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "price_discount_section", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Price / Discount", | ||||
|    "fieldname": "priority",  | ||||
|    "fieldtype": "Select",  | ||||
|    "label": "Priority",  | ||||
|    "options": "\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "default": "Discount Percentage", | ||||
|    "fieldname": "price_or_discount", | ||||
|    "fieldtype": "Select", | ||||
|    "label": "Price or Discount", | ||||
|    "options": "\nPrice\nDiscount Percentage", | ||||
|    "permlevel": 0, | ||||
|    "fieldname": "disable",  | ||||
|    "fieldtype": "Check",  | ||||
|    "label": "Disable",  | ||||
|    "permlevel": 0 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "price_discount_section",  | ||||
|    "fieldtype": "Section Break",  | ||||
|    "label": "Price / Discount",  | ||||
|    "permlevel": 0 | ||||
|   },  | ||||
|   { | ||||
|    "default": "Discount Percentage",  | ||||
|    "fieldname": "price_or_discount",  | ||||
|    "fieldtype": "Select",  | ||||
|    "label": "Price or Discount",  | ||||
|    "options": "\nPrice\nDiscount Percentage",  | ||||
|    "permlevel": 0,  | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "col_break2", | ||||
|    "fieldtype": "Column Break", | ||||
|    "fieldname": "col_break2",  | ||||
|    "fieldtype": "Column Break",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "depends_on": "eval:doc.price_or_discount==\"Price\"", | ||||
|    "fieldname": "price", | ||||
|    "fieldtype": "Float", | ||||
|    "label": "Price", | ||||
|    "depends_on": "eval:doc.price_or_discount==\"Price\"",  | ||||
|    "fieldname": "price",  | ||||
|    "fieldtype": "Float",  | ||||
|    "label": "Price",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "depends_on": "eval:doc.price_or_discount==\"Discount Percentage\"", | ||||
|    "fieldname": "discount_percentage", | ||||
|    "fieldtype": "Float", | ||||
|    "label": "Discount Percentage", | ||||
|    "depends_on": "eval:doc.price_or_discount==\"Discount Percentage\"",  | ||||
|    "fieldname": "discount_percentage",  | ||||
|    "fieldtype": "Float",  | ||||
|    "label": "Discount Percentage",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "depends_on": "eval:doc.price_or_discount==\"Discount Percentage\"", | ||||
|    "fieldname": "for_price_list", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "For Price List", | ||||
|    "options": "Price List", | ||||
|    "depends_on": "eval:doc.price_or_discount==\"Discount Percentage\"",  | ||||
|    "fieldname": "for_price_list",  | ||||
|    "fieldtype": "Link",  | ||||
|    "label": "For Price List",  | ||||
|    "options": "Price List",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "help_section", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "", | ||||
|    "options": "Simple", | ||||
|    "fieldname": "help_section",  | ||||
|    "fieldtype": "Section Break",  | ||||
|    "label": "",  | ||||
|    "options": "Simple",  | ||||
|    "permlevel": 0 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "pricing_rule_help", | ||||
|    "fieldtype": "HTML", | ||||
|    "label": "Pricing Rule Help", | ||||
|    "fieldname": "pricing_rule_help",  | ||||
|    "fieldtype": "HTML",  | ||||
|    "label": "Pricing Rule Help",  | ||||
|    "permlevel": 0 | ||||
|   } | ||||
|  ], | ||||
|  "icon": "icon-gift", | ||||
|  "idx": 1, | ||||
|  "istable": 0, | ||||
|  "modified": "2014-05-28 15:36:29.403659", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Accounts", | ||||
|  "name": "Pricing Rule", | ||||
|  "owner": "Administrator", | ||||
|  ],  | ||||
|  "icon": "icon-gift",  | ||||
|  "idx": 1,  | ||||
|  "istable": 0,  | ||||
|  "modified": "2014-06-20 19:36:22.502381",  | ||||
|  "modified_by": "Administrator",  | ||||
|  "module": "Accounts",  | ||||
|  "name": "Pricing Rule",  | ||||
|  "owner": "Administrator",  | ||||
|  "permissions": [ | ||||
|   { | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "export": 0, | ||||
|    "import": 0, | ||||
|    "permlevel": 0, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "Accounts Manager", | ||||
|    "create": 1,  | ||||
|    "delete": 1,  | ||||
|    "export": 1,  | ||||
|    "import": 1,  | ||||
|    "permlevel": 0,  | ||||
|    "read": 1,  | ||||
|    "report": 1,  | ||||
|    "role": "Accounts Manager",  | ||||
|    "write": 1 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "export": 0, | ||||
|    "import": 0, | ||||
|    "permlevel": 0, | ||||
|    "print": 0, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "Sales Manager", | ||||
|    "create": 1,  | ||||
|    "delete": 1,  | ||||
|    "export": 0,  | ||||
|    "import": 0,  | ||||
|    "permlevel": 0,  | ||||
|    "print": 0,  | ||||
|    "read": 1,  | ||||
|    "report": 1,  | ||||
|    "role": "Sales Manager",  | ||||
|    "write": 1 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "permlevel": 0, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "Purchase Manager", | ||||
|    "create": 1,  | ||||
|    "delete": 1,  | ||||
|    "permlevel": 0,  | ||||
|    "read": 1,  | ||||
|    "report": 1,  | ||||
|    "role": "Purchase Manager",  | ||||
|    "write": 1 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "permlevel": 0, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "Website Manager", | ||||
|    "create": 1,  | ||||
|    "delete": 1,  | ||||
|    "permlevel": 0,  | ||||
|    "read": 1,  | ||||
|    "report": 1,  | ||||
|    "role": "Website Manager",  | ||||
|    "write": 1 | ||||
|   }, | ||||
|   },  | ||||
|   { | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "export": 1, | ||||
|    "import": 1, | ||||
|    "permlevel": 0, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "set_user_permissions": 1, | ||||
|    "role": "System Manager", | ||||
|    "create": 1,  | ||||
|    "delete": 1,  | ||||
|    "export": 1,  | ||||
|    "import": 1,  | ||||
|    "permlevel": 0,  | ||||
|    "read": 1,  | ||||
|    "report": 1,  | ||||
|    "role": "System Manager",  | ||||
|    "write": 1 | ||||
|   } | ||||
|  ], | ||||
|  "sort_field": "modified", | ||||
|  ],  | ||||
|  "sort_field": "modified",  | ||||
|  "sort_order": "DESC" | ||||
| } | ||||
| } | ||||
| @ -5,16 +5,21 @@ | ||||
| 
 | ||||
| from __future__ import unicode_literals | ||||
| import frappe | ||||
| import json | ||||
| from frappe import throw, _ | ||||
| from frappe.utils import flt | ||||
| from frappe.utils import flt, cint | ||||
| from frappe.model.document import Document | ||||
| 
 | ||||
| class MultiplePricingRuleConflict(frappe.ValidationError): pass | ||||
| 
 | ||||
| class PricingRule(Document): | ||||
| 	def validate(self): | ||||
| 		self.validate_mandatory() | ||||
| 		self.validate_applicable_for_selling_or_buying() | ||||
| 		self.validate_min_max_qty() | ||||
| 		self.cleanup_fields_value() | ||||
| 		self.validate_price_or_discount() | ||||
| 		self.validate_max_discount() | ||||
| 
 | ||||
| 	def validate_mandatory(self): | ||||
| 		for field in ["apply_on", "applicable_for"]: | ||||
| @ -22,6 +27,18 @@ class PricingRule(Document): | ||||
| 			if tocheck and not self.get(tocheck): | ||||
| 				throw(_("{0} is required").format(self.meta.get_label(tocheck)), frappe.MandatoryError) | ||||
| 
 | ||||
| 	def validate_applicable_for_selling_or_buying(self): | ||||
| 		if not self.selling and not self.buying: | ||||
| 			throw(_("Atleast one of the Selling or Buying must be selected")) | ||||
| 
 | ||||
| 		if not self.selling and self.applicable_for in ["Customer", "Customer Group", | ||||
| 				"Territory", "Sales Partner", "Campaign"]: | ||||
| 			throw(_("Selling must be checked, if Applicable For is selected as {0}" | ||||
| 				.format(self.applicable_for))) | ||||
| 
 | ||||
| 		if not self.buying and self.applicable_for in ["Supplier", "Supplier Type"]: | ||||
| 			throw(_("Buying must be checked, if Applicable For is selected as {0}" | ||||
| 				.format(self.applicable_for))) | ||||
| 
 | ||||
| 	def validate_min_max_qty(self): | ||||
| 		if self.min_qty and self.max_qty and flt(self.min_qty) > flt(self.max_qty): | ||||
| @ -44,3 +61,189 @@ class PricingRule(Document): | ||||
| 		for field in ["Price", "Discount Percentage"]: | ||||
| 			if flt(self.get(frappe.scrub(field))) < 0: | ||||
| 				throw(_("{0} can not be negative").format(field)) | ||||
| 
 | ||||
| 	def validate_max_discount(self): | ||||
| 		if self.price_or_discount == "Discount Percentage" and self.item_code: | ||||
| 			max_discount = frappe.db.get_value("Item", self.item_code, "max_discount") | ||||
| 			if max_discount and flt(self.discount_percentage) > flt(max_discount): | ||||
| 				throw(_("Max discount allowed for item: {0} is {1}%").format(self.item_code, max_discount)) | ||||
| 
 | ||||
| 
 | ||||
| #-------------------------------------------------------------------------------- | ||||
| 
 | ||||
| @frappe.whitelist() | ||||
| def apply_pricing_rule(args): | ||||
| 	""" | ||||
| 		args = { | ||||
| 			"item_list": [{"doctype": "", "name": "", "item_code": "", "brand": "", "item_group": ""}, ...], | ||||
| 			"customer": "something", | ||||
| 			"customer_group": "something", | ||||
| 			"territory": "something", | ||||
| 			"supplier": "something", | ||||
| 			"supplier_type": "something", | ||||
| 			"currency": "something", | ||||
| 			"conversion_rate": "something", | ||||
| 			"price_list": "something", | ||||
| 			"plc_conversion_rate": "something", | ||||
| 			"company": "something", | ||||
| 			"transaction_date": "something", | ||||
| 			"campaign": "something", | ||||
| 			"sales_partner": "something", | ||||
| 			"ignore_pricing_rule": "something" | ||||
| 		} | ||||
| 	""" | ||||
| 	if isinstance(args, basestring): | ||||
| 		args = json.loads(args) | ||||
| 
 | ||||
| 	args = frappe._dict(args) | ||||
| 
 | ||||
| 	# list of dictionaries | ||||
| 	out = [] | ||||
| 
 | ||||
| 	if args.get("parenttype") == "Material Request": return out | ||||
| 
 | ||||
| 	if not args.transaction_type: | ||||
| 		args.transaction_type = "buying" if frappe.get_meta(args.parenttype).get_field("supplier") \ | ||||
| 			else "selling" | ||||
| 
 | ||||
| 	for item in args.get("item_list"): | ||||
| 		args_copy = args.copy() | ||||
| 		args_copy.update(item) | ||||
| 		out.append(get_pricing_rule_for_item(args_copy)) | ||||
| 
 | ||||
| 	return out | ||||
| 
 | ||||
| def get_pricing_rule_for_item(args): | ||||
| 	if args.get("parenttype") == "Material Request": return {} | ||||
| 
 | ||||
| 	item_details = frappe._dict({ | ||||
| 		"doctype": args.doctype, | ||||
| 		"name": args.name, | ||||
| 		"pricing_rule": None | ||||
| 	}) | ||||
| 
 | ||||
| 	if args.ignore_pricing_rule or not args.item_code: | ||||
| 		return item_details | ||||
| 
 | ||||
| 	if not (args.item_group and args.brand): | ||||
| 		args.item_group, args.brand = frappe.db.get_value("Item", args.item_code, ["item_group", "brand"]) | ||||
| 
 | ||||
| 	if args.customer and not (args.customer_group and args.territory): | ||||
| 		args.customer_group, args.territory = frappe.db.get_value("Customer", args.customer, | ||||
| 			["customer_group", "territory"]) | ||||
| 	elif args.supplier and not args.supplier_type: | ||||
| 		args.supplier_type = frappe.db.get_value("Supplier", args.supplier, "supplier_type") | ||||
| 
 | ||||
| 	pricing_rules = get_pricing_rules(args) | ||||
| 	pricing_rule = filter_pricing_rules(args, pricing_rules) | ||||
| 
 | ||||
| 	if pricing_rule: | ||||
| 		item_details.pricing_rule = pricing_rule.name | ||||
| 		if pricing_rule.price_or_discount == "Price": | ||||
| 			item_details.update({ | ||||
| 				"price_list_rate": pricing_rule.price/flt(args.conversion_rate) \ | ||||
| 					if args.conversion_rate else 0.0, | ||||
| 				"discount_percentage": 0.0 | ||||
| 			}) | ||||
| 		else: | ||||
| 			item_details.discount_percentage = pricing_rule.discount_percentage | ||||
| 
 | ||||
| 	return item_details | ||||
| 
 | ||||
| def get_pricing_rules(args): | ||||
| 	def _get_tree_conditions(parenttype, allow_blank=True): | ||||
| 		field = frappe.scrub(parenttype) | ||||
| 		condition = "" | ||||
| 		if args.get(field): | ||||
| 			lft, rgt = frappe.db.get_value(parenttype, args[field], ["lft", "rgt"]) | ||||
| 			parent_groups = frappe.db.sql_list("""select name from `tab%s` | ||||
| 				where lft<=%s and rgt>=%s""" % (parenttype, '%s', '%s'), (lft, rgt)) | ||||
| 
 | ||||
| 			if parent_groups: | ||||
| 				if allow_blank: parent_groups.append('') | ||||
| 				condition = " ifnull("+field+", '') in ('" + "', '".join(parent_groups)+"')" | ||||
| 
 | ||||
| 		return condition | ||||
| 
 | ||||
| 
 | ||||
| 	conditions = "" | ||||
| 	for field in ["company", "customer", "supplier", "supplier_type", "campaign", "sales_partner"]: | ||||
| 		if args.get(field): | ||||
| 			conditions += " and ifnull("+field+", '') in (%("+field+")s, '')" | ||||
| 		else: | ||||
| 			conditions += " and ifnull("+field+", '') = ''" | ||||
| 
 | ||||
| 	for parenttype in ["Customer Group", "Territory"]: | ||||
| 		group_condition = _get_tree_conditions(parenttype) | ||||
| 		if group_condition: | ||||
| 			conditions += " and " + group_condition | ||||
| 
 | ||||
| 	conditions += " and ifnull(for_price_list, '') in (%(price_list)s, '')" | ||||
| 
 | ||||
| 	if args.get("transaction_date"): | ||||
| 		conditions += """ and %(transaction_date)s between ifnull(valid_from, '2000-01-01') | ||||
| 			and ifnull(valid_upto, '2500-12-31')""" | ||||
| 
 | ||||
| 	return frappe.db.sql("""select * from `tabPricing Rule` | ||||
| 		where (item_code=%(item_code)s or {item_group_condition} or brand=%(brand)s) | ||||
| 			and docstatus < 2 and ifnull(disable, 0) = 0 | ||||
| 			and ifnull({transaction_type}, 0) = 1 {conditions} | ||||
| 		order by priority desc, name desc""".format( | ||||
| 			item_group_condition=_get_tree_conditions("Item Group", False), | ||||
| 			transaction_type=args.transaction_type, conditions=conditions), args, as_dict=1) | ||||
| 
 | ||||
| def filter_pricing_rules(args, pricing_rules): | ||||
| 	# filter for qty | ||||
| 	if pricing_rules and args.get("qty"): | ||||
| 		pricing_rules = filter(lambda x: (args.qty>=flt(x.min_qty) | ||||
| 			and (args.qty<=x.max_qty if x.max_qty else True)), pricing_rules) | ||||
| 
 | ||||
| 	# find pricing rule with highest priority | ||||
| 	if pricing_rules: | ||||
| 		max_priority = max([cint(p.priority) for p in pricing_rules]) | ||||
| 		if max_priority: | ||||
| 			pricing_rules = filter(lambda x: cint(x.priority)==max_priority, pricing_rules) | ||||
| 
 | ||||
| 	# apply internal priority | ||||
| 	all_fields = ["item_code", "item_group", "brand", "customer", "customer_group", "territory", | ||||
| 		"supplier", "supplier_type", "campaign", "sales_partner"] | ||||
| 
 | ||||
| 	if len(pricing_rules) > 1: | ||||
| 		for field_set in [["item_code", "item_group", "brand"], | ||||
| 			["customer", "customer_group", "territory"], ["supplier", "supplier_type"]]: | ||||
| 				remaining_fields = list(set(all_fields) - set(field_set)) | ||||
| 				if if_all_rules_same(pricing_rules, remaining_fields): | ||||
| 					pricing_rules = apply_internal_priority(pricing_rules, field_set, args) | ||||
| 					break | ||||
| 
 | ||||
| 	if len(pricing_rules) > 1: | ||||
| 		price_or_discount = list(set([d.price_or_discount for d in pricing_rules])) | ||||
| 		if len(price_or_discount) == 1 and price_or_discount[0] == "Discount Percentage": | ||||
| 			pricing_rules = filter(lambda x: x.for_price_list==args.price_list, pricing_rules) \ | ||||
| 				or pricing_rules | ||||
| 
 | ||||
| 	if len(pricing_rules) > 1: | ||||
| 		frappe.throw(_("Multiple Price Rule exists with same criteria, please resolve \ | ||||
| 			conflict by assigning priority. Price Rules: {0}") | ||||
| 			.format("\n".join([d.name for d in pricing_rules])), MultiplePricingRuleConflict) | ||||
| 	elif pricing_rules: | ||||
| 		return pricing_rules[0] | ||||
| 
 | ||||
| def if_all_rules_same(pricing_rules, fields): | ||||
| 	all_rules_same = True | ||||
| 	val = [pricing_rules[0][k] for k in fields] | ||||
| 	for p in pricing_rules[1:]: | ||||
| 		if val != [p[k] for k in fields]: | ||||
| 			all_rules_same = False | ||||
| 			break | ||||
| 
 | ||||
| 	return all_rules_same | ||||
| 
 | ||||
| def apply_internal_priority(pricing_rules, field_set, args): | ||||
| 	filtered_rules = [] | ||||
| 	for field in field_set: | ||||
| 		if args.get(field): | ||||
| 			filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules) | ||||
| 			if filtered_rules: break | ||||
| 
 | ||||
| 	return filtered_rules or pricing_rules | ||||
|  | ||||
| @ -17,6 +17,7 @@ class TestPricingRule(unittest.TestCase): | ||||
| 			"doctype": "Pricing Rule", | ||||
| 			"apply_on": "Item Code", | ||||
| 			"item_code": "_Test Item", | ||||
| 			"selling": 1, | ||||
| 			"price_or_discount": "Discount Percentage", | ||||
| 			"price": 0, | ||||
| 			"discount_percentage": 10, | ||||
| @ -29,13 +30,15 @@ class TestPricingRule(unittest.TestCase): | ||||
| 			"company": "_Test Company", | ||||
| 			"price_list": "_Test Price List", | ||||
| 			"currency": "_Test Currency", | ||||
| 			"doctype": "Sales Order", | ||||
| 			"parenttype": "Sales Order", | ||||
| 			"conversion_rate": 1, | ||||
| 			"price_list_currency": "_Test Currency", | ||||
| 			"plc_conversion_rate": 1, | ||||
| 			"order_type": "Sales", | ||||
| 			"transaction_type": "selling", | ||||
| 			"customer": "_Test Customer", | ||||
| 			"doctype": "Sales Order Item", | ||||
| 			"name": None | ||||
| 		}) | ||||
| 		details = get_item_details(args) | ||||
| 		self.assertEquals(details.get("discount_percentage"), 10) | ||||
| @ -71,7 +74,7 @@ class TestPricingRule(unittest.TestCase): | ||||
| 		self.assertEquals(details.get("discount_percentage"), 5) | ||||
| 
 | ||||
| 		frappe.db.sql("update `tabPricing Rule` set priority=NULL where campaign='_Test Campaign'") | ||||
| 		from erpnext.stock.get_item_details import MultiplePricingRuleConflict | ||||
| 		from erpnext.accounts.doctype.pricing_rule.pricing_rule	import MultiplePricingRuleConflict | ||||
| 		self.assertRaises(MultiplePricingRuleConflict, get_item_details, args) | ||||
| 
 | ||||
| 		args.item_code = "_Test Item 2" | ||||
|  | ||||
| @ -231,6 +231,14 @@ | ||||
|    "print_hide": 1,  | ||||
|    "read_only": 0 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "ignore_pricing_rule",  | ||||
|    "fieldtype": "Check",  | ||||
|    "label": "Ignore Pricing Rule",  | ||||
|    "no_copy": 1,  | ||||
|    "permlevel": 1,  | ||||
|    "print_hide": 1 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "items",  | ||||
|    "fieldtype": "Section Break",  | ||||
| @ -744,7 +752,7 @@ | ||||
|  "icon": "icon-file-text",  | ||||
|  "idx": 1,  | ||||
|  "is_submittable": 1,  | ||||
|  "modified": "2014-06-04 08:45:25.582170",  | ||||
|  "modified": "2014-06-19 15:50:50.898237",  | ||||
|  "modified_by": "Administrator",  | ||||
|  "module": "Accounts",  | ||||
|  "name": "Purchase Invoice",  | ||||
| @ -823,6 +831,12 @@ | ||||
|    "role": "Auditor",  | ||||
|    "submit": 0,  | ||||
|    "write": 0 | ||||
|   },  | ||||
|   { | ||||
|    "permlevel": 1,  | ||||
|    "read": 1,  | ||||
|    "role": "Accounts Manager",  | ||||
|    "write": 1 | ||||
|   } | ||||
|  ],  | ||||
|  "read_only_onload": 1,  | ||||
|  | ||||
| @ -241,6 +241,14 @@ | ||||
|    "read_only": 0,  | ||||
|    "reqd": 1 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "ignore_pricing_rule",  | ||||
|    "fieldtype": "Check",  | ||||
|    "label": "Ignore Pricing Rule",  | ||||
|    "no_copy": 1,  | ||||
|    "permlevel": 1,  | ||||
|    "print_hide": 1 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "items",  | ||||
|    "fieldtype": "Section Break",  | ||||
| @ -1180,7 +1188,7 @@ | ||||
|  "icon": "icon-file-text",  | ||||
|  "idx": 1,  | ||||
|  "is_submittable": 1,  | ||||
|  "modified": "2014-05-27 03:49:17.806077",  | ||||
|  "modified": "2014-06-19 16:01:19.720382",  | ||||
|  "modified_by": "Administrator",  | ||||
|  "module": "Accounts",  | ||||
|  "name": "Sales Invoice",  | ||||
| @ -1225,6 +1233,12 @@ | ||||
|    "read": 1,  | ||||
|    "report": 1,  | ||||
|    "role": "Customer" | ||||
|   },  | ||||
|   { | ||||
|    "permlevel": 1,  | ||||
|    "read": 1,  | ||||
|    "role": "Accounts Manager",  | ||||
|    "write": 1 | ||||
|   } | ||||
|  ],  | ||||
|  "read_only_onload": 1,  | ||||
|  | ||||
| @ -197,6 +197,14 @@ | ||||
|    "permlevel": 0,  | ||||
|    "print_hide": 1 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "ignore_pricing_rule",  | ||||
|    "fieldtype": "Check",  | ||||
|    "label": "Ignore Pricing Rule",  | ||||
|    "no_copy": 1,  | ||||
|    "permlevel": 1,  | ||||
|    "print_hide": 1 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "items",  | ||||
|    "fieldtype": "Section Break",  | ||||
| @ -636,7 +644,7 @@ | ||||
|  "icon": "icon-file-text",  | ||||
|  "idx": 1,  | ||||
|  "is_submittable": 1,  | ||||
|  "modified": "2014-05-27 03:49:15.948363",  | ||||
|  "modified": "2014-06-19 15:58:06.375217",  | ||||
|  "modified_by": "Administrator",  | ||||
|  "module": "Buying",  | ||||
|  "name": "Purchase Order",  | ||||
| @ -696,6 +704,12 @@ | ||||
|    "read": 1,  | ||||
|    "report": 1,  | ||||
|    "role": "Supplier" | ||||
|   },  | ||||
|   { | ||||
|    "permlevel": 1,  | ||||
|    "read": 1,  | ||||
|    "role": "Purchase Manager",  | ||||
|    "write": 1 | ||||
|   } | ||||
|  ],  | ||||
|  "read_only_onload": 1,  | ||||
|  | ||||
| @ -187,12 +187,13 @@ class PurchaseOrder(BuyingController): | ||||
| 	def on_update(self): | ||||
| 		pass | ||||
| 
 | ||||
| def set_missing_values(source, target): | ||||
| 	target.ignore_pricing_rule = 1 | ||||
| 	target.run_method("set_missing_values") | ||||
| 	target.run_method("calculate_taxes_and_totals") | ||||
| 
 | ||||
| @frappe.whitelist() | ||||
| def make_purchase_receipt(source_name, target_doc=None): | ||||
| 	def set_missing_values(source, target): | ||||
| 		target.run_method("set_missing_values") | ||||
| 		target.run_method("calculate_taxes_and_totals") | ||||
| 
 | ||||
| 	def update_item(obj, target, source_parent): | ||||
| 		target.qty = flt(obj.qty) - flt(obj.received_qty) | ||||
| 		target.stock_qty = (flt(obj.qty) - flt(obj.received_qty)) * flt(obj.conversion_factor) | ||||
| @ -226,10 +227,6 @@ def make_purchase_receipt(source_name, target_doc=None): | ||||
| 
 | ||||
| @frappe.whitelist() | ||||
| def make_purchase_invoice(source_name, target_doc=None): | ||||
| 	def set_missing_values(source, target): | ||||
| 		target.run_method("set_missing_values") | ||||
| 		target.run_method("calculate_taxes_and_totals") | ||||
| 
 | ||||
| 	def update_item(obj, target, source_parent): | ||||
| 		target.amount = flt(obj.amount) - flt(obj.billed_amt) | ||||
| 		target.base_amount = target.amount * flt(source_parent.conversion_rate) | ||||
|  | ||||
| @ -196,6 +196,14 @@ | ||||
|    "permlevel": 0,  | ||||
|    "print_hide": 1 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "ignore_pricing_rule",  | ||||
|    "fieldtype": "Check",  | ||||
|    "label": "Ignore Pricing Rule",  | ||||
|    "no_copy": 1,  | ||||
|    "permlevel": 1,  | ||||
|    "print_hide": 1 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "items",  | ||||
|    "fieldtype": "Section Break",  | ||||
| @ -562,7 +570,7 @@ | ||||
|  "icon": "icon-shopping-cart",  | ||||
|  "idx": 1,  | ||||
|  "is_submittable": 1,  | ||||
|  "modified": "2014-05-27 03:49:20.226683",  | ||||
|  "modified": "2014-06-19 15:54:27.919675",  | ||||
|  "modified_by": "Administrator",  | ||||
|  "module": "Buying",  | ||||
|  "name": "Supplier Quotation",  | ||||
| @ -640,6 +648,12 @@ | ||||
|    "role": "Supplier",  | ||||
|    "submit": 0,  | ||||
|    "write": 0 | ||||
|   },  | ||||
|   { | ||||
|    "permlevel": 1,  | ||||
|    "read": 1,  | ||||
|    "role": "Purchase Manager",  | ||||
|    "write": 1 | ||||
|   } | ||||
|  ],  | ||||
|  "read_only_onload": 1,  | ||||
|  | ||||
| @ -54,6 +54,7 @@ class SupplierQuotation(BuyingController): | ||||
| @frappe.whitelist() | ||||
| def make_purchase_order(source_name, target_doc=None): | ||||
| 	def set_missing_values(source, target): | ||||
| 		target.ignore_pricing_rule = 1 | ||||
| 		target.run_method("set_missing_values") | ||||
| 		target.run_method("get_schedule_dates") | ||||
| 		target.run_method("calculate_taxes_and_totals") | ||||
|  | ||||
| @ -89,14 +89,14 @@ class AccountsController(TransactionBase): | ||||
| 		"""set missing item values""" | ||||
| 		from erpnext.stock.get_item_details import get_item_details | ||||
| 		if hasattr(self, "fname"): | ||||
| 			parent_dict = {"doctype": self.doctype} | ||||
| 			parent_dict = {} | ||||
| 			for fieldname in self.meta.get_valid_columns(): | ||||
| 				parent_dict[fieldname] = self.get(fieldname) | ||||
| 
 | ||||
| 			for item in self.get(self.fname): | ||||
| 				if item.get("item_code"): | ||||
| 					args = item.as_dict() | ||||
| 					args.update(parent_dict) | ||||
| 					args = parent_dict.copy() | ||||
| 					args.update(item.as_dict()) | ||||
| 					ret = get_item_details(args) | ||||
| 
 | ||||
| 					for fieldname, value in ret.items(): | ||||
|  | ||||
| @ -62,3 +62,4 @@ erpnext.patches.v4_0.update_other_charges_in_custom_purchase_print_formats | ||||
| erpnext.patches.v4_0.create_price_list_if_missing | ||||
| execute:frappe.db.sql("update `tabItem` set end_of_life=null where end_of_life='0000-00-00'") #2014-06-16 | ||||
| erpnext.patches.v4_0.update_users_report_view_settings | ||||
| erpnext.patches.v4_0.set_pricing_rule_for_buying_or_selling | ||||
|  | ||||
| @ -0,0 +1,13 @@ | ||||
| # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | ||||
| # License: GNU General Public License v3. See license.txt | ||||
| 
 | ||||
| from __future__ import unicode_literals | ||||
| import frappe | ||||
| 
 | ||||
| def execute(): | ||||
| 	frappe.reload_doc("accounts", "doctype", "pricing_rule") | ||||
| 	frappe.db.sql("""update `tabPricing Rule` set selling=1 where ifnull(applicable_for, '') in | ||||
| 		('', 'Customer', 'Customer Group', 'Territory', 'Sales Partner', 'Campaign')""") | ||||
| 
 | ||||
| 	frappe.db.sql("""update `tabPricing Rule` set buying=1 where ifnull(applicable_for, '') in | ||||
| 		('', 'Supplier', 'Supplier Type')""") | ||||
| @ -116,8 +116,8 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ | ||||
| 							barcode: item.barcode, | ||||
| 							serial_no: item.serial_no, | ||||
| 							warehouse: item.warehouse, | ||||
| 							doctype: me.frm.doc.doctype, | ||||
| 							docname: me.frm.doc.name, | ||||
| 							parenttype: me.frm.doc.doctype, | ||||
| 							parent: me.frm.doc.name, | ||||
| 							customer: me.frm.doc.customer, | ||||
| 							supplier: me.frm.doc.supplier, | ||||
| 							currency: me.frm.doc.currency, | ||||
| @ -130,7 +130,10 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ | ||||
| 							order_type: me.frm.doc.order_type, | ||||
| 							is_pos: cint(me.frm.doc.is_pos), | ||||
| 							is_subcontracted: me.frm.doc.is_subcontracted, | ||||
| 							transaction_date: me.frm.doc.transaction_date | ||||
| 							transaction_date: me.frm.doc.transaction_date, | ||||
| 							ignore_pricing_rule: me.frm.doc.ignore_pricing_rule, | ||||
| 							doctype: item.doctype, | ||||
| 							name: item.name | ||||
| 						} | ||||
| 					}, | ||||
| 					callback: function(r) { | ||||
| @ -196,7 +199,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ | ||||
| 			} | ||||
| 
 | ||||
| 			this.frm.script_manager.trigger("currency"); | ||||
| 			this.apply_pricing_rule() | ||||
| 			this.apply_pricing_rule(); | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| @ -229,7 +232,12 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ | ||||
| 				this.frm.set_value("plc_conversion_rate", this.frm.doc.conversion_rate); | ||||
| 		} | ||||
| 		if(flt(this.frm.doc.conversion_rate)>0.0) { | ||||
| 			this.apply_pricing_rule(); | ||||
| 			if(this.frm.doc.ignore_pricing_rule) { | ||||
| 				this.calculate_taxes_and_totals(); | ||||
| 			} else { | ||||
| 				this.apply_pricing_rule(); | ||||
| 			} | ||||
| 
 | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| @ -283,12 +291,11 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ | ||||
| 		} | ||||
| 		if(this.frm.doc.price_list_currency === this.frm.doc.currency) { | ||||
| 			this.frm.set_value("conversion_rate", this.frm.doc.plc_conversion_rate); | ||||
| 			this.apply_pricing_rule(); | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	qty: function(doc, cdt, cdn) { | ||||
| 		this.apply_pricing_rule(frappe.get_doc(cdt, cdn)); | ||||
| 		this.apply_pricing_rule(frappe.get_doc(cdt, cdn), true); | ||||
| 	}, | ||||
| 
 | ||||
| 	// tax rate
 | ||||
| @ -331,51 +338,71 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ | ||||
| 		this.calculate_taxes_and_totals(); | ||||
| 	}, | ||||
| 
 | ||||
| 	apply_pricing_rule: function(item) { | ||||
| 	ignore_pricing_rule: function() { | ||||
| 		this.apply_pricing_rule(); | ||||
| 	}, | ||||
| 
 | ||||
| 	apply_pricing_rule: function(item, calculate_taxes_and_totals) { | ||||
| 		var me = this; | ||||
| 
 | ||||
| 		var _apply_pricing_rule = function(item) { | ||||
| 			return me.frm.call({ | ||||
| 				method: "erpnext.stock.get_item_details.apply_pricing_rule", | ||||
| 				child: item, | ||||
| 				args: { | ||||
| 					args: { | ||||
| 						item_code: item.item_code, | ||||
| 						item_group: item.item_group, | ||||
| 						brand: item.brand, | ||||
| 						qty: item.qty, | ||||
| 						customer: me.frm.doc.customer, | ||||
| 						customer_group: me.frm.doc.customer_group, | ||||
| 						territory: me.frm.doc.territory, | ||||
| 						supplier: me.frm.doc.supplier, | ||||
| 						supplier_type: me.frm.doc.supplier_type, | ||||
| 						currency: me.frm.doc.currency, | ||||
| 						conversion_rate: me.frm.doc.conversion_rate, | ||||
| 						price_list: me.frm.doc.selling_price_list || | ||||
| 							 me.frm.doc.buying_price_list, | ||||
| 						plc_conversion_rate: me.frm.doc.plc_conversion_rate, | ||||
| 						company: me.frm.doc.company, | ||||
| 						transaction_date: me.frm.doc.transaction_date || me.frm.doc.posting_date, | ||||
| 						campaign: me.frm.doc.campaign, | ||||
| 						sales_partner: me.frm.doc.sales_partner | ||||
| 					} | ||||
| 				}, | ||||
| 				callback: function(r) { | ||||
| 					if(!r.exc) { | ||||
| 						me.frm.script_manager.trigger("price_list_rate", item.doctype, item.name); | ||||
| 					} | ||||
| 		var item_list = this._get_item_list(item); | ||||
| 		var args = { | ||||
| 			"item_list": item_list, | ||||
| 			"customer": me.frm.doc.customer, | ||||
| 			"customer_group": me.frm.doc.customer_group, | ||||
| 			"territory": me.frm.doc.territory, | ||||
| 			"supplier": me.frm.doc.supplier, | ||||
| 			"supplier_type": me.frm.doc.supplier_type, | ||||
| 			"currency": me.frm.doc.currency, | ||||
| 			"conversion_rate": me.frm.doc.conversion_rate, | ||||
| 			"price_list": me.frm.doc.selling_price_list || me.frm.doc.buying_price_list, | ||||
| 			"plc_conversion_rate": me.frm.doc.plc_conversion_rate, | ||||
| 			"company": me.frm.doc.company, | ||||
| 			"transaction_date": me.frm.doc.transaction_date || me.frm.doc.posting_date, | ||||
| 			"campaign": me.frm.doc.campaign, | ||||
| 			"sales_partner": me.frm.doc.sales_partner, | ||||
| 			"ignore_pricing_rule": me.frm.doc.ignore_pricing_rule, | ||||
| 			"parenttype": me.frm.doc.doctype, | ||||
| 			"parent": me.frm.doc.name | ||||
| 		}; | ||||
| 		return this.frm.call({ | ||||
| 			method: "erpnext.accounts.doctype.pricing_rule.pricing_rule.apply_pricing_rule", | ||||
| 			args: {	args: args }, | ||||
| 			callback: function(r) { | ||||
| 				if (!r.exc) { | ||||
| 					$.each(r.message, function(i, d) { | ||||
| 						$.each(d, function(k, v) { | ||||
| 							if (["doctype", "name"].indexOf(k)===-1) { | ||||
| 								frappe.model.set_value(d.doctype, d.name, k, v); | ||||
| 							} | ||||
| 						}); | ||||
| 					}); | ||||
| 					if(calculate_taxes_and_totals) me.calculate_taxes_and_totals(); | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 	}, | ||||
| 
 | ||||
| 	_get_item_list: function(item) { | ||||
| 		var item_list = []; | ||||
| 		var append_item = function(d) { | ||||
| 			item_list.push({ | ||||
| 				"doctype": d.doctype, | ||||
| 				"name": d.name, | ||||
| 				"item_code": d.item_code, | ||||
| 				"item_group": d.item_group, | ||||
| 				"brand": d.brand, | ||||
| 				"qty": d.qty | ||||
| 			}); | ||||
| 		} | ||||
| 		}; | ||||
| 
 | ||||
| 
 | ||||
| 		if(item) { | ||||
| 			_apply_pricing_rule(item); | ||||
| 		if (item) { | ||||
| 			append_item(item); | ||||
| 		} else { | ||||
| 			$.each(this.get_item_doclist(), function(n, item) { | ||||
| 				_apply_pricing_rule(item); | ||||
| 			$.each(this.get_item_doclist(), function(i, d) { | ||||
| 				append_item(d); | ||||
| 			}); | ||||
| 		} | ||||
| 		return item_list; | ||||
| 	}, | ||||
| 
 | ||||
| 	included_in_print_rate: function(doc, cdt, cdn) { | ||||
|  | ||||
| @ -274,6 +274,14 @@ | ||||
|    "read_only": 0,  | ||||
|    "reqd": 1 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "ignore_pricing_rule",  | ||||
|    "fieldtype": "Check",  | ||||
|    "label": "Ignore Pricing Rule",  | ||||
|    "no_copy": 1,  | ||||
|    "permlevel": 1,  | ||||
|    "print_hide": 1 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "items",  | ||||
|    "fieldtype": "Section Break",  | ||||
| @ -818,7 +826,7 @@ | ||||
|  "idx": 1,  | ||||
|  "is_submittable": 1,  | ||||
|  "max_attachments": 1,  | ||||
|  "modified": "2014-05-27 03:49:16.670976",  | ||||
|  "modified": "2014-06-19 15:59:30.019826",  | ||||
|  "modified_by": "Administrator",  | ||||
|  "module": "Selling",  | ||||
|  "name": "Quotation",  | ||||
| @ -896,6 +904,12 @@ | ||||
|    "role": "Maintenance User",  | ||||
|    "submit": 1,  | ||||
|    "write": 1 | ||||
|   },  | ||||
|   { | ||||
|    "permlevel": 1,  | ||||
|    "read": 1,  | ||||
|    "role": "Sales Manager",  | ||||
|    "write": 1 | ||||
|   } | ||||
|  ],  | ||||
|  "read_only_onload": 1,  | ||||
|  | ||||
| @ -102,7 +102,7 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False): | ||||
| 		if customer: | ||||
| 			target.customer = customer.name | ||||
| 			target.customer_name = customer.customer_name | ||||
| 
 | ||||
| 		target.ignore_pricing_rule = 1 | ||||
| 		target.ignore_permissions = ignore_permissions | ||||
| 		target.run_method("set_missing_values") | ||||
| 		target.run_method("calculate_taxes_and_totals") | ||||
|  | ||||
| @ -285,6 +285,14 @@ | ||||
|    "print_hide": 1,  | ||||
|    "reqd": 1 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "ignore_pricing_rule",  | ||||
|    "fieldtype": "Check",  | ||||
|    "label": "Ignore Pricing Rule",  | ||||
|    "no_copy": 1,  | ||||
|    "permlevel": 1,  | ||||
|    "print_hide": 1 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "items",  | ||||
|    "fieldtype": "Section Break",  | ||||
| @ -874,7 +882,7 @@ | ||||
|  "idx": 1,  | ||||
|  "is_submittable": 1,  | ||||
|  "issingle": 0,  | ||||
|  "modified": "2014-05-27 08:39:19.027965",  | ||||
|  "modified": "2014-06-19 16:00:06.626037",  | ||||
|  "modified_by": "Administrator",  | ||||
|  "module": "Selling",  | ||||
|  "name": "Sales Order",  | ||||
| @ -953,6 +961,12 @@ | ||||
|    "read": 1,  | ||||
|    "report": 1,  | ||||
|    "role": "Material User" | ||||
|   },  | ||||
|   { | ||||
|    "permlevel": 1,  | ||||
|    "read": 1,  | ||||
|    "role": "Sales Manager",  | ||||
|    "write": 1 | ||||
|   } | ||||
|  ],  | ||||
|  "read_only_onload": 1,  | ||||
|  | ||||
| @ -245,9 +245,6 @@ class SalesOrder(SellingController): | ||||
| 	def get_portal_page(self): | ||||
| 		return "order" if self.docstatus==1 else None | ||||
| 
 | ||||
| def set_missing_values(source, target): | ||||
| 	target.run_method("set_missing_values") | ||||
| 	target.run_method("calculate_taxes_and_totals") | ||||
| 
 | ||||
| @frappe.whitelist() | ||||
| def make_material_request(source_name, target_doc=None): | ||||
| @ -274,6 +271,11 @@ def make_material_request(source_name, target_doc=None): | ||||
| 
 | ||||
| @frappe.whitelist() | ||||
| def make_delivery_note(source_name, target_doc=None): | ||||
| 	def set_missing_values(source, target): | ||||
| 		target.ignore_pricing_rule = 1 | ||||
| 		target.run_method("set_missing_values") | ||||
| 		target.run_method("calculate_taxes_and_totals") | ||||
| 
 | ||||
| 	def update_item(source, target, source_parent): | ||||
| 		target.base_amount = (flt(source.qty) - flt(source.delivered_qty)) * flt(source.base_rate) | ||||
| 		target.amount = (flt(source.qty) - flt(source.delivered_qty)) * flt(source.rate) | ||||
| @ -312,6 +314,7 @@ def make_delivery_note(source_name, target_doc=None): | ||||
| def make_sales_invoice(source_name, target_doc=None): | ||||
| 	def set_missing_values(source, target): | ||||
| 		target.is_pos = 0 | ||||
| 		target.ignore_pricing_rule = 1 | ||||
| 		target.run_method("set_missing_values") | ||||
| 		target.run_method("calculate_taxes_and_totals") | ||||
| 
 | ||||
|  | ||||
| @ -275,6 +275,14 @@ | ||||
|    "read_only": 0,  | ||||
|    "reqd": 1 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "ignore_pricing_rule",  | ||||
|    "fieldtype": "Check",  | ||||
|    "label": "Ignore Pricing Rule",  | ||||
|    "no_copy": 1,  | ||||
|    "permlevel": 1,  | ||||
|    "print_hide": 1 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "items",  | ||||
|    "fieldtype": "Section Break",  | ||||
| @ -999,7 +1007,7 @@ | ||||
|  "idx": 1,  | ||||
|  "in_create": 0,  | ||||
|  "is_submittable": 1,  | ||||
|  "modified": "2014-05-27 03:49:09.721622",  | ||||
|  "modified": "2014-06-19 16:00:47.326127",  | ||||
|  "modified_by": "Administrator",  | ||||
|  "module": "Stock",  | ||||
|  "name": "Delivery Note",  | ||||
| @ -1073,6 +1081,12 @@ | ||||
|    "read": 1,  | ||||
|    "report": 1,  | ||||
|    "role": "Customer" | ||||
|   },  | ||||
|   { | ||||
|    "permlevel": 1,  | ||||
|    "read": 1,  | ||||
|    "role": "Material Manager",  | ||||
|    "write": 1 | ||||
|   } | ||||
|  ],  | ||||
|  "read_only_onload": 1,  | ||||
|  | ||||
| @ -280,6 +280,7 @@ def make_sales_invoice(source_name, target_doc=None): | ||||
| 
 | ||||
| 	def update_accounts(source, target): | ||||
| 		target.is_pos = 0 | ||||
| 		target.ignore_pricing_rule = 1 | ||||
| 		target.run_method("set_missing_values") | ||||
| 
 | ||||
| 		if len(target.get("entries")) == 0: | ||||
|  | ||||
| @ -17,7 +17,7 @@ class TestItem(unittest.TestCase): | ||||
| 		item.is_stock_item = "Yes" | ||||
| 		item.default_warehouse = None | ||||
| 		self.assertRaises(WarehouseNotSet, item.insert) | ||||
| 		 | ||||
| 
 | ||||
| 	def test_get_item_details(self): | ||||
| 		from erpnext.stock.get_item_details import get_item_details | ||||
| 		to_check = { | ||||
| @ -41,23 +41,23 @@ class TestItem(unittest.TestCase): | ||||
| 			"uom": "_Test UOM", | ||||
| 			"conversion_factor": 1.0, | ||||
| 		} | ||||
| 		 | ||||
| 
 | ||||
| 		make_test_records("Item Price") | ||||
| 				 | ||||
| 
 | ||||
| 		details = get_item_details({ | ||||
| 			"item_code": "_Test Item", | ||||
| 			"company": "_Test Company", | ||||
| 			"price_list": "_Test Price List", | ||||
| 			"currency": "_Test Currency", | ||||
| 			"doctype": "Sales Order", | ||||
| 			"parenttype": "Sales Order", | ||||
| 			"conversion_rate": 1, | ||||
| 			"price_list_currency": "_Test Currency", | ||||
| 			"plc_conversion_rate": 1, | ||||
| 			"order_type": "Sales", | ||||
| 			"transaction_type": "selling" | ||||
| 		}) | ||||
| 		 | ||||
| 
 | ||||
| 		for key, value in to_check.iteritems(): | ||||
| 			self.assertEquals(value, details.get(key)) | ||||
| 
 | ||||
| test_records = frappe.get_test_records('Item') | ||||
| test_records = frappe.get_test_records('Item') | ||||
|  | ||||
| @ -195,6 +195,14 @@ | ||||
|    "permlevel": 0,  | ||||
|    "print_hide": 1 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "ignore_pricing_rule",  | ||||
|    "fieldtype": "Check",  | ||||
|    "label": "Ignore Pricing Rule",  | ||||
|    "no_copy": 1,  | ||||
|    "permlevel": 1,  | ||||
|    "print_hide": 1 | ||||
|   },  | ||||
|   { | ||||
|    "fieldname": "items",  | ||||
|    "fieldtype": "Section Break",  | ||||
| @ -754,7 +762,7 @@ | ||||
|  "icon": "icon-truck",  | ||||
|  "idx": 1,  | ||||
|  "is_submittable": 1,  | ||||
|  "modified": "2014-05-27 03:49:16.302198",  | ||||
|  "modified": "2014-06-19 15:58:37.932064",  | ||||
|  "modified_by": "Administrator",  | ||||
|  "module": "Stock",  | ||||
|  "name": "Purchase Receipt",  | ||||
| @ -821,6 +829,12 @@ | ||||
|    "read": 1,  | ||||
|    "report": 1,  | ||||
|    "role": "Supplier" | ||||
|   },  | ||||
|   { | ||||
|    "permlevel": 1,  | ||||
|    "read": 1,  | ||||
|    "role": "Material Manager",  | ||||
|    "write": 1 | ||||
|   } | ||||
|  ],  | ||||
|  "read_only_onload": 1,  | ||||
|  | ||||
| @ -287,6 +287,7 @@ def make_purchase_invoice(source_name, target_doc=None): | ||||
| 			frappe.throw(_("All items have already been invoiced")) | ||||
| 
 | ||||
| 		doc = frappe.get_doc(target) | ||||
| 		doc.ignore_pricing_rule = 1 | ||||
| 		doc.run_method("set_missing_values") | ||||
| 		doc.run_method("calculate_taxes_and_totals") | ||||
| 
 | ||||
|  | ||||
| @ -6,8 +6,7 @@ import frappe | ||||
| from frappe import _, throw | ||||
| from frappe.utils import flt, cint, add_days | ||||
| import json | ||||
| 
 | ||||
| class MultiplePricingRuleConflict(frappe.ValidationError): pass | ||||
| from erpnext.accounts.doctype.pricing_rule.pricing_rule import get_pricing_rule_for_item | ||||
| 
 | ||||
| @frappe.whitelist() | ||||
| def get_item_details(args): | ||||
| @ -20,14 +19,15 @@ def get_item_details(args): | ||||
| 			"selling_price_list": None, | ||||
| 			"price_list_currency": None, | ||||
| 			"plc_conversion_rate": 1.0, | ||||
| 			"doctype": "", | ||||
| 			"docname": "", | ||||
| 			"parenttype": "", | ||||
| 			"parent": "", | ||||
| 			"supplier": None, | ||||
| 			"transaction_date": None, | ||||
| 			"conversion_rate": 1.0, | ||||
| 			"buying_price_list": None, | ||||
| 			"is_subcontracted": "Yes" / "No", | ||||
| 			"transaction_type": "selling" | ||||
| 			"transaction_type": "selling", | ||||
| 			"ignore_pricing_rule": 0/1 | ||||
| 		} | ||||
| 	""" | ||||
| 
 | ||||
| @ -37,7 +37,8 @@ def get_item_details(args): | ||||
| 	args = frappe._dict(args) | ||||
| 
 | ||||
| 	if not args.get("transaction_type"): | ||||
| 		if args.get("doctype")=="Material Request" or frappe.get_meta(args.get("doctype")).get_field("supplier"): | ||||
| 		if args.get("parenttype")=="Material Request" or \ | ||||
| 				frappe.get_meta(args.get("parenttype")).get_field("supplier"): | ||||
| 			args.transaction_type = "buying" | ||||
| 		else: | ||||
| 			args.transaction_type = "selling" | ||||
| @ -73,9 +74,9 @@ def get_item_details(args): | ||||
| 		if args.get(key) is None: | ||||
| 			args[key] = value | ||||
| 
 | ||||
| 	out.update(apply_pricing_rule(args)) | ||||
| 	out.update(get_pricing_rule_for_item(args)) | ||||
| 
 | ||||
| 	if args.get("doctype") in ("Sales Invoice", "Delivery Note"): | ||||
| 	if args.get("parenttype") in ("Sales Invoice", "Delivery Note"): | ||||
| 		if item_doc.has_serial_no == "Yes" and not args.serial_no: | ||||
| 			out.serial_no = get_serial_nos_by_fifo(args, item_doc) | ||||
| 
 | ||||
| @ -113,7 +114,7 @@ def validate_item_details(args, item): | ||||
| 		elif item.is_sales_item != "Yes": | ||||
| 			throw(_("Item {0} must be a Sales Item").format(item.name)) | ||||
| 
 | ||||
| 	elif args.transaction_type == "buying" and args.doctype != "Material Request": | ||||
| 	elif args.transaction_type == "buying" and args.parenttype != "Material Request": | ||||
| 		# validate if purchase item or subcontracted item | ||||
| 		if item.is_purchase_item != "Yes": | ||||
| 			throw(_("Item {0} must be a Purchase Item").format(item.name)) | ||||
| @ -144,7 +145,7 @@ def get_basic_details(args, item_doc): | ||||
| 		"item_tax_rate": json.dumps(dict(([d.tax_type, d.tax_rate] for d in | ||||
| 			item_doc.get("item_tax")))), | ||||
| 		"uom": item.stock_uom, | ||||
| 		"min_order_qty": flt(item.min_order_qty) if args.doctype == "Material Request" else "", | ||||
| 		"min_order_qty": flt(item.min_order_qty) if args.parenttype == "Material Request" else "", | ||||
| 		"conversion_factor": 1.0, | ||||
| 		"qty": 1.0, | ||||
| 		"price_list_rate": 0.0, | ||||
| @ -162,7 +163,7 @@ def get_basic_details(args, item_doc): | ||||
| 	return out | ||||
| 
 | ||||
| def get_price_list_rate(args, item_doc, out): | ||||
| 	meta = frappe.get_meta(args.doctype) | ||||
| 	meta = frappe.get_meta(args.parenttype) | ||||
| 
 | ||||
| 	if meta.get_field("currency"): | ||||
| 		validate_price_list(args) | ||||
| @ -179,7 +180,7 @@ def get_price_list_rate(args, item_doc, out): | ||||
| 		if not out.price_list_rate and args.transaction_type == "buying": | ||||
| 			from erpnext.stock.doctype.item.item import get_last_purchase_details | ||||
| 			out.update(get_last_purchase_details(item_doc.name, | ||||
| 				args.docname, args.conversion_rate)) | ||||
| 				args.parent, args.conversion_rate)) | ||||
| 
 | ||||
| def validate_price_list(args): | ||||
| 	if args.get("price_list"): | ||||
| @ -248,142 +249,6 @@ def get_pos_settings(company): | ||||
| 
 | ||||
| 	return pos_settings and pos_settings[0] or None | ||||
| 
 | ||||
| @frappe.whitelist() | ||||
| def apply_pricing_rule(args): | ||||
| 	if isinstance(args, basestring): | ||||
| 		args = json.loads(args) | ||||
| 
 | ||||
| 	args = frappe._dict(args) | ||||
| 	out = frappe._dict() | ||||
| 	if args.get("doctype") == "Material Request" or not args.get("item_code"): return out | ||||
| 
 | ||||
| 	if not args.get("item_group") or not args.get("brand"): | ||||
| 		args.item_group, args.brand = frappe.db.get_value("Item", | ||||
| 			args.item_code, ["item_group", "brand"]) | ||||
| 
 | ||||
| 	if args.get("customer") and (not args.get("customer_group") or not args.get("territory")): | ||||
| 		args.customer_group, args.territory = frappe.db.get_value("Customer", | ||||
| 			args.customer, ["customer_group", "territory"]) | ||||
| 
 | ||||
| 	if args.get("supplier") and not args.get("supplier_type"): | ||||
| 		args.supplier_type = frappe.db.get_value("Supplier", args.supplier, "supplier_type") | ||||
| 
 | ||||
| 	pricing_rules = get_pricing_rules(args) | ||||
| 
 | ||||
| 	pricing_rule = filter_pricing_rules(args, pricing_rules) | ||||
| 
 | ||||
| 	if pricing_rule: | ||||
| 		out.pricing_rule = pricing_rule.name | ||||
| 		if pricing_rule.price_or_discount == "Price": | ||||
| 			out.base_price_list_rate = pricing_rule.price | ||||
| 			out.price_list_rate = pricing_rule.price*flt(args.plc_conversion_rate)/flt(args.conversion_rate) | ||||
| 			out.base_rate = out.base_price_list_rate | ||||
| 			out.rate = out.price_list_rate | ||||
| 			out.discount_percentage = 0.0 | ||||
| 		else: | ||||
| 			out.discount_percentage = pricing_rule.discount_percentage | ||||
| 	else: | ||||
| 		out.pricing_rule = None | ||||
| 
 | ||||
| 	return out | ||||
| 
 | ||||
| 
 | ||||
| def get_pricing_rules(args): | ||||
| 	def _get_tree_conditions(doctype, allow_blank=True): | ||||
| 		field = frappe.scrub(doctype) | ||||
| 		condition = "" | ||||
| 		if args.get(field): | ||||
| 			lft, rgt = frappe.db.get_value(doctype, args[field], ["lft", "rgt"]) | ||||
| 			parent_groups = frappe.db.sql_list("""select name from `tab%s` | ||||
| 				where lft<=%s and rgt>=%s""" % (doctype, '%s', '%s'), (lft, rgt)) | ||||
| 
 | ||||
| 			if parent_groups: | ||||
| 				if allow_blank: parent_groups.append('') | ||||
| 				condition = " ifnull("+field+", '') in ('" + "', '".join(parent_groups)+"')" | ||||
| 
 | ||||
| 		return condition | ||||
| 
 | ||||
| 
 | ||||
| 	conditions = "" | ||||
| 	for field in ["company", "customer", "supplier", "supplier_type", "campaign", "sales_partner"]: | ||||
| 			if args.get(field): | ||||
| 				conditions += " and ifnull("+field+", '') in (%("+field+")s, '')" | ||||
| 			else: | ||||
| 				conditions += " and ifnull("+field+", '') = ''" | ||||
| 
 | ||||
| 	for doctype in ["Customer Group", "Territory"]: | ||||
| 		group_condition = _get_tree_conditions(doctype) | ||||
| 		if group_condition: | ||||
| 			conditions += " and " + group_condition | ||||
| 
 | ||||
| 	conditions += " and ifnull(for_price_list, '') in (%(price_list)s, '')" | ||||
| 
 | ||||
| 	if args.get("transaction_date"): | ||||
| 		conditions += """ and %(transaction_date)s between ifnull(valid_from, '2000-01-01') | ||||
| 			and ifnull(valid_upto, '2500-12-31')""" | ||||
| 
 | ||||
| 	return frappe.db.sql("""select * from `tabPricing Rule` | ||||
| 		where (item_code=%(item_code)s or {item_group_condition} or brand=%(brand)s) | ||||
| 			and docstatus < 2 and ifnull(disable, 0) = 0 {conditions} | ||||
| 		order by priority desc, name desc""".format( | ||||
| 			item_group_condition=_get_tree_conditions("Item Group", False), conditions=conditions), | ||||
| 			args, as_dict=1) | ||||
| 
 | ||||
| def filter_pricing_rules(args, pricing_rules): | ||||
| 	# filter for qty | ||||
| 	if pricing_rules and args.get("qty"): | ||||
| 		pricing_rules = filter(lambda x: (args.qty>=flt(x.min_qty) | ||||
| 			and (args.qty<=x.max_qty if x.max_qty else True)), pricing_rules) | ||||
| 
 | ||||
| 	# find pricing rule with highest priority | ||||
| 	if pricing_rules: | ||||
| 		max_priority = max([cint(p.priority) for p in pricing_rules]) | ||||
| 		if max_priority: | ||||
| 			pricing_rules = filter(lambda x: cint(x.priority)==max_priority, pricing_rules) | ||||
| 
 | ||||
| 	# apply internal priority | ||||
| 	all_fields = ["item_code", "item_group", "brand", "customer", "customer_group", "territory", | ||||
| 		"supplier", "supplier_type", "campaign", "sales_partner"] | ||||
| 
 | ||||
| 	if len(pricing_rules) > 1: | ||||
| 		for field_set in [["item_code", "item_group", "brand"], | ||||
| 			["customer", "customer_group", "territory"], ["supplier", "supplier_type"]]: | ||||
| 				remaining_fields = list(set(all_fields) - set(field_set)) | ||||
| 				if if_all_rules_same(pricing_rules, remaining_fields): | ||||
| 					pricing_rules = apply_internal_priority(pricing_rules, field_set, args) | ||||
| 					break | ||||
| 
 | ||||
| 	if len(pricing_rules) > 1: | ||||
| 		price_or_discount = list(set([d.price_or_discount for d in pricing_rules])) | ||||
| 		if len(price_or_discount) == 1 and price_or_discount[0] == "Discount Percentage": | ||||
| 			pricing_rules = filter(lambda x: x.for_price_list==args.price_list, pricing_rules) \ | ||||
| 				or pricing_rules | ||||
| 
 | ||||
| 	if len(pricing_rules) > 1: | ||||
| 		frappe.throw(_("Multiple Price Rule exists with same criteria, please resolve \ | ||||
| 			conflict by assigning priority. Price Rules: {0}") | ||||
| 			.format("\n".join([d.name for d in pricing_rules])), MultiplePricingRuleConflict) | ||||
| 	elif pricing_rules: | ||||
| 		return pricing_rules[0] | ||||
| 
 | ||||
| def if_all_rules_same(pricing_rules, fields): | ||||
| 	all_rules_same = True | ||||
| 	val = [pricing_rules[0][k] for k in fields] | ||||
| 	for p in pricing_rules[1:]: | ||||
| 		if val != [p[k] for k in fields]: | ||||
| 			all_rules_same = False | ||||
| 			break | ||||
| 
 | ||||
| 	return all_rules_same | ||||
| 
 | ||||
| def apply_internal_priority(pricing_rules, field_set, args): | ||||
| 	filtered_rules = [] | ||||
| 	for field in field_set: | ||||
| 		if args.get(field): | ||||
| 			filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules) | ||||
| 			if filtered_rules: break | ||||
| 
 | ||||
| 	return filtered_rules or pricing_rules | ||||
| 
 | ||||
| def get_serial_nos_by_fifo(args, item_doc): | ||||
| 	return "\n".join(frappe.db.sql_list("""select name from `tabSerial No` | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user