From c819ea38a0712f8b99a7c274794c51ed7b5f1966 Mon Sep 17 00:00:00 2001
From: Saif Ur Rehman
Date: Tue, 25 Sep 2018 14:53:12 +0500
Subject: [PATCH 01/86] -Added Item Default child table for Brand -Item Default
Precedence: Get defaults from Item Group, if no default, fetch from Brand
-Remove auto set Item's Item Defaults from Item Group: Item Default should be
manually entered to override both Item Group and Brand defaults
---
erpnext/setup/doctype/brand/brand.json | 431 ++++++++++++++-----------
erpnext/setup/doctype/brand/brand.py | 16 +-
erpnext/stock/get_item_details.py | 32 +-
3 files changed, 282 insertions(+), 197 deletions(-)
diff --git a/erpnext/setup/doctype/brand/brand.json b/erpnext/setup/doctype/brand/brand.json
index 2914ef1bc8..5558358078 100644
--- a/erpnext/setup/doctype/brand/brand.json
+++ b/erpnext/setup/doctype/brand/brand.json
@@ -1,204 +1,269 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:brand",
- "beta": 0,
- "creation": "2013-02-22 01:27:54",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 0,
+ "allow_copy": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:brand",
+ "beta": 0,
+ "creation": "2013-02-22 01:27:54",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 0,
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "brand",
- "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": "Brand Name",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "brand",
- "oldfieldtype": "Data",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "brand",
+ "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": "Brand Name",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "brand",
+ "oldfieldtype": "Data",
+ "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,
+ "translatable": 0,
"unique": 1
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "description",
- "fieldtype": "Text",
- "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,
- "oldfieldname": "description",
- "oldfieldtype": "Text",
- "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,
- "translatable": 0,
- "unique": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "description",
+ "fieldtype": "Text",
+ "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,
+ "oldfieldname": "description",
+ "oldfieldtype": "Text",
+ "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,
+ "translatable": 0,
+ "unique": 0,
"width": "300px"
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "defaults",
+ "fieldtype": "Section Break",
+ "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": "Defaults",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "brand_defaults",
+ "fieldtype": "Table",
+ "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": "Brand Defaults",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Item Default",
+ "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,
+ "translatable": 0,
+ "unique": 0
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "icon": "fa fa-certificate",
- "idx": 1,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-08-29 06:35:44.740318",
- "modified_by": "Administrator",
- "module": "Setup",
- "name": "Brand",
- "owner": "Administrator",
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "icon": "fa fa-certificate",
+ "idx": 1,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2018-09-25 13:27:37.090157",
+ "modified_by": "Administrator",
+ "module": "Setup",
+ "name": "Brand",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 1,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Item Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "amend": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 1,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Item Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Stock User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
+ "amend": 0,
+ "cancel": 0,
+ "create": 0,
+ "delete": 0,
+ "email": 1,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Stock User",
+ "set_user_permissions": 0,
+ "share": 0,
+ "submit": 0,
"write": 0
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Sales User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
+ "amend": 0,
+ "cancel": 0,
+ "create": 0,
+ "delete": 0,
+ "email": 1,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Sales User",
+ "set_user_permissions": 0,
+ "share": 0,
+ "submit": 0,
"write": 0
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Purchase User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
+ "amend": 0,
+ "cancel": 0,
+ "create": 0,
+ "delete": 0,
+ "email": 1,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Purchase User",
+ "set_user_permissions": 0,
+ "share": 0,
+ "submit": 0,
"write": 0
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Accounts User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
+ "amend": 0,
+ "cancel": 0,
+ "create": 0,
+ "delete": 0,
+ "email": 1,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts User",
+ "set_user_permissions": 0,
+ "share": 0,
+ "submit": 0,
"write": 0
}
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 1,
- "sort_order": "ASC",
- "track_changes": 0,
- "track_seen": 0,
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 1,
+ "sort_order": "ASC",
+ "track_changes": 0,
+ "track_seen": 0,
"track_views": 0
}
\ No newline at end of file
diff --git a/erpnext/setup/doctype/brand/brand.py b/erpnext/setup/doctype/brand/brand.py
index d90aa5a9b6..12839d18ae 100644
--- a/erpnext/setup/doctype/brand/brand.py
+++ b/erpnext/setup/doctype/brand/brand.py
@@ -3,8 +3,22 @@
from __future__ import unicode_literals
import frappe
+import copy
from frappe.model.document import Document
class Brand(Document):
- pass
\ No newline at end of file
+ pass
+
+def get_brand_defaults(item, company):
+ item = frappe.get_cached_doc("Item", item)
+ if item.brand:
+ brand = frappe.get_cached_doc("Brand", item.brand)
+
+ for d in brand.brand_defaults or []:
+ if d.company == company:
+ row = copy.deepcopy(d.as_dict())
+ row.pop("name")
+ return row
+
+ return frappe._dict()
\ No newline at end of file
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 01ee9db1ca..ae643f7818 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -13,6 +13,7 @@ from erpnext.stock.doctype.batch.batch import get_batch_no
from erpnext import get_company_currency
from erpnext.stock.doctype.item.item import get_item_defaults, get_uom_conv_factor
from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
+from erpnext.setup.doctype.brand.brand import get_brand_defaults
from six import string_types, iteritems
@@ -218,9 +219,10 @@ def get_basic_details(args, item):
item_defaults = get_item_defaults(item.name, args.company)
item_group_defaults = get_item_group_defaults(item.name, args.company)
+ brand_defaults = get_brand_defaults(item.name, args.company)
warehouse = user_default_warehouse or item_defaults.get("default_warehouse") or\
- item_group_defaults.get("default_warehouse") or args.warehouse
+ item_group_defaults.get("default_warehouse") or brand_defaults.get("default_warehouse") or args.warehouse
if args.get('doctype') == "Material Request" and not args.get('material_request_type'):
args['material_request_type'] = frappe.db.get_value('Material Request',
@@ -242,9 +244,9 @@ def get_basic_details(args, item):
"description": cstr(item.description).strip(),
"image": cstr(item.image).strip(),
"warehouse": warehouse,
- "income_account": get_default_income_account(args, item_defaults, item_group_defaults),
- "expense_account": get_default_expense_account(args, item_defaults, item_group_defaults),
- "cost_center": get_default_cost_center(args, item_defaults, item_group_defaults),
+ "income_account": get_default_income_account(args, item_defaults, item_group_defaults, brand_defaults),
+ "expense_account": get_default_expense_account(args, item_defaults, item_group_defaults, brand_defaults),
+ "cost_center": get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults),
'has_serial_no': item.has_serial_no,
'has_batch_no': item.has_batch_no,
"batch_no": None,
@@ -263,7 +265,7 @@ def get_basic_details(args, item):
"net_rate": 0.0,
"net_amount": 0.0,
"discount_percentage": 0.0,
- "supplier": get_default_supplier(args, item_defaults, item_group_defaults),
+ "supplier": get_default_supplier(args, item_defaults, item_group_defaults, brand_defaults),
"update_stock": args.get("update_stock") if args.get('doctype') in ['Sales Invoice', 'Purchase Invoice'] else 0,
"delivered_by_supplier": item.delivered_by_supplier if args.get("doctype") in ["Sales Order", "Sales Invoice"] else 0,
"is_fixed_asset": item.is_fixed_asset,
@@ -325,14 +327,16 @@ def calculate_service_end_date(args, item=None):
return deferred_detail
-def get_default_income_account(args, item, item_group):
+def get_default_income_account(args, item, item_group, brand):
return (item.get("income_account")
or item_group.get("income_account")
+ or brand.get("income_account")
or args.income_account)
-def get_default_expense_account(args, item, item_group):
+def get_default_expense_account(args, item, item_group, brand):
return (item.get("expense_account")
or item_group.get("expense_account")
+ or brand.get("expense_account")
or args.expense_account)
def get_default_deferred_account(args, item, fieldname=None):
@@ -343,22 +347,23 @@ def get_default_deferred_account(args, item, fieldname=None):
else:
return None
-def get_default_cost_center(args, item, item_group):
+def get_default_cost_center(args, item, item_group, brand):
cost_center = None
if args.get('project'):
cost_center = frappe.db.get_value("Project", args.get("project"), "cost_center", cache=True)
if not cost_center:
if args.get('customer'):
- cost_center = item.get('selling_cost_center') or item_group.get('selling_cost_center')
+ cost_center = item.get('selling_cost_center') or item_group.get('selling_cost_center') or brand.get('selling_cost_center')
else:
- cost_center = item.get('buying_cost_center') or item_group.get('buying_cost_center')
+ cost_center = item.get('buying_cost_center') or item_group.get('buying_cost_center') or brand.get('buying_cost_center')
return cost_center or args.get("cost_center")
-def get_default_supplier(args, item, item_group):
+def get_default_supplier(args, item, item_group, brand):
return (item.get("default_supplier")
- or item_group.get("default_supplier"))
+ or item_group.get("default_supplier")
+ or brand.get("default_supplier"))
def get_price_list_rate(args, item_doc, out):
meta = frappe.get_meta(args.parenttype or args.doctype)
@@ -825,10 +830,11 @@ def get_default_bom(item_code=None):
def get_valuation_rate(item_code, company, warehouse=None):
item = get_item_defaults(item_code, company)
item_group = get_item_group_defaults(item_code, company)
+ brand = get_brand_defaults(item_code, company)
# item = frappe.get_doc("Item", item_code)
if item.get("is_stock_item"):
if not warehouse:
- warehouse = item.get("default_warehouse") or item_group.get("default_warehouse")
+ warehouse = item.get("default_warehouse") or item_group.get("default_warehouse") or brand.get("default_warehouse")
return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse},
["valuation_rate"], as_dict=True) or {"valuation_rate": 0}
From 127b3f552b62f40db1d88cc2a29758ddf972b51c Mon Sep 17 00:00:00 2001
From: Saif Ur Rehman
Date: Wed, 26 Sep 2018 23:23:56 +0500
Subject: [PATCH 02/86] At least add a row for old logic to work properly
---
erpnext/stock/doctype/item/item.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 566b6386fe..e2922b33a0 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -128,6 +128,7 @@ class Item(WebsiteGenerator):
self.validate_uom_conversion_factor()
self.validate_item_defaults()
self.update_defaults_from_item_group()
+ self.update_defaults_add_company()
if not self.get("__islocal"):
self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
@@ -135,6 +136,10 @@ class Item(WebsiteGenerator):
from `tabWebsite Item Group`
where parentfield='website_item_groups' and parenttype='Item' and parent=%s""", self.name)
+ def update_defaults_add_company(self):
+ if not self.item_defaults:
+ self.append("item_defaults", {"company": frappe.defaults.get_defaults().company})
+
def on_update(self):
invalidate_cache_for_item(self)
self.validate_name_with_item_group()
From 7d9ee83d5ae3af28feae380098b267751a293a07 Mon Sep 17 00:00:00 2001
From: Saif Ur Rehman
Date: Wed, 26 Sep 2018 23:41:12 +0500
Subject: [PATCH 03/86] -Fix for updated get_default_cost_center -Back to not
updating item's defaults child table
---
erpnext/stock/doctype/item/item.py | 11 ++---------
erpnext/stock/doctype/stock_entry/stock_entry.py | 4 +++-
2 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index e2922b33a0..a1aa6b14bd 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -86,7 +86,7 @@ class Item(WebsiteGenerator):
def after_insert(self):
'''set opening stock and item price'''
if self.standard_rate:
- for default in self.item_defaults:
+ for default in self.item_defaults or [frappe._dict()]:
self.add_price(default.default_price_list)
if self.opening_stock:
@@ -126,9 +126,6 @@ class Item(WebsiteGenerator):
self.validate_fixed_asset()
self.validate_retain_sample()
self.validate_uom_conversion_factor()
- self.validate_item_defaults()
- self.update_defaults_from_item_group()
- self.update_defaults_add_company()
if not self.get("__islocal"):
self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
@@ -136,10 +133,6 @@ class Item(WebsiteGenerator):
from `tabWebsite Item Group`
where parentfield='website_item_groups' and parenttype='Item' and parent=%s""", self.name)
- def update_defaults_add_company(self):
- if not self.item_defaults:
- self.append("item_defaults", {"company": frappe.defaults.get_defaults().company})
-
def on_update(self):
invalidate_cache_for_item(self)
self.validate_name_with_item_group()
@@ -181,7 +174,7 @@ class Item(WebsiteGenerator):
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
# default warehouse, or Stores
- for default in self.item_defaults:
+ for default in self.item_defaults or [frappe._dict({'company': frappe.defaults.get_defaults().company})]:
default_warehouse = (default.default_warehouse
or frappe.db.get_single_value('Stock Settings', 'default_warehouse')
or frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')}))
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 5d3c6c4adc..5c6555a7a1 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -10,6 +10,7 @@ from erpnext.stock.utils import get_incoming_rate
from erpnext.stock.stock_ledger import get_previous_sle, NegativeStockError, get_valuation_rate
from erpnext.stock.get_item_details import get_bin_details, get_default_cost_center, get_conversion_factor, get_reserved_qty_for_so
from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
+from erpnext.setup.doctype.brand.brand import get_brand_defaults
from erpnext.stock.doctype.batch.batch import get_batch_no, set_batch_nos, get_batch_qty
from erpnext.stock.doctype.item.item import get_item_defaults
from erpnext.manufacturing.doctype.bom.bom import validate_bom_no, add_additional_cost
@@ -631,6 +632,7 @@ class StockEntry(StockController):
item = item[0]
item_group_defaults = get_item_group_defaults(item.name, self.company)
+ brand_defaults = get_brand_defaults(item.name, self.company)
ret = frappe._dict({
'uom' : item.stock_uom,
@@ -639,7 +641,7 @@ class StockEntry(StockController):
'image' : item.image,
'item_name' : item.item_name,
'expense_account' : args.get("expense_account"),
- 'cost_center' : get_default_cost_center(args, item, item_group_defaults),
+ 'cost_center' : get_default_cost_center(args, item, item_group_defaults, brand_defaults),
'qty' : args.get("qty"),
'transfer_qty' : args.get('qty'),
'conversion_factor' : 1,
From 07acc2bf5a68456a7ccd17402d62bd7fb761038b Mon Sep 17 00:00:00 2001
From: Saif Ur Rehman
Date: Tue, 23 Oct 2018 23:18:16 +0500
Subject: [PATCH 04/86] Allow brand in quick entry
---
erpnext/setup/doctype/brand/brand.json | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/erpnext/setup/doctype/brand/brand.json b/erpnext/setup/doctype/brand/brand.json
index 5558358078..03e025c762 100644
--- a/erpnext/setup/doctype/brand/brand.json
+++ b/erpnext/setup/doctype/brand/brand.json
@@ -1,5 +1,6 @@
{
"allow_copy": 0,
+ "allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
@@ -14,7 +15,7 @@
"fields": [
{
"allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
+ "allow_in_quick_entry": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -156,7 +157,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-09-25 13:27:37.090157",
+ "modified": "2018-10-23 23:18:06.067612",
"modified_by": "Administrator",
"module": "Setup",
"name": "Brand",
From 1ea98cbbe1f1d93adac518c5c4c354615fd2f8b0 Mon Sep 17 00:00:00 2001
From: Saif Ur Rehman
Date: Fri, 28 Dec 2018 00:29:43 +0500
Subject: [PATCH 05/86] fix: missing line due to conflict resolution
---
erpnext/stock/doctype/item/item.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index a1aa6b14bd..a9360011ff 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -126,6 +126,7 @@ class Item(WebsiteGenerator):
self.validate_fixed_asset()
self.validate_retain_sample()
self.validate_uom_conversion_factor()
+ self.validate_item_defaults()
if not self.get("__islocal"):
self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
From 00aaa4877945a9258638405e308c1943bdffe692 Mon Sep 17 00:00:00 2001
From: Saif Ur Rehman
Date: Sat, 2 Feb 2019 02:43:44 +0500
Subject: [PATCH 06/86] test(Item): test_item_defaults
---
.../accounts/doctype/account/test_account.py | 2 +
erpnext/setup/doctype/brand/test_records.json | 11 ++++
erpnext/stock/doctype/item/test_item.py | 55 +++++++++++++++++++
3 files changed, 68 insertions(+)
diff --git a/erpnext/accounts/doctype/account/test_account.py b/erpnext/accounts/doctype/account/test_account.py
index acaa0966a2..1c3375050e 100644
--- a/erpnext/accounts/doctype/account/test_account.py
+++ b/erpnext/accounts/doctype/account/test_account.py
@@ -129,6 +129,8 @@ def _make_test_records(verbose):
["_Test Write Off", "Indirect Expenses", 0, None, None],
["_Test Exchange Gain/Loss", "Indirect Expenses", 0, None, None],
+ ["_Test Account Sales", "Direct Income", 0, None, None],
+
# related to Account Inventory Integration
["_Test Account Stock In Hand", "Current Assets", 0, None, None],
diff --git a/erpnext/setup/doctype/brand/test_records.json b/erpnext/setup/doctype/brand/test_records.json
index d2a4ad4e23..17b5a6b0a3 100644
--- a/erpnext/setup/doctype/brand/test_records.json
+++ b/erpnext/setup/doctype/brand/test_records.json
@@ -2,5 +2,16 @@
{
"brand": "_Test Brand",
"doctype": "Brand"
+ },
+ {
+ "brand": "_Test Brand With Item Defaults",
+ "doctype": "Brand",
+ "brand_defaults": [{
+ "company": "_Test Company",
+ "expense_account": "_Test Account Cost for Goods Sold - _TC",
+ "income_account": "_Test Account Sales - _TC",
+ "buying_cost_center": "_Test Cost Center - _TC",
+ "selling_cost_center": "_Test Cost Center - _TC"
+ }]
}
]
\ No newline at end of file
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index d02559ebcb..6ec7ba1d1f 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -102,6 +102,61 @@ class TestItem(unittest.TestCase):
for key, value in iteritems(to_check):
self.assertEqual(value, details.get(key))
+ def test_item_defaults(self):
+ frappe.delete_doc_if_exists("Item", "Test Item With Defaults", force=1)
+ make_item("Test Item With Defaults", {
+ "item_group": "_Test Item Group",
+ "brand": "_Test Brand With Item Defaults",
+ "item_defaults": [{
+ "company": "_Test Company",
+ "default_warehouse": "_Test Warehouse 2 - _TC", # no override
+ "expense_account": "_Test Account Stock Expenses - _TC", # override brand default
+ "buying_cost_center": "_Test Write Off Cost Center - _TC", # override item group default
+ }]
+ })
+
+ sales_item_check = {
+ "item_code": "Test Item With Defaults",
+ "warehouse": "_Test Warehouse 2 - _TC", # from item
+ "income_account": "_Test Account Sales - _TC", # from brand
+ "expense_account": "_Test Account Stock Expenses - _TC", # from item
+ "cost_center": "_Test Cost Center 2 - _TC", # from item group
+ }
+ sales_item_details = get_item_details({
+ "item_code": "Test Item With Defaults",
+ "company": "_Test Company",
+ "price_list": "_Test Price List",
+ "currency": "_Test Currency",
+ "doctype": "Sales Invoice",
+ "conversion_rate": 1,
+ "price_list_currency": "_Test Currency",
+ "plc_conversion_rate": 1,
+ "customer": "_Test Customer",
+ })
+ for key, value in iteritems(sales_item_check):
+ self.assertEqual(value, sales_item_details.get(key))
+
+ purchase_item_check = {
+ "item_code": "Test Item With Defaults",
+ "warehouse": "_Test Warehouse 2 - _TC", # from item
+ "expense_account": "_Test Account Stock Expenses - _TC", # from item
+ "income_account": "_Test Account Sales - _TC", # from brand
+ "cost_center": "_Test Write Off Cost Center - _TC" # from item
+ }
+ purchase_item_details = get_item_details({
+ "item_code": "Test Item With Defaults",
+ "company": "_Test Company",
+ "price_list": "_Test Price List",
+ "currency": "_Test Currency",
+ "doctype": "Purchase Invoice",
+ "conversion_rate": 1,
+ "price_list_currency": "_Test Currency",
+ "plc_conversion_rate": 1,
+ "supplier": "_Test Supplier",
+ })
+ for key, value in iteritems(purchase_item_check):
+ self.assertEqual(value, purchase_item_details.get(key))
+
def test_item_attribute_change_after_variant(self):
frappe.delete_doc_if_exists("Item", "_Test Variant Item-L", force=1)
From 143973166fb9fa1f2a74f6755ba8081e5cbf196a Mon Sep 17 00:00:00 2001
From: Rohan Bansal
Date: Thu, 21 Feb 2019 15:32:52 +0530
Subject: [PATCH 07/86] fix(payments): Only check for Draft or Submitted
paymentswhile cancelling payment requests
---
.../accounts/doctype/payment_request/payment_request.py | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index 014efd948c..1fbde753d4 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -214,9 +214,11 @@ class PaymentRequest(Document):
def check_if_payment_entry_exists(self):
if self.status == "Paid":
- payment_entry = frappe.db.sql_list("""select parent from `tabPayment Entry Reference`
- where reference_name=%s""", self.reference_name)
- if payment_entry:
+ payment_entry = frappe.get_all("Payment Entry Reference",
+ filters={"reference_name": self.reference_name, "docstatus": ["<", 2]},
+ fields=["distinct(parent)"])
+
+ if any(payment_entry):
frappe.throw(_("Payment Entry already exists"), title=_('Error'))
def make_communication_entry(self):
From 6635583103840dbdcca52e2552417fc3d2ca0bae Mon Sep 17 00:00:00 2001
From: "FinByz Tech Pvt. Ltd"
Date: Fri, 1 Mar 2019 11:57:06 +0530
Subject: [PATCH 08/86] fix: Rounding adjustment in Rounded Total
In Purchase Receipt and GST Purchase Receipt report, the Rounded Total column doesn't display rounding adjustment of Base Grand Total. So, we have created a fix for that rounding adjustment.
---
.../accounts/report/purchase_register/purchase_register.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py
index e33b90d019..3f8abb76e2 100644
--- a/erpnext/accounts/report/purchase_register/purchase_register.py
+++ b/erpnext/accounts/report/purchase_register/purchase_register.py
@@ -66,8 +66,8 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
total_tax += tax_amount
row.append(tax_amount)
- # total tax, grand total, outstanding amount & rounded total
- row += [total_tax, inv.base_grand_total, flt(inv.base_grand_total, 2), inv.outstanding_amount]
+ # total tax, grand total, rounded total & outstanding amount
+ row += [total_tax, inv.base_grand_total, flt(inv.base_grand_total, 0), inv.outstanding_amount]
data.append(row)
return columns, data
From 33d0a9f6841cc1c239d79753ba86d5daebada14b Mon Sep 17 00:00:00 2001
From: Raffael Meyer
Date: Tue, 5 Mar 2019 21:57:11 +0100
Subject: [PATCH 09/86] fix(projects): change fieldtype of billing amounts to
Currency
---
erpnext/projects/doctype/timesheet/timesheet.json | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/erpnext/projects/doctype/timesheet/timesheet.json b/erpnext/projects/doctype/timesheet/timesheet.json
index 5ad2ab3a37..c29c11b746 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.json
+++ b/erpnext/projects/doctype/timesheet/timesheet.json
@@ -739,7 +739,7 @@
"collapsible": 0,
"columns": 0,
"fieldname": "total_costing_amount",
- "fieldtype": "Float",
+ "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -805,7 +805,7 @@
"depends_on": "",
"description": "",
"fieldname": "total_billable_amount",
- "fieldtype": "Float",
+ "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -837,7 +837,7 @@
"collapsible": 0,
"columns": 0,
"fieldname": "total_billed_amount",
- "fieldtype": "Float",
+ "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -1000,7 +1000,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2019-01-30 11:28:18.518590",
+ "modified": "2019-03-05 21:54:02.654690",
"modified_by": "Administrator",
"module": "Projects",
"name": "Timesheet",
From 9757a603fa99c3d05151c7b94d2eddffb04a6ddb Mon Sep 17 00:00:00 2001
From: Jay Parikh
Date: Wed, 6 Mar 2019 12:44:41 +0000
Subject: [PATCH 10/86] Fix Company Default to Total Stock Summary Report
---
.../stock/report/total_stock_summary/total_stock_summary.js | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/erpnext/stock/report/total_stock_summary/total_stock_summary.js b/erpnext/stock/report/total_stock_summary/total_stock_summary.js
index 223a603004..b7461c485f 100644
--- a/erpnext/stock/report/total_stock_summary/total_stock_summary.js
+++ b/erpnext/stock/report/total_stock_summary/total_stock_summary.js
@@ -18,7 +18,9 @@ frappe.query_reports["Total Stock Summary"] = {
"label": __("Company"),
"fieldtype": "Link",
"width": "80",
- "options": "Company"
+ "options": "Company",
+ "default": frappe.defaults.get_user_default("Company"),
+ "reqd": 1
},
]
}
From 783331c64573cf56635bbe1cdb8e59c8f32db018 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Wed, 6 Mar 2019 18:44:04 +0530
Subject: [PATCH 11/86] sales_order to work_order item desc fix
---
erpnext/selling/doctype/sales_order/sales_order.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index b589cdeaa4..2345762233 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -388,6 +388,7 @@ class SalesOrder(SellingController):
items.append(dict(
name= i.name,
item_code= i.item_code,
+ description= i.description,
bom = bom,
warehouse = i.warehouse,
pending_qty = pending_qty,
@@ -398,6 +399,7 @@ class SalesOrder(SellingController):
items.append(dict(
name= i.name,
item_code= i.item_code,
+ description= i.description,
bom = '',
warehouse = i.warehouse,
pending_qty = pending_qty,
@@ -901,7 +903,8 @@ def make_work_orders(items, sales_order, company, project=None):
sales_order=sales_order,
sales_order_item=i['sales_order_item'],
project=project,
- fg_warehouse=i['warehouse']
+ fg_warehouse=i['warehouse'],
+ description=i['description']
)).insert()
work_order.set_work_order_operations()
work_order.save()
From 4f1737c2dd248850f8d086736e170b44b66d1a2f Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Wed, 6 Mar 2019 22:19:15 +0530
Subject: [PATCH 12/86] fix sales order test for creating work order from sales
order
---
erpnext/selling/doctype/sales_order/test_sales_order.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index 0eb19e3417..f270938ad3 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -573,7 +573,8 @@ class TestSalesOrder(unittest.TestCase):
"item_code": item.get("item_code"),
"pending_qty": item.get("pending_qty"),
"sales_order_item": item.get("sales_order_item"),
- "bom": item.get("bom")
+ "bom": item.get("bom"),
+ "description": item.get("description")
})
so_item_name[item.get("sales_order_item")]= item.get("pending_qty")
make_work_orders(json.dumps({"items":po_items}), so.name, so.company)
From 59699bf46e2288ef89208ed7a602016455754aef Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Wed, 6 Mar 2019 23:33:03 +0530
Subject: [PATCH 13/86] [debug] locally tests passed but travis failed
---
erpnext/selling/doctype/sales_order/sales_order.py | 1 +
erpnext/selling/doctype/sales_order/test_sales_order.py | 1 +
2 files changed, 2 insertions(+)
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 2345762233..a84fa1430b 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -886,6 +886,7 @@ def get_supplier(doctype, txt, searchfield, start, page_len, filters):
def make_work_orders(items, sales_order, company, project=None):
'''Make Work Orders against the given Sales Order for the given `items`'''
items = json.loads(items).get('items')
+ print(items)
out = []
for i in items:
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index f270938ad3..584b5b99c6 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -577,6 +577,7 @@ class TestSalesOrder(unittest.TestCase):
"description": item.get("description")
})
so_item_name[item.get("sales_order_item")]= item.get("pending_qty")
+ print(po_items)
make_work_orders(json.dumps({"items":po_items}), so.name, so.company)
# Check if Work Orders were raised
From 7ab961f79881c4861dd2c7664aaceb165ebc3bc7 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Wed, 6 Mar 2019 23:53:38 +0530
Subject: [PATCH 14/86] remove debug code
---
erpnext/selling/doctype/sales_order/sales_order.py | 1 -
erpnext/selling/doctype/sales_order/test_sales_order.py | 1 -
2 files changed, 2 deletions(-)
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index a84fa1430b..2345762233 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -886,7 +886,6 @@ def get_supplier(doctype, txt, searchfield, start, page_len, filters):
def make_work_orders(items, sales_order, company, project=None):
'''Make Work Orders against the given Sales Order for the given `items`'''
items = json.loads(items).get('items')
- print(items)
out = []
for i in items:
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index 584b5b99c6..f270938ad3 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -577,7 +577,6 @@ class TestSalesOrder(unittest.TestCase):
"description": item.get("description")
})
so_item_name[item.get("sales_order_item")]= item.get("pending_qty")
- print(po_items)
make_work_orders(json.dumps({"items":po_items}), so.name, so.company)
# Check if Work Orders were raised
From 1b0f5fd4304e8d2cd9c24de659c3cf8678b893aa Mon Sep 17 00:00:00 2001
From: Anurag Mishra
Date: Thu, 7 Mar 2019 16:17:00 +0530
Subject: [PATCH 15/86] fix: pass correct argument to method
get_deprication_amount
---
erpnext/assets/doctype/asset/asset.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index a38b40bc60..3cab3b348f 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -255,7 +255,7 @@ class Asset(AccountsController):
def get_depreciation_amount(self, depreciable_value, total_number_of_depreciations, row):
percentage_value = 100.0 if row.depreciation_method == 'Written Down Value' else 200.0
- factor = percentage_value / total_number_of_depreciations
+ factor = percentage_value / cint(total_number_of_depreciations)
depreciation_amount = flt(depreciable_value * factor / 100, 0)
value_after_depreciation = flt(depreciable_value) - depreciation_amount
@@ -275,7 +275,7 @@ class Asset(AccountsController):
flt(row.expected_value_after_useful_life)) / (cint(row.total_number_of_depreciations) -
cint(self.number_of_depreciations_booked)) * prorata_temporis
else:
- depreciation_amount = self.get_depreciation_amount(depreciable_value, row)
+ depreciation_amount = self.get_depreciation_amount(depreciable_value, row.total_number_of_depreciations, row)
return depreciation_amount
From 78a32ae172063a9456c51185ccb348d97db1c58a Mon Sep 17 00:00:00 2001
From: deepeshgarg007
Date: Thu, 7 Mar 2019 20:00:07 +0530
Subject: [PATCH 16/86] fix: Remove validation for relieving date from
additional salary
---
erpnext/hr/doctype/additional_salary/additional_salary.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/erpnext/hr/doctype/additional_salary/additional_salary.py b/erpnext/hr/doctype/additional_salary/additional_salary.py
index e25e69e75f..968a1c4571 100644
--- a/erpnext/hr/doctype/additional_salary/additional_salary.py
+++ b/erpnext/hr/doctype/additional_salary/additional_salary.py
@@ -19,8 +19,6 @@ class AdditionalSalary(Document):
["date_of_joining", "relieving_date"])
if date_of_joining and getdate(self.payroll_date) < getdate(date_of_joining):
frappe.throw(_("Payroll date can not be less than employee's joining date"))
- elif relieving_date and getdate(self.payroll_date) > getdate(relieving_date):
- frappe.throw(_("To date can not greater than employee's relieving date"))
def get_amount(self, sal_start_date, sal_end_date):
start_date = getdate(sal_start_date)
From 821a002125cfed5b71559b7281c3f8cd7c634bae Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Thu, 7 Mar 2019 19:27:54 +0530
Subject: [PATCH 17/86] feat: added provision to disable CWIP accounting in
asset settings
---
.../purchase_invoice/purchase_invoice.py | 18 +++++--
erpnext/assets/doctype/asset/asset.py | 23 ++++++---
.../asset_settings/asset_settings.json | 50 +++++++++++++++++--
.../purchase_receipt/purchase_receipt.py | 5 +-
4 files changed, 78 insertions(+), 18 deletions(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index c0d0d837fe..bc44bc80f4 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -8,6 +8,7 @@ from frappe.utils import cint, cstr, formatdate, flt, getdate, nowdate
from frappe import _, throw
import frappe.defaults
+from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
from erpnext.controllers.buying_controller import BuyingController
from erpnext.accounts.party import get_party_account, get_due_date
from erpnext.accounts.utils import get_account_currency, get_fiscal_year
@@ -17,7 +18,7 @@ from erpnext.accounts.general_ledger import make_gl_entries, merge_similar_entri
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
from erpnext.buying.utils import check_for_closed_status
from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center
-from erpnext.assets.doctype.asset.asset import get_asset_account
+from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_disabled
from frappe.model.mapper import get_mapped_doc
from six import iteritems
from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_invoice,\
@@ -238,6 +239,13 @@ class PurchaseInvoice(BuyingController):
item.expense_account = warehouse_account[item.warehouse]["account"]
else:
item.expense_account = stock_not_billed_account
+ elif item.is_fixed_asset and is_cwip_accounting_disabled():
+ if not item.asset:
+ frappe.throw(_("Row {0}: asset is required for item {1}")
+ .format(item.idx, item.item_code))
+
+ item.expense_account = get_asset_category_account(item.asset, 'fixed_asset_account',
+ company = self.company)
elif item.is_fixed_asset and item.pr_detail:
item.expense_account = asset_received_but_not_billed
elif not item.expense_account and for_validate:
@@ -383,7 +391,9 @@ class PurchaseInvoice(BuyingController):
self.make_supplier_gl_entry(gl_entries)
self.make_item_gl_entries(gl_entries)
- self.get_asset_gl_entry(gl_entries)
+ if not is_cwip_accounting_disabled():
+ self.get_asset_gl_entry(gl_entries)
+
self.make_tax_gl_entries(gl_entries)
gl_entries = merge_similar_entries(gl_entries)
@@ -475,7 +485,7 @@ class PurchaseInvoice(BuyingController):
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"credit": flt(item.rm_supp_cost)
}, warehouse_account[self.supplier_warehouse]["account_currency"]))
- elif not item.is_fixed_asset:
+ elif not item.is_fixed_asset or (item.is_fixed_asset and is_cwip_accounting_disabled()):
gl_entries.append(
self.get_gl_dict({
"account": item.expense_account if not item.enable_deferred_expense else item.deferred_expense_account,
@@ -520,7 +530,7 @@ class PurchaseInvoice(BuyingController):
base_asset_amount = flt(item.base_net_amount + item.item_tax_amount)
if (not item.expense_account or frappe.db.get_value('Account',
- item.expense_account, 'account_type') != 'Asset Received But Not Billed'):
+ item.expense_account, 'account_type') not in ['Asset Received But Not Billed', 'Fixed Asset']):
arbnb_account = self.get_company_default("asset_received_but_not_billed")
item.expense_account = arbnb_account
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index a38b40bc60..6b145956f3 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -33,7 +33,7 @@ class Asset(AccountsController):
self.validate_in_use_date()
self.set_status()
self.update_stock_movement()
- if not self.booked_fixed_asset:
+ if not self.booked_fixed_asset and not is_cwip_accounting_disabled():
self.make_gl_entries()
def on_cancel(self):
@@ -71,14 +71,15 @@ class Asset(AccountsController):
if not flt(self.gross_purchase_amount):
frappe.throw(_("Gross Purchase Amount is mandatory"), frappe.MandatoryError)
- if not self.is_existing_asset and not (self.purchase_receipt or self.purchase_invoice):
- frappe.throw(_("Please create purchase receipt or purchase invoice for the item {0}").
- format(self.item_code))
+ if not is_cwip_accounting_disabled():
+ if not self.is_existing_asset and not (self.purchase_receipt or self.purchase_invoice):
+ frappe.throw(_("Please create purchase receipt or purchase invoice for the item {0}").
+ format(self.item_code))
- if (not self.purchase_receipt and self.purchase_invoice
- and not frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock')):
- frappe.throw(_("Update stock must be enable for the purchase invoice {0}").
- format(self.purchase_invoice))
+ if (not self.purchase_receipt and self.purchase_invoice
+ and not frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock')):
+ frappe.throw(_("Update stock must be enable for the purchase invoice {0}").
+ format(self.purchase_invoice))
if not self.calculate_depreciation:
return
@@ -404,6 +405,9 @@ def update_maintenance_status():
asset.set_status('Out of Order')
def make_post_gl_entry():
+ if is_cwip_accounting_disabled():
+ return
+
assets = frappe.db.sql_list(""" select name from `tabAsset`
where ifnull(booked_fixed_asset, 0) = 0 and available_for_use_date = %s""", nowdate())
@@ -551,3 +555,6 @@ def make_journal_entry(asset_name):
})
return je
+
+def is_cwip_accounting_disabled():
+ return cint(frappe.db.get_single_value("Asset Settings", "disable_cwip_accounting"))
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset_settings/asset_settings.json b/erpnext/assets/doctype/asset_settings/asset_settings.json
index d6ddd33c30..a3fee96f4e 100644
--- a/erpnext/assets/doctype/asset_settings/asset_settings.json
+++ b/erpnext/assets/doctype/asset_settings/asset_settings.json
@@ -1,5 +1,6 @@
{
"allow_copy": 0,
+ "allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
@@ -14,10 +15,12 @@
"fields": [
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "depreciation_options",
"fieldtype": "Section Break",
"hidden": 0,
@@ -40,14 +43,17 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "schedule_based_on_fiscal_year",
"fieldtype": "Check",
"hidden": 0,
@@ -70,10 +76,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -81,6 +89,7 @@
"default": "360",
"depends_on": "eval:doc.schedule_based_on_fiscal_year",
"description": "This value is used for pro-rata temporis calculation",
+ "fetch_if_empty": 0,
"fieldname": "number_of_days_in_fiscal_year",
"fieldtype": "Data",
"hidden": 0,
@@ -103,6 +112,40 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fetch_if_empty": 0,
+ "fieldname": "disable_cwip_accounting",
+ "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": "Disable CWIP Accounting",
+ "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,
+ "translatable": 0,
"unique": 0
}
],
@@ -116,7 +159,7 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-01-05 10:10:39.803255",
+ "modified": "2019-03-08 10:44:41.924547",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Settings",
@@ -125,7 +168,6 @@
"permissions": [
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@@ -145,7 +187,6 @@
},
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@@ -171,5 +212,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
- "track_seen": 0
+ "track_seen": 0,
+ "track_views": 0
}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index cb51e220b8..ed7f2ca432 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -13,7 +13,7 @@ from erpnext.controllers.buying_controller import BuyingController
from erpnext.accounts.utils import get_account_currency
from frappe.desk.notifications import clear_doctype_notifications
from erpnext.buying.utils import check_for_closed_status
-from erpnext.assets.doctype.asset.asset import get_asset_account
+from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_disabled
from six import iteritems
form_grid_templates = {
@@ -258,7 +258,8 @@ class PurchaseReceipt(BuyingController):
d.rejected_warehouse not in warehouse_with_no_account:
warehouse_with_no_account.append(d.warehouse)
- self.get_asset_gl_entry(gl_entries)
+ if not is_cwip_accounting_disabled():
+ self.get_asset_gl_entry(gl_entries)
# Cost center-wise amount breakup for other charges included for valuation
valuation_tax = {}
for tax in self.get("taxes"):
From 6b33c9b9342ed39cc059cf89432345b58b400976 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Fri, 8 Mar 2019 11:13:35 +0530
Subject: [PATCH 18/86] fix: purchase receipt not able to submit because
default inventory account has not selected in another company
---
.../doctype/purchase_invoice/purchase_invoice.py | 7 ++++---
.../accounts/doctype/sales_invoice/sales_invoice.py | 3 ++-
erpnext/accounts/utils.py | 4 ++--
erpnext/controllers/stock_controller.py | 13 +++++++------
.../v7_0/repost_future_gle_for_purchase_invoice.py | 11 ++++++-----
erpnext/stock/__init__.py | 11 ++++++++---
6 files changed, 29 insertions(+), 20 deletions(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index c0d0d837fe..df1f29aa22 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -222,7 +222,7 @@ class PurchaseInvoice(BuyingController):
self.validate_item_code()
self.validate_warehouse()
if auto_accounting_for_stock:
- warehouse_account = get_warehouse_account_map()
+ warehouse_account = get_warehouse_account_map(self.company)
for item in self.get("items"):
# in case of auto inventory accounting,
@@ -366,7 +366,8 @@ class PurchaseInvoice(BuyingController):
if repost_future_gle and cint(self.update_stock) and self.auto_accounting_for_stock:
from erpnext.controllers.stock_controller import update_gl_entries_after
items, warehouses = self.get_items_and_warehouses()
- update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items)
+ update_gl_entries_after(self.posting_date, self.posting_time,
+ warehouses, items, company = self.company)
elif self.docstatus == 2 and cint(self.update_stock) and self.auto_accounting_for_stock:
delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
@@ -423,7 +424,7 @@ class PurchaseInvoice(BuyingController):
stock_items = self.get_stock_items()
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
if self.update_stock and self.auto_accounting_for_stock:
- warehouse_account = get_warehouse_account_map()
+ warehouse_account = get_warehouse_account_map(self.company)
voucher_wise_stock_value = {}
if self.update_stock:
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 62d8ffd897..926e2b8c52 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -695,7 +695,8 @@ class SalesInvoice(SellingController):
if repost_future_gle and cint(self.update_stock) \
and cint(auto_accounting_for_stock):
items, warehouses = self.get_items_and_warehouses()
- update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items)
+ update_gl_entries_after(self.posting_date, self.posting_time,
+ warehouses, items, company = self.company)
elif self.docstatus == 2 and cint(self.update_stock) \
and cint(auto_accounting_for_stock):
from erpnext.accounts.general_ledger import delete_gl_entries
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index d4e1840eb9..2de5104183 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -544,14 +544,14 @@ def fix_total_debit_credit():
(dr_or_cr, dr_or_cr, '%s', '%s', '%s', dr_or_cr),
(d.diff, d.voucher_type, d.voucher_no))
-def get_stock_and_account_difference(account_list=None, posting_date=None):
+def get_stock_and_account_difference(account_list=None, posting_date=None, company=None):
from erpnext.stock.utils import get_stock_value_on
from erpnext.stock import get_warehouse_account_map
if not posting_date: posting_date = nowdate()
difference = {}
- warehouse_account = get_warehouse_account_map()
+ warehouse_account = get_warehouse_account_map(company)
for warehouse, account_data in iteritems(warehouse_account):
if account_data.get('account') in account_list:
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 0a3cd3499b..d1ffd7db66 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -26,7 +26,7 @@ class StockController(AccountsController):
delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
if cint(erpnext.is_perpetual_inventory_enabled(self.company)):
- warehouse_account = get_warehouse_account_map()
+ warehouse_account = get_warehouse_account_map(self.company)
if self.docstatus==1:
if not gl_entries:
@@ -36,7 +36,7 @@ class StockController(AccountsController):
if repost_future_gle:
items, warehouses = self.get_items_and_warehouses()
update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items,
- warehouse_account)
+ warehouse_account, company=self.company)
elif self.doctype in ['Purchase Receipt', 'Purchase Invoice'] and self.docstatus == 1:
gl_entries = []
gl_entries = self.get_asset_gl_entry(gl_entries)
@@ -46,7 +46,7 @@ class StockController(AccountsController):
default_cost_center=None):
if not warehouse_account:
- warehouse_account = get_warehouse_account_map()
+ warehouse_account = get_warehouse_account_map(self.company)
sle_map = self.get_stock_ledger_details()
voucher_details = self.get_voucher_details(default_expense_account, default_cost_center, sle_map)
@@ -199,7 +199,8 @@ class StockController(AccountsController):
def make_adjustment_entry(self, expected_gle, voucher_obj):
from erpnext.accounts.utils import get_stock_and_account_difference
account_list = [d.account for d in expected_gle]
- acc_diff = get_stock_and_account_difference(account_list, expected_gle[0].posting_date)
+ acc_diff = get_stock_and_account_difference(account_list,
+ expected_gle[0].posting_date, self.company)
cost_center = self.get_company_default("cost_center")
stock_adjustment_account = self.get_company_default("stock_adjustment_account")
@@ -361,13 +362,13 @@ class StockController(AccountsController):
frappe.get_doc("Blanket Order", blanket_order).update_ordered_qty()
def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None,
- warehouse_account=None):
+ warehouse_account=None, company=None):
def _delete_gl_entries(voucher_type, voucher_no):
frappe.db.sql("""delete from `tabGL Entry`
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
if not warehouse_account:
- warehouse_account = get_warehouse_account_map()
+ warehouse_account = get_warehouse_account_map(company)
future_stock_vouchers = get_future_stock_vouchers(posting_date, posting_time, for_warehouses, for_items)
gle = get_voucherwise_gl_entries(future_stock_vouchers, posting_date)
diff --git a/erpnext/patches/v7_0/repost_future_gle_for_purchase_invoice.py b/erpnext/patches/v7_0/repost_future_gle_for_purchase_invoice.py
index 22f9db6b2b..9e21fb699b 100644
--- a/erpnext/patches/v7_0/repost_future_gle_for_purchase_invoice.py
+++ b/erpnext/patches/v7_0/repost_future_gle_for_purchase_invoice.py
@@ -10,14 +10,15 @@ from erpnext.controllers.stock_controller import update_gl_entries_after
def execute():
company_list = frappe.db.sql_list("""Select name from tabCompany where enable_perpetual_inventory = 1""")
frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
-
- frappe.reload_doctype("Purchase Invoice")
+
+ frappe.reload_doctype("Purchase Invoice")
wh_account = get_warehouse_account_map()
-
+
for pi in frappe.get_all("Purchase Invoice", fields=["name", "company"], filters={"docstatus": 1, "update_stock": 1}):
if pi.company in company_list:
pi_doc = frappe.get_doc("Purchase Invoice", pi.name)
items, warehouses = pi_doc.get_items_and_warehouses()
- update_gl_entries_after(pi_doc.posting_date, pi_doc.posting_time, warehouses, items, wh_account)
-
+ update_gl_entries_after(pi_doc.posting_date, pi_doc.posting_time,
+ warehouses, items, wh_account, company = pi.company)
+
frappe.db.commit()
\ No newline at end of file
diff --git a/erpnext/stock/__init__.py b/erpnext/stock/__init__.py
index ea3d1036d2..32a03e7373 100644
--- a/erpnext/stock/__init__.py
+++ b/erpnext/stock/__init__.py
@@ -8,16 +8,21 @@ install_docs = [
{"doctype":"Role", "role_name":"Stock User", "name":"Stock User"},
{"doctype":"Role", "role_name":"Quality Manager", "name":"Quality Manager"},
{"doctype":"Item Group", "item_group_name":"All Item Groups", "is_group": 1},
- {"doctype":"Item Group", "item_group_name":"Default",
+ {"doctype":"Item Group", "item_group_name":"Default",
"parent_item_group":"All Item Groups", "is_group": 0},
]
-def get_warehouse_account_map():
+def get_warehouse_account_map(company=None):
if not frappe.flags.warehouse_account_map or frappe.flags.in_test:
warehouse_account = frappe._dict()
+ filters = {}
+ if company:
+ filters['company'] = company
+
for d in frappe.get_all('Warehouse',
fields = ["name", "account", "parent_warehouse", "company"],
+ filters = filters,
order_by="lft, rgt"):
if not d.account:
d.account = get_warehouse_account(d, warehouse_account)
@@ -57,6 +62,6 @@ def get_warehouse_account(warehouse, warehouse_account=None):
frappe.throw(_("Please set Account in Warehouse {0} or Default Inventory Account in Company {1}")
.format(warehouse.name, warehouse.company))
return account
-
+
def get_company_default_inventory_account(company):
return frappe.get_cached_value('Company', company, 'default_inventory_account')
From 701c0b792ca70d58bb40f7af778f65559b6a46b9 Mon Sep 17 00:00:00 2001
From: Rushabh Mehta
Date: Fri, 8 Mar 2019 12:30:42 +0530
Subject: [PATCH 19/86] feat: Pre mark attendance for Leave Application
---
erpnext/hr/doctype/attendance/attendance.json | 35 +++++++++++++++-
erpnext/hr/doctype/attendance/attendance.py | 3 +-
.../leave_application/leave_application.py | 31 +++++++-------
.../test_leave_application.py | 41 ++++++++++++++++++-
4 files changed, 91 insertions(+), 19 deletions(-)
diff --git a/erpnext/hr/doctype/attendance/attendance.json b/erpnext/hr/doctype/attendance/attendance.json
index 97d28e7e88..2459b7a6df 100644
--- a/erpnext/hr/doctype/attendance/attendance.json
+++ b/erpnext/hr/doctype/attendance/attendance.json
@@ -218,6 +218,39 @@
"translatable": 0,
"unique": 0
},
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "leave_application",
+ "fieldtype": "Link",
+ "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": "Leave Application",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Leave Application",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@@ -428,7 +461,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2019-01-30 11:28:13.075959",
+ "modified": "2019-03-08 12:00:14.043535",
"modified_by": "Administrator",
"module": "HR",
"name": "Attendance",
diff --git a/erpnext/hr/doctype/attendance/attendance.py b/erpnext/hr/doctype/attendance/attendance.py
index 74a53035ad..7dd9f0e10c 100644
--- a/erpnext/hr/doctype/attendance/attendance.py
+++ b/erpnext/hr/doctype/attendance/attendance.py
@@ -40,7 +40,8 @@ class Attendance(Document):
def validate_attendance_date(self):
date_of_joining = frappe.db.get_value("Employee", self.employee, "date_of_joining")
- if getdate(self.attendance_date) > getdate(nowdate()):
+ # leaves can be marked for future dates
+ if self.status not in ('On Leave', 'Half Day') and getdate(self.attendance_date) > getdate(nowdate()):
frappe.throw(_("Attendance can not be marked for future dates"))
elif date_of_joining and getdate(self.attendance_date) < getdate(date_of_joining):
frappe.throw(_("Attendance date can not be less than employee's joining date"))
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index b85f38b295..819bbf9d20 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -117,28 +117,29 @@ class LeaveApplication(Document):
def update_attendance(self):
if self.status == "Approved":
- attendance = frappe.db.sql("""select name from `tabAttendance` where employee = %s\
- and (attendance_date between %s and %s) and docstatus < 2""",(self.employee, self.from_date, self.to_date), as_dict=1)
+ for dt in daterange(getdate(self.from_date), getdate(self.to_date)):
+ date = dt.strftime("%Y-%m-%d")
+ status = "Half Day" if date == self.half_day_date else "On Leave"
- if attendance:
- for d in attendance:
- doc = frappe.get_doc("Attendance", d.name)
- if getdate(self.half_day_date) == doc.attendance_date:
- status = "Half Day"
- else:
- status = "On Leave"
- frappe.db.sql("""update `tabAttendance` set status = %s, leave_type = %s\
- where name = %s""",(status, self.leave_type, d.name))
+ attendance_name = frappe.db.exists('Attendance', dict(employee = self.employee,
+ attenance_date = date, docstatus = ('!=', 2)))
- elif getdate(self.to_date) <= getdate(nowdate()):
- for dt in daterange(getdate(self.from_date), getdate(self.to_date)):
- date = dt.strftime("%Y-%m-%d")
+ if attendance_name:
+ # update existing attendance, change absent to on leave
+ doc = frappe.get_doc('Attendance', attendance_date)
+ if doc.status != status:
+ doc.db_set('status', status)
+ doc.db_set('leave_type', self.leave_type)
+ doc.db_set('leave_application', self.name)
+ else:
+ # make new attendance and submit it
doc = frappe.new_doc("Attendance")
doc.employee = self.employee
doc.attendance_date = date
doc.company = self.company
doc.leave_type = self.leave_type
- doc.status = "Half Day" if date == self.half_day_date else "On Leave"
+ doc.leave_application = self.name
+ doc.status = status
doc.flags.ignore_validate = True
doc.insert(ignore_permissions=True)
doc.submit()
diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py
index a682e8b76f..d3dcca1da0 100644
--- a/erpnext/hr/doctype/leave_application/test_leave_application.py
+++ b/erpnext/hr/doctype/leave_application/test_leave_application.py
@@ -7,7 +7,7 @@ import unittest
from erpnext.hr.doctype.leave_application.leave_application import LeaveDayBlockedError, OverlapError, NotAnOptionalHoliday, get_leave_balance_on
from frappe.permissions import clear_user_permissions_for_doctype
-from frappe.utils import add_days, nowdate, now_datetime
+from frappe.utils import add_days, nowdate, now_datetime, getdate
test_dependencies = ["Leave Allocation", "Leave Block List"]
@@ -67,6 +67,43 @@ class TestLeaveApplication(unittest.TestCase):
application.to_date = "2013-01-05"
return application
+ def test_attendance_creation(self):
+ '''check attendance is automatically created on leave approval'''
+ make_allocation_record()
+ application = self.get_application(_test_records[0])
+ application.status = 'Approved'
+ application.from_date = '2018-01-01'
+ application.to_date = '2018-01-03'
+ application.insert()
+ application.submit()
+
+ attendance = frappe.get_all('Attendance', ['name', 'status', 'attendance_date'], dict(leave_application = application.name))
+
+ # attendance created for all 3 days
+ self.assertEqual(len(attendance), 3)
+
+ # all on leave
+ self.assertTrue(all([d.status == 'On Leave' for d in attendance]))
+
+ # dates
+ dates = [d.attendance_date for d in attendance]
+ for d in ('2018-01-01', '2018-01-02', '2018-01-03'):
+ self.assertTrue(getdate(d) in dates)
+
+ def test_overwrite_attendance(self):
+ # employee marked as absent
+ doc = frappe.new_doc("Attendance")
+ doc.employee = '_T-Employee-00001'
+ doc.attendance_date = '2018-01-01'
+ doc.company = '_Test Company'
+ doc.status = 'Absent'
+ doc.flags.ignore_validate = True
+ doc.insert(ignore_permissions=True)
+ doc.submit()
+
+ # now check if the status has been updated
+ self.test_attendance_creation()
+
def test_block_list(self):
self._clear_roles()
@@ -428,7 +465,7 @@ def make_allocation_record(employee=None, leave_type=None):
"employee": employee or "_T-Employee-00001",
"leave_type": leave_type or "_Test Leave Type",
"from_date": "2013-01-01",
- "to_date": "2015-12-31",
+ "to_date": "2019-12-31",
"new_leaves_allocated": 30
})
From 96842c9de6f336ce23926e145cfe777bcc1e5559 Mon Sep 17 00:00:00 2001
From: Rushabh Mehta
Date: Fri, 8 Mar 2019 12:36:43 +0530
Subject: [PATCH 20/86] fix(typo): leave_application.py
---
erpnext/hr/doctype/leave_application/leave_application.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index 819bbf9d20..cb0484f58f 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -126,7 +126,7 @@ class LeaveApplication(Document):
if attendance_name:
# update existing attendance, change absent to on leave
- doc = frappe.get_doc('Attendance', attendance_date)
+ doc = frappe.get_doc('Attendance', attendance_name)
if doc.status != status:
doc.db_set('status', status)
doc.db_set('leave_type', self.leave_type)
From 1692fbaf1c6a1a2f839ad0b1806c1153c40ba92c Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Fri, 8 Mar 2019 18:37:34 +0530
Subject: [PATCH 21/86] fetch from fix
---
erpnext/regional/united_arab_emirates/setup.py | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py
index 3c8328b107..250659e54d 100644
--- a/erpnext/regional/united_arab_emirates/setup.py
+++ b/erpnext/regional/united_arab_emirates/setup.py
@@ -28,24 +28,24 @@ def make_custom_fields():
purchase_invoice_fields = [
dict(fieldname='company_trn', label='Company TRN',
fieldtype='Read Only', insert_after='shipping_address',
- options='company.tax_id', print_hide=1),
+ fetch_from='company.tax_id', print_hide=1),
dict(fieldname='supplier_name_in_arabic', label='Supplier Name in Arabic',
fieldtype='Read Only', insert_after='supplier_name',
- options='supplier.supplier_name_in_arabic', print_hide=1)
+ fetch_from='supplier.supplier_name_in_arabic', print_hide=1)
]
sales_invoice_fields = [
dict(fieldname='company_trn', label='Company TRN',
fieldtype='Read Only', insert_after='company_address',
- options='company.tax_id', print_hide=1),
+ fetch_from='company.tax_id', print_hide=1),
dict(fieldname='customer_name_in_arabic', label='Customer Name in Arabic',
fieldtype='Read Only', insert_after='customer_name',
- options='customer.customer_name_in_arabic', print_hide=1),
+ fetch_from='customer.customer_name_in_arabic', print_hide=1),
]
invoice_item_fields = [
dict(fieldname='tax_code', label='Tax Code',
- fieldtype='Read Only', options='item_code.tax_code', insert_after='description',
+ fieldtype='Read Only', fetch_from='item_code.tax_code', insert_after='description',
allow_on_submit=1, print_hide=1),
dict(fieldname='tax_rate', label='Tax Rate',
fieldtype='Float', insert_after='tax_code',
From 52729bf36934711d2d748f99b73be35fb4651da1 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Sun, 10 Mar 2019 14:26:30 +0530
Subject: [PATCH 22/86] feat: child table to add multiple time logs in job card
---
.../doctype/job_card/job_card.js | 29 ++-
.../doctype/job_card/job_card.json | 205 +++++++++++++----
.../doctype/job_card/job_card.py | 109 +++++----
.../doctype/job_card_time_log/__init__.py | 0
.../job_card_time_log/job_card_time_log.json | 208 ++++++++++++++++++
.../job_card_time_log/job_card_time_log.py | 9 +
.../doctype/work_order/test_work_order.py | 15 +-
erpnext/patches.txt | 1 +
.../patches/v11_1/make_job_card_time_logs.py | 29 +++
9 files changed, 513 insertions(+), 92 deletions(-)
create mode 100644 erpnext/manufacturing/doctype/job_card_time_log/__init__.py
create mode 100644 erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.json
create mode 100644 erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.py
create mode 100644 erpnext/patches/v11_1/make_job_card_time_logs.py
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.js b/erpnext/manufacturing/doctype/job_card/job_card.js
index 3fe9b8af30..95549d5a24 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.js
+++ b/erpnext/manufacturing/doctype/job_card/job_card.js
@@ -18,20 +18,27 @@ frappe.ui.form.on('Job Card', {
}
if (frm.doc.docstatus == 0) {
- if (!frm.doc.actual_start_date || !frm.doc.actual_end_date) {
- frm.trigger("make_dashboard");
- }
+ frm.trigger("make_dashboard");
- if (!frm.doc.actual_start_date) {
+ if (!frm.doc.job_started) {
frm.add_custom_button(__("Start Job"), () => {
- frm.set_value('actual_start_date', frappe.datetime.now_datetime());
+ let row = frappe.model.add_child(frm.doc, 'Job Card Time Log', 'time_logs');
+ row.from_time = frappe.datetime.now_datetime();
+ frm.set_value('job_started', 1);
+ frm.set_value('started_time' , row.from_time);
frm.save();
});
- } else if (!frm.doc.actual_end_date) {
+ } else {
frm.add_custom_button(__("Complete Job"), () => {
- frm.set_value('actual_end_date', frappe.datetime.now_datetime());
- frm.save();
- frm.savesubmit();
+ let completed_time = frappe.datetime.now_datetime();
+ frm.doc.time_logs.forEach(d => {
+ if (d.from_time && !d.to_time) {
+ d.to_time = completed_time;
+ frm.set_value('started_time' , '');
+ frm.set_value('job_started', 0);
+ frm.save();
+ }
+ })
});
}
}
@@ -53,8 +60,8 @@ frappe.ui.form.on('Job Card', {
var section = frm.dashboard.add_section(timer);
- if (frm.doc.actual_start_date) {
- let currentIncrement = moment(frappe.datetime.now_datetime()).diff(moment(frm.doc.actual_start_date),"seconds");
+ if (frm.doc.started_time) {
+ let currentIncrement = moment(frappe.datetime.now_datetime()).diff(moment(frm.doc.started_time),"seconds");
initialiseTimer();
function initialiseTimer() {
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.json b/erpnext/manufacturing/doctype/job_card/job_card.json
index b020c89053..39c5cce313 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.json
+++ b/erpnext/manufacturing/doctype/job_card/job_card.json
@@ -21,6 +21,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "work_order",
"fieldtype": "Link",
"hidden": 0,
@@ -54,6 +55,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "bom_no",
"fieldtype": "Link",
"hidden": 0,
@@ -87,6 +89,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "workstation",
"fieldtype": "Link",
"hidden": 0,
@@ -120,6 +123,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "operation",
"fieldtype": "Link",
"hidden": 0,
@@ -153,6 +157,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "column_break_4",
"fieldtype": "Column Break",
"hidden": 0,
@@ -185,6 +190,7 @@
"collapsible": 0,
"columns": 0,
"default": "Today",
+ "fetch_if_empty": 0,
"fieldname": "posting_date",
"fieldtype": "Date",
"hidden": 0,
@@ -217,6 +223,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -250,6 +257,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "for_quantity",
"fieldtype": "Float",
"hidden": 0,
@@ -282,6 +290,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "wip_warehouse",
"fieldtype": "Link",
"hidden": 0,
@@ -315,6 +324,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "timing_detail",
"fieldtype": "Section Break",
"hidden": 0,
@@ -347,6 +357,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "employee",
"fieldtype": "Link",
"hidden": 0,
@@ -380,7 +391,74 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "time_in_mins",
+ "fetch_if_empty": 0,
+ "fieldname": "time_logs",
+ "fieldtype": "Table",
+ "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": "Time Logs",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Job Card Time Log",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fetch_if_empty": 0,
+ "fieldname": "section_break_13",
+ "fieldtype": "Section Break",
+ "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,
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fetch_if_empty": 0,
+ "fieldname": "total_completed_qty",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -389,7 +467,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Time In Mins",
+ "label": "Total Completed Qty",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -412,7 +490,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "column_break_13",
+ "fetch_if_empty": 0,
+ "fieldname": "column_break_15",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -443,8 +522,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "actual_start_date",
- "fieldtype": "Datetime",
+ "fetch_if_empty": 0,
+ "fieldname": "total_time_in_mins",
+ "fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -452,46 +532,14 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Actual Start Date",
+ "label": "Total Time in Mins",
"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,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "actual_end_date",
- "fieldtype": "Datetime",
- "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": "Actual End Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
+ "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
@@ -507,6 +555,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "section_break_8",
"fieldtype": "Section Break",
"hidden": 0,
@@ -539,6 +588,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "items",
"fieldtype": "Table",
"hidden": 0,
@@ -572,6 +622,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "more_information",
"fieldtype": "Section Break",
"hidden": 0,
@@ -604,6 +655,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "operation_id",
"fieldtype": "Data",
"hidden": 1,
@@ -637,6 +689,7 @@
"collapsible": 0,
"columns": 0,
"default": "0",
+ "fetch_if_empty": 0,
"fieldname": "transferred_qty",
"fieldtype": "Float",
"hidden": 0,
@@ -670,6 +723,7 @@
"collapsible": 0,
"columns": 0,
"default": "0",
+ "fetch_if_empty": 0,
"fieldname": "requested_qty",
"fieldtype": "Float",
"hidden": 0,
@@ -702,6 +756,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "project",
"fieldtype": "Link",
"hidden": 0,
@@ -735,6 +790,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "remarks",
"fieldtype": "Small Text",
"hidden": 0,
@@ -767,6 +823,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "column_break_20",
"fieldtype": "Column Break",
"hidden": 0,
@@ -799,6 +856,7 @@
"collapsible": 0,
"columns": 0,
"default": "Open",
+ "fetch_if_empty": 0,
"fieldname": "status",
"fieldtype": "Select",
"hidden": 0,
@@ -832,6 +890,73 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
+ "fieldname": "job_started",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Job Started",
+ "length": 0,
+ "no_copy": 1,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fetch_if_empty": 0,
+ "fieldname": "started_time",
+ "fieldtype": "Datetime",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Started Time",
+ "length": 0,
+ "no_copy": 1,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
@@ -868,7 +993,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-12-13 17:23:57.986381",
+ "modified": "2019-03-10 17:38:37.499871",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Job Card",
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py
index ea9f714fc8..23a4e5105c 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/job_card.py
@@ -11,44 +11,56 @@ from frappe.model.document import Document
class JobCard(Document):
def validate(self):
- self.validate_actual_dates()
- self.set_time_in_mins()
+ self.validate_time_logs()
self.set_status()
- def validate_actual_dates(self):
- if get_datetime(self.actual_start_date) > get_datetime(self.actual_end_date):
- frappe.throw(_("Actual start date must be less than actual end date"))
+ def validate_time_logs(self):
+ self.total_completed_qty = 0.0
+ self.total_time_in_mins = 0.0
- if not (self.employee and self.actual_start_date and self.actual_end_date):
- return
+ for d in self.get('time_logs'):
+ if get_datetime(d.from_time) > get_datetime(d.to_time):
+ frappe.throw(_("Row {0}: From time must be less than to time").format(d.idx))
- data = frappe.db.sql(""" select name from `tabJob Card`
- where
- ((%(actual_start_date)s > actual_start_date and %(actual_start_date)s < actual_end_date) or
- (%(actual_end_date)s > actual_start_date and %(actual_end_date)s < actual_end_date) or
- (%(actual_start_date)s <= actual_start_date and %(actual_end_date)s >= actual_end_date)) and
- name != %(name)s and employee = %(employee)s and docstatus =1
- """, {
- 'actual_start_date': self.actual_start_date,
- 'actual_end_date': self.actual_end_date,
- 'employee': self.employee,
- 'name': self.name
- }, as_dict=1)
+ data = self.get_overlap_for(d)
+ if data:
+ frappe.throw(_("Row {0}: From Time and To Time of {1} is overlapping with {2}")
+ .format(d.idx, self.name, data.name))
- if data:
- frappe.throw(_("Start date and end date is overlapping with the job card {1}")
- .format(data[0].name, data[0].name))
+ if d.from_time and d.to_time:
+ d.time_in_mins = time_diff_in_hours(d.to_time, d.from_time) * 60
+ self.total_time_in_mins += d.time_in_mins
- def set_time_in_mins(self):
- if self.actual_start_date and self.actual_end_date:
- self.time_in_mins = time_diff_in_hours(self.actual_end_date, self.actual_start_date) * 60
+ if d.completed_qty:
+ self.total_completed_qty += d.completed_qty
+
+ def get_overlap_for(self, args):
+ existing = frappe.db.sql("""select jc.name as name from
+ `tabJob Card Time Log` jctl, `tabJob Card` jc where jctl.parent = jc.name and
+ (
+ (%(from_time)s > jctl.from_time and %(from_time)s < jctl.to_time) or
+ (%(to_time)s > jctl.from_time and %(to_time)s < jctl.to_time) or
+ (%(from_time)s <= jctl.from_time and %(to_time)s >= jctl.to_time))
+ and jctl.name!=%(name)s
+ and jc.name!=%(parent)s
+ and jc.docstatus < 2
+ and jc.employee = %(employee)s """,
+ {
+ "from_time": args.from_time,
+ "to_time": args.to_time,
+ "name": args.name or "No Name",
+ "parent": args.parent or "No Name",
+ "employee": self.employee
+ }, as_dict=True)
+
+ return existing[0] if existing else None
def get_required_items(self):
if not self.get('work_order'):
return
doc = frappe.get_doc('Work Order', self.get('work_order'))
- if doc.transfer_material_against == 'Work Order' and doc.skip_transfer:
+ if doc.transfer_material_against == 'Work Order' or doc.skip_transfer:
return
for d in doc.required_items:
@@ -67,36 +79,51 @@ class JobCard(Document):
})
def on_submit(self):
- self.validate_dates()
+ self.validate_job_card()
self.update_work_order()
self.set_transferred_qty()
- def validate_dates(self):
- if not self.actual_start_date and not self.actual_end_date:
- frappe.throw(_("Actual start date and actual end date is mandatory"))
-
def on_cancel(self):
self.update_work_order()
self.set_transferred_qty()
+ def validate_job_card(self):
+ if not self.time_logs:
+ frappe.throw(_("Time logs are required for job card {0}").format(self.name))
+
+ if self.total_completed_qty <= 0.0:
+ frappe.throw(_("Total completed qty must be greater than zero"))
+
+ if self.total_completed_qty > self.for_quantity:
+ frappe.throw(_("Total completed qty can not be greater than for quantity"))
+
def update_work_order(self):
if not self.work_order:
return
- data = frappe.db.get_value("Job Card", {'docstatus': 1, 'operation_id': self.operation_id},
- ['sum(time_in_mins)', 'min(actual_start_date)', 'max(actual_end_date)', 'sum(for_quantity)'])
+ for_quantity, time_in_mins = 0, 0
+ from_time_list, to_time_list = [], []
- if data:
- time_in_mins, actual_start_date, actual_end_date, for_quantity = data
+ for d in frappe.get_all('Job Card',
+ filters = {'docstatus': 1, 'operation_id': self.operation_id}):
+ doc = frappe.get_doc('Job Card', d.name)
+
+ for_quantity += doc.total_completed_qty
+ time_in_mins += doc.total_time_in_mins
+ for time_log in doc.time_logs:
+ from_time_list.append(time_log.from_time)
+ to_time_list.append(time_log.to_time)
+
+ if for_quantity:
wo = frappe.get_doc('Work Order', self.work_order)
for data in wo.operations:
if data.name == self.operation_id:
data.completed_qty = for_quantity
data.actual_operation_time = time_in_mins
- data.actual_start_time = actual_start_date
- data.actual_end_time = actual_end_date
+ data.actual_start_time = min(from_time_list)
+ data.actual_end_time = max(to_time_list)
wo.flags.ignore_validate_update_after_submit = True
wo.update_operation_status()
@@ -132,9 +159,11 @@ class JobCard(Document):
break
if completed:
- job_cards = frappe.get_all('Job Card', filters = {'work_order': self.work_order,
+ job_cards = frappe.get_all('Job Card', filters = {'work_order': self.work_order,
'docstatus': ('!=', 2)}, fields = 'sum(transferred_qty) as qty', group_by='operation_id')
- qty = min([d.qty for d in job_cards])
+
+ if job_cards:
+ qty = min([d.qty for d in job_cards])
doc.db_set('material_transferred_for_manufacturing', qty)
@@ -147,7 +176,7 @@ class JobCard(Document):
2: "Cancelled"
}[self.docstatus or 0]
- if self.actual_start_date:
+ if self.time_logs:
self.status = 'Work In Progress'
if (self.docstatus == 1 and
diff --git a/erpnext/manufacturing/doctype/job_card_time_log/__init__.py b/erpnext/manufacturing/doctype/job_card_time_log/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.json b/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.json
new file mode 100644
index 0000000000..2aab71dee4
--- /dev/null
+++ b/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.json
@@ -0,0 +1,208 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2019-03-08 23:56:43.187569",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fetch_if_empty": 0,
+ "fieldname": "from_time",
+ "fieldtype": "Datetime",
+ "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": "From Time",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fetch_if_empty": 0,
+ "fieldname": "to_time",
+ "fieldtype": "Datetime",
+ "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": "To Time",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fetch_if_empty": 0,
+ "fieldname": "column_break_2",
+ "fieldtype": "Column Break",
+ "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,
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fetch_if_empty": 0,
+ "fieldname": "time_in_mins",
+ "fieldtype": "Float",
+ "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": "Time In Mins",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "0",
+ "fetch_if_empty": 0,
+ "fieldname": "completed_qty",
+ "fieldtype": "Float",
+ "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": "Completed Qty",
+ "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": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2019-03-10 17:08:46.504910",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Job Card Time Log",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.py b/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.py
new file mode 100644
index 0000000000..3dc6689121
--- /dev/null
+++ b/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.py
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+from frappe.model.document import Document
+
+class JobCardTimeLog(Document):
+ pass
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py
index 69381c53b3..b292047aa6 100644
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py
@@ -302,6 +302,19 @@ class TestWorkOrder(unittest.TestCase):
self.assertEqual(len(ste.additional_costs), 1)
self.assertEqual(ste.total_additional_costs, 1000)
+ def test_job_card(self):
+ data = frappe.get_cached_value('BOM',
+ {'docstatus': 1, 'with_operations': 1, 'company': '_Test Company'}, ['name', 'item'])
+
+ if data:
+ bom, bom_item = data
+
+ bom_doc = frappe.get_doc('BOM', bom)
+ work_order = make_wo_order_test_record(item=bom_item, qty=1, bom_no=bom)
+
+ job_cards = frappe.get_all('Job Card', filters = {'work_order': work_order})
+ self.assertEqual(len(job_cards), len(bom_doc.operations))
+
def test_work_order_with_non_transfer_item(self):
items = {'Finished Good Transfer Item': 1, '_Test FG Item': 1, '_Test FG Item 1': 0}
for item, allow_transfer in items.items():
@@ -346,7 +359,7 @@ def make_wo_order_test_record(**args):
wo_order = frappe.new_doc("Work Order")
wo_order.production_item = args.production_item or args.item or args.item_code or "_Test FG Item"
- wo_order.bom_no = frappe.db.get_value("BOM", {"item": wo_order.production_item,
+ wo_order.bom_no = args.bom_no or frappe.db.get_value("BOM", {"item": wo_order.production_item,
"is_active": 1, "is_default": 1})
wo_order.qty = args.qty or 10
wo_order.wip_warehouse = args.wip_warehouse or "_Test Warehouse - _TC"
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 433141cdf6..7d49ad5fe3 100755
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -588,3 +588,4 @@ execute:frappe.delete_doc('DocType', 'Notification Control')
erpnext.patches.v11_0.remove_barcodes_field_from_copy_fields_to_variants
erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019
erpnext.patches.v11_0.make_italian_localization_fields # 01-03-2019
+erpnext.patches.v11_1.make_job_card_time_logs
\ No newline at end of file
diff --git a/erpnext/patches/v11_1/make_job_card_time_logs.py b/erpnext/patches/v11_1/make_job_card_time_logs.py
new file mode 100644
index 0000000000..6e708df48d
--- /dev/null
+++ b/erpnext/patches/v11_1/make_job_card_time_logs.py
@@ -0,0 +1,29 @@
+# Copyright (c) 2015, Frappe 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('manufacturing', 'doctype', 'job_card_time_log')
+
+ if (frappe.db.table_exists("Job Card")
+ and frappe.get_meta("Job Card").has_field("actual_start_date")):
+ time_logs = []
+ for d in frappe.get_all('Job Card',
+ fields = ["actual_start_date", "actual_end_date", "time_in_mins", "name", "for_quantity"],
+ filters = {'docstatus': ("<", 2)}):
+ if d.actual_start_date:
+ time_logs.append([d.actual_start_date, d.actual_end_date, d.time_in_mins,
+ d.for_quantity, d.name, 'Job Card', 'time_logs', frappe.generate_hash("", 10)])
+
+ if time_logs:
+ frappe.db.sql(""" INSERT INTO
+ `tabJob Card Time Log`
+ (from_time, to_time, time_in_mins, completed_qty, parent, parenttype, parentfield, name)
+ values {values}
+ """.format(values = ','.join(['%s'] * len(time_logs))), tuple(time_logs))
+
+ frappe.reload_doc('manufacturing', 'doctype', 'job_card')
+ frappe.db.sql(""" update `tabJob Card` set total_completed_qty = for_quantity,
+ total_time_in_mins = time_in_mins where docstatus < 2 """)
\ No newline at end of file
From 175709ed5070ebd1b61394e42b39e84595cf507e Mon Sep 17 00:00:00 2001
From: Faris Ansari
Date: Tue, 12 Mar 2019 10:55:39 +0530
Subject: [PATCH 23/86] fix: Update Training Level
- Rename Expert to Intermediate, since it was ambiguous with Advance
---
erpnext/hr/doctype/training_event/training_event.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/hr/doctype/training_event/training_event.json b/erpnext/hr/doctype/training_event/training_event.json
index 4b812a992e..527ac1bc8f 100644
--- a/erpnext/hr/doctype/training_event/training_event.json
+++ b/erpnext/hr/doctype/training_event/training_event.json
@@ -214,7 +214,7 @@
"label": "Level",
"length": 0,
"no_copy": 0,
- "options": "\nBeginner\nExpert\nAdvance",
+ "options": "\nBeginner\nIntermediate\nAdvance",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -847,4 +847,4 @@
"title_field": "event_name",
"track_changes": 0,
"track_seen": 0
-}
\ No newline at end of file
+}
From 47f1080f1e4e819c88c94fd87489c7a08e2eaa21 Mon Sep 17 00:00:00 2001
From: Faris Ansari
Date: Tue, 12 Mar 2019 10:57:35 +0530
Subject: [PATCH 24/86] fix: Update modified
---
erpnext/hr/doctype/training_event/training_event.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/hr/doctype/training_event/training_event.json b/erpnext/hr/doctype/training_event/training_event.json
index 527ac1bc8f..fcf845a587 100644
--- a/erpnext/hr/doctype/training_event/training_event.json
+++ b/erpnext/hr/doctype/training_event/training_event.json
@@ -809,7 +809,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-10-23 06:13:29.065781",
+ "modified": "2019-03-12 10:56:29.065781",
"modified_by": "Administrator",
"module": "HR",
"name": "Training Event",
From b4745ec6683075e7d077984eb7b614a0c755bd6b Mon Sep 17 00:00:00 2001
From: Rohan Bansal
Date: Mon, 4 Feb 2019 17:52:51 +0530
Subject: [PATCH 25/86] fix(work_order): Change Work Order title to show item
name instead of item code
---
.../doctype/work_order/work_order.js | 5 +-
.../doctype/work_order/work_order.json | 3275 +++++++++--------
.../doctype/work_order/work_order.py | 7 +-
erpnext/patches.txt | 1 +
.../v12_0/add_item_name_in_work_orders.py | 13 +
5 files changed, 1674 insertions(+), 1627 deletions(-)
mode change 100644 => 100755 erpnext/patches.txt
create mode 100644 erpnext/patches/v12_0/add_item_name_in_work_orders.py
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js
index 8a8a6c900c..8ce6154656 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.js
+++ b/erpnext/manufacturing/doctype/work_order/work_order.js
@@ -303,8 +303,9 @@ frappe.ui.form.on("Work Order", {
frm.set_value('sales_order', "");
frm.trigger('set_sales_order');
erpnext.in_production_item_onchange = true;
- $.each(["description", "stock_uom", "project", "bom_no",
- "allow_alternative_item", "transfer_material_against"], function(i, field) {
+
+ $.each(["description", "stock_uom", "project", "bom_no", "allow_alternative_item",
+ "transfer_material_against", "item_name"], function(i, field) {
frm.set_value(field, r.message[field]);
});
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.json b/erpnext/manufacturing/doctype/work_order/work_order.json
index a65d04f61b..f22697fe27 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.json
+++ b/erpnext/manufacturing/doctype/work_order/work_order.json
@@ -1,1732 +1,1765 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "autoname": "naming_series:",
- "beta": 0,
- "creation": "2013-01-10 16:34:16",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 0,
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 1,
+ "allow_rename": 0,
+ "autoname": "naming_series:",
+ "beta": 0,
+ "creation": "2013-01-10 16:34:16",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 0,
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "item",
- "fieldtype": "Section Break",
- "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": "",
- "length": 0,
- "no_copy": 0,
- "options": "fa fa-gift",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "item",
+ "fieldtype": "Section Break",
+ "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": "",
+ "length": 0,
+ "no_copy": 0,
+ "options": "fa fa-gift",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fieldname": "naming_series",
- "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": "Series",
- "length": 0,
- "no_copy": 0,
- "options": "MFG-WO-.YYYY.-",
- "permlevel": 0,
- "print_hide": 1,
- "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": 1,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "",
+ "fieldname": "naming_series",
+ "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": "Series",
+ "length": 0,
+ "no_copy": 0,
+ "options": "MFG-WO-.YYYY.-",
+ "permlevel": 0,
+ "print_hide": 1,
+ "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": 1,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Draft",
- "depends_on": "eval:!doc.__islocal",
- "fieldname": "status",
- "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": "Status",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "status",
- "oldfieldtype": "Select",
- "options": "\nDraft\nSubmitted\nNot Started\nIn Process\nCompleted\nStopped\nCancelled",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "Draft",
+ "depends_on": "eval:!doc.__islocal",
+ "fieldname": "status",
+ "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": "Status",
+ "length": 0,
+ "no_copy": 1,
+ "oldfieldname": "status",
+ "oldfieldtype": "Select",
+ "options": "\nDraft\nSubmitted\nNot Started\nIn Process\nCompleted\nStopped\nCancelled",
+ "permlevel": 0,
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 1,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "production_item",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Item To Manufacture",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "production_item",
- "oldfieldtype": "Link",
- "options": "Item",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "production_item",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 1,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Item To Manufacture",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "production_item",
+ "oldfieldtype": "Link",
+ "options": "Item",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "description": "",
- "fieldname": "bom_no",
- "fieldtype": "Link",
- "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": "BOM No",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "bom_no",
- "oldfieldtype": "Link",
- "options": "BOM",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "eval:doc.production_item",
+ "fieldname": "item_name",
+ "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": "Item Name",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "allow_alternative_item",
- "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": "Allow Alternative Item",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "",
+ "description": "",
+ "fieldname": "bom_no",
+ "fieldtype": "Link",
+ "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": "BOM No",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "bom_no",
+ "oldfieldtype": "Link",
+ "options": "BOM",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "description": "Plan material for sub-assemblies",
- "fieldname": "use_multi_level_bom",
- "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": "Use Multi-Level BOM",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "allow_alternative_item",
+ "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": "Allow Alternative Item",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "Check if material transfer entry is not required",
- "fieldname": "skip_transfer",
- "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": "Skip Material Transfer",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "1",
+ "description": "Plan material for sub-assemblies",
+ "fieldname": "use_multi_level_bom",
+ "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": "Use Multi-Level BOM",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "print_hide": 1,
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break1",
- "fieldtype": "Column Break",
- "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,
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Column Break",
- "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,
- "translatable": 0,
- "unique": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "description": "Check if material transfer entry is not required",
+ "fieldname": "skip_transfer",
+ "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": "Skip Material Transfer",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break1",
+ "fieldtype": "Column Break",
+ "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,
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldtype": "Column Break",
+ "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,
+ "translatable": 0,
+ "unique": 0,
"width": "50%"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "company",
- "fieldtype": "Link",
- "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": "Company",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "company",
- "oldfieldtype": "Link",
- "options": "Company",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 1,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "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": "Company",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "company",
+ "oldfieldtype": "Link",
+ "options": "Company",
+ "permlevel": 0,
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 1,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "qty",
- "fieldtype": "Float",
- "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": "Qty To Manufacture",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "qty",
- "oldfieldtype": "Currency",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "",
+ "fieldname": "qty",
+ "fieldtype": "Float",
+ "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": "Qty To Manufacture",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "qty",
+ "oldfieldtype": "Currency",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "depends_on": "eval:doc.docstatus==1 && doc.skip_transfer==0",
- "description": "",
- "fieldname": "material_transferred_for_manufacturing",
- "fieldtype": "Float",
- "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": "Material Transferred for Manufacturing",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "0",
+ "depends_on": "eval:doc.docstatus==1 && doc.skip_transfer==0",
+ "description": "",
+ "fieldname": "material_transferred_for_manufacturing",
+ "fieldtype": "Float",
+ "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": "Material Transferred for Manufacturing",
+ "length": 0,
+ "no_copy": 1,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "depends_on": "eval:doc.docstatus==1",
- "description": "",
- "fieldname": "produced_qty",
- "fieldtype": "Float",
- "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": "Manufactured Qty",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "produced_qty",
- "oldfieldtype": "Currency",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "0",
+ "depends_on": "eval:doc.docstatus==1",
+ "description": "",
+ "fieldname": "produced_qty",
+ "fieldtype": "Float",
+ "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": "Manufactured Qty",
+ "length": 0,
+ "no_copy": 1,
+ "oldfieldname": "produced_qty",
+ "oldfieldtype": "Currency",
+ "permlevel": 0,
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "",
- "fieldname": "sales_order",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Sales Order",
- "length": 0,
- "no_copy": 0,
- "options": "Sales Order",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 1,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "description": "",
+ "fieldname": "sales_order",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 1,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Sales Order",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Sales Order",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "project",
- "fieldtype": "Link",
- "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": "Project",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "project",
- "oldfieldtype": "Link",
- "options": "Project",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "project",
+ "fieldtype": "Link",
+ "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": "Project",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "project",
+ "oldfieldtype": "Link",
+ "options": "Project",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "skip_transfer",
- "fieldname": "from_wip_warehouse",
- "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": "Backflush raw materials from work-in-progress warehouse",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "skip_transfer",
+ "fieldname": "from_wip_warehouse",
+ "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": "Backflush raw materials from work-in-progress warehouse",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "warehouses",
- "fieldtype": "Section Break",
- "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": "Warehouses",
- "length": 0,
- "no_copy": 0,
- "options": "fa fa-building",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "warehouses",
+ "fieldtype": "Section Break",
+ "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": "Warehouses",
+ "length": 0,
+ "no_copy": 0,
+ "options": "fa fa-building",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "wip_warehouse",
- "fieldtype": "Link",
- "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": "Work-in-Progress Warehouse",
- "length": 0,
- "no_copy": 0,
- "options": "Warehouse",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "wip_warehouse",
+ "fieldtype": "Link",
+ "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": "Work-in-Progress Warehouse",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Warehouse",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "description": "",
- "fieldname": "fg_warehouse",
- "fieldtype": "Link",
- "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": "Target Warehouse",
- "length": 0,
- "no_copy": 0,
- "options": "Warehouse",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "",
+ "description": "",
+ "fieldname": "fg_warehouse",
+ "fieldtype": "Link",
+ "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": "Target Warehouse",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Warehouse",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_12",
- "fieldtype": "Column Break",
- "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,
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_12",
+ "fieldtype": "Column Break",
+ "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,
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "scrap_warehouse",
- "fieldtype": "Link",
- "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": "Scrap Warehouse",
- "length": 0,
- "no_copy": 0,
- "options": "Warehouse",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "scrap_warehouse",
+ "fieldtype": "Link",
+ "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": "Scrap Warehouse",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Warehouse",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "required_items_section",
- "fieldtype": "Section Break",
- "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": "Required Items",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "required_items_section",
+ "fieldtype": "Section Break",
+ "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": "Required Items",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "required_items",
- "fieldtype": "Table",
- "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": "Required Items",
- "length": 0,
- "no_copy": 1,
- "options": "Work Order Item",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "required_items",
+ "fieldtype": "Table",
+ "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": "Required Items",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Work Order Item",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "time",
- "fieldtype": "Section Break",
- "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": "Time",
- "length": 0,
- "no_copy": 0,
- "options": "fa fa-time",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "time",
+ "fieldtype": "Section Break",
+ "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": "Time",
+ "length": 0,
+ "no_copy": 0,
+ "options": "fa fa-time",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "now",
- "fieldname": "planned_start_date",
- "fieldtype": "Datetime",
- "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": "Planned Start Date",
- "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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 1,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "now",
+ "fieldname": "planned_start_date",
+ "fieldtype": "Datetime",
+ "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": "Planned Start Date",
+ "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": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "actual_start_date",
- "fieldtype": "Datetime",
- "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": "Actual Start Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "actual_start_date",
+ "fieldtype": "Datetime",
+ "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": "Actual Start Date",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_13",
- "fieldtype": "Column Break",
- "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,
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_13",
+ "fieldtype": "Column Break",
+ "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,
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "planned_end_date",
- "fieldtype": "Datetime",
- "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": "Planned End Date",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "planned_end_date",
+ "fieldtype": "Datetime",
+ "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": "Planned End Date",
+ "length": 0,
+ "no_copy": 1,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "actual_end_date",
- "fieldtype": "Datetime",
- "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": "Actual End Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "actual_end_date",
+ "fieldtype": "Datetime",
+ "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": "Actual End Date",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "expected_delivery_date",
- "fieldtype": "Date",
- "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": "Expected Delivery Date",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 1,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "",
+ "fieldname": "expected_delivery_date",
+ "fieldtype": "Date",
+ "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": "Expected Delivery Date",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "operations_section",
- "fieldtype": "Section Break",
- "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": "Operations",
- "length": 0,
- "no_copy": 0,
- "options": "fa fa-wrench",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "",
+ "fieldname": "operations_section",
+ "fieldtype": "Section Break",
+ "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": "Operations",
+ "length": 0,
+ "no_copy": 0,
+ "options": "fa fa-wrench",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Work Order",
- "depends_on": "operations",
- "fieldname": "transfer_material_against",
- "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": "Transfer Material Against",
- "length": 0,
- "no_copy": 0,
- "options": "\nWork Order\nJob Card",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "Work Order",
+ "depends_on": "operations",
+ "fieldname": "transfer_material_against",
+ "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": "Transfer Material Against",
+ "length": 0,
+ "no_copy": 0,
+ "options": "\nWork Order\nJob Card",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "operations",
- "fieldtype": "Table",
- "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": "Operations",
- "length": 0,
- "no_copy": 0,
- "options": "Work Order Operation",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "",
+ "fieldname": "operations",
+ "fieldtype": "Table",
+ "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": "Operations",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Work Order Operation",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "operations",
- "fieldname": "section_break_22",
- "fieldtype": "Section Break",
- "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": "Operation Cost",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "operations",
+ "fieldname": "section_break_22",
+ "fieldtype": "Section Break",
+ "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": "Operation Cost",
+ "length": 0,
+ "no_copy": 0,
+ "options": "",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "planned_operating_cost",
- "fieldtype": "Currency",
- "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": "Planned Operating Cost",
- "length": 0,
- "no_copy": 0,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "planned_operating_cost",
+ "fieldtype": "Currency",
+ "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": "Planned Operating Cost",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Company:company:default_currency",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "actual_operating_cost",
- "fieldtype": "Currency",
- "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": "Actual Operating Cost",
- "length": 0,
- "no_copy": 1,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "actual_operating_cost",
+ "fieldtype": "Currency",
+ "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": "Actual Operating Cost",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "additional_operating_cost",
- "fieldtype": "Currency",
- "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": "Additional Operating Cost",
- "length": 0,
- "no_copy": 1,
- "options": "Company:company:default_currency",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "additional_operating_cost",
+ "fieldtype": "Currency",
+ "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": "Additional Operating Cost",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_24",
- "fieldtype": "Column Break",
- "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,
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_24",
+ "fieldtype": "Column Break",
+ "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,
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "total_operating_cost",
- "fieldtype": "Currency",
- "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": "Total Operating Cost",
- "length": 0,
- "no_copy": 1,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "total_operating_cost",
+ "fieldtype": "Currency",
+ "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": "Total Operating Cost",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fieldname": "more_info",
- "fieldtype": "Section Break",
- "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": "More Information",
- "length": 0,
- "no_copy": 0,
- "options": "fa fa-file-text",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 1,
+ "columns": 0,
+ "fieldname": "more_info",
+ "fieldtype": "Section Break",
+ "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": "More Information",
+ "length": 0,
+ "no_copy": 0,
+ "options": "fa fa-file-text",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "description",
- "fieldtype": "Small Text",
- "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": "Item Description",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "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": "Item Description",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "stock_uom",
- "fieldtype": "Link",
- "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": "Stock UOM",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "stock_uom",
- "oldfieldtype": "Data",
- "options": "UOM",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "",
+ "fieldname": "stock_uom",
+ "fieldtype": "Link",
+ "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": "Stock UOM",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "stock_uom",
+ "oldfieldtype": "Data",
+ "options": "UOM",
+ "permlevel": 0,
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break2",
- "fieldtype": "Column Break",
- "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,
- "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,
- "translatable": 0,
- "unique": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break2",
+ "fieldtype": "Column Break",
+ "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,
+ "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,
+ "translatable": 0,
+ "unique": 0,
"width": "50%"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "Manufacture against Material Request",
- "fieldname": "material_request",
- "fieldtype": "Link",
- "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": "Material Request",
- "length": 0,
- "no_copy": 0,
- "options": "Material Request",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "description": "Manufacture against Material Request",
+ "fieldname": "material_request",
+ "fieldtype": "Link",
+ "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": "Material Request",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Material Request",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "material_request_item",
- "fieldtype": "Data",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Material Request Item",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "material_request_item",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Material Request Item",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sales_order_item",
- "fieldtype": "Data",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Sales Order Item",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "sales_order_item",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Sales Order Item",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "production_plan",
- "fieldtype": "Link",
- "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": "Production Plan",
- "length": 0,
- "no_copy": 1,
- "options": "Production Plan",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "production_plan",
+ "fieldtype": "Link",
+ "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": "Production Plan",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Production Plan",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "production_plan_item",
- "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": "Production Plan Item",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "production_plan_item",
+ "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": "Production Plan Item",
+ "length": 0,
+ "no_copy": 1,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "product_bundle_item",
- "fieldtype": "Link",
- "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": "Product Bundle Item",
- "length": 0,
- "no_copy": 1,
- "options": "Item",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "product_bundle_item",
+ "fieldtype": "Link",
+ "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": "Product Bundle Item",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Item",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amended_from",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Amended From",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "amended_from",
- "oldfieldtype": "Data",
- "options": "Work Order",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 1,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Amended From",
+ "length": 0,
+ "no_copy": 1,
+ "oldfieldname": "amended_from",
+ "oldfieldtype": "Data",
+ "options": "Work Order",
+ "permlevel": 0,
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "icon": "fa fa-cogs",
- "idx": 1,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-12-13 15:33:12.490710",
- "modified_by": "Administrator",
- "module": "Manufacturing",
- "name": "Work Order",
- "owner": "Administrator",
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "icon": "fa fa-cogs",
+ "idx": 1,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 1,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2019-02-05 03:02:39.126868",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Work Order",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 1,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Manufacturing User",
- "set_user_permissions": 1,
- "share": 1,
- "submit": 1,
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 1,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Manufacturing User",
+ "set_user_permissions": 1,
+ "share": 1,
+ "submit": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 0,
- "read": 1,
- "report": 1,
- "role": "Stock User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
+ "amend": 0,
+ "cancel": 0,
+ "create": 0,
+ "delete": 0,
+ "email": 0,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 0,
+ "read": 1,
+ "report": 1,
+ "role": "Stock User",
+ "set_user_permissions": 0,
+ "share": 0,
+ "submit": 0,
"write": 0
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_order": "ASC",
- "title_field": "production_item",
- "track_changes": 1,
- "track_seen": 1,
+ ],
+ "quick_entry": 0,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_order": "ASC",
+ "title_field": "production_item",
+ "track_changes": 1,
+ "track_seen": 1,
"track_views": 0
}
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index 947d6931e2..59a88d46da 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -568,11 +568,10 @@ def get_item_details(item, project = None):
frappe.throw(_("Default BOM for {0} not found").format(item))
bom_data = frappe.db.get_value('BOM', res['bom_no'],
- ['project', 'allow_alternative_item', 'transfer_material_against'], as_dict=1)
+ ['project', 'allow_alternative_item', 'transfer_material_against', 'item_name'], as_dict=1)
- res['project'] = project or bom_data.project
- res['allow_alternative_item'] = bom_data.allow_alternative_item
- res['transfer_material_against'] = bom_data.transfer_material_against
+ res['project'] = project or bom_data.pop("project")
+ res.update(bom_data)
res.update(check_if_scrap_warehouse_mandatory(res["bom_no"]))
return res
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
old mode 100644
new mode 100755
index b7e673da34..3785ec4fc7
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -586,3 +586,4 @@ erpnext.patches.v11_0.remove_barcodes_field_from_copy_fields_to_variants
erpnext.patches.v12_0.set_task_status
erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019
erpnext.patches.v11_0.make_italian_localization_fields # 01-03-2019
+erpnext.patches.v12_0.add_item_name_in_work_orders
diff --git a/erpnext/patches/v12_0/add_item_name_in_work_orders.py b/erpnext/patches/v12_0/add_item_name_in_work_orders.py
new file mode 100644
index 0000000000..35d526aaa3
--- /dev/null
+++ b/erpnext/patches/v12_0/add_item_name_in_work_orders.py
@@ -0,0 +1,13 @@
+import frappe
+
+
+def execute():
+ frappe.reload_doc("manufacturing", "doctype", "work_order")
+
+ for wo in frappe.get_all("Work Order"):
+ item_code = frappe.db.get_value("Work Order", wo.name, "production_item")
+ item_name = frappe.db.get_value("Item", item_code, "item_name")
+
+ frappe.db.set_value("Work Order", wo.name, "item_name", item_name, update_modified=False)
+
+ frappe.db.commit()
\ No newline at end of file
From 6cbd3998fb143c48396841fa7c8fe8c3c4c4574b Mon Sep 17 00:00:00 2001
From: Rohan Bansal
Date: Mon, 18 Feb 2019 12:29:57 +0530
Subject: [PATCH 26/86] fix(work_order): Use single update query
---
erpnext/patches.txt | 2 +-
.../patches/v12_0/add_item_name_in_work_orders.py | 13 +++++++------
2 files changed, 8 insertions(+), 7 deletions(-)
mode change 100755 => 100644 erpnext/patches.txt
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
old mode 100755
new mode 100644
index 3785ec4fc7..ee86816593
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -586,4 +586,4 @@ erpnext.patches.v11_0.remove_barcodes_field_from_copy_fields_to_variants
erpnext.patches.v12_0.set_task_status
erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019
erpnext.patches.v11_0.make_italian_localization_fields # 01-03-2019
-erpnext.patches.v12_0.add_item_name_in_work_orders
+erpnext.patches.v12_0.add_item_name_in_work_orders
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/add_item_name_in_work_orders.py b/erpnext/patches/v12_0/add_item_name_in_work_orders.py
index 35d526aaa3..485dd314a1 100644
--- a/erpnext/patches/v12_0/add_item_name_in_work_orders.py
+++ b/erpnext/patches/v12_0/add_item_name_in_work_orders.py
@@ -4,10 +4,11 @@ import frappe
def execute():
frappe.reload_doc("manufacturing", "doctype", "work_order")
- for wo in frappe.get_all("Work Order"):
- item_code = frappe.db.get_value("Work Order", wo.name, "production_item")
- item_name = frappe.db.get_value("Item", item_code, "item_name")
-
- frappe.db.set_value("Work Order", wo.name, "item_name", item_name, update_modified=False)
-
+ frappe.db.sql("""
+ UPDATE
+ `tabWork Order` wo
+ JOIN `tabItem` item ON wo.production_item = item.item_code
+ SET
+ wo.item_name = item.item_name
+ """)
frappe.db.commit()
\ No newline at end of file
From e14758c89713c07ce35f15d6ff1a011aab95e999 Mon Sep 17 00:00:00 2001
From: Bassam Ramadan
Date: Thu, 14 Mar 2019 11:31:50 +0200
Subject: [PATCH 27/86] fix: add returns field to cashier closing (#16911)
---
.../cashier_closing/cashier_closing.json | 858 +++++++++---------
.../cashier_closing/cashier_closing.py | 4 +-
2 files changed, 435 insertions(+), 427 deletions(-)
diff --git a/erpnext/accounts/doctype/cashier_closing/cashier_closing.json b/erpnext/accounts/doctype/cashier_closing/cashier_closing.json
index 14e9070f30..115728dc7b 100644
--- a/erpnext/accounts/doctype/cashier_closing/cashier_closing.json
+++ b/erpnext/accounts/doctype/cashier_closing/cashier_closing.json
@@ -1,426 +1,434 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "naming_series:",
- "beta": 0,
- "creation": "2018-06-18 16:51:49.994750",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Cashier-closing-",
- "fieldname": "naming_series",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 1,
- "in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 1,
- "label": "Series",
- "length": 0,
- "no_copy": 0,
- "options": "Cashier-closing-",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "user",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "User",
- "length": 0,
- "no_copy": 0,
- "options": "User",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Today",
- "fieldname": "date",
- "fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 1,
- "label": "Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "from_time",
- "fieldtype": "Time",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 1,
- "label": "From Time",
- "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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fieldname": "time",
- "fieldtype": "Time",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 1,
- "label": "To Time",
- "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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0.00",
- "fieldname": "expense",
- "fieldtype": "Float",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Expense",
- "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,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0.00",
- "fieldname": "custody",
- "fieldtype": "Float",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Custody",
- "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,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0.00",
- "fieldname": "outstanding_amount",
- "fieldtype": "Float",
- "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": "Outstanding Amount",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0.0",
- "fieldname": "payments",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Payments",
- "length": 0,
- "no_copy": 0,
- "options": "Cashier Closing Payments",
- "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,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "net_amount",
- "fieldtype": "Float",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Net Amount",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amended_from",
- "fieldtype": "Link",
- "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": "Amended From",
- "length": 0,
- "no_copy": 1,
- "options": "Cashier Closing",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2019-02-19 08:35:23.157327",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Cashier Closing",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
- "write": 1
- }
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
-}
\ No newline at end of file
+ "allow_copy": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "autoname": "naming_series:",
+ "beta": 0,
+ "creation": "2018-06-18 16:51:49.994750",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "POS-CLO-",
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_global_search": 1,
+ "in_list_view": 0,
+ "in_standard_filter": 1,
+ "label": "Series",
+ "length": 0,
+ "no_copy": 0,
+ "options": "POS-CLO-",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "user",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "User",
+ "length": 0,
+ "no_copy": 0,
+ "options": "User",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "Today",
+ "fieldname": "date",
+ "fieldtype": "Date",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 1,
+ "label": "Date",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "from_time",
+ "fieldtype": "Time",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 1,
+ "label": "From Time",
+ "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": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "",
+ "fieldname": "time",
+ "fieldtype": "Time",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 1,
+ "label": "To Time",
+ "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": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "0.00",
+ "fieldname": "expense",
+ "fieldtype": "Float",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Expense",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "2",
+ "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_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "0.00",
+ "fieldname": "custody",
+ "fieldtype": "Float",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Custody",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "2",
+ "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_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "0.00",
+ "fieldname": "returns",
+ "fieldtype": "Float",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Returns",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "2",
+ "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_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "0.00",
+ "fieldname": "outstanding_amount",
+ "fieldtype": "Float",
+ "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": "Outstanding Amount",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "2",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "0.0",
+ "fieldname": "payments",
+ "fieldtype": "Table",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Payments",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Cashier Closing Payments",
+ "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_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "net_amount",
+ "fieldtype": "Float",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 1,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Net Amount",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "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": "Amended From",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Cashier Closing",
+ "permlevel": 0,
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 1,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2019-03-14 09:14:26.727129",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Cashier Closing",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 0,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0
+ }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/cashier_closing/cashier_closing.py b/erpnext/accounts/doctype/cashier_closing/cashier_closing.py
index 906bc7f18a..6de62ee577 100644
--- a/erpnext/accounts/doctype/cashier_closing/cashier_closing.py
+++ b/erpnext/accounts/doctype/cashier_closing/cashier_closing.py
@@ -29,8 +29,8 @@ class CashierClosing(Document):
for i in self.payments:
total += flt(i.amount)
- self.net_amount = total + self.outstanding_amount + self.expense - self.custody
+ self.net_amount = total + self.outstanding_amount + self.expense - self.custody + self.returns
def validate_time(self):
if self.from_time >= self.time:
- frappe.throw(_("From Time Should Be Less Than To Time"))
+ frappe.throw(_("From Time Should Be Less Than To Time"))
\ No newline at end of file
From 59a3012a5ce3b9e0229ed54d64f421da9cf60df7 Mon Sep 17 00:00:00 2001
From: Rushabh Mehta
Date: Fri, 15 Mar 2019 08:57:49 +0530
Subject: [PATCH 28/86] Update payment_request.py
---
.../accounts/doctype/payment_request/payment_request.py | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index 1fbde753d4..64c4124da6 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -214,11 +214,10 @@ class PaymentRequest(Document):
def check_if_payment_entry_exists(self):
if self.status == "Paid":
- payment_entry = frappe.get_all("Payment Entry Reference",
+ if frappe.get_all("Payment Entry Reference",
filters={"reference_name": self.reference_name, "docstatus": ["<", 2]},
- fields=["distinct(parent)"])
-
- if any(payment_entry):
+ fields=["parent"],
+ limit=1):
frappe.throw(_("Payment Entry already exists"), title=_('Error'))
def make_communication_entry(self):
From 08a209bc529358c0d641e189c6c1c59e74b67937 Mon Sep 17 00:00:00 2001
From: rushin29
Date: Fri, 15 Mar 2019 15:28:50 +0530
Subject: [PATCH 29/86] fix: gst_state_number for address with Unregistered GST
(#16798)
---
erpnext/regional/india/utils.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index e7d0d5052e..9747b24569 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -9,6 +9,8 @@ from erpnext.hr.utils import get_salary_assignment
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
def validate_gstin_for_india(doc, method):
+ if hasattr(doc, 'gst_state') and doc.gst_state:
+ doc.gst_state_number = state_numbers[doc.gst_state]
if not hasattr(doc, 'gstin') or not doc.gstin:
return
From 2ae7ed4cf0de848f1fbca04e278780f14a9daaf6 Mon Sep 17 00:00:00 2001
From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com>
Date: Sun, 17 Mar 2019 09:49:24 +0530
Subject: [PATCH 30/86] fix: Gross profit report fix (#16935)
---
erpnext/accounts/report/gross_profit/gross_profit.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py
index 073516fb88..e5aaafaff4 100644
--- a/erpnext/accounts/report/gross_profit/gross_profit.py
+++ b/erpnext/accounts/report/gross_profit/gross_profit.py
@@ -125,10 +125,11 @@ class GrossProfitGenerator(object):
# get buying amount
if row.item_code in product_bundles:
- row.buying_amount = self.get_buying_amount_from_product_bundle(row,
- product_bundles[row.item_code])
+ row.buying_amount = flt(self.get_buying_amount_from_product_bundle(row,
+ product_bundles[row.item_code]), self.currency_precision)
else:
- row.buying_amount = self.get_buying_amount(row, row.item_code)
+ row.buying_amount = flt(self.get_buying_amount(row, row.item_code),
+ self.currency_precision)
# get buying rate
if row.qty:
@@ -215,7 +216,7 @@ class GrossProfitGenerator(object):
if packed_item.get("parent_detail_docname")==row.item_row:
buying_amount += self.get_buying_amount(row, packed_item.item_code)
- return buying_amount
+ return flt(buying_amount, self.currency_precision)
def get_buying_amount(self, row, item_code):
# IMP NOTE
From 3ead70ba3c4304f8f1248a91c128e18cf8996170 Mon Sep 17 00:00:00 2001
From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com>
Date: Mon, 18 Mar 2019 08:22:57 +0530
Subject: [PATCH 31/86] fix: Change IBAN Account length from 25 to 30 (#16847)
---
erpnext/accounts/doctype/bank_account/bank_account.json | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/bank_account/bank_account.json b/erpnext/accounts/doctype/bank_account/bank_account.json
index 4897097b4a..84a8e6857c 100644
--- a/erpnext/accounts/doctype/bank_account/bank_account.json
+++ b/erpnext/accounts/doctype/bank_account/bank_account.json
@@ -1,5 +1,6 @@
{
"allow_copy": 0,
+ "allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 1,
@@ -290,7 +291,7 @@
"in_list_view": 1,
"in_standard_filter": 0,
"label": "IBAN",
- "length": 25,
+ "length": 30,
"no_copy": 0,
"permlevel": 0,
"precision": "",
@@ -669,7 +670,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-07-20 13:55:36.996465",
+ "modified": "2019-03-05 17:56:05.103238",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Account",
From ace95d5a67915ea0b621f59d834750a9d450609f Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Mon, 18 Mar 2019 11:53:04 +0530
Subject: [PATCH 32/86] feat: added cost center filter in AR/AP reports
---
.../doctype/purchase_invoice/purchase_invoice.js | 9 +++++++++
.../doctype/sales_invoice/sales_invoice.js | 9 +++++++++
.../report/accounts_payable/accounts_payable.js | 14 ++++++++++++++
.../accounts_payable_summary.js | 14 ++++++++++++++
.../accounts_receivable/accounts_receivable.js | 14 ++++++++++++++
.../accounts_receivable/accounts_receivable.py | 7 +++++++
.../accounts_receivable_summary.js | 14 ++++++++++++++
erpnext/selling/doctype/customer/customer.py | 15 ++++++++++++---
.../customer_credit_balance.js | 16 +++++++++++++++-
.../customer_credit_balance.py | 5 +++--
10 files changed, 111 insertions(+), 6 deletions(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 5c0e8fa74a..ac2ce8e6d8 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -510,6 +510,15 @@ frappe.ui.form.on("Purchase Invoice", {
}
}
}
+
+ frm.set_query("cost_center", function() {
+ return {
+ filters: {
+ company: frm.doc.company,
+ is_group: 0
+ }
+ };
+ });
},
onload: function(frm) {
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index a4a5940fc7..9a40d2b17e 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -564,6 +564,15 @@ frappe.ui.form.on('Sales Invoice', {
};
});
+ frm.set_query("cost_center", function() {
+ return {
+ filters: {
+ company: frm.doc.company,
+ is_group: 0
+ }
+ };
+ });
+
frm.custom_make_buttons = {
'Delivery Note': 'Delivery',
'Sales Invoice': 'Sales Return',
diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js
index 0a025f68d5..9dd552f3b8 100644
--- a/erpnext/accounts/report/accounts_payable/accounts_payable.js
+++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js
@@ -50,6 +50,20 @@ frappe.query_reports["Accounts Payable"] = {
"fieldtype": "Link",
"options": "Finance Book"
},
+ {
+ "fieldname":"cost_center",
+ "label": __("Cost Center"),
+ "fieldtype": "Link",
+ "options": "Cost Center",
+ get_query: () => {
+ var company = frappe.query_report.get_filter_value('company');
+ return {
+ filters: {
+ 'company': company
+ }
+ }
+ }
+ },
{
"fieldname":"supplier",
"label": __("Supplier"),
diff --git a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js
index 7823cac89c..31c0193f33 100644
--- a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js
+++ b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js
@@ -50,6 +50,20 @@ frappe.query_reports["Accounts Payable Summary"] = {
"fieldtype": "Link",
"options": "Finance Book"
},
+ {
+ "fieldname":"cost_center",
+ "label": __("Cost Center"),
+ "fieldtype": "Link",
+ "options": "Cost Center",
+ get_query: () => {
+ var company = frappe.query_report.get_filter_value('company');
+ return {
+ filters: {
+ 'company': company
+ }
+ }
+ }
+ },
{
"fieldname":"supplier",
"label": __("Supplier"),
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
index bbfee1112f..dce7e75578 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
@@ -50,6 +50,20 @@ frappe.query_reports["Accounts Receivable"] = {
"fieldtype": "Link",
"options": "Finance Book"
},
+ {
+ "fieldname":"cost_center",
+ "label": __("Cost Center"),
+ "fieldtype": "Link",
+ "options": "Cost Center",
+ get_query: () => {
+ var company = frappe.query_report.get_filter_value('company');
+ return {
+ filters: {
+ 'company': company
+ }
+ }
+ }
+ },
{
"fieldname":"customer",
"label": __("Customer"),
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 0e3317dcaa..4932ae1327 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -537,6 +537,13 @@ class ReceivablePayableReport(object):
where supplier_group=%s)""")
values.append(self.filters.get("supplier_group"))
+ if self.filters.get("cost_center"):
+ lft, rgt = frappe.get_cached_value("Cost Center",
+ self.filters.get("cost_center"), ['lft', 'rgt'])
+
+ conditions.append("""cost_center in (select name from `tabCost Center` where
+ lft >= {0} and rgt <= {1})""".format(lft, rgt))
+
accounts = [d.name for d in frappe.get_all("Account",
filters={"account_type": account_type, "company": self.filters.company})]
conditions.append("account in (%s)" % ','.join(['%s'] *len(accounts)))
diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
index a6f1457954..47b087db8b 100644
--- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
+++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
@@ -50,6 +50,20 @@ frappe.query_reports["Accounts Receivable Summary"] = {
"fieldtype": "Link",
"options": "Finance Book"
},
+ {
+ "fieldname":"cost_center",
+ "label": __("Cost Center"),
+ "fieldtype": "Link",
+ "options": "Cost Center",
+ get_query: () => {
+ var company = frappe.query_report.get_filter_value('company');
+ return {
+ filters: {
+ 'company': company
+ }
+ }
+ }
+ },
{
"fieldname":"customer",
"label": __("Customer"),
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index a8fae7b5a9..ec27498cc7 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -260,12 +260,21 @@ def check_credit_limit(customer, company, ignore_outstanding_sales_order=False,
throw(_("Please contact to the user who have Sales Master Manager {0} role")
.format(" / " + credit_controller if credit_controller else ""))
-def get_customer_outstanding(customer, company, ignore_outstanding_sales_order=False):
+def get_customer_outstanding(customer, company, ignore_outstanding_sales_order=False, cost_center=None):
# Outstanding based on GL Entries
+
+ cond = ""
+ if cost_center:
+ lft, rgt = frappe.get_cached_value("Cost Center",
+ cost_center, ['lft', 'rgt'])
+
+ cond = """ and cost_center in (select name from `tabCost Center` where
+ lft >= {0} and rgt <= {1})""".format(lft, rgt)
+
outstanding_based_on_gle = frappe.db.sql("""
select sum(debit) - sum(credit)
- from `tabGL Entry`
- where party_type = 'Customer' and party = %s and company=%s""", (customer, company))
+ from `tabGL Entry` where party_type = 'Customer'
+ and party = %s and company=%s {0}""".format(cond), (customer, company), debug=1)
outstanding_based_on_gle = flt(outstanding_based_on_gle[0][0]) if outstanding_based_on_gle else 0
diff --git a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.js b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.js
index 3a99eb0891..de8abdc498 100644
--- a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.js
+++ b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.js
@@ -16,6 +16,20 @@ frappe.query_reports["Customer Credit Balance"] = {
"label": __("Customer"),
"fieldtype": "Link",
"options": "Customer"
- }
+ },
+ {
+ "fieldname":"cost_center",
+ "label": __("Cost Center"),
+ "fieldtype": "Link",
+ "options": "Cost Center",
+ get_query: () => {
+ var company = frappe.query_report.get_filter_value('company');
+ return {
+ filters: {
+ 'company': company
+ }
+ }
+ }
+ },
]
}
diff --git a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py
index fe58af61c8..a57d975740 100644
--- a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py
+++ b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py
@@ -21,9 +21,10 @@ def execute(filters=None):
row = []
outstanding_amt = get_customer_outstanding(d.name, filters.get("company"),
- ignore_outstanding_sales_order=d.bypass_credit_limit_check_at_sales_order)
+ ignore_outstanding_sales_order=d.bypass_credit_limit_check_at_sales_order,
+ cost_center=filters.get("cost_center"))
- credit_limit = get_credit_limit(d.name, filters.get("company"))
+ credit_limit = get_credit_limit(d.name, filters.get("company"))
bal = flt(credit_limit) - flt(outstanding_amt)
From aa03ea2a56a9a5d513ba35b43629a4cf04861f07 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Mon, 18 Mar 2019 12:36:42 +0530
Subject: [PATCH 33/86] disbale pl check for Sales and Purchase Invoice
---
erpnext/accounts/doctype/gl_entry/gl_entry.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py
index 810b6f79b5..5c76799e4e 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.py
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py
@@ -74,7 +74,8 @@ class GLEntry(Document):
def check_pl_account(self):
if self.is_opening=='Yes' and \
- frappe.db.get_value("Account", self.account, "report_type")=="Profit and Loss":
+ frappe.db.get_value("Account", self.account, "report_type")=="Profit and Loss" and \
+ self.voucher_type not in ['Purchase Invoice', 'Sales Invoice']:
frappe.throw(_("{0} {1}: 'Profit and Loss' type account {2} not allowed in Opening Entry")
.format(self.voucher_type, self.voucher_no, self.account))
From 1a4bfdd090c0c5f73bde90f81d3783d2b7d0a4c7 Mon Sep 17 00:00:00 2001
From: Zlash65
Date: Mon, 28 Jan 2019 16:35:41 +0530
Subject: [PATCH 34/86] feat: selecting parent_company should disable
chart_of_accounts based fields
---
erpnext/setup/doctype/company/company.js | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index 70e047a4e8..dbfbc5932e 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -16,6 +16,14 @@ frappe.ui.form.on("Company", {
filters: {"is_additional_component": 1}
}
});
+
+ frm.set_df_property("create_chart_of_accounts_based_on", "read_only", frm.doc.parent_company ? 1 : 0);
+ frm.set_df_property("existing_company", "read_only", frm.doc.parent_company ? 1 : 0);
+ frm.set_query("parent_company", function() {
+ return {
+ filters: {"is_group": 1}
+ }
+ });
},
company_name: function(frm) {
@@ -28,6 +36,12 @@ frappe.ui.form.on("Company", {
}
},
+ parent_company: function(frm) {
+ if(!frm.doc.parent_company) return;
+ frm.set_value("create_chart_of_accounts_based_on", "Existing Company");
+ frm.set_value("existing_company", frm.doc.parent_company);
+ },
+
date_of_commencement: function(frm) {
if(frm.doc.date_of_commencement
Date: Mon, 28 Jan 2019 16:39:14 +0530
Subject: [PATCH 35/86] feat: once company is saved, parent_company cannot be
selected
---
erpnext/setup/doctype/company/company.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index dbfbc5932e..5592e9bd64 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -53,8 +53,9 @@ frappe.ui.form.on("Company", {
},
refresh: function(frm) {
- if(frm.doc.abbr && !frm.doc.__islocal) {
+ if(!frm.doc.__islocal) {
frm.set_df_property("abbr", "read_only", 1);
+ frm.set_df_property("parent_company", "read_only", 1);
}
frm.toggle_display('address_html', !frm.doc.__islocal);
From 2def228da88043f944053826d4e7a92f15895c6d Mon Sep 17 00:00:00 2001
From: Zlash65
Date: Tue, 29 Jan 2019 12:28:56 +0530
Subject: [PATCH 36/86] feat: allow adding account only if topmost parent
company - hidden filter for Parent Company added - Add button overriden with
new condition
---
.../accounts/doctype/account/account_tree.js | 58 ++++++++++++++++---
1 file changed, 49 insertions(+), 9 deletions(-)
diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js
index a9cbdd5dee..5a80258e71 100644
--- a/erpnext/accounts/doctype/account/account_tree.js
+++ b/erpnext/accounts/doctype/account/account_tree.js
@@ -4,13 +4,40 @@ frappe.treeview_settings["Account"] = {
breadcrumbs: "Accounts",
title: __("Chart Of Accounts"),
get_tree_root: false,
- filters: [{
- fieldname: "company",
- fieldtype:"Select",
- options: erpnext.utils.get_tree_options("company"),
- label: __("Company"),
- default: erpnext.utils.get_tree_default("company")
- }],
+ filters: [
+ {
+ fieldname: "company",
+ fieldtype:"Select",
+ options: erpnext.utils.get_tree_options("company"),
+ label: __("Company"),
+ default: erpnext.utils.get_tree_default("company"),
+ on_change: function() {
+ var me = frappe.treeview_settings['Account'].treeview;
+ var company = me.page.fields_dict.company.get_value();
+ frappe.call({
+ method: "frappe.client.get_value",
+ args: {
+ doctype: "Company",
+ fieldname: "parent_company",
+ filters: { name: company},
+ },
+ callback: function(r, rt) {
+ if(r.message) {
+ me.page.fields_dict.parent_company.set_value(r.message["parent_company"] || "");
+ }
+ }
+ });
+ }
+ },
+ {
+ fieldname: "parent_company",
+ fieldtype:"Data",
+ fetch_from: "company.parent_company",
+ label: __("Parent Company"),
+ hidden: true,
+ disable_onchange: true
+ }
+ ],
root_label: "Accounts",
get_tree_nodes: 'erpnext.accounts.utils.get_children',
add_tree_node: 'erpnext.accounts.utils.add_ac',
@@ -42,8 +69,8 @@ frappe.treeview_settings["Account"] = {
],
ignore_fields:["parent_account"],
onload: function(treeview) {
- frappe.treeview_settings['Account'].page = {};
- $.extend(frappe.treeview_settings['Account'].page, treeview.page);
+ frappe.treeview_settings['Account'].treeview = {};
+ $.extend(frappe.treeview_settings['Account'].treeview, treeview);
function get_company() {
return treeview.page.fields_dict.company.get_value();
}
@@ -93,6 +120,19 @@ frappe.treeview_settings["Account"] = {
}
},
toolbar: [
+ {
+ label:__("Add Child"),
+ condition: function(node) {
+ return frappe.boot.user.can_create.indexOf("Account") !== -1 &&
+ !frappe.treeview_settings['Account'].treeview.page.fields_dict.parent_company.get_value() &&
+ node.expandable && !node.hide_add;
+ },
+ click: function(node) {
+ var me = frappe.treeview_settings['Account'].treeview;
+ me.new_node(node);
+ },
+ btnClass: "hidden-xs"
+ },
{
condition: function(node) {
return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1
From 0407bf1e005a316322118bcf7043b834183fb788 Mon Sep 17 00:00:00 2001
From: Zlash65
Date: Wed, 30 Jan 2019 11:12:15 +0530
Subject: [PATCH 37/86] fix: override primary action button, change filter to
root company
---
.../accounts/doctype/account/account_tree.js | 32 ++++++++++++-------
1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js
index 5a80258e71..4bedb3c26c 100644
--- a/erpnext/accounts/doctype/account/account_tree.js
+++ b/erpnext/accounts/doctype/account/account_tree.js
@@ -15,25 +15,23 @@ frappe.treeview_settings["Account"] = {
var me = frappe.treeview_settings['Account'].treeview;
var company = me.page.fields_dict.company.get_value();
frappe.call({
- method: "frappe.client.get_value",
+ method: "erpnext.accounts.doctype.account.account.get_root_company",
args: {
- doctype: "Company",
- fieldname: "parent_company",
- filters: { name: company},
+ company: company,
},
callback: function(r, rt) {
if(r.message) {
- me.page.fields_dict.parent_company.set_value(r.message["parent_company"] || "");
+ let root_company = r.message.length ? r.message[0] : "";
+ me.page.fields_dict.root_company.set_value(root_company);
}
}
});
}
},
{
- fieldname: "parent_company",
+ fieldname: "root_company",
fieldtype:"Data",
- fetch_from: "company.parent_company",
- label: __("Parent Company"),
+ label: __("Root Company"),
hidden: true,
disable_onchange: true
}
@@ -105,6 +103,18 @@ frappe.treeview_settings["Account"] = {
}
},
+ post_render: function(treeview) {
+ frappe.treeview_settings['Account'].treeview["tree"] = treeview.tree;
+ treeview.page.set_primary_action(__("New"), function() {
+ let root_company = treeview.page.fields_dict.root_company.get_value();
+
+ if(root_company) {
+ frappe.throw(__("Please add the account to root level Company - ") + root_company);
+ } else {
+ treeview.new_node();
+ }
+ }, "octicon octicon-plus");
+ },
onrender: function(node) {
if(frappe.boot.user.can_read.indexOf("GL Entry") !== -1){
var dr_or_cr = node.data.balance < 0 ? "Cr" : "Dr";
@@ -124,12 +134,12 @@ frappe.treeview_settings["Account"] = {
label:__("Add Child"),
condition: function(node) {
return frappe.boot.user.can_create.indexOf("Account") !== -1 &&
- !frappe.treeview_settings['Account'].treeview.page.fields_dict.parent_company.get_value() &&
+ !frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value() &&
node.expandable && !node.hide_add;
},
click: function(node) {
var me = frappe.treeview_settings['Account'].treeview;
- me.new_node(node);
+ me.new_node();
},
btnClass: "hidden-xs"
},
@@ -143,7 +153,7 @@ frappe.treeview_settings["Account"] = {
"account": node.label,
"from_date": frappe.sys_defaults.year_start_date,
"to_date": frappe.sys_defaults.year_end_date,
- "company": frappe.treeview_settings['Account'].page.fields_dict.company.get_value()
+ "company": frappe.treeview_settings['Account'].treeview.page.fields_dict.company.get_value()
};
frappe.set_route("query-report", "General Ledger");
},
From 88c990901d5a060a7d2e9c4db27c30d95b064d8f Mon Sep 17 00:00:00 2001
From: Zlash65
Date: Wed, 30 Jan 2019 11:12:28 +0530
Subject: [PATCH 38/86] fix: added validation to if account is being added to
child company
---
erpnext/accounts/doctype/account/account.py | 14 ++++++++++++++
erpnext/setup/doctype/company/company.py | 1 +
2 files changed, 15 insertions(+)
diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index 5d504b94be..d699146049 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -34,6 +34,7 @@ class Account(NestedSet):
return
self.validate_parent()
self.validate_root_details()
+ self.validate_root_company()
validate_field_number("Account", self.name, self.account_number, self.company, "account_number")
self.validate_group_or_ledger()
self.set_root_and_report_type()
@@ -90,6 +91,13 @@ class Account(NestedSet):
if not self.parent_account and not self.is_group:
frappe.throw(_("Root Account must be a group"))
+ def validate_root_company(self):
+ # fetch all ancestors in top-down hierarchy
+ if frappe.local.flags.ignore_root_company_validation: return
+ ancestors = get_root_company(self.company)
+ if ancestors:
+ frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
+
def validate_group_or_ledger(self):
if self.get("__islocal"):
return
@@ -250,3 +258,9 @@ def merge_account(old, new, is_group, root_type, company):
frappe.rename_doc("Account", old, new, merge=1, ignore_permissions=1)
return new
+
+@frappe.whitelist()
+def get_root_company(company):
+ # return the topmost company in the hierarchy
+ ancestors = frappe.utils.nestedset.get_ancestors_of('Company', company, "lft asc")
+ return [ancestors[0]] if ancestors else []
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index c49c264251..33361e81d4 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -141,6 +141,7 @@ class Company(NestedSet):
def create_default_accounts(self):
from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import create_charts
+ frappe.local.flags.ignore_root_company_validation = True
create_charts(self.name, self.chart_of_accounts, self.existing_company)
frappe.db.set(self, "default_receivable_account", frappe.db.get_value("Account",
From d787ef8b8e504a499c5fda283861a3f17910f781 Mon Sep 17 00:00:00 2001
From: Zlash65
Date: Wed, 30 Jan 2019 14:00:56 +0530
Subject: [PATCH 39/86] feat: sync account created for a group company to all
its descendants
---
erpnext/accounts/doctype/account/account.py | 30 ++++++++++++++++-----
1 file changed, 24 insertions(+), 6 deletions(-)
diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index d699146049..dea82d8ed6 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -5,7 +5,7 @@ from __future__ import unicode_literals
import frappe
from frappe.utils import cint, cstr
from frappe import throw, _
-from frappe.utils.nestedset import NestedSet
+from frappe.utils.nestedset import NestedSet, get_ancestors_of, get_descendants_of
class RootNotEditable(frappe.ValidationError): pass
class BalanceMismatchError(frappe.ValidationError): pass
@@ -34,7 +34,6 @@ class Account(NestedSet):
return
self.validate_parent()
self.validate_root_details()
- self.validate_root_company()
validate_field_number("Account", self.name, self.account_number, self.company, "account_number")
self.validate_group_or_ledger()
self.set_root_and_report_type()
@@ -42,6 +41,7 @@ class Account(NestedSet):
self.validate_frozen_accounts_modifier()
self.validate_balance_must_be_debit_or_credit()
self.validate_account_currency()
+ self.validate_root_company_and_sync_account_to_children()
def validate_parent(self):
"""Fetch Parent Details and validate parent account"""
@@ -91,12 +91,30 @@ class Account(NestedSet):
if not self.parent_account and not self.is_group:
frappe.throw(_("Root Account must be a group"))
- def validate_root_company(self):
- # fetch all ancestors in top-down hierarchy
- if frappe.local.flags.ignore_root_company_validation: return
+ def validate_root_company_and_sync_account_to_children(self):
+ # ignore validation while creating new compnay or while syncing to child companies
+ if frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation:
+ return
+
ancestors = get_root_company(self.company)
if ancestors:
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
+ else:
+ descendants = get_descendants_of('Company', self.company)
+ acc_name = frappe.db.get_value('Account', self.parent_account, "account_name")
+
+ acc_name_map = {}
+ for d in frappe.db.get_values('Account',
+ {"company": ["in", descendants], "account_name": acc_name},
+ ["company", "name"], as_dict=True):
+ acc_name_map[d["company"]] = d["name"]
+
+ for company in descendants:
+ doc = frappe.copy_doc(self)
+ doc.flags.ignore_root_company_validation = True
+ doc.update({"company": company, "account_currency": None,
+ "parent": acc_name_map[company], "parent_account": acc_name_map[company]})
+ doc.save()
def validate_group_or_ledger(self):
if self.get("__islocal"):
@@ -262,5 +280,5 @@ def merge_account(old, new, is_group, root_type, company):
@frappe.whitelist()
def get_root_company(company):
# return the topmost company in the hierarchy
- ancestors = frappe.utils.nestedset.get_ancestors_of('Company', company, "lft asc")
+ ancestors = get_ancestors_of('Company', company, "lft asc")
return [ancestors[0]] if ancestors else []
From 73acb8c83702e636a4b126add7a2181ddad2a012 Mon Sep 17 00:00:00 2001
From: Zlash65
Date: Wed, 13 Feb 2019 16:31:37 +0530
Subject: [PATCH 40/86] fix: set chart of accounts based on parent company on
server side
---
erpnext/setup/doctype/company/company.py | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index 33361e81d4..ad9d64baf5 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -39,6 +39,7 @@ class Company(NestedSet):
self.validate_coa_input()
self.validate_perpetual_inventory()
self.check_country_change()
+ self.set_chart_of_accounts()
def validate_abbr(self):
if not self.abbr:
@@ -174,6 +175,12 @@ class Company(NestedSet):
self.country != frappe.get_cached_value('Company', self.name, 'country'):
frappe.flags.country_change = True
+ def set_chart_of_accounts(self):
+ ''' If parent company is set, chart of accounts will be based on that company '''
+ if self.parent_company:
+ self.create_chart_of_accounts_based_on = "Existing Company"
+ self.existing_company = self.parent_company
+
def set_default_accounts(self):
self._set_default_account("default_cash_account", "Cash")
self._set_default_account("default_bank_account", "Bank")
From f71cb8dc6db03ee5ddc50aac58ef52b4fc783c71 Mon Sep 17 00:00:00 2001
From: Zlash65
Date: Wed, 13 Feb 2019 16:32:04 +0530
Subject: [PATCH 41/86] fix: return if no descendants found
---
erpnext/accounts/doctype/account/account.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index dea82d8ed6..e241fc4a3a 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -101,9 +101,10 @@ class Account(NestedSet):
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
else:
descendants = get_descendants_of('Company', self.company)
- acc_name = frappe.db.get_value('Account', self.parent_account, "account_name")
+ if not descendants: return
acc_name_map = {}
+ acc_name = frappe.db.get_value('Account', self.parent_account, "account_name")
for d in frappe.db.get_values('Account',
{"company": ["in", descendants], "account_name": acc_name},
["company", "name"], as_dict=True):
From cc65447e62d768354984bb042e6f3a01043fc031 Mon Sep 17 00:00:00 2001
From: Zlash65
Date: Wed, 13 Feb 2019 16:32:50 +0530
Subject: [PATCH 42/86] fix: chart of accounts field toggling improv
---
erpnext/setup/doctype/company/company.js | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index 5592e9bd64..aff4baf931 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -17,8 +17,6 @@ frappe.ui.form.on("Company", {
}
});
- frm.set_df_property("create_chart_of_accounts_based_on", "read_only", frm.doc.parent_company ? 1 : 0);
- frm.set_df_property("existing_company", "read_only", frm.doc.parent_company ? 1 : 0);
frm.set_query("parent_company", function() {
return {
filters: {"is_group": 1}
@@ -37,9 +35,10 @@ frappe.ui.form.on("Company", {
},
parent_company: function(frm) {
- if(!frm.doc.parent_company) return;
- frm.set_value("create_chart_of_accounts_based_on", "Existing Company");
- frm.set_value("existing_company", frm.doc.parent_company);
+ var bool = frm.doc.parent_company ? true : false;
+ frm.set_value('create_chart_of_accounts_based_on', bool ? "Existing Company" : "");
+ frm.set_value('existing_company', bool ? frm.doc.parent_company : "");
+ disbale_coa_fields(frm, bool);
},
date_of_commencement: function(frm) {
@@ -54,8 +53,9 @@ frappe.ui.form.on("Company", {
refresh: function(frm) {
if(!frm.doc.__islocal) {
- frm.set_df_property("abbr", "read_only", 1);
+ frm.doc.abbr && frm.set_df_property("abbr", "read_only", 1);
frm.set_df_property("parent_company", "read_only", 1);
+ disbale_coa_fields(frm);
}
frm.toggle_display('address_html', !frm.doc.__islocal);
@@ -271,3 +271,9 @@ erpnext.company.set_custom_query = function(frm, v) {
}
});
}
+
+var disbale_coa_fields = function(frm, bool=true) {
+ frm.set_df_property("create_chart_of_accounts_based_on", "read_only", bool);
+ frm.set_df_property("chart_of_accounts", "read_only", bool);
+ frm.set_df_property("existing_company", "read_only", bool);
+};
\ No newline at end of file
From 11bba571afb7a6bd49e5ac6bed623bdc8149e7be Mon Sep 17 00:00:00 2001
From: Zlash65
Date: Wed, 13 Feb 2019 16:33:28 +0530
Subject: [PATCH 43/86] test case added to check account syncing
---
.../accounts/doctype/account/test_account.py | 13 +++++++
.../setup/doctype/company/test_records.json | 34 +++++++++++++++++++
2 files changed, 47 insertions(+)
diff --git a/erpnext/accounts/doctype/account/test_account.py b/erpnext/accounts/doctype/account/test_account.py
index acaa0966a2..4c057d9549 100644
--- a/erpnext/accounts/doctype/account/test_account.py
+++ b/erpnext/accounts/doctype/account/test_account.py
@@ -97,6 +97,19 @@ class TestAccount(unittest.TestCase):
self.assertRaises(frappe.ValidationError, merge_account, "Capital Stock - _TC",\
"Softwares - _TC", doc.is_group, doc.root_type, doc.company)
+ def test_account_sync(self):
+ del frappe.local.flags["ignore_root_company_validation"]
+ acc = frappe.new_doc("Account")
+ acc.account_name = "Test Sync Account"
+ acc.parent_account = "Temporary Accounts - _TC3"
+ acc.company = "_Test Company 3"
+ acc.insert()
+
+ acc_tc_4 = frappe.db.get_value('Account', {'account_name': "Test Sync Account", "company": "_Test Company 4"})
+ acc_tc_5 = frappe.db.get_value('Account', {'account_name': "Test Sync Account", "company": "_Test Company 5"})
+ self.assertEqual(acc_tc_4, "Test Sync Account - _TC4")
+ self.assertEqual(acc_tc_5, "Test Sync Account - _TC5")
+
def _make_test_records(verbose):
from frappe.test_runner import make_test_objects
diff --git a/erpnext/setup/doctype/company/test_records.json b/erpnext/setup/doctype/company/test_records.json
index 7e26ca3207..bf9d4bdd19 100644
--- a/erpnext/setup/doctype/company/test_records.json
+++ b/erpnext/setup/doctype/company/test_records.json
@@ -28,5 +28,39 @@
"domain": "Retail",
"chart_of_accounts": "Standard",
"default_holiday_list": "_Test Holiday List"
+ },
+ {
+ "abbr": "_TC3",
+ "company_name": "_Test Company 3",
+ "is_group": 1,
+ "country": "India",
+ "default_currency": "INR",
+ "doctype": "Company",
+ "domain": "Manufacturing",
+ "chart_of_accounts": "Standard",
+ "default_holiday_list": "_Test Holiday List"
+ },
+ {
+ "abbr": "_TC4",
+ "company_name": "_Test Company 4",
+ "parent_company": "_Test Company 3",
+ "is_group": 1,
+ "country": "India",
+ "default_currency": "INR",
+ "doctype": "Company",
+ "domain": "Manufacturing",
+ "chart_of_accounts": "Standard",
+ "default_holiday_list": "_Test Holiday List"
+ },
+ {
+ "abbr": "_TC5",
+ "company_name": "_Test Company 5",
+ "parent_company": "_Test Company 4",
+ "country": "India",
+ "default_currency": "INR",
+ "doctype": "Company",
+ "domain": "Manufacturing",
+ "chart_of_accounts": "Standard",
+ "default_holiday_list": "_Test Holiday List"
}
]
From 01086ff60c54a5463f23f747c2681ac45a531ff9 Mon Sep 17 00:00:00 2001
From: Zlash65
Date: Wed, 13 Feb 2019 16:33:42 +0530
Subject: [PATCH 44/86] codacy fixes
---
erpnext/accounts/doctype/account/account_tree.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js
index 4bedb3c26c..df0486cc27 100644
--- a/erpnext/accounts/doctype/account/account_tree.js
+++ b/erpnext/accounts/doctype/account/account_tree.js
@@ -19,7 +19,7 @@ frappe.treeview_settings["Account"] = {
args: {
company: company,
},
- callback: function(r, rt) {
+ callback: function(r) {
if(r.message) {
let root_company = r.message.length ? r.message[0] : "";
me.page.fields_dict.root_company.set_value(root_company);
@@ -137,7 +137,7 @@ frappe.treeview_settings["Account"] = {
!frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value() &&
node.expandable && !node.hide_add;
},
- click: function(node) {
+ click: function() {
var me = frappe.treeview_settings['Account'].treeview;
me.new_node();
},
From d4e4316d0b9432a0b4ed36a54cdd97bc3a49d2fc Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Mon, 18 Mar 2019 10:53:43 +0530
Subject: [PATCH 45/86] fix: test cases and codacy
---
erpnext/accounts/doctype/account/account.py | 2 +
.../hr/doctype/staffing_plan/staffing_plan.py | 10 ++
.../staffing_plan/test_staffing_plan.py | 10 +-
.../setup/doctype/company/test_records.json | 128 +++++++++---------
4 files changed, 81 insertions(+), 69 deletions(-)
diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index e241fc4a3a..427f3dba20 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -116,6 +116,8 @@ class Account(NestedSet):
doc.update({"company": company, "account_currency": None,
"parent": acc_name_map[company], "parent_account": acc_name_map[company]})
doc.save()
+ frappe.msgprint(_("Account {0} is added in the child company {1}")
+ .format(doc.name, company))
def validate_group_or_ledger(self):
if self.get("__islocal"):
diff --git a/erpnext/hr/doctype/staffing_plan/staffing_plan.py b/erpnext/hr/doctype/staffing_plan/staffing_plan.py
index 70e185cde5..83e53135ef 100644
--- a/erpnext/hr/doctype/staffing_plan/staffing_plan.py
+++ b/erpnext/hr/doctype/staffing_plan/staffing_plan.py
@@ -20,6 +20,7 @@ class StaffingPlan(Document):
self.total_estimated_budget = 0
for detail in self.get("staffing_details"):
+ self.set_vacancies(detail)
self.validate_overlap(detail)
self.validate_with_subsidiary_plans(detail)
self.validate_with_parent_plan(detail)
@@ -39,6 +40,15 @@ class StaffingPlan(Document):
else: detail.vacancies = detail.number_of_positions = detail.total_estimated_cost = 0
self.total_estimated_budget += detail.total_estimated_cost
+ def set_vacancies(self, row):
+ if not row.vacancies:
+ current_openings = 0
+ for field in ['current_count', 'current_openings']:
+ if row.get(field):
+ current_openings += row.get(field)
+
+ row.vacancies = row.number_of_positions - current_openings
+
def validate_overlap(self, staffing_plan_detail):
# Validate if any submitted Staffing Plan exist for any Designations in this plan
# and spd.vacancies>0 ?
diff --git a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py
index 66d9cdd07a..22dba99af0 100644
--- a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py
+++ b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py
@@ -18,7 +18,7 @@ class TestStaffingPlan(unittest.TestCase):
if frappe.db.exists("Staffing Plan", "Test"):
return
staffing_plan = frappe.new_doc("Staffing Plan")
- staffing_plan.company = "_Test Company 3"
+ staffing_plan.company = "_Test Company 10"
staffing_plan.name = "Test"
staffing_plan.from_date = nowdate()
staffing_plan.to_date = add_days(nowdate(), 10)
@@ -67,7 +67,7 @@ class TestStaffingPlan(unittest.TestCase):
if frappe.db.exists("Staffing Plan", "Test 1"):
return
staffing_plan = frappe.new_doc("Staffing Plan")
- staffing_plan.company = "_Test Company 3"
+ staffing_plan.company = "_Test Company 10"
staffing_plan.name = "Test 1"
staffing_plan.from_date = nowdate()
staffing_plan.to_date = add_days(nowdate(), 10)
@@ -85,11 +85,11 @@ def _set_up():
make_company()
def make_company():
- if frappe.db.exists("Company", "_Test Company 3"):
+ if frappe.db.exists("Company", "_Test Company 10"):
return
company = frappe.new_doc("Company")
- company.company_name = "_Test Company 3"
- company.abbr = "_TC3"
+ company.company_name = "_Test Company 10"
+ company.abbr = "_TC10"
company.parent_company = "_Test Company"
company.default_currency = "INR"
company.country = "India"
diff --git a/erpnext/setup/doctype/company/test_records.json b/erpnext/setup/doctype/company/test_records.json
index bf9d4bdd19..58d8b5c334 100644
--- a/erpnext/setup/doctype/company/test_records.json
+++ b/erpnext/setup/doctype/company/test_records.json
@@ -1,66 +1,66 @@
[
- {
- "abbr": "_TC",
- "company_name": "_Test Company",
- "country": "India",
- "default_currency": "INR",
- "doctype": "Company",
- "domain": "Manufacturing",
- "chart_of_accounts": "Standard",
- "default_holiday_list": "_Test Holiday List"
- },
- {
- "abbr": "_TC1",
- "company_name": "_Test Company 1",
- "country": "United States",
- "default_currency": "USD",
- "doctype": "Company",
- "domain": "Retail",
- "chart_of_accounts": "Standard",
- "default_holiday_list": "_Test Holiday List"
- },
- {
- "abbr": "_TC2",
- "company_name": "_Test Company 2",
- "default_currency": "EUR",
- "country": "Germany",
- "doctype": "Company",
- "domain": "Retail",
- "chart_of_accounts": "Standard",
- "default_holiday_list": "_Test Holiday List"
- },
- {
- "abbr": "_TC3",
- "company_name": "_Test Company 3",
- "is_group": 1,
- "country": "India",
- "default_currency": "INR",
- "doctype": "Company",
- "domain": "Manufacturing",
- "chart_of_accounts": "Standard",
- "default_holiday_list": "_Test Holiday List"
- },
- {
- "abbr": "_TC4",
- "company_name": "_Test Company 4",
- "parent_company": "_Test Company 3",
- "is_group": 1,
- "country": "India",
- "default_currency": "INR",
- "doctype": "Company",
- "domain": "Manufacturing",
- "chart_of_accounts": "Standard",
- "default_holiday_list": "_Test Holiday List"
- },
- {
- "abbr": "_TC5",
- "company_name": "_Test Company 5",
- "parent_company": "_Test Company 4",
- "country": "India",
- "default_currency": "INR",
- "doctype": "Company",
- "domain": "Manufacturing",
- "chart_of_accounts": "Standard",
- "default_holiday_list": "_Test Holiday List"
- }
+ {
+ "abbr": "_TC",
+ "company_name": "_Test Company",
+ "country": "India",
+ "default_currency": "INR",
+ "doctype": "Company",
+ "domain": "Manufacturing",
+ "chart_of_accounts": "Standard",
+ "default_holiday_list": "_Test Holiday List"
+ },
+ {
+ "abbr": "_TC1",
+ "company_name": "_Test Company 1",
+ "country": "United States",
+ "default_currency": "USD",
+ "doctype": "Company",
+ "domain": "Retail",
+ "chart_of_accounts": "Standard",
+ "default_holiday_list": "_Test Holiday List"
+ },
+ {
+ "abbr": "_TC2",
+ "company_name": "_Test Company 2",
+ "default_currency": "EUR",
+ "country": "Germany",
+ "doctype": "Company",
+ "domain": "Retail",
+ "chart_of_accounts": "Standard",
+ "default_holiday_list": "_Test Holiday List"
+ },
+ {
+ "abbr": "_TC3",
+ "company_name": "_Test Company 3",
+ "is_group": 1,
+ "country": "India",
+ "default_currency": "INR",
+ "doctype": "Company",
+ "domain": "Manufacturing",
+ "chart_of_accounts": "Standard",
+ "default_holiday_list": "_Test Holiday List"
+ },
+ {
+ "abbr": "_TC4",
+ "company_name": "_Test Company 4",
+ "parent_company": "_Test Company 3",
+ "is_group": 1,
+ "country": "India",
+ "default_currency": "INR",
+ "doctype": "Company",
+ "domain": "Manufacturing",
+ "chart_of_accounts": "Standard",
+ "default_holiday_list": "_Test Holiday List"
+ },
+ {
+ "abbr": "_TC5",
+ "company_name": "_Test Company 5",
+ "parent_company": "_Test Company 4",
+ "country": "India",
+ "default_currency": "INR",
+ "doctype": "Company",
+ "domain": "Manufacturing",
+ "chart_of_accounts": "Standard",
+ "default_holiday_list": "_Test Holiday List"
+ }
]
From ac199580af30b82bbb5dd77a5c25b4483b4536bb Mon Sep 17 00:00:00 2001
From: Himanshu
Date: Mon, 18 Mar 2019 15:44:54 +0530
Subject: [PATCH 46/86] fix(Customer Ledger): ambiguous error in where clause
(#16914)
fix for error "InternalError: (1052, u"Column 'company' in where clause is ambiguous")" in Customer Ledger Summary
---
.../report/customer_ledger_summary/customer_ledger_summary.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
index e33bd61411..eceabf56af 100644
--- a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
+++ b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
@@ -195,7 +195,7 @@ class PartyLedgerSummaryReport(object):
conditions = [""]
if self.filters.company:
- conditions.append("company=%(company)s")
+ conditions.append("gle.company=%(company)s")
self.filters.company_finance_book = erpnext.get_default_finance_book(self.filters.company)
From 5b43e2f31a187594a16cd52083fe2c8438856285 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Mon, 18 Mar 2019 17:00:44 +0530
Subject: [PATCH 47/86] code cleanup
---
erpnext/selling/doctype/customer/customer.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index ec27498cc7..ba20cbc73e 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -274,7 +274,7 @@ def get_customer_outstanding(customer, company, ignore_outstanding_sales_order=F
outstanding_based_on_gle = frappe.db.sql("""
select sum(debit) - sum(credit)
from `tabGL Entry` where party_type = 'Customer'
- and party = %s and company=%s {0}""".format(cond), (customer, company), debug=1)
+ and party = %s and company=%s {0}""".format(cond), (customer, company))
outstanding_based_on_gle = flt(outstanding_based_on_gle[0][0]) if outstanding_based_on_gle else 0
From f060831cced725e26fe18a85dd7c24c6fa51b058 Mon Sep 17 00:00:00 2001
From: Rushabh Mehta
Date: Mon, 18 Mar 2019 18:04:34 +0530
Subject: [PATCH 48/86] fix(escaping): make_italian_localization_fields.py
---
erpnext/patches/v11_0/make_italian_localization_fields.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/patches/v11_0/make_italian_localization_fields.py b/erpnext/patches/v11_0/make_italian_localization_fields.py
index 44a281f86f..d9a7b35e77 100644
--- a/erpnext/patches/v11_0/make_italian_localization_fields.py
+++ b/erpnext/patches/v11_0/make_italian_localization_fields.py
@@ -19,7 +19,7 @@ def execute():
# Set state codes
condition = ""
for state, code in state_codes.items():
- condition += " when '{0}' then '{1}'".format(frappe.db.escape(state), frappe.db.escape(code))
+ condition += " when {0} then {1}".format(frappe.db.escape(state), frappe.db.escape(code))
if condition:
condition = "state_code = (case state {0} end),".format(condition)
From 642a5b69f58337db0911704668e532e8f0457ac0 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Mon, 18 Mar 2019 21:53:33 +0530
Subject: [PATCH 49/86] fix: change customer to supplier
---
.../report/supplier_ledger_summary/supplier_ledger_summary.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js b/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js
index 6fd16f2090..f81297760e 100644
--- a/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js
+++ b/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js
@@ -35,9 +35,9 @@ frappe.query_reports["Supplier Ledger Summary"] = {
},
{
"fieldname":"party",
- "label": __("Customer"),
+ "label": __("Supplier"),
"fieldtype": "Link",
- "options": "Customer",
+ "options": "Supplier",
on_change: () => {
var party = frappe.query_report.get_filter_value('party');
if (party) {
From 5f8b358fd4746394cbe5c349b0e5bd1280c5af3a Mon Sep 17 00:00:00 2001
From: Faris Ansari
Date: Tue, 19 Mar 2019 11:48:32 +0530
Subject: [PATCH 50/86] Website: Product Configurator and Bootstrap 4 (#15965)
- Refactored Homepage with customisable Hero Section
- New Homepage Section to add content on Homepage as cards or using Custom HTML
- Products page at "/all-products" with customisable filters
- Item Configure dialog to find an Item Variant filtered by attribute values
- Contact Us dialog on Item page
- Customisable Item page content using the Website Content field
---
erpnext/config/website.py | 10 +
erpnext/hooks.py | 3 +-
erpnext/hr/doctype/job_opening/job_opening.py | 23 +
.../templates/job_opening_row.html | 9 +
erpnext/patches.txt | 2 +-
.../add_variant_of_in_item_attribute_table.py | 8 +
.../v12_0/set_default_homepage_type.py | 4 +
erpnext/portal/doctype/homepage/homepage.js | 7 +-
erpnext/portal/doctype/homepage/homepage.json | 277 +++-
erpnext/portal/doctype/homepage/homepage.py | 2 -
.../portal/doctype/homepage/test_homepage.py | 19 +
.../doctype/homepage_section/__init__.py | 0
.../homepage_section/homepage_section.js | 6 +
.../homepage_section/homepage_section.json | 336 +++++
.../homepage_section/homepage_section.py | 12 +
.../homepage_section/test_homepage_section.py | 76 +
.../doctype/homepage_section_card/__init__.py | 0
.../homepage_section_card.json | 203 +++
.../homepage_section_card.py | 9 +
.../products_settings/products_settings.js | 11 +
.../products_settings/products_settings.json | 604 ++++----
.../products_settings/products_settings.py | 21 +
.../doctype/website_attribute/__init__.py | 0
.../website_attribute/website_attribute.json | 76 +
.../website_attribute/website_attribute.py | 9 +
.../doctype/website_filter_field/__init__.py | 0
.../website_filter_field.json | 76 +
.../website_filter_field.py | 9 +
.../portal/product_configurator/__init__.py | 0
.../item_variants_cache.py | 94 ++
.../test_product_configurator.py | 84 ++
erpnext/portal/product_configurator/utils.py | 402 ++++++
erpnext/public/build.json | 2 +-
erpnext/public/js/shopping_cart.js | 10 +-
erpnext/public/js/templates/address_list.html | 4 +-
erpnext/public/js/templates/contact_list.html | 4 +-
erpnext/public/js/website_theme.js | 17 +
erpnext/public/less/products.less | 69 +
erpnext/public/less/website.less | 29 +-
erpnext/public/node_modules | 1 +
erpnext/public/scss/website.scss | 53 +
.../quotation_item/quotation_item.json | 146 +-
.../setup/doctype/item_group/item_group.py | 20 +-
.../operations/default_website.py | 2 +-
erpnext/shopping_cart/cart.py | 55 +-
.../shopping_cart_settings.json | 1238 +++++++++--------
erpnext/shopping_cart/product_info.py | 4 +-
erpnext/stock/doctype/item/item.js | 4 +
erpnext/stock/doctype/item/item.json | 74 +-
erpnext/stock/doctype/item/item.py | 101 +-
erpnext/stock/doctype/item/test_records.json | 3 +-
.../doctype/item_attribute/item_attribute.js | 6 +
.../item_attribute/item_attribute.json | 101 +-
.../item_variant_attribute.json | 57 +-
erpnext/templates/generators/item.html | 143 --
erpnext/templates/generators/item/item.html | 32 +
.../generators/item/item_add_to_cart.html | 67 +
.../generators/item/item_configure.html | 23 +
.../generators/item/item_configure.js | 318 +++++
.../generators/item/item_details.html | 22 +
.../templates/generators/item/item_image.html | 107 ++
.../templates/generators/item/item_inquiry.js | 70 +
.../generators/item/item_specifications.html | 16 +
erpnext/templates/generators/item_group.html | 41 +-
erpnext/templates/includes/address_row.html | 12 +-
erpnext/templates/includes/cart.js | 97 +-
.../templates/includes/cart/address_card.html | 12 +
.../templates/includes/cart/cart_address.html | 161 ++-
.../templates/includes/cart/cart_items.html | 69 +-
.../includes/footer/footer_extension.html | 17 +-
.../includes/footer/footer_powered.html | 3 +-
erpnext/templates/includes/macros.html | 43 +-
.../includes/navbar/navbar_items.html | 12 +-
.../includes/order/order_macros.html | 8 +-
.../templates/includes/order/order_taxes.html | 44 +-
erpnext/templates/includes/product_page.js | 215 ---
erpnext/templates/pages/cart.html | 138 +-
erpnext/templates/pages/help.html | 2 +-
erpnext/templates/pages/home.css | 9 +
erpnext/templates/pages/home.html | 130 +-
erpnext/templates/pages/home.py | 45 +-
.../pages/material_request_info.html | 4 +-
.../pages/non_profit/leave-chapter.html | 2 +-
erpnext/templates/pages/order.html | 40 +-
erpnext/templates/pages/product_search.html | 2 +-
erpnext/templates/pages/projects.html | 4 +-
erpnext/templates/pages/task_info.html | 4 +-
erpnext/www/all-products/__init__.py | 0
erpnext/www/all-products/index.html | 163 +++
erpnext/www/all-products/index.js | 161 +++
erpnext/www/all-products/index.py | 26 +
erpnext/www/all-products/item_row.html | 24 +
erpnext/www/all-products/not_found.html | 1 +
93 files changed, 5057 insertions(+), 1622 deletions(-)
create mode 100644 erpnext/hr/doctype/job_opening/templates/job_opening_row.html
create mode 100644 erpnext/patches/v12_0/add_variant_of_in_item_attribute_table.py
create mode 100644 erpnext/patches/v12_0/set_default_homepage_type.py
create mode 100644 erpnext/portal/doctype/homepage/test_homepage.py
create mode 100644 erpnext/portal/doctype/homepage_section/__init__.py
create mode 100644 erpnext/portal/doctype/homepage_section/homepage_section.js
create mode 100644 erpnext/portal/doctype/homepage_section/homepage_section.json
create mode 100644 erpnext/portal/doctype/homepage_section/homepage_section.py
create mode 100644 erpnext/portal/doctype/homepage_section/test_homepage_section.py
create mode 100644 erpnext/portal/doctype/homepage_section_card/__init__.py
create mode 100644 erpnext/portal/doctype/homepage_section_card/homepage_section_card.json
create mode 100644 erpnext/portal/doctype/homepage_section_card/homepage_section_card.py
create mode 100644 erpnext/portal/doctype/website_attribute/__init__.py
create mode 100644 erpnext/portal/doctype/website_attribute/website_attribute.json
create mode 100644 erpnext/portal/doctype/website_attribute/website_attribute.py
create mode 100644 erpnext/portal/doctype/website_filter_field/__init__.py
create mode 100644 erpnext/portal/doctype/website_filter_field/website_filter_field.json
create mode 100644 erpnext/portal/doctype/website_filter_field/website_filter_field.py
create mode 100644 erpnext/portal/product_configurator/__init__.py
create mode 100644 erpnext/portal/product_configurator/item_variants_cache.py
create mode 100644 erpnext/portal/product_configurator/test_product_configurator.py
create mode 100644 erpnext/portal/product_configurator/utils.py
create mode 100644 erpnext/public/js/website_theme.js
create mode 100644 erpnext/public/less/products.less
create mode 120000 erpnext/public/node_modules
create mode 100644 erpnext/public/scss/website.scss
create mode 100644 erpnext/stock/doctype/item_attribute/item_attribute.js
delete mode 100644 erpnext/templates/generators/item.html
create mode 100644 erpnext/templates/generators/item/item.html
create mode 100644 erpnext/templates/generators/item/item_add_to_cart.html
create mode 100644 erpnext/templates/generators/item/item_configure.html
create mode 100644 erpnext/templates/generators/item/item_configure.js
create mode 100644 erpnext/templates/generators/item/item_details.html
create mode 100644 erpnext/templates/generators/item/item_image.html
create mode 100644 erpnext/templates/generators/item/item_inquiry.js
create mode 100644 erpnext/templates/generators/item/item_specifications.html
create mode 100644 erpnext/templates/includes/cart/address_card.html
delete mode 100644 erpnext/templates/includes/product_page.js
create mode 100644 erpnext/templates/pages/home.css
create mode 100644 erpnext/www/all-products/__init__.py
create mode 100644 erpnext/www/all-products/index.html
create mode 100644 erpnext/www/all-products/index.js
create mode 100644 erpnext/www/all-products/index.py
create mode 100644 erpnext/www/all-products/item_row.html
create mode 100644 erpnext/www/all-products/not_found.html
diff --git a/erpnext/config/website.py b/erpnext/config/website.py
index 59e7d404d4..d31b057881 100644
--- a/erpnext/config/website.py
+++ b/erpnext/config/website.py
@@ -11,6 +11,16 @@ def get_data():
"name": "Homepage",
"description": _("Settings for website homepage"),
},
+ {
+ "type": "doctype",
+ "name": "Homepage Section",
+ "description": _("Add cards or custom sections on homepage"),
+ },
+ {
+ "type": "doctype",
+ "name": "Products Settings",
+ "description": _("Settings for website product listing"),
+ },
{
"type": "doctype",
"name": "Shopping Cart Settings",
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index a6876ac1f3..d28666c48b 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -22,7 +22,8 @@ web_include_css = "assets/css/erpnext-web.css"
doctype_js = {
"Communication": "public/js/communication.js",
- "Event": "public/js/event.js"
+ "Event": "public/js/event.js",
+ "Website Theme": "public/js/website_theme.js"
}
welcome_email = "erpnext.setup.utils.welcome_email"
diff --git a/erpnext/hr/doctype/job_opening/job_opening.py b/erpnext/hr/doctype/job_opening/job_opening.py
index 4fc2ac1ded..00883d75f1 100644
--- a/erpnext/hr/doctype/job_opening/job_opening.py
+++ b/erpnext/hr/doctype/job_opening/job_opening.py
@@ -53,3 +53,26 @@ class JobOpening(WebsiteGenerator):
def get_list_context(context):
context.title = _("Jobs")
context.introduction = _('Current Job Openings')
+ context.get_list = get_job_openings
+
+def get_job_openings(doctype, txt=None, filters=None, limit_start=0, limit_page_length=20, order_by=None):
+ fields = ['name', 'status', 'job_title', 'description']
+
+ filters = filters or {}
+ filters.update({
+ 'status': 'Open'
+ })
+
+ if txt:
+ filters.update({
+ 'job_title': ['like', '%{0}%'.format(txt)],
+ 'description': ['like', '%{0}%'.format(txt)]
+ })
+
+ return frappe.get_all(doctype,
+ filters,
+ fields,
+ start=limit_start,
+ page_length=limit_page_length,
+ order_by=order_by
+ )
diff --git a/erpnext/hr/doctype/job_opening/templates/job_opening_row.html b/erpnext/hr/doctype/job_opening/templates/job_opening_row.html
new file mode 100644
index 0000000000..5da8cc82a2
--- /dev/null
+++ b/erpnext/hr/doctype/job_opening/templates/job_opening_row.html
@@ -0,0 +1,9 @@
+
+
{{ doc.job_title }}
+
{{ doc.description }}
+
+
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index b7e673da34..cb1e77c73f 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -577,6 +577,7 @@ erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019
erpnext.patches.v11_0.update_delivery_trip_status
erpnext.patches.v11_0.set_missing_gst_hsn_code
erpnext.patches.v11_0.rename_bom_wo_fields
+erpnext.patches.v12_0.set_default_homepage_type
erpnext.patches.v11_0.rename_additional_salary_component_additional_salary
erpnext.patches.v11_0.renamed_from_to_fields_in_project
erpnext.patches.v11_0.add_permissions_in_gst_settings
@@ -584,5 +585,4 @@ erpnext.patches.v11_1.setup_guardian_role
execute:frappe.delete_doc('DocType', 'Notification Control')
erpnext.patches.v11_0.remove_barcodes_field_from_copy_fields_to_variants
erpnext.patches.v12_0.set_task_status
-erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019
erpnext.patches.v11_0.make_italian_localization_fields # 01-03-2019
diff --git a/erpnext/patches/v12_0/add_variant_of_in_item_attribute_table.py b/erpnext/patches/v12_0/add_variant_of_in_item_attribute_table.py
new file mode 100644
index 0000000000..bc6119067c
--- /dev/null
+++ b/erpnext/patches/v12_0/add_variant_of_in_item_attribute_table.py
@@ -0,0 +1,8 @@
+import frappe
+
+def execute():
+ frappe.db.sql('''
+ UPDATE `tabItem Variant Attribute` t1
+ INNER JOIN `tabItem` t2 ON t2.name = t1.parent
+ SET t1.variant_of = t2.variant_of
+ ''')
diff --git a/erpnext/patches/v12_0/set_default_homepage_type.py b/erpnext/patches/v12_0/set_default_homepage_type.py
new file mode 100644
index 0000000000..241e4b9b5e
--- /dev/null
+++ b/erpnext/patches/v12_0/set_default_homepage_type.py
@@ -0,0 +1,4 @@
+import frappe
+
+def execute():
+ frappe.db.set_value('Homepage', 'Homepage', 'hero_section_based_on', 'Default')
\ No newline at end of file
diff --git a/erpnext/portal/doctype/homepage/homepage.js b/erpnext/portal/doctype/homepage/homepage.js
index 0b07814f75..ca34d69576 100644
--- a/erpnext/portal/doctype/homepage/homepage.js
+++ b/erpnext/portal/doctype/homepage/homepage.js
@@ -11,7 +11,12 @@ frappe.ui.form.on('Homepage', {
},
refresh: function(frm) {
-
+ frm.add_custom_button(__('Set Meta Tags'), () => {
+ frappe.utils.set_meta_tag('home');
+ });
+ frm.add_custom_button(__('Customize Homepage Sections'), () => {
+ frappe.set_route('List', 'Homepage Section', 'List');
+ });
},
});
diff --git a/erpnext/portal/doctype/homepage/homepage.json b/erpnext/portal/doctype/homepage/homepage.json
index 81433b1c5d..ad27278dc6 100644
--- a/erpnext/portal/doctype/homepage/homepage.json
+++ b/erpnext/portal/doctype/homepage/homepage.json
@@ -1,5 +1,7 @@
{
"allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "",
@@ -10,18 +12,24 @@
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 0,
+ "engine": "InnoDB",
"fields": [
{
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
- "in_list_view": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
"label": "Company",
"length": 0,
"no_copy": 0,
@@ -31,24 +39,63 @@
"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,
+ "translatable": 0,
"unique": 0
},
{
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "title",
- "fieldtype": "Data",
+ "columns": 0,
+ "fieldname": "hero_section_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,
- "label": "TItle",
+ "in_standard_filter": 0,
+ "label": "Hero Section Based On",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Default\nSlideshow\nHomepage Section",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_2",
+ "fieldtype": "Column Break",
+ "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,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -56,16 +103,88 @@
"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,
+ "translatable": 0,
"unique": 0
},
{
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
+ "depends_on": "",
+ "fieldname": "title",
+ "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": "Title",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "",
+ "fieldname": "section_break_4",
+ "fieldtype": "Section Break",
+ "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": "Hero Section",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "eval:doc.hero_section_based_on === 'Default'",
"description": "Company Tagline for website homepage",
"fieldname": "tag_line",
"fieldtype": "Data",
@@ -73,7 +192,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
- "in_list_view": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
"label": "Tag Line",
"length": 0,
"no_copy": 0,
@@ -82,16 +203,22 @@
"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,
+ "translatable": 0,
"unique": 0
},
{
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
+ "depends_on": "eval:doc.hero_section_based_on === 'Default'",
"description": "Company Description for website homepage",
"fieldname": "description",
"fieldtype": "Text",
@@ -99,7 +226,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
- "in_list_view": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
"label": "Description",
"length": 0,
"no_copy": 0,
@@ -108,23 +237,133 @@
"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,
+ "translatable": 0,
"unique": 0
},
{
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
+ "depends_on": "eval:doc.hero_section_based_on === 'Default'",
+ "fieldname": "hero_image",
+ "fieldtype": "Attach Image",
+ "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": "Hero Image",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "eval:doc.hero_section_based_on === 'Slideshow'",
+ "description": "",
+ "fieldname": "slideshow",
+ "fieldtype": "Link",
+ "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": "Homepage Slideshow",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Website Slideshow",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "eval:doc.hero_section_based_on === 'Homepage Section'",
+ "fieldname": "hero_section",
+ "fieldtype": "Link",
+ "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": "Homepage Section",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Homepage Section",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "",
"fieldname": "products_section",
"fieldtype": "Section Break",
"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": "Products",
"length": 0,
"no_copy": 0,
@@ -133,16 +372,21 @@
"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,
+ "translatable": 0,
"unique": 0
},
{
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
"default": "/products",
"fieldname": "products_url",
"fieldtype": "Data",
@@ -150,7 +394,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "URL for \"All Products\"",
"length": 0,
"no_copy": 0,
@@ -159,16 +405,21 @@
"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,
+ "translatable": 0,
"unique": 0
},
{
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "columns": 0,
"description": "Products to be shown on website homepage",
"fieldname": "products",
"fieldtype": "Table",
@@ -176,7 +427,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Products",
"length": 0,
"no_copy": 0,
@@ -186,14 +439,17 @@
"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,
+ "translatable": 0,
"unique": 0,
"width": "40px"
}
],
+ "has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
@@ -203,7 +459,7 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-08-29 01:28:00.961623",
+ "modified": "2019-03-02 23:12:59.676202",
"modified_by": "Administrator",
"module": "Portal",
"name": "Homepage",
@@ -212,7 +468,6 @@
"permissions": [
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@@ -232,7 +487,6 @@
},
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@@ -254,8 +508,11 @@
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
+ "show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "company",
- "track_seen": 0
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
}
\ No newline at end of file
diff --git a/erpnext/portal/doctype/homepage/homepage.py b/erpnext/portal/doctype/homepage/homepage.py
index f8f73fdcd0..4e4d4774ab 100644
--- a/erpnext/portal/doctype/homepage/homepage.py
+++ b/erpnext/portal/doctype/homepage/homepage.py
@@ -9,8 +9,6 @@ from frappe.website.utils import delete_page_cache
class Homepage(Document):
def validate(self):
- if not self.products:
- self.setup_items()
if not self.description:
self.description = frappe._("This is an example website auto-generated from ERPNext")
delete_page_cache('home')
diff --git a/erpnext/portal/doctype/homepage/test_homepage.py b/erpnext/portal/doctype/homepage/test_homepage.py
new file mode 100644
index 0000000000..b262c4640c
--- /dev/null
+++ b/erpnext/portal/doctype/homepage/test_homepage.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+from frappe.tests.test_website import set_request
+from frappe.website.render import render
+
+class TestHomepage(unittest.TestCase):
+ def test_homepage_load(self):
+ set_request(method='GET', path='home')
+ response = render()
+
+ self.assertEquals(response.status_code, 200)
+
+ html = frappe.safe_decode(response.get_data())
+ self.assertTrue('My custom html',
+ }).insert()
+
+ set_request(method='GET', path='home')
+ response = render()
+
+ self.assertEquals(response.status_code, 200)
+
+ html = frappe.safe_decode(response.get_data())
+
+ soup = BeautifulSoup(html, 'html.parser')
+ sections = soup.find('main').find_all(class_='custom-section')
+ self.assertEqual(len(sections), 1)
+
+ homepage_section = sections[0]
+ self.assertEqual(homepage_section.text, 'My custom html')
+
+ # cleanup
+ frappe.db.rollback()
diff --git a/erpnext/portal/doctype/homepage_section_card/__init__.py b/erpnext/portal/doctype/homepage_section_card/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/portal/doctype/homepage_section_card/homepage_section_card.json b/erpnext/portal/doctype/homepage_section_card/homepage_section_card.json
new file mode 100644
index 0000000000..9092b268c5
--- /dev/null
+++ b/erpnext/portal/doctype/homepage_section_card/homepage_section_card.json
@@ -0,0 +1,203 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2019-02-10 19:39:02.734686",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "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": "Title",
+ "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": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "subtitle",
+ "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": "Subtitle",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "image",
+ "fieldtype": "Attach Image",
+ "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": "Image",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "content",
+ "fieldtype": "Text",
+ "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": "Content",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "route",
+ "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": "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,
+ "translatable": 0,
+ "unique": 0
+ }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2019-02-10 20:11:41.040716",
+ "modified_by": "Administrator",
+ "module": "Portal",
+ "name": "Homepage Section Card",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/portal/doctype/homepage_section_card/homepage_section_card.py b/erpnext/portal/doctype/homepage_section_card/homepage_section_card.py
new file mode 100644
index 0000000000..bd17279f99
--- /dev/null
+++ b/erpnext/portal/doctype/homepage_section_card/homepage_section_card.py
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+from frappe.model.document import Document
+
+class HomepageSectionCard(Document):
+ pass
diff --git a/erpnext/portal/doctype/products_settings/products_settings.js b/erpnext/portal/doctype/products_settings/products_settings.js
index 7a57abaf9b..b68b5d7aa8 100644
--- a/erpnext/portal/doctype/products_settings/products_settings.js
+++ b/erpnext/portal/doctype/products_settings/products_settings.js
@@ -3,6 +3,17 @@
frappe.ui.form.on('Products Settings', {
refresh: function(frm) {
+ frappe.model.with_doctype('Item', () => {
+ const item_meta = frappe.get_meta('Item');
+ const valid_fields = item_meta.fields.filter(
+ df => ['Link', 'Table MultiSelect'].includes(df.fieldtype) && !df.hidden
+ ).map(df => ({ label: df.label, value: df.fieldname }));
+
+ const field = frappe.meta.get_docfield("Website Filter Field", "fieldname", frm.docname);
+ field.fieldtype = 'Select';
+ field.options = valid_fields;
+ frm.fields_dict.filter_fields.grid.refresh();
+ });
}
});
diff --git a/erpnext/portal/doctype/products_settings/products_settings.json b/erpnext/portal/doctype/products_settings/products_settings.json
index 69abae13a4..2cf8431497 100644
--- a/erpnext/portal/doctype/products_settings/products_settings.json
+++ b/erpnext/portal/doctype/products_settings/products_settings.json
@@ -1,255 +1,389 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2016-04-22 09:11:55.272398",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 0,
- "engine": "InnoDB",
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2016-04-22 09:11:55.272398",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 0,
+ "engine": "InnoDB",
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "If checked, the Home page will be the default Item Group for the website",
- "fieldname": "home_page_is_products",
- "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": "Home Page is Products",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "description": "If checked, the Home page will be the default Item Group for the website",
+ "fieldname": "home_page_is_products",
+ "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": "Home Page is Products",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_3",
- "fieldtype": "Column Break",
- "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,
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break",
+ "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,
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "products_as_list",
- "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": "Show Products as a List",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "show_availability_status",
+ "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": "Show Availability Status",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "show_availability_status",
- "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": "Show Availability Status",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "section_break_5",
+ "fieldtype": "Section Break",
+ "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": "Product Page",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_5",
- "fieldtype": "Section Break",
- "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,
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "6",
+ "fieldname": "products_per_page",
+ "fieldtype": "Int",
+ "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": "Products per Page",
+ "length": 0,
+ "no_copy": 0,
+ "options": "",
+ "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,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "6",
- "fieldname": "products_per_page",
- "fieldtype": "Int",
- "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": "Products per Page",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "enable_field_filters",
+ "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": "Enable Field Filters",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "enable_field_filters",
+ "fieldname": "filter_fields",
+ "fieldtype": "Table",
+ "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": "Item Fields",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Website Filter Field",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "enable_attribute_filters",
+ "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": "Enable Attribute Filters",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "enable_attribute_filters",
+ "fieldname": "filter_attributes",
+ "fieldtype": "Table",
+ "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": "Attributes",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Website Attribute",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "hide_variants",
+ "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": "Hide Variants",
+ "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,
+ "translatable": 0,
"unique": 0
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 1,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-08-14 17:59:58.473100",
- "modified_by": "Administrator",
- "module": "Portal",
- "name": "Products Settings",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 1,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2019-03-07 19:18:31.822309",
+ "modified_by": "Administrator",
+ "module": "Portal",
+ "name": "Products Settings",
+ "name_case": "",
+ "owner": "Administrator",
"permissions": [
{
- "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": 0,
- "role": "Website Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "amend": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 0,
+ "role": "Website Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
"write": 1
}
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
}
\ No newline at end of file
diff --git a/erpnext/portal/doctype/products_settings/products_settings.py b/erpnext/portal/doctype/products_settings/products_settings.py
index f17ae9fee9..82afebf2f1 100644
--- a/erpnext/portal/doctype/products_settings/products_settings.py
+++ b/erpnext/portal/doctype/products_settings/products_settings.py
@@ -5,6 +5,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cint
+from frappe import _
from frappe.model.document import Document
class ProductsSettings(Document):
@@ -14,6 +15,26 @@ class ProductsSettings(Document):
website_settings.home_page = 'products'
website_settings.save()
+ self.validate_field_filters()
+ self.validate_attribute_filters()
+
+ def validate_field_filters(self):
+ if not (self.enable_field_filters and self.filter_fields): return
+
+ item_meta = frappe.get_meta('Item')
+ valid_fields = [df.fieldname for df in item_meta.fields if df.fieldtype in ['Link', 'Table MultiSelect']]
+
+ for f in self.filter_fields:
+ if f.fieldname not in valid_fields:
+ frappe.throw(_('Filter Fields Row #{0}: Fieldname {1} must be of type "Link" or "Table MultiSelect"').format(f.idx, f.fieldname))
+
+ def validate_attribute_filters(self):
+ if not (self.enable_attribute_filters and self.filter_attributes): return
+
+ # if attribute filters are enabled, hide_variants should be disabled
+ self.hide_variants = 0
+
+
def home_page_is_products(doc, method):
'''Called on saving Website Settings'''
home_page_is_products = cint(frappe.db.get_single_value('Products Settings', 'home_page_is_products'))
diff --git a/erpnext/portal/doctype/website_attribute/__init__.py b/erpnext/portal/doctype/website_attribute/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/portal/doctype/website_attribute/website_attribute.json b/erpnext/portal/doctype/website_attribute/website_attribute.json
new file mode 100644
index 0000000000..2874dc432c
--- /dev/null
+++ b/erpnext/portal/doctype/website_attribute/website_attribute.json
@@ -0,0 +1,76 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2019-01-01 13:04:54.479079",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "attribute",
+ "fieldtype": "Link",
+ "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": "Attribute",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Item Attribute",
+ "permlevel": 0,
+ "precision": "",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2019-01-01 13:04:59.715572",
+ "modified_by": "Administrator",
+ "module": "Portal",
+ "name": "Website Attribute",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/portal/doctype/website_attribute/website_attribute.py b/erpnext/portal/doctype/website_attribute/website_attribute.py
new file mode 100644
index 0000000000..b8b667a613
--- /dev/null
+++ b/erpnext/portal/doctype/website_attribute/website_attribute.py
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+from frappe.model.document import Document
+
+class WebsiteAttribute(Document):
+ pass
diff --git a/erpnext/portal/doctype/website_filter_field/__init__.py b/erpnext/portal/doctype/website_filter_field/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/portal/doctype/website_filter_field/website_filter_field.json b/erpnext/portal/doctype/website_filter_field/website_filter_field.json
new file mode 100644
index 0000000000..67c0d0ae73
--- /dev/null
+++ b/erpnext/portal/doctype/website_filter_field/website_filter_field.json
@@ -0,0 +1,76 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2018-12-31 17:06:08.716134",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "fieldname",
+ "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": "Fieldname",
+ "length": 0,
+ "no_copy": 0,
+ "options": "",
+ "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,
+ "translatable": 0,
+ "unique": 0
+ }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2019-01-01 18:26:11.550380",
+ "modified_by": "Administrator",
+ "module": "Portal",
+ "name": "Website Filter Field",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/portal/doctype/website_filter_field/website_filter_field.py b/erpnext/portal/doctype/website_filter_field/website_filter_field.py
new file mode 100644
index 0000000000..2aa8a6f98d
--- /dev/null
+++ b/erpnext/portal/doctype/website_filter_field/website_filter_field.py
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+from frappe.model.document import Document
+
+class WebsiteFilterField(Document):
+ pass
diff --git a/erpnext/portal/product_configurator/__init__.py b/erpnext/portal/product_configurator/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/portal/product_configurator/item_variants_cache.py b/erpnext/portal/product_configurator/item_variants_cache.py
new file mode 100644
index 0000000000..cd557b5075
--- /dev/null
+++ b/erpnext/portal/product_configurator/item_variants_cache.py
@@ -0,0 +1,94 @@
+import frappe
+
+class ItemVariantsCacheManager:
+ def __init__(self, item_code):
+ self.item_code = item_code
+
+ def get_item_variants_data(self):
+ val = frappe.cache().hget('item_variants_data', self.item_code)
+
+ if not val:
+ self.build_cache()
+
+ return frappe.cache().hget('item_variants_data', self.item_code)
+
+
+ def get_attribute_value_item_map(self):
+ val = frappe.cache().hget('attribute_value_item_map', self.item_code)
+
+ if not val:
+ self.build_cache()
+
+ return frappe.cache().hget('attribute_value_item_map', self.item_code)
+
+
+ def get_item_attribute_value_map(self):
+ val = frappe.cache().hget('item_attribute_value_map', self.item_code)
+
+ if not val:
+ self.build_cache()
+
+ return frappe.cache().hget('item_attribute_value_map', self.item_code)
+
+
+ def get_optional_attributes(self):
+ val = frappe.cache().hget('optional_attributes', self.item_code)
+
+ if not val:
+ self.build_cache()
+
+ return frappe.cache().hget('optional_attributes', self.item_code)
+
+
+ def build_cache(self):
+ parent_item_code = self.item_code
+
+ attributes = [a.attribute for a in frappe.db.get_all('Item Variant Attribute',
+ {'parent': parent_item_code}, ['attribute'], order_by='idx asc')
+ ]
+
+ item_variants_data = frappe.db.get_all('Item Variant Attribute',
+ {'variant_of': parent_item_code}, ['parent', 'attribute', 'attribute_value'],
+ order_by='parent',
+ as_list=1
+ )
+
+ attribute_value_item_map = frappe._dict({})
+ item_attribute_value_map = frappe._dict({})
+
+ for row in item_variants_data:
+ item_code, attribute, attribute_value = row
+ # (attr, value) => [item1, item2]
+ attribute_value_item_map.setdefault((attribute, attribute_value), []).append(item_code)
+ # item => {attr1: value1, attr2: value2}
+ item_attribute_value_map.setdefault(item_code, {})[attribute] = attribute_value
+
+ optional_attributes = set()
+ for item_code, attr_dict in item_attribute_value_map.items():
+ for attribute in attributes:
+ if attribute not in attr_dict:
+ optional_attributes.add(attribute)
+
+ frappe.cache().hset('attribute_value_item_map', parent_item_code, attribute_value_item_map)
+ frappe.cache().hset('item_attribute_value_map', parent_item_code, item_attribute_value_map)
+ frappe.cache().hset('item_variants_data', parent_item_code, item_variants_data)
+ frappe.cache().hset('optional_attributes', parent_item_code, optional_attributes)
+
+ def clear_cache(self):
+ keys = ['attribute_value_item_map', 'item_attribute_value_map', 'item_variants_data', 'optional_attributes']
+
+ for key in keys:
+ frappe.cache().hdel(key, self.item_code)
+
+
+def build_cache(item_code):
+ frappe.cache().hset('item_cache_build_in_progress', item_code, 1)
+ print('ItemVariantsCacheManager: Building cache for', item_code)
+ i = ItemVariantsCacheManager(item_code)
+ i.build_cache()
+ frappe.cache().hset('item_cache_build_in_progress', item_code, 0)
+
+def enqueue_build_cache(item_code):
+ if frappe.cache().hget('item_cache_build_in_progress', item_code):
+ return
+ frappe.enqueue(build_cache, item_code=item_code, queue='short')
diff --git a/erpnext/portal/product_configurator/test_product_configurator.py b/erpnext/portal/product_configurator/test_product_configurator.py
new file mode 100644
index 0000000000..a534e5f838
--- /dev/null
+++ b/erpnext/portal/product_configurator/test_product_configurator.py
@@ -0,0 +1,84 @@
+from __future__ import unicode_literals
+
+from bs4 import BeautifulSoup
+import frappe, unittest
+from frappe.tests.test_website import set_request, get_html_for_route
+from frappe.website.render import render
+from erpnext.portal.product_configurator.utils import get_products_for_website
+from erpnext.stock.doctype.item.test_item import make_item_variant
+
+test_dependencies = ["Item"]
+
+class TestProductConfigurator(unittest.TestCase):
+ def setUp(self):
+ self.create_variant_item()
+
+ def test_product_list(self):
+ template_items = frappe.get_all('Item', {'show_in_website': 1})
+ variant_items = frappe.get_all('Item', {'show_variant_in_website': 1})
+
+ products_settings = frappe.get_doc('Products Settings')
+ products_settings.enable_field_filters = 1
+ products_settings.append('filter_fields', {'fieldname': 'item_group'})
+ products_settings.append('filter_fields', {'fieldname': 'stock_uom'})
+ products_settings.save()
+
+ html = get_html_for_route('all-products')
+
+ soup = BeautifulSoup(html, 'html.parser')
+ products_list = soup.find(class_='products-list')
+ items = products_list.find_all(class_='card')
+ self.assertEqual(len(items), len(template_items + variant_items))
+
+ items_with_item_group = frappe.get_all('Item', {'item_group': '_Test Item Group Desktops', 'show_in_website': 1})
+ variants_with_item_group = frappe.get_all('Item', {'item_group': '_Test Item Group Desktops', 'show_variant_in_website': 1})
+
+ # mock query params
+ frappe.form_dict = frappe._dict({
+ 'field_filters': '{"item_group":["_Test Item Group Desktops"]}'
+ })
+ html = get_html_for_route('all-products')
+ soup = BeautifulSoup(html, 'html.parser')
+ products_list = soup.find(class_='products-list')
+ items = products_list.find_all(class_='card')
+ self.assertEqual(len(items), len(items_with_item_group + variants_with_item_group))
+
+
+ def test_get_products_for_website(self):
+ items = get_products_for_website(attribute_filters={
+ 'Test Size': ['Medium']
+ })
+ self.assertEqual(len(items), 1)
+
+
+ def create_variant_item(self):
+ if not frappe.db.exists('Item', '_Test Variant Item 1'):
+ frappe.get_doc({
+ "description": "_Test Variant Item 12",
+ "doctype": "Item",
+ "is_stock_item": 1,
+ "variant_of": "_Test Variant Item",
+ "item_code": "_Test Variant Item 1",
+ "item_group": "_Test Item Group",
+ "item_name": "_Test Variant Item 1",
+ "stock_uom": "_Test UOM",
+ "item_defaults": [{
+ "company": "_Test Company",
+ "default_warehouse": "_Test Warehouse - _TC",
+ "expense_account": "_Test Account Cost for Goods Sold - _TC",
+ "buying_cost_center": "_Test Cost Center - _TC",
+ "selling_cost_center": "_Test Cost Center - _TC",
+ "income_account": "Sales - _TC"
+ }],
+ "attributes": [
+ {
+ "attribute": "Test Size",
+ "attribute_value": "Medium"
+ }
+ ],
+ "show_variant_in_website": 1
+ }).insert()
+
+
+ def tearDown(self):
+ frappe.db.rollback()
\ No newline at end of file
diff --git a/erpnext/portal/product_configurator/utils.py b/erpnext/portal/product_configurator/utils.py
new file mode 100644
index 0000000000..3594bc4467
--- /dev/null
+++ b/erpnext/portal/product_configurator/utils.py
@@ -0,0 +1,402 @@
+import frappe
+from erpnext.portal.product_configurator.item_variants_cache import ItemVariantsCacheManager
+
+def get_field_filter_data():
+ product_settings = get_product_settings()
+ filter_fields = [row.fieldname for row in product_settings.filter_fields]
+
+ meta = frappe.get_meta('Item')
+ fields = [df for df in meta.fields if df.fieldname in filter_fields]
+
+ filter_data = []
+ for f in fields:
+ doctype = f.get_link_doctype()
+
+ # apply enable/disable filter
+ meta = frappe.get_meta(doctype)
+ filters = {}
+ if meta.has_field('enabled'):
+ filters['enabled'] = 1
+ if meta.has_field('disabled'):
+ filters['disabled'] = 0
+
+ values = [d.name for d in frappe.get_all(doctype, filters)]
+ filter_data.append([f, values])
+
+ return filter_data
+
+
+def get_attribute_filter_data():
+ product_settings = get_product_settings()
+ attributes = [row.attribute for row in product_settings.filter_attributes]
+ attribute_docs = [
+ frappe.get_doc('Item Attribute', attribute) for attribute in attributes
+ ]
+
+ # mark attribute values as checked if they are present in the request url
+ if frappe.form_dict:
+ for attr in attribute_docs:
+ if attr.name in frappe.form_dict:
+ value = frappe.form_dict[attr.name]
+ if value:
+ enabled_values = value.split(',')
+ else:
+ enabled_values = []
+
+ for v in enabled_values:
+ for item_attribute_row in attr.item_attribute_values:
+ if v == item_attribute_row.attribute_value:
+ item_attribute_row.checked = True
+
+ return attribute_docs
+
+
+def get_products_for_website(field_filters=None, attribute_filters=None, search=None):
+
+ if attribute_filters:
+ item_codes = get_item_codes_by_attributes(attribute_filters)
+ items_by_attributes = get_items([['name', 'in', item_codes]])
+
+ if field_filters:
+ items_by_fields = get_items_by_fields(field_filters)
+
+ if attribute_filters and not field_filters:
+ return items_by_attributes
+
+ if field_filters and not attribute_filters:
+ return items_by_fields
+
+ if field_filters and attribute_filters:
+ items_intersection = []
+ item_codes_in_attribute = [item.name for item in items_by_attributes]
+
+ for item in items_by_fields:
+ if item.name in item_codes_in_attribute:
+ items_intersection.append(item)
+
+ return items_intersection
+
+ if search:
+ return get_items(search=search)
+
+ return get_items()
+
+
+@frappe.whitelist(allow_guest=True)
+def get_products_html_for_website(field_filters=None, attribute_filters=None):
+ field_filters = frappe.parse_json(field_filters)
+ attribute_filters = frappe.parse_json(attribute_filters)
+
+ items = get_products_for_website(field_filters, attribute_filters)
+ html = ''.join(get_html_for_items(items))
+
+ if not items:
+ html = frappe.render_template('erpnext/www/all-products/not_found.html', {})
+
+ return html
+
+
+def get_item_codes_by_attributes(attribute_filters, template_item_code=None):
+ items = []
+
+ for attribute, values in attribute_filters.items():
+ attribute_values = values
+
+ if not attribute_values: continue
+
+ wheres = []
+ query_values = []
+ for attribute_value in attribute_values:
+ wheres.append('( attribute = %s and attribute_value = %s )')
+ query_values += [attribute, attribute_value]
+
+ attribute_query = ' or '.join(wheres)
+
+ if template_item_code:
+ variant_of_query = 'AND t2.variant_of = %s'
+ query_values.append(template_item_code)
+ else:
+ variant_of_query = ''
+
+ query = '''
+ SELECT
+ t1.parent
+ FROM
+ `tabItem Variant Attribute` t1
+ WHERE
+ 1 = 1
+ AND (
+ {attribute_query}
+ )
+ AND EXISTS (
+ SELECT
+ 1
+ FROM
+ `tabItem` t2
+ WHERE
+ t2.name = t1.parent
+ {variant_of_query}
+ )
+ GROUP BY
+ t1.parent
+ ORDER BY
+ NULL
+ '''.format(attribute_query=attribute_query, variant_of_query=variant_of_query)
+
+ item_codes = set([r[0] for r in frappe.db.sql(query, query_values)])
+ items.append(item_codes)
+
+ res = list(set.intersection(*items))
+
+ return res
+
+
+@frappe.whitelist(allow_guest=True)
+def get_attributes_and_values(item_code):
+ '''Build a list of attributes and their possible values.
+ This will ignore the values upon selection of which there cannot exist one item.
+ '''
+ item_cache = ItemVariantsCacheManager(item_code)
+ item_variants_data = item_cache.get_item_variants_data()
+
+ attributes = get_item_attributes(item_code)
+ attribute_list = [a.attribute for a in attributes]
+
+ valid_options = {}
+ for item_code, attribute, attribute_value in item_variants_data:
+ if attribute in attribute_list:
+ valid_options.setdefault(attribute, set()).add(attribute_value)
+
+ for attr in attributes:
+ attr['values'] = valid_options.get(attr.attribute, [])
+
+ return attributes
+
+
+@frappe.whitelist(allow_guest=True)
+def get_next_attribute_and_values(item_code, selected_attributes):
+ '''Find the count of Items that match the selected attributes.
+ Also, find the attribute values that are not applicable for further searching.
+ If less than equal to 10 items are found, return item_codes of those items.
+ If one item is matched exactly, return item_code of that item.
+ '''
+ selected_attributes = frappe.parse_json(selected_attributes)
+
+ item_cache = ItemVariantsCacheManager(item_code)
+ item_variants_data = item_cache.get_item_variants_data()
+
+ attributes = get_item_attributes(item_code)
+ attribute_list = [a.attribute for a in attributes]
+ filtered_items = get_items_with_selected_attributes(item_code, selected_attributes)
+
+ next_attribute = None
+
+ for attribute in attribute_list:
+ if attribute not in selected_attributes:
+ next_attribute = attribute
+ break
+
+ valid_options_for_attributes = frappe._dict({})
+
+ for a in attribute_list:
+ valid_options_for_attributes[a] = set()
+
+ selected_attribute = selected_attributes.get(a, None)
+ if selected_attribute:
+ # already selected attribute values are valid options
+ valid_options_for_attributes[a].add(selected_attribute)
+
+ for row in item_variants_data:
+ item_code, attribute, attribute_value = row
+ if item_code in filtered_items and attribute not in selected_attributes and attribute in attribute_list:
+ valid_options_for_attributes[attribute].add(attribute_value)
+
+ optional_attributes = item_cache.get_optional_attributes()
+ exact_match = []
+ # search for exact match if all selected attributes are required attributes
+ if len(selected_attributes.keys()) >= (len(attribute_list) - len(optional_attributes)):
+ item_attribute_value_map = item_cache.get_item_attribute_value_map()
+ for item_code, attr_dict in item_attribute_value_map.items():
+ if item_code in filtered_items and set(attr_dict.keys()) == set(selected_attributes.keys()):
+ exact_match.append(item_code)
+
+ filtered_items_count = len(filtered_items)
+
+ # get product info if exact match
+ from erpnext.shopping_cart.product_info import get_product_info_for_website
+ if exact_match:
+ data = get_product_info_for_website(exact_match[0])
+ product_info = data.product_info
+ if not data.cart_settings.show_price:
+ product_info = None
+ else:
+ product_info = None
+
+ return {
+ 'next_attribute': next_attribute,
+ 'valid_options_for_attributes': valid_options_for_attributes,
+ 'filtered_items_count': filtered_items_count,
+ 'filtered_items': filtered_items if filtered_items_count < 10 else [],
+ 'exact_match': exact_match,
+ 'product_info': product_info
+ }
+
+
+def get_items_with_selected_attributes(item_code, selected_attributes):
+ item_cache = ItemVariantsCacheManager(item_code)
+ attribute_value_item_map = item_cache.get_attribute_value_item_map()
+
+ items = []
+ for attribute, value in selected_attributes.items():
+ items.append(set(attribute_value_item_map[(attribute, value)]))
+
+ return set.intersection(*items)
+
+
+def get_items_by_fields(field_filters):
+ meta = frappe.get_meta('Item')
+ filters = []
+ for fieldname, values in field_filters.items():
+ if not values: continue
+
+ _doctype = 'Item'
+ _fieldname = fieldname
+
+ df = meta.get_field(fieldname)
+ if df.fieldtype == 'Table MultiSelect':
+ child_doctype = df.options
+ child_meta = frappe.get_meta(child_doctype)
+ fields = child_meta.get("fields", { "fieldtype": "Link", "in_list_view": 1 })
+ if fields:
+ _doctype = child_doctype
+ _fieldname = fields[0].fieldname
+
+ if len(values) == 1:
+ filters.append([_doctype, _fieldname, '=', values[0]])
+ else:
+ filters.append([_doctype, _fieldname, 'in', values])
+
+ return get_items(filters)
+
+
+def get_items(filters=None, search=None):
+ start = frappe.form_dict.start or 0
+ products_settings = get_product_settings()
+ page_length = products_settings.products_per_page
+
+ filters = filters or []
+ # convert to list of filters
+ if isinstance(filters, dict):
+ filters = [['Item', fieldname, '=', value] for fieldname, value in filters.items()]
+
+ show_in_website_condition = ''
+ if products_settings.hide_variants:
+ show_in_website_condition = get_conditions({'show_in_website': 1 }, 'and')
+ else:
+ show_in_website_condition = get_conditions([
+ ['show_in_website', '=', 1],
+ ['show_variant_in_website', '=', 1]
+ ], 'or')
+
+ search_condition = ''
+ if search:
+ search = '%{}%'.format(search)
+ or_filters = [
+ ['name', 'like', search],
+ ['item_name', 'like', search],
+ ['description', 'like', search],
+ ['item_group', 'like', search]
+ ]
+ search_condition = get_conditions(or_filters, 'or')
+
+ filter_condition = get_conditions(filters, 'and')
+
+ where_conditions = ' and '.join(
+ [condition for condition in [show_in_website_condition, search_condition, filter_condition] if condition]
+ )
+
+ left_joins = []
+ for f in filters:
+ if len(f) == 4 and f[0] != 'Item':
+ left_joins.append(f[0])
+
+ left_join = ' '.join(['LEFT JOIN `tab{0}` on (`tab{0}`.parent = `tabItem`.name)'.format(l) for l in left_joins])
+
+ results = frappe.db.sql('''
+ SELECT
+ `tabItem`.`name`, `tabItem`.`item_name`,
+ `tabItem`.`website_image`, `tabItem`.`image`,
+ `tabItem`.`web_long_description`, `tabItem`.`description`,
+ `tabItem`.`route`
+ FROM
+ `tabItem`
+ {left_join}
+ WHERE
+ {where_conditions}
+ GROUP BY
+ `tabItem`.`name`
+ ORDER BY
+ `tabItem`.`weightage` DESC
+ LIMIT
+ {page_length}
+ OFFSET
+ {start}
+ '''.format(
+ where_conditions=where_conditions,
+ start=start,
+ page_length=page_length,
+ left_join=left_join
+ )
+ , as_dict=1)
+
+ for r in results:
+ r.description = r.web_long_description or r.description
+ r.image = r.website_image or r.image
+
+ return results
+
+
+def get_conditions(filter_list, and_or='and'):
+ from frappe.model.db_query import DatabaseQuery
+
+ if not filter_list:
+ return ''
+
+ conditions = []
+ DatabaseQuery('Item').build_filter_conditions(filter_list, conditions, ignore_permissions=True)
+ join_by = ' {0} '.format(and_or)
+
+ return '(' + join_by.join(conditions) + ')'
+
+# utilities
+
+def get_item_attributes(item_code):
+ attributes = frappe.db.get_all('Item Variant Attribute',
+ fields=['attribute'],
+ filters={
+ 'parenttype': 'Item',
+ 'parent': item_code
+ },
+ order_by='idx asc'
+ )
+
+ optional_attributes = ItemVariantsCacheManager(item_code).get_optional_attributes()
+
+ for a in attributes:
+ if a.attribute in optional_attributes:
+ a.optional = True
+
+ return attributes
+
+def get_html_for_items(items):
+ html = []
+ for item in items:
+ html.append(frappe.render_template('erpnext/www/all-products/item_row.html', {
+ 'item': item
+ }))
+ return html
+
+def get_product_settings():
+ doc = frappe.get_cached_doc('Products Settings')
+ doc.products_per_page = doc.products_per_page or 20
+ return doc
diff --git a/erpnext/public/build.json b/erpnext/public/build.json
index c34eef2508..60e72dad71 100644
--- a/erpnext/public/build.json
+++ b/erpnext/public/build.json
@@ -11,7 +11,7 @@
"public/js/shopping_cart.js"
],
"css/erpnext-web.css": [
- "public/less/website.less"
+ "public/scss/website.scss"
],
"js/marketplace.min.js": [
"public/js/hub/marketplace.js"
diff --git a/erpnext/public/js/shopping_cart.js b/erpnext/public/js/shopping_cart.js
index 7755141da6..5a0526814f 100644
--- a/erpnext/public/js/shopping_cart.js
+++ b/erpnext/public/js/shopping_cart.js
@@ -48,6 +48,7 @@ $.extend(shopping_cart, {
args: {
item_code: opts.item_code,
qty: opts.qty,
+ additional_notes: opts.additional_notes !== undefined ? opts.additional_notes : undefined,
with_items: opts.with_items || 0
},
btn: opts.btn,
@@ -94,11 +95,12 @@ $.extend(shopping_cart, {
}
},
- shopping_cart_update: function(item_code, newVal, cart_dropdown) {
+ shopping_cart_update: function({item_code, qty, cart_dropdown, additional_notes}) {
frappe.freeze();
shopping_cart.update_cart({
- item_code: item_code,
- qty: newVal,
+ item_code,
+ qty,
+ additional_notes,
with_items: 1,
btn: this,
callback: function(r) {
@@ -131,7 +133,7 @@ $.extend(shopping_cart, {
}
input.val(newVal);
var item_code = input.attr("data-item-code");
- shopping_cart.shopping_cart_update(item_code, newVal, true);
+ shopping_cart.shopping_cart_update({item_code, qty: newVal, cart_dropdown: true});
return false;
});
diff --git a/erpnext/public/js/templates/address_list.html b/erpnext/public/js/templates/address_list.html
index 2379ef6b48..0bc86edb08 100644
--- a/erpnext/public/js/templates/address_list.html
+++ b/erpnext/public/js/templates/address_list.html
@@ -9,7 +9,7 @@
({%= __("Shipping") %}){% } %}
{%= __("Edit") %}
@@ -19,5 +19,5 @@
{% if(!addr_list.length) { %}
{%= __("No address added yet.") %}
{% } %}
-
+
diff --git a/erpnext/public/js/templates/contact_list.html b/erpnext/public/js/templates/contact_list.html
index 893b4e0ec2..2144893961 100644
--- a/erpnext/public/js/templates/contact_list.html
+++ b/erpnext/public/js/templates/contact_list.html
@@ -10,7 +10,7 @@
– {%= contact_list[i].designation %}
{% } %}
{%= __("Edit") %}
@@ -33,6 +33,6 @@
{% if(!contact_list.length) { %}
{%= __("No contacts added yet.") %}
{% } %}
-