Merge branch 'staging-fixes' of https://github.com/frappe/erpnext into update_items_bug
diff --git a/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py b/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py
index 05c8fb7..c234da0 100644
--- a/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py
+++ b/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py
@@ -108,33 +108,33 @@
def get_pos_invoice_data(filters):
conditions = get_conditions(filters)
result = frappe.db.sql(''
- 'SELECT '
- 'posting_date, owner, sum(net_total) as "net_total", sum(total_taxes) as "total_taxes", '
- 'sum(paid_amount) as "paid_amount", sum(outstanding_amount) as "outstanding_amount", '
- 'mode_of_payment, warehouse, cost_center '
- 'FROM ('
- 'SELECT '
- 'parent, item_code, sum(amount) as "base_total", warehouse, cost_center '
- 'from `tabSales Invoice Item` group by parent'
- ') t1 '
- 'left join '
- '(select parent, mode_of_payment from `tabSales Invoice Payment` group by parent) t3 '
- 'on (t3.parent = t1.parent) '
- 'JOIN ('
- 'SELECT '
- 'docstatus, company, is_pos, name, posting_date, owner, sum(base_total) as "base_total", '
- 'sum(net_total) as "net_total", sum(total_taxes_and_charges) as "total_taxes", '
- 'sum(base_paid_amount) as "paid_amount", sum(outstanding_amount) as "outstanding_amount" '
- 'FROM `tabSales Invoice` '
- 'GROUP BY name'
- ') a '
- 'ON ('
- 't1.parent = a.name and t1.base_total = a.base_total) '
- 'WHERE a.docstatus = 1'
- ' AND {conditions} '
- 'GROUP BY '
- 'owner, posting_date, warehouse'.format(conditions=conditions), filters, as_dict=1
- )
+ 'SELECT '
+ 'posting_date, owner, sum(net_total) as "net_total", sum(total_taxes) as "total_taxes", '
+ 'sum(paid_amount) as "paid_amount", sum(outstanding_amount) as "outstanding_amount", '
+ 'mode_of_payment, warehouse, cost_center '
+ 'FROM ('
+ 'SELECT '
+ 'parent, item_code, sum(amount) as "base_total", warehouse, cost_center '
+ 'from `tabSales Invoice Item` group by parent'
+ ') t1 '
+ 'left join '
+ '(select parent, mode_of_payment from `tabSales Invoice Payment` group by parent) t3 '
+ 'on (t3.parent = t1.parent) '
+ 'JOIN ('
+ 'SELECT '
+ 'docstatus, company, is_pos, name, posting_date, owner, sum(base_total) as "base_total", '
+ 'sum(net_total) as "net_total", sum(total_taxes_and_charges) as "total_taxes", '
+ 'sum(base_paid_amount) as "paid_amount", sum(outstanding_amount) as "outstanding_amount" '
+ 'FROM `tabSales Invoice` '
+ 'GROUP BY name'
+ ') a '
+ 'ON ('
+ 't1.parent = a.name and t1.base_total = a.base_total) '
+ 'WHERE a.docstatus = 1'
+ ' AND {conditions} '
+ 'GROUP BY '
+ 'owner, posting_date, warehouse'.format(conditions=conditions), filters, as_dict=1
+ )
return result
@@ -156,7 +156,6 @@
def get_mode_of_payments(filters):
- frappe.log_error(filters, 'filters')
mode_of_payments = {}
invoice_list = get_invoices(filters)
invoice_list_names = ",".join(['"' + invoice['name'] + '"' for invoice in invoice_list])
@@ -164,12 +163,14 @@
inv_mop = frappe.db.sql("""select a.owner,a.posting_date, ifnull(b.mode_of_payment, '') as mode_of_payment
from `tabSales Invoice` a, `tabSales Invoice Payment` b
where a.name = b.parent
+ and a.docstatus = 1
and a.name in ({invoice_list_names})
union
select a.owner,a.posting_date, ifnull(b.mode_of_payment, '') as mode_of_payment
from `tabSales Invoice` a, `tabPayment Entry` b,`tabPayment Entry Reference` c
where a.name = c.reference_name
and b.name = c.parent
+ and b.docstatus = 1
and a.name in ({invoice_list_names})
union
select a.owner, a.posting_date,
@@ -196,13 +197,13 @@
def get_mode_of_payment_details(filters):
mode_of_payment_details = {}
invoice_list = get_invoices(filters)
- frappe.log_error(invoice_list, 'invoice_list')
invoice_list_names = ",".join(['"' + invoice['name'] + '"' for invoice in invoice_list])
if invoice_list:
inv_mop_detail = frappe.db.sql("""select a.owner, a.posting_date,
ifnull(b.mode_of_payment, '') as mode_of_payment, sum(b.base_amount) as paid_amount
from `tabSales Invoice` a, `tabSales Invoice Payment` b
where a.name = b.parent
+ and a.docstatus = 1
and a.name in ({invoice_list_names})
group by a.owner, a.posting_date, mode_of_payment
union
@@ -211,6 +212,7 @@
from `tabSales Invoice` a, `tabPayment Entry` b,`tabPayment Entry Reference` c
where a.name = c.reference_name
and b.name = c.parent
+ and b.docstatus = 1
and a.name in ({invoice_list_names})
group by a.owner, a.posting_date, mode_of_payment
union
diff --git a/erpnext/accounts/report/sales_payment_summary/test_sales_payment_summary.py b/erpnext/accounts/report/sales_payment_summary/test_sales_payment_summary.py
new file mode 100644
index 0000000..62843e7
--- /dev/null
+++ b/erpnext/accounts/report/sales_payment_summary/test_sales_payment_summary.py
@@ -0,0 +1,165 @@
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import unittest
+import frappe
+from erpnext.accounts.report.sales_payment_summary.sales_payment_summary import get_mode_of_payments, get_mode_of_payment_details
+from frappe.utils import today
+from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
+
+test_dependencies = ["Sales Invoice"]
+
+class TestSalesPaymentSummary(unittest.TestCase):
+ @classmethod
+ def setUpClass(self):
+ create_records()
+ pes = frappe.get_all("Payment Entry")
+ jes = frappe.get_all("Journal Entry")
+ sis = frappe.get_all("Sales Invoice")
+ for pe in pes:
+ frappe.db.set_value("Payment Entry", pe.name, "docstatus", 2)
+ for je in jes:
+ frappe.db.set_value("Journal Entry", je.name, "docstatus", 2)
+ for si in sis:
+ frappe.db.set_value("Sales Invoice", si.name, "docstatus", 2)
+
+ def test_get_mode_of_payments(self):
+ filters = get_filters()
+
+ for dummy in range(2):
+ si = create_sales_invoice_record()
+ si.insert()
+ si.submit()
+
+ if int(si.name[-3:])%2 == 0:
+ bank_account = "_Test Cash - _TC"
+ mode_of_payment = "Cash"
+ else:
+ bank_account = "_Test Bank - _TC"
+ mode_of_payment = "Credit Card"
+
+ pe = get_payment_entry("Sales Invoice", si.name, bank_account=bank_account)
+ pe.reference_no = "_Test"
+ pe.reference_date = today()
+ pe.mode_of_payment = mode_of_payment
+ pe.insert()
+ pe.submit()
+
+ mop = get_mode_of_payments(filters)
+ self.assertTrue('Credit Card' in mop.values()[0])
+ self.assertTrue('Cash' in mop.values()[0])
+
+ # Cancel all Cash payment entry and check if this mode of payment is still fetched.
+ payment_entries = frappe.get_all("Payment Entry", filters={"mode_of_payment": "Cash", "docstatus": 1}, fields=["name", "docstatus"])
+ for payment_entry in payment_entries:
+ pe = frappe.get_doc("Payment Entry", payment_entry.name)
+ pe.cancel()
+
+ mop = get_mode_of_payments(filters)
+ self.assertTrue('Credit Card' in mop.values()[0])
+ self.assertTrue('Cash' not in mop.values()[0])
+
+ def test_get_mode_of_payments_details(self):
+ filters = get_filters()
+
+ for dummy in range(2):
+ si = create_sales_invoice_record()
+ si.insert()
+ si.submit()
+
+ if int(si.name[-3:])%2 == 0:
+ bank_account = "_Test Cash - _TC"
+ mode_of_payment = "Cash"
+ else:
+ bank_account = "_Test Bank - _TC"
+ mode_of_payment = "Credit Card"
+
+ pe = get_payment_entry("Sales Invoice", si.name, bank_account=bank_account)
+ pe.reference_no = "_Test"
+ pe.reference_date = today()
+ pe.mode_of_payment = mode_of_payment
+ pe.insert()
+ pe.submit()
+
+ mopd = get_mode_of_payment_details(filters)
+
+ mopd_values = mopd.values()[0]
+ for mopd_value in mopd_values:
+ if mopd_value[0] == "Credit Card":
+ cc_init_amount = mopd_value[1]
+
+ # Cancel one Credit Card Payment Entry and check that it is not fetched in mode of payment details.
+ payment_entries = frappe.get_all("Payment Entry", filters={"mode_of_payment": "Credit Card", "docstatus": 1}, fields=["name", "docstatus"])
+ for payment_entry in payment_entries[:1]:
+ pe = frappe.get_doc("Payment Entry", payment_entry.name)
+ pe.cancel()
+
+ mopd = get_mode_of_payment_details(filters)
+ mopd_values = mopd.values()[0]
+ for mopd_value in mopd_values:
+ if mopd_value[0] == "Credit Card":
+ cc_final_amount = mopd_value[1]
+
+ self.assertTrue(cc_init_amount > cc_final_amount)
+
+def get_filters():
+ return {
+ "from_date": "1900-01-01",
+ "to_date": today(),
+ "company": "_Test Company"
+ }
+
+def create_sales_invoice_record(qty=1):
+ # return sales invoice doc object
+ return frappe.get_doc({
+ "doctype": "Sales Invoice",
+ "customer": frappe.get_doc('Customer', {"customer_name": "Prestiga-Biz"}).name,
+ "company": '_Test Company',
+ "due_date": today(),
+ "posting_date": today(),
+ "currency": "INR",
+ "taxes_and_charges": "",
+ "debit_to": "Debtors - _TC",
+ "taxes": [],
+ "items": [{
+ 'doctype': 'Sales Invoice Item',
+ 'item_code': frappe.get_doc('Item', {'item_name': 'Consulting'}).name,
+ 'qty': qty,
+ "rate": 10000,
+ 'income_account': 'Sales - _TC',
+ 'cost_center': 'Main - _TC',
+ 'expense_account': 'Cost of Goods Sold - _TC'
+ }]
+ })
+
+def create_records():
+ if frappe.db.exists("Customer", "Prestiga-Biz"):
+ return
+
+ #customer
+ frappe.get_doc({
+ "customer_group": "_Test Customer Group",
+ "customer_name": "Prestiga-Biz",
+ "customer_type": "Company",
+ "doctype": "Customer",
+ "territory": "_Test Territory"
+ }).insert()
+
+ # item
+ item = frappe.get_doc({
+ "doctype": "Item",
+ "item_code": "Consulting",
+ "item_name": "Consulting",
+ "item_group": "All Item Groups",
+ "company": "_Test Company",
+ "is_stock_item": 0
+ }).insert()
+
+ # item price
+ frappe.get_doc({
+ "doctype": "Item Price",
+ "price_list": "Standard Selling",
+ "item_code": item.item_code,
+ "price_list_rate": 10000
+ }).insert()
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py
index 66d9bad..d518cd8 100755
--- a/erpnext/hr/doctype/employee/employee.py
+++ b/erpnext/hr/doctype/employee/employee.py
@@ -13,8 +13,8 @@
from erpnext.utilities.transaction_base import delete_events
from frappe.utils.nestedset import NestedSet
-class EmployeeUserDisabledError(frappe.ValidationError):
- pass
+class EmployeeUserDisabledError(frappe.ValidationError): pass
+class EmployeeLeftValidationError(frappe.ValidationError): pass
class Employee(NestedSet):
nsm_parent_field = 'reports_to'
@@ -147,8 +147,16 @@
validate_email_add(self.personal_email, True)
def validate_status(self):
- if self.status == 'Left' and not self.relieving_date:
- throw(_("Please enter relieving date."))
+ if self.status == 'Left':
+ reports_to = frappe.db.get_all('Employee',
+ filters={'reports_to': self.name}
+ )
+ if reports_to:
+ link_to_employees = [frappe.utils.get_link_to_form('Employee', employee.name) for employee in reports_to]
+ throw(_("Employee status cannot be set to 'Left' as following employees are currently reporting to this employee: ")
+ + ', '.join(link_to_employees), EmployeeLeftValidationError)
+ if not self.relieving_date:
+ throw(_("Please enter relieving date."))
def validate_for_enabled_user_id(self, enabled):
if not self.status == 'Active':
diff --git a/erpnext/hr/doctype/employee/test_employee.py b/erpnext/hr/doctype/employee/test_employee.py
index 1afb8f4..5a63beb 100644
--- a/erpnext/hr/doctype/employee/test_employee.py
+++ b/erpnext/hr/doctype/employee/test_employee.py
@@ -7,6 +7,7 @@
import erpnext
import unittest
import frappe.utils
+from erpnext.hr.doctype.employee.employee import EmployeeLeftValidationError
test_records = frappe.get_test_records('Employee')
@@ -32,6 +33,18 @@
email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
self.assertTrue("Subject: Birthday Reminder" in email_queue[0].message)
+ def test_employee_status_left(self):
+ employee1 = make_employee("test_employee_1@company.com")
+ employee2 = make_employee("test_employee_2@company.com")
+ employee1_doc = frappe.get_doc("Employee", employee1)
+ employee2_doc = frappe.get_doc("Employee", employee2)
+ employee2_doc.reload()
+ employee2_doc.reports_to = employee1_doc.name
+ employee2_doc.save()
+ employee1_doc.reload()
+ employee1_doc.status = 'Left'
+ self.assertRaises(EmployeeLeftValidationError, employee1_doc.save)
+
def make_employee(user):
if not frappe.db.get_value("User", user):
frappe.get_doc({
diff --git a/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py b/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py
new file mode 100644
index 0000000..5ab2847
--- /dev/null
+++ b/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+from frappe.utils import getdate
+from erpnext.hr.doctype.upload_attendance.upload_attendance import get_data
+from erpnext.hr.doctype.employee.test_employee import make_employee
+
+class TestUploadAttendance(unittest.TestCase):
+ def test_date_range(self):
+ employee = make_employee("test_employee@company.com")
+ employee_doc = frappe.get_doc("Employee", employee)
+ date_of_joining = "2018-01-02"
+ relieving_date = "2018-01-03"
+ from_date = "2018-01-01"
+ to_date = "2018-01-04"
+ employee_doc.date_of_joining = date_of_joining
+ employee_doc.relieving_date = relieving_date
+ employee_doc.save()
+ args = {
+ "from_date": from_date,
+ "to_date": to_date
+ }
+ data = get_data(args)
+ filtered_data = []
+ for row in data:
+ if row[1] == employee:
+ filtered_data.append(row)
+ print(filtered_data)
+ for row in filtered_data:
+ self.assertTrue(getdate(row[3]) >= getdate(date_of_joining) and getdate(row[3]) <= getdate(relieving_date))
diff --git a/erpnext/hr/doctype/upload_attendance/upload_attendance.py b/erpnext/hr/doctype/upload_attendance/upload_attendance.py
index 3d080a7..db74b10 100644
--- a/erpnext/hr/doctype/upload_attendance/upload_attendance.py
+++ b/erpnext/hr/doctype/upload_attendance/upload_attendance.py
@@ -41,16 +41,28 @@
return w
def add_data(w, args):
+ data = get_data(args)
+ writedata(w, data)
+ return w
+
+def get_data(args):
dates = get_dates(args)
employees = get_active_employees()
existing_attendance_records = get_existing_attendance_records(args)
+ data = []
for date in dates:
for employee in employees:
+ if getdate(date) < getdate(employee.date_of_joining):
+ continue
+ if employee.relieving_date:
+ if getdate(date) > getdate(employee.relieving_date):
+ continue
existing_attendance = {}
if existing_attendance_records \
- and tuple([getdate(date), employee.name]) in existing_attendance_records:
+ and tuple([getdate(date), employee.name]) in existing_attendance_records \
+ and getdate(employee.date_of_joining) >= getdate(date) \
+ and getdate(employee.relieving_date) <= getdate(date):
existing_attendance = existing_attendance_records[tuple([getdate(date), employee.name])]
-
row = [
existing_attendance and existing_attendance.name or "",
employee.name, employee.employee_name, date,
@@ -58,8 +70,12 @@
existing_attendance and existing_attendance.leave_type or "", employee.company,
existing_attendance and existing_attendance.naming_series or get_naming_series(),
]
- w.writerow(row)
- return w
+ data.append(row)
+ return data
+
+def writedata(w, data):
+ for row in data:
+ w.writerow(row)
def get_dates(args):
"""get list of dates in between from date and to date"""
@@ -68,8 +84,13 @@
return dates
def get_active_employees():
- employees = frappe.db.sql("""select name, employee_name, company
- from tabEmployee where docstatus < 2 and status = 'Active'""", as_dict=1)
+ employees = frappe.db.get_all('Employee',
+ fields=['name', 'employee_name', 'date_of_joining', 'company', 'relieving_date'],
+ filters={
+ 'docstatus': ['<', 2],
+ 'status': 'Active'
+ }
+ )
return employees
def get_existing_attendance_records(args):
diff --git a/erpnext/manufacturing/doctype/bom_item/bom_item.json b/erpnext/manufacturing/doctype/bom_item/bom_item.json
index 8a380f7..8d4d69b 100644
--- a/erpnext/manufacturing/doctype/bom_item/bom_item.json
+++ b/erpnext/manufacturing/doctype/bom_item/bom_item.json
@@ -79,67 +79,67 @@
"unique": 0
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "operation",
- "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": "Item operation",
- "length": 0,
- "no_copy": 0,
- "options": "Operation",
- "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": "operation",
+ "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": "Item operation",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Operation",
+ "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
},
{
@@ -966,6 +966,7 @@
"collapsible": 0,
"columns": 0,
"fetch_from": "item_code.include_item_in_manufacturing",
+ "fieldname": "include_item_in_manufacturing",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -974,6 +975,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
+ "label": "Include Item In Manufacturing",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -987,29 +989,6 @@
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
- "fieldname": "include_item_in_manufacturing",
- "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": "Include Item In Manufacturing",
- "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
},
{
@@ -1044,71 +1023,6 @@
"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": "operation",
- "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": "Item operation",
- "length": 0,
- "no_copy": 0,
- "options": "Operation",
- "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": "allow_alternative_item",
- "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": "Allow Alternative 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
}
],
"has_web_view": 0,
@@ -1121,7 +1035,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2018-12-26 15:04:56.187136",
+ "modified": "2018-12-28 16:38:56.529079",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM Item",