Merge branch 'develop' into issue-webview-fixed
3
erpnext/accounts/doctype/asset/asset_list.js
Normal file
@ -0,0 +1,3 @@
|
||||
frappe.listview_settings['Asset'] = {
|
||||
add_fields: ['image']
|
||||
}
|
@ -12,19 +12,42 @@ class InvalidItemAttributeValueError(frappe.ValidationError): pass
|
||||
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 @@ def create_variant(item, args):
|
||||
|
||||
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 create_variant(item, args):
|
||||
|
||||
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"""
|
||||
|
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 291 KiB |
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 203 KiB |
BIN
erpnext/docs/assets/img/setup/workflow-3.png
Normal file
After Width: | Height: | Size: 180 KiB |
BIN
erpnext/docs/assets/img/setup/workflow-4.png
Normal file
After Width: | Height: | Size: 211 KiB |
BIN
erpnext/docs/assets/img/setup/workflow-5.png
Normal file
After Width: | Height: | Size: 184 KiB |
BIN
erpnext/docs/assets/img/stock/select-mfg-for-variant.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
erpnext/docs/assets/img/stock/set-variant-by-mfg.png
Normal file
After Width: | Height: | Size: 19 KiB |
@ -12,7 +12,7 @@ attitude.
|
||||
|
||||
Like exercise.
|
||||
|
||||
Human body may seem like it does not require exercise today or even tomorrow,
|
||||
The human body may seem like it does not require exercise today or even tomorrow,
|
||||
but in the long run, if you wish to maintain your body and its health, you
|
||||
should get on the treadmill.
|
||||
|
||||
|
@ -4,9 +4,9 @@ ERPNext tracks the multiple permissions before submission.
|
||||
|
||||
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 @@ workflow transition step that says from submitted you can cancel.
|
||||
|
||||
#### 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"
|
||||
|
||||

|
||||

|
||||
|
||||
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.
|
||||
|
||||

|
||||

|
||||
|
||||
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.
|
||||
|
||||

|
||||

|
||||
|
||||
{next}
|
||||
|
@ -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 @@ To create 'Item Variants' against a 'Template' select 'Make Variants'
|
||||
<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"
|
@ -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
|
||||
}
|
@ -148,10 +148,9 @@ class SalarySlip(TransactionBase):
|
||||
})
|
||||
|
||||
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 = ''
|
||||
|
@ -327,4 +327,3 @@ body[data-route="pos"] .btn-more {
|
||||
body[data-route="pos"] .collapse-btn {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
@ -177,11 +177,11 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
||||
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() {
|
||||
|
@ -31,10 +31,14 @@ def get_cart_quotation(doc=None):
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -261,6 +261,44 @@ $.extend(erpnext.item, {
|
||||
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 @@ $.extend(erpnext.item, {
|
||||
})
|
||||
});
|
||||
},
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -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",
|
||||
|
@ -643,7 +643,7 @@ class Item(WebsiteGenerator):
|
||||
.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 @@ class Item(WebsiteGenerator):
|
||||
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 @@ def get_timeline_data(doctype, name):
|
||||
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 })
|
||||
|
@ -7,7 +7,7 @@ import frappe
|
||||
|
||||
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 @@ class TestItem(unittest.TestCase):
|
||||
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 @@ def create_item(item_code, is_stock_item=None):
|
||||
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()
|
||||
|
@ -63,7 +63,7 @@ def get_list_context(context=None):
|
||||
'no_breadcrumbs': True
|
||||
}
|
||||
|
||||
def get_issue_list(doctype, txt, filters, limit_start, limit_page_length = 20, order_by = None):
|
||||
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
|
||||
|
@ -24,9 +24,17 @@ $.extend(shopping_cart, {
|
||||
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")
|
||||
|
@ -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>
|
||||
|