Merge pull request #8075 from netchampfaris/asset-image-fix

[fix] asset image in image view
diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py
index f8c9c0a..53421b7 100644
--- a/erpnext/controllers/item_variant.py
+++ b/erpnext/controllers/item_variant.py
@@ -12,19 +12,42 @@
 class ItemTemplateCannotHaveStock(frappe.ValidationError): pass
 
 @frappe.whitelist()
-def get_variant(template, args, variant=None):
-	"""Validates Attributes and their Values, then looks for an exactly matching Item Variant
+def get_variant(template, args=None, variant=None, manufacturer=None,
+	manufacturer_part_no=None):
+	"""Validates Attributes and their Values, then looks for an exactly
+		matching Item Variant
 
 		:param item: Template Item
 		:param args: A dictionary with "Attribute" as key and "Attribute Value" as value
 	"""
-	if isinstance(args, basestring):
-		args = json.loads(args)
+	item_template = frappe.get_doc('Item', template)
 
-	if not args:
-		frappe.throw(_("Please specify at least one attribute in the Attributes table"))
+	if item_template.variant_based_on=='Manufacturer' and manufacturer:
+		return make_variant_based_on_manufacturer(item_template, manufacturer,
+			manufacturer_part_no)
+	else:
+		if isinstance(args, basestring):
+			args = json.loads(args)
 
-	return find_variant(template, args, variant)
+		if not args:
+			frappe.throw(_("Please specify at least one attribute in the Attributes table"))
+		return find_variant(template, args, variant)
+
+def make_variant_based_on_manufacturer(template, manufacturer, manufacturer_part_no):
+	'''Make and return a new variant based on manufacturer and
+		manufacturer part no'''
+	from frappe.model.naming import append_number_if_name_exists
+
+	variant = frappe.new_doc('Item')
+
+	copy_attributes_to_variant(template, variant)
+
+	variant.manufacturer = manufacturer
+	variant.manufacturer_part_no = manufacturer_part_no
+
+	variant.item_code = append_number_if_name_exists('Item', template.name)
+
+	return variant
 
 def validate_item_variant_attributes(item, args=None):
 	if isinstance(item, basestring):
@@ -131,6 +154,7 @@
 
 	template = frappe.get_doc("Item", item)
 	variant = frappe.new_doc("Item")
+	variant.variant_based_on = 'Item Attribute'
 	variant_attributes = []
 
 	for d in template.attributes:
@@ -147,17 +171,28 @@
 
 def copy_attributes_to_variant(item, variant):
 	from frappe.model import no_value_fields
+
+	# copy non no-copy fields
+
+	exclude_fields = ["item_code", "item_name", "show_in_website"]
+
+	if item.variant_based_on=='Manufacturer':
+		# don't copy manufacturer values if based on part no
+		exclude_fields += ['manufacturer', 'manufacturer_part_no']
+
 	for field in item.meta.fields:
 		if field.fieldtype not in no_value_fields and (not field.no_copy)\
-			and field.fieldname not in ("item_code", "item_name", "show_in_website"):
+			and field.fieldname not in exclude_fields:
 			if variant.get(field.fieldname) != item.get(field.fieldname):
 				variant.set(field.fieldname, item.get(field.fieldname))
 	variant.variant_of = item.name
 	variant.has_variants = 0
-	if variant.attributes:
-		variant.description += "\n"
-		for d in variant.attributes:
-			variant.description += "<p>" + d.attribute + ": " + cstr(d.attribute_value) + "</p>"
+
+	if item.variant_based_on=='Item Attribute':
+		if variant.attributes:
+			variant.description += "\n"
+			for d in variant.attributes:
+				variant.description += "<p>" + d.attribute + ": " + cstr(d.attribute_value) + "</p>"
 
 def make_variant_item_code(template_item_code, variant):
 	"""Uses template's item code and abbreviations to make variant's item code"""
diff --git a/erpnext/docs/assets/img/setup/workflow-1.png b/erpnext/docs/assets/img/setup/workflow-1.png
index 632e1fb..7fd6f17 100644
--- a/erpnext/docs/assets/img/setup/workflow-1.png
+++ b/erpnext/docs/assets/img/setup/workflow-1.png
Binary files differ
diff --git a/erpnext/docs/assets/img/setup/workflow-2.png b/erpnext/docs/assets/img/setup/workflow-2.png
index 2041860..1023a39 100644
--- a/erpnext/docs/assets/img/setup/workflow-2.png
+++ b/erpnext/docs/assets/img/setup/workflow-2.png
Binary files differ
diff --git a/erpnext/docs/assets/img/setup/workflow-3.png b/erpnext/docs/assets/img/setup/workflow-3.png
new file mode 100644
index 0000000..fc29c88
--- /dev/null
+++ b/erpnext/docs/assets/img/setup/workflow-3.png
Binary files differ
diff --git a/erpnext/docs/assets/img/setup/workflow-4.png b/erpnext/docs/assets/img/setup/workflow-4.png
new file mode 100644
index 0000000..ee991f9
--- /dev/null
+++ b/erpnext/docs/assets/img/setup/workflow-4.png
Binary files differ
diff --git a/erpnext/docs/assets/img/setup/workflow-5.png b/erpnext/docs/assets/img/setup/workflow-5.png
new file mode 100644
index 0000000..ad360c6
--- /dev/null
+++ b/erpnext/docs/assets/img/setup/workflow-5.png
Binary files differ
diff --git a/erpnext/docs/assets/img/stock/select-mfg-for-variant.png b/erpnext/docs/assets/img/stock/select-mfg-for-variant.png
new file mode 100644
index 0000000..4da1d6c
--- /dev/null
+++ b/erpnext/docs/assets/img/stock/select-mfg-for-variant.png
Binary files differ
diff --git a/erpnext/docs/assets/img/stock/set-variant-by-mfg.png b/erpnext/docs/assets/img/stock/set-variant-by-mfg.png
new file mode 100644
index 0000000..2eaa8f0
--- /dev/null
+++ b/erpnext/docs/assets/img/stock/set-variant-by-mfg.png
Binary files differ
diff --git a/erpnext/docs/user/manual/en/setting-up/workflows.md b/erpnext/docs/user/manual/en/setting-up/workflows.md
index a4ddc38..5593a53 100644
--- a/erpnext/docs/user/manual/en/setting-up/workflows.md
+++ b/erpnext/docs/user/manual/en/setting-up/workflows.md
@@ -4,9 +4,9 @@
 
 Example of a leave application workflow is given below:
 
-If an user applies for a leave, then his request will be sent to the HR
-department. The HR department(HR User) will either reject or approve this
-request. Once this process is completed, the user's Manager(leave approver)
+If a user applies for a leave, then his request will be sent to the HR
+department. The HR department (HR User) will either reject or approve this
+request. Once this process is completed, the user's Manager (leave approver)
 will get an indication that the HR department has Accepted or Rejected. The
 Manager, who is the approving authority, will either Approve or Reject this
 request. Accordingly,the user will get his Approved or Rejected status.
@@ -44,23 +44,17 @@
 
 #### Example of a Leave Application Process:  
 
-Go to the Human Resources Module and click on Leave Application. Apply for a
-Leave.
+When a Leave Application is saved by Employee, the status of the document changes to "Applied"
 
-When a Leave Application is submitted, the status on the right hand corner of
-the page shows as "Applied"
-
-![Workflow Employee LA]({{docs_base_url}}/assets/old_images/erpnext/workflow-employee-la.png)
+![Workflow Employee LA]({{docs_base_url}}/assets/img/setup/workflow-3.png)
 
 When the HR User logs in, he can either Approve or Reject. If approved the
-status on the right hand corner of the page shows as Approved. However, a blue
-band of information is displayed saying approval is pending by leave approver.
+status of the document changes to "Approved by HR". However, it is yet to be approved by Leave Approver.
 
-![Leave Approver]({{docs_base_url}}/assets/old_images/erpnext/workflow-hr-user-la.png)
+![Leave Approver]({{docs_base_url}}/assets/img/setup/workflow-4.png)
 
-When the leave approver opens the Leave Application page, he should select the
-status and convert to Approved or Rejected.
+When the Leave Approver opens the Leave Application page, he can finally "Approve" or "Reject" the Leave Application.
 
-![Workflow Leave Approver]({{docs_base_url}}/assets/old_images/erpnext/workflow-leave-approver-la.png)
+![Workflow Leave Approver]({{docs_base_url}}/assets/img/setup/workflow-5.png)
 
 {next}
diff --git a/erpnext/docs/user/manual/en/stock/item/item-variants.md b/erpnext/docs/user/manual/en/stock/item/item-variants.md
index cdca6ed..7514404 100644
--- a/erpnext/docs/user/manual/en/stock/item/item-variants.md
+++ b/erpnext/docs/user/manual/en/stock/item/item-variants.md
@@ -1,15 +1,28 @@
+# Item Variants
+
+### What are Variants?
+
 A Item Variant is a version of a Item, such as differing sizes or differing colours (like a _blue_ t-shirt in size _small_ rather then just a t-shirt).
-Without Item variants, you would have to treat the _small, medium_ and _large_ versions of a t-shirt as three separate Items; 
+Without Item variants, you would have to treat the _small, medium_ and _large_ versions of a t-shirt as three separate Items;
 Item variants let you treat the _small, medium_ and _large_ versions of a t-shirt as variations of the one Item 't-shirt'.
 
+### Using Variants
+
+Variants can be based on two things
+
+1. Item Attributes
+1. Manufacturers
+
+### Variants Based on Item Attributes
+
 To use Item Variants in ERPNext, create an Item and check 'Has Variants'.
 
-* The Item shall then be referred to as a so called 'Template'. Such a Template is not identical to a regular 'Item' any longer. For example it (the Template) can not be used directly in any Transactions (Sales Order, Delivery Note, Purchase Invoice) itself. Only the Variants of an Item (_blue_ t-shirt in size _small)_ can be practically used in such. Therefore it would be ideal to decide whether an item 'Has Variants' or not directly when creating it. 
+* The Item shall then be referred to as a so called 'Template'. Such a Template is not identical to a regular 'Item' any longer. For example it (the Template) can not be used directly in any Transactions (Sales Order, Delivery Note, Purchase Invoice) itself. Only the Variants of an Item (_blue_ t-shirt in size _small)_ can be practically used in such. Therefore it would be ideal to decide whether an item 'Has Variants' or not directly when creating it.
 
 <img class="screenshot" alt="Has Variants" src="{{docs_base_url}}/assets/img/stock/item-has-variants.png">
 
 On selecting 'Has Variants' a table shall appear. Specify the variant attributes for the Item in the table.
-In case the attribute has Numeric Values, you can specify the range and increment values here. 
+In case the attribute has Numeric Values, you can specify the range and increment values here.
 
 <img class="screenshot" alt="Valid Attributes" src="{{docs_base_url}}/assets/img/stock/item-attributes.png">
 
@@ -22,3 +35,17 @@
 <img class="screenshot" alt="Make Variants" src="{{docs_base_url}}/assets/img/stock/make-variant-1.png">
 
 To learn more about setting Attributes Master check [Item Attributes]({{docs_base_url}}/user/manual/en/stock/setup/item-attribute.html)
+
+### Variants Based on Manufacturers
+
+To setup variants based on Manufactueres, in your Item template, set "Variants Based On" as "Manufacturers"
+
+<img class='screenshot' alt='Setup Item Variant by Manufacturer'
+	src='{{docs_base_url}}/assets/img/stock/select-mfg-for-variant.png'>
+
+When you make a new Variant, the system will prompt you to select a Manufacturer. You can also optionally put in a Manufacturer Part Number
+
+<img class='screenshot' alt='Setup Item Variant by Manufacturer'
+	src='{{docs_base_url}}/assets/img/stock/set-variant-by-mfg.png'>
+
+The naming of the variant will be the name (ID) of the template Item with a number suffix. e.g. "ITEM000" will have variant "ITEM000-1"
\ No newline at end of file
diff --git a/erpnext/hr/doctype/job_opening/job_opening.json b/erpnext/hr/doctype/job_opening/job_opening.json
index 39bc75f..cde97e5 100644
--- a/erpnext/hr/doctype/job_opening/job_opening.json
+++ b/erpnext/hr/doctype/job_opening/job_opening.json
@@ -1,201 +1,228 @@
 {
- "allow_copy": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "field:route",
- "beta": 0,
- "creation": "2013-01-15 16:13:36",
- "custom": 0,
- "description": "Description of a Job Opening",
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Document",
- "editable_grid": 0,
- "engine": "InnoDB",
+ "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "autoname": "field:route", 
+ "beta": 0, 
+ "creation": "2013-01-15 16:13:36", 
+ "custom": 0, 
+ "description": "Description of a Job Opening", 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "Document", 
+ "editable_grid": 0, 
+ "engine": "InnoDB", 
  "fields": [
   {
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
-   "fieldname": "job_title",
-   "fieldtype": "Data",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_list_view": 1,
-   "in_standard_filter": 0,
-   "label": "Job Title",
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 1,
-   "search_index": 0,
-   "set_only_once": 0,
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "job_title", 
+   "fieldtype": "Data", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Job Title", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
    "unique": 0
-  },
+  }, 
   {
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
-   "fieldname": "publish",
-   "fieldtype": "Check",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
-   "label": "Publish on website",
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "publish", 
+   "fieldtype": "Check", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Publish on website", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
    "unique": 0
-  },
+  }, 
   {
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
-   "depends_on": "publish",
-   "fieldname": "route",
-   "fieldtype": "Data",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
-   "label": "Route",
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "depends_on": "publish", 
+   "fieldname": "route", 
+   "fieldtype": "Data", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Route", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
    "unique": 1
-  },
+  }, 
   {
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
-   "fieldname": "status",
-   "fieldtype": "Select",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_list_view": 1,
-   "in_standard_filter": 1,
-   "label": "Status",
-   "length": 0,
-   "no_copy": 0,
-   "options": "Open\nClosed",
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "status", 
+   "fieldtype": "Select", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 1, 
+   "label": "Status", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Open\nClosed", 
+   "permlevel": 0, 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
    "unique": 0
-  },
+  }, 
   {
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
-   "description": "Job profile, qualifications required etc.",
-   "fieldname": "description",
-   "fieldtype": "Text Editor",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_list_view": 1,
-   "in_standard_filter": 0,
-   "label": "Description",
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "description": "Job profile, qualifications required etc.", 
+   "fieldname": "description", 
+   "fieldtype": "Text Editor", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Description", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
    "unique": 0
   }
- ],
- "hide_heading": 0,
- "hide_toolbar": 0,
- "icon": "fa fa-bookmark",
- "idx": 1,
- "image_view": 0,
- "in_create": 0,
- "in_dialog": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2016-12-19 05:54:38.298496",
- "modified_by": "Administrator",
- "module": "HR",
- "name": "Job Opening",
- "owner": "Administrator",
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "icon": "fa fa-bookmark", 
+ "idx": 1, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 0, 
+ "max_attachments": 0, 
+ "modified": "2017-03-22 12:36:26.807200", 
+ "modified_by": "Administrator", 
+ "module": "HR", 
+ "name": "Job Opening", 
+ "owner": "Administrator", 
  "permissions": [
   {
-   "amend": 0,
-   "apply_user_permissions": 0,
-   "cancel": 0,
-   "create": 1,
-   "delete": 1,
-   "email": 1,
-   "export": 0,
-   "if_owner": 0,
-   "import": 0,
-   "is_custom": 0,
-   "permlevel": 0,
-   "print": 1,
-   "read": 1,
-   "report": 1,
-   "role": "HR User",
-   "set_user_permissions": 0,
-   "share": 1,
-   "submit": 0,
+   "amend": 0, 
+   "apply_user_permissions": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 0, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "HR User", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
    "write": 1
+  }, 
+  {
+   "amend": 0, 
+   "apply_user_permissions": 0, 
+   "cancel": 0, 
+   "create": 0, 
+   "delete": 0, 
+   "email": 0, 
+   "export": 0, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 0, 
+   "read": 1, 
+   "report": 0, 
+   "role": "Guest", 
+   "set_user_permissions": 0, 
+   "share": 0, 
+   "submit": 0, 
+   "write": 0
   }
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "sort_order": "ASC",
+ ], 
+ "quick_entry": 0, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "show_name_in_global_search": 0, 
+ "sort_order": "ASC", 
+ "track_changes": 0, 
  "track_seen": 0
 }
\ No newline at end of file
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index b8382ec..c629e87 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -148,10 +148,9 @@
 				})
 
 	def get_date_details(self):
-		if not self.end_date:
-			date_details = get_start_end_dates(self.payroll_frequency, self.start_date or self.posting_date)
-			self.start_date = date_details.start_date
-			self.end_date = date_details.end_date
+		date_details = get_start_end_dates(self.payroll_frequency, self.start_date or self.posting_date)
+		self.start_date = date_details.start_date
+		self.end_date = date_details.end_date
 
 	def check_sal_struct(self, joining_date, relieving_date):
 		cond = ''
diff --git a/erpnext/public/css/erpnext.css b/erpnext/public/css/erpnext.css
index 697c078..a51472f 100644
--- a/erpnext/public/css/erpnext.css
+++ b/erpnext/public/css/erpnext.css
@@ -327,4 +327,3 @@
 body[data-route="pos"] .collapse-btn {
   cursor: pointer;
 }
-
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index 891f37c..f149baf 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -177,11 +177,11 @@
 							fields: [
 								{fieldtype:'Read Only', fieldname:'item_code',
 									label: __('Item Code'), in_list_view:1},
-								{fieldtype:'Link', fieldname:'bom', options: 'BOM',
+								{fieldtype:'Link', fieldname:'bom', options: 'BOM', reqd: 1,
 									label: __('Select BOM'), in_list_view:1, get_query: function(doc) {
 										return {filters: {item: doc.item_code}};
 									}},
-								{fieldtype:'Float', fieldname:'pending_qty',
+								{fieldtype:'Float', fieldname:'pending_qty', reqd: 1,
 									label: __('Qty'), in_list_view:1},
 							],
 							get_data: function() {
diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py
index b427b94..61ec78c 100644
--- a/erpnext/shopping_cart/cart.py
+++ b/erpnext/shopping_cart/cart.py
@@ -31,10 +31,14 @@
 		doc = quotation
 		set_cart_count(quotation)
 
+	addresses = get_address_docs(party=party)
+
 	return {
 		"doc": decorate_quotation_doc(doc),
-		"addresses": [{"name": address.name, "display": address.display}
-			for address in get_address_docs(party=party)],
+		"shipping_addresses": [{"name": address.name, "display": address.display}
+			for address in addresses if address.address_type == "Shipping"],
+		"billing_addresses": [{"name": address.name, "display": address.display}
+			for address in addresses if address.address_type == "Billing"],
 		"shipping_rules": get_applicable_shipping_rules(party)
 	}
 
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 7068c99..8327ea7 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -261,6 +261,44 @@
 	make_variant: function(frm) {
 		var fields = []
 
+		if(frm.doc.variant_based_on==="Item Attribute") {
+			erpnext.item.show_modal_for_item_attribute_selection(frm);
+		} else {
+			erpnext.item.show_modal_for_manufacturers(frm);
+		}
+	},
+
+	show_modal_for_manufacturers: function(frm) {
+		var dialog = new frappe.ui.Dialog({
+			fields: [
+				{fieldtype:'Link', options:'Manufacturer',
+					reqd:1, label:'Manufacturer'},
+				{fieldtype:'Data', label:'Manufacturer Part Number',
+					fieldname: 'manufacturer_part_no'},
+			]
+		});
+
+		dialog.set_primary_action(__('Make'), function() {
+			var data = dialog.get_values();
+			if(!data) return;
+
+			// call the server to make the variant
+			data.template = frm.doc.name;
+			frappe.call({
+				method:"erpnext.controllers.item_variant.get_variant",
+				args: data,
+				callback: function(r) {
+					var doclist = frappe.model.sync(r.message);
+					dialog.hide();
+					frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
+				}
+			});
+		})
+
+		dialog.show();
+	},
+
+	show_modal_for_item_attribute_selection: function(frm) {
 		for(var i=0;i< frm.doc.attributes.length;i++){
 			var fieldtype, desc;
 			var row = frm.doc.attributes[i];
@@ -371,13 +409,42 @@
 				})
 		});
 	},
-	toggle_attributes: function(frm) {
-		frm.toggle_display("attributes", frm.doc.has_variants || frm.doc.variant_of);
-		frm.fields_dict.attributes.grid.toggle_reqd("attribute_value", frm.doc.variant_of ? 1 : 0);
-		frm.fields_dict.attributes.grid.set_column_disp("attribute_value", frm.doc.variant_of ? 1 : 0);
 
-		frm.toggle_enable("attributes", !frm.doc.variant_of);
-		frm.fields_dict.attributes.grid.toggle_enable("attribute", !frm.doc.variant_of);
-		frm.fields_dict.attributes.grid.toggle_enable("attribute_value", !frm.doc.variant_of);
+	toggle_attributes: function(frm) {
+		if((frm.doc.has_variants || frm.doc.variant_of)
+			&& frm.doc.variant_based_on==='Item Attribute') {
+			frm.toggle_display("attributes", true);
+
+			var grid = frm.fields_dict.attributes.grid;
+
+			if(frm.doc.variant_of) {
+				// variant
+
+				// value column is displayed but not editable
+				grid.set_column_disp("attribute_value", true);
+				grid.toggle_enable("attribute_value", false);
+
+				grid.toggle_enable("attribute", false);
+
+				// can't change attributes since they are
+				// saved when the variant was created
+				frm.toggle_enable("attributes", false);
+			} else {
+				// template - values not required!
+
+				// make the grid editable
+				frm.toggle_enable("attributes", true);
+
+				// value column is hidden
+				grid.set_column_disp("attribute_value", false);
+
+				// enable the grid so you can add more attributes
+				grid.toggle_enable("attribute", true);
+			}
+
+		} else {
+			// nothing to do with attributes, hide it
+			frm.toggle_display("attributes", false);
+		}
 	}
 });
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index 4a5094e..db327cc 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
  "allow_import": 1, 
  "allow_rename": 1, 
  "autoname": "field:item_code", 
@@ -1218,7 +1219,39 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "depends_on": "", 
+   "default": "Item Attribute", 
+   "depends_on": "has_variants", 
+   "fieldname": "variant_based_on", 
+   "fieldtype": "Select", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Variant Based On", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Item Attribute\nManufacturer", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "depends_on": "eval:doc.has_variants && doc.variant_based_on==='Item Attribute'", 
    "fieldname": "attributes", 
    "fieldtype": "Table", 
    "hidden": 1, 
@@ -2792,6 +2825,7 @@
    "unique": 0
   }
  ], 
+ "has_web_view": 0, 
  "hide_heading": 0, 
  "hide_toolbar": 0, 
  "icon": "fa fa-tag", 
@@ -2799,12 +2833,11 @@
  "image_field": "image", 
  "image_view": 0, 
  "in_create": 0, 
- "in_dialog": 0, 
  "is_submittable": 0, 
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 1, 
- "modified": "2017-02-20 13:26:45.446617", 
+ "modified": "2017-03-21 21:03:10.715674", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Item", 
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 0f0205b..4d0c3ac 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -643,7 +643,7 @@
 					.format(self.stock_uom, template_uom))
 
 	def validate_attributes(self):
-		if self.has_variants or self.variant_of:
+		if (self.has_variants or self.variant_of) and self.variant_based_on=='Item Attribute':
 			attributes = []
 			if not self.attributes:
 				frappe.throw(_("Attribute table is mandatory"))
@@ -654,7 +654,7 @@
 					attributes.append(d.attribute)
 
 	def validate_variant_attributes(self):
-		if self.variant_of:
+		if self.variant_of and self.variant_based_on=='Item Attribute':
 			args = {}
 			for d in self.attributes:
 				if not d.attribute_value:
@@ -675,7 +675,7 @@
 		from `tabStock Ledger Entry` where item_code=%s
 			and posting_date > date_sub(curdate(), interval 1 year)
 			group by posting_date''', name))
-	
+
 	for date, count in items.iteritems():
 		timestamp = get_timestamp(date)
 		out.update({ timestamp: count })
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index 15a1118..2a8e434 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -7,7 +7,7 @@
 
 from frappe.test_runner import make_test_records
 from erpnext.controllers.item_variant import (create_variant, ItemVariantExistsError,
-	InvalidItemAttributeValueError)
+	InvalidItemAttributeValueError, get_variant)
 
 from frappe.model.rename_doc import rename_doc
 from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
@@ -167,31 +167,66 @@
 		variant.item_name = "_Test Numeric Variant Large 1.1m"
 		self.assertRaises(InvalidItemAttributeValueError, variant.save)
 
-		variant = create_variant("_Test Numeric Template Item", 
+		variant = create_variant("_Test Numeric Template Item",
 			{"Test Size": "Large", "Test Item Length": 1.5})
 		self.assertEquals(variant.item_code, "_Test Numeric Template Item-L-1.5")
 		variant.item_code = "_Test Numeric Variant-L-1.5"
 		variant.item_name = "_Test Numeric Variant Large 1.5m"
 		variant.save()
-		
-	def test_item_merging(self):		
+
+	def test_item_merging(self):
 		create_item("Test Item for Merging 1")
 		create_item("Test Item for Merging 2")
-		
-		make_stock_entry(item_code="Test Item for Merging 1", target="_Test Warehouse - _TC", 
+
+		make_stock_entry(item_code="Test Item for Merging 1", target="_Test Warehouse - _TC",
 			qty=1, rate=100)
-		make_stock_entry(item_code="Test Item for Merging 2", target="_Test Warehouse 1 - _TC", 
+		make_stock_entry(item_code="Test Item for Merging 2", target="_Test Warehouse 1 - _TC",
 			qty=1, rate=100)
-		
+
 		rename_doc("Item", "Test Item for Merging 1", "Test Item for Merging 2", merge=True)
-		
+
 		self.assertFalse(frappe.db.exists("Item", "Test Item for Merging 1"))
-		
-		self.assertTrue(frappe.db.get_value("Bin", 
+
+		self.assertTrue(frappe.db.get_value("Bin",
 			{"item_code": "Test Item for Merging 2", "warehouse": "_Test Warehouse - _TC"}))
-			
-		self.assertTrue(frappe.db.get_value("Bin", 
-			{"item_code": "Test Item for Merging 2", "warehouse": "_Test Warehouse 1 - _TC"}))		
+
+		self.assertTrue(frappe.db.get_value("Bin",
+			{"item_code": "Test Item for Merging 2", "warehouse": "_Test Warehouse 1 - _TC"}))
+
+	def test_item_variant_by_manufacturer(self):
+		if frappe.db.exists('Item', '_Test Variant Mfg'):
+			frappe.delete_doc('Item', '_Test Variant Mfg')
+		if frappe.db.exists('Item', '_Test Variant Mfg-1'):
+			frappe.delete_doc('Item', '_Test Variant Mfg-1')
+		if frappe.db.exists('Manufacturer', 'MSG1'):
+			frappe.delete_doc('Manufacturer', 'MSG1')
+
+		template = frappe.get_doc(dict(
+			doctype='Item',
+			item_code='_Test Variant Mfg',
+			has_variant=1,
+			item_group='Products',
+			variant_based_on='Manufacturer'
+		)).insert()
+
+		manufacturer = frappe.get_doc(dict(
+			doctype='Manufacturer',
+			short_name='MSG1'
+		)).insert()
+
+		variant = get_variant(template.name, manufacturer=manufacturer.name)
+		self.assertEquals(variant.item_code, '_Test Variant Mfg-1')
+		self.assertEquals(variant.description, '_Test Variant Mfg')
+		self.assertEquals(variant.manufacturer, 'MSG1')
+		variant.insert()
+
+		variant = get_variant(template.name, manufacturer=manufacturer.name,
+			manufacturer_part_no='007')
+		self.assertEquals(variant.item_code, '_Test Variant Mfg-2')
+		self.assertEquals(variant.description, '_Test Variant Mfg')
+		self.assertEquals(variant.manufacturer, 'MSG1')
+		self.assertEquals(variant.manufacturer_part_no, '007')
+
 
 def make_item_variant():
 	if not frappe.db.exists("Item", "_Test Variant Item-S"):
@@ -215,6 +250,5 @@
 		item.item_name = item_code
 		item.description = item_code
 		item.item_group = "All Item Groups"
-		item.is_stock_item = is_stock_item or 1		
+		item.is_stock_item = is_stock_item or 1
 		item.save()
-		
\ No newline at end of file
diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py
index a1f8077..8a0be85 100644
--- a/erpnext/support/doctype/issue/issue.py
+++ b/erpnext/support/doctype/issue/issue.py
@@ -63,7 +63,7 @@
 		'no_breadcrumbs': True
 	}
 
-def get_issue_list(doctype, txt, filters, limit_start, limit_page_length=20):
+def get_issue_list(doctype, txt, filters, limit_start, limit_page_length=20, order_by=None):
 	from frappe.www.list import get_list
 	user = frappe.session.user
 	ignore_permissions = False
diff --git a/erpnext/templates/includes/cart.js b/erpnext/templates/includes/cart.js
index dbb93a9..ee98b23 100644
--- a/erpnext/templates/includes/cart.js
+++ b/erpnext/templates/includes/cart.js
@@ -24,9 +24,17 @@
 			if($(this).prop("checked")) {
 				var me = this;
 
+				// uncheck other shipping or billing addresses:
+				if ( $(this).is('input[data-fieldname=customer_address]') ) {
+					$('input[data-fieldname=customer_address]').not(this).prop('checked', false);
+				} else {
+					$('input[data-fieldname=shipping_address_name]').not(this).prop('checked', false);
+				}
+
 				return frappe.call({
 					type: "POST",
 					method: "erpnext.shopping_cart.cart.update_cart_address",
+					freeze: true,
 					args: {
 						address_fieldname: $(this).attr("data-fieldname"),
 						address_name: $(this).attr("data-address-name")
diff --git a/erpnext/templates/includes/cart/cart_address.html b/erpnext/templates/includes/cart/cart_address.html
index 29d4f4b..d83f609 100644
--- a/erpnext/templates/includes/cart/cart_address.html
+++ b/erpnext/templates/includes/cart/cart_address.html
@@ -7,7 +7,7 @@
 		<div class="h6 text-uppercase">{{ _("Shipping Address") }}</div>
 		<div id="cart-shipping-address" class="panel-group"
 			data-fieldname="shipping_address_name">
-            {% for address in addresses %}
+            {% for address in shipping_addresses %}
                 {{ show_address(address, doc, "shipping_address_name", select_address) }}
             {% endfor %}
         </div>
@@ -18,7 +18,7 @@
 		<div class="h6 text-uppercase">Billing Address</div>
 		<div id="cart-billing-address" class="panel-group"
 			data-fieldname="customer_address">
-            {% for address in addresses %}
+            {% for address in billing_addresses %}
                 {{ show_address(address, doc, "customer_address", select_address) }}
             {% endfor %}
         </div>