diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 2a375ae2ee..ee4ca0c791 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '11.1.16' +__version__ = '11.1.17' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/selling/report/sales_partner_wise_transaction_summary/__init__.py b/erpnext/accounts/dashboard_chart_source/__init__.py similarity index 100% rename from erpnext/selling/report/sales_partner_wise_transaction_summary/__init__.py rename to erpnext/accounts/dashboard_chart_source/__init__.py diff --git a/erpnext/selling/report/sales_person_target_variance_item_group_wise/__init__.py b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/__init__.py similarity index 100% rename from erpnext/selling/report/sales_person_target_variance_item_group_wise/__init__.py rename to erpnext/accounts/dashboard_chart_source/account_balance_timeline/__init__.py diff --git a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.js b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.js new file mode 100644 index 0000000000..eebd2dbd34 --- /dev/null +++ b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.js @@ -0,0 +1,45 @@ +frappe.dashboard_chart_sources["Account Balance Timeline"] = { + method_path: "erpnext.accounts.dashboard_chart_source.account_balance_timeline.account_balance_timeline.get", + filters: [ + { + fieldname: "company", + label: __("Company"), + fieldtype: "Link", + options: "Company", + default: frappe.defaults.get_user_default("Company"), + reqd: 1 + }, + { + fieldname: "account", + label: __("Account"), + fieldtype: "Link", + options: "Account", + reqd: 1 + }, + { + fieldname: "timespan", + label: __("Period"), + fieldtype: "Select", + options: [ + {value: "Last Year", label: __("Last Year")}, + {value: "Last Quarter", label: __("Last Quarter")}, + {value: "Last Month", label: __("Last Month")}, + {value: "Last Week", label: __("Last Week")} + ], + reqd: 1 + }, + { + fieldname: "timegrain", + label: __("Periodicity"), + fieldtype: "Select", + options: [ + {value: "Quarterly", label: __("Quarterly")}, + {value: "Monthly", label: __("Monthly")}, + {value: "Weekly", label: __("Weekly")}, + {value: "Daily", label: __("Daily")} + ], + reqd: 1 + }, + ], + is_time_series: true +}; \ No newline at end of file diff --git a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.json b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.json new file mode 100644 index 0000000000..b7ea601564 --- /dev/null +++ b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.json @@ -0,0 +1,13 @@ +{ + "config": "{\n \"method_path\": \"erpnext.accounts.dashboard_chart_source.account_balance_timeline.account_balance_timeline.get\",\n\t\"filters\": [\n\t\t{\n\t\t\t\"fieldname\": \"company\",\n\t\t\t\"label\": \"Company\",\n\t\t\t\"fieldtype\": \"Link\",\n\t\t\t\"options\": \"Company\",\n\t\t\t\"reqd\": 1\n\t\t},\n\t\t{\n\t\t\t\"fieldname\": \"account\",\n\t\t\t\"label\": \"Account\",\n\t\t\t\"fieldtype\": \"Link\",\n\t\t\t\"options\": \"Account\",\n\t\t\t\"reqd\": 1\n\t\t},\n\t\t{\n\t\t\t\"fieldname\": \"timespan\",\n\t\t\t\"label\": \"Period\",\n\t\t\t\"fieldtype\": \"Select\",\n\t\t\t\"options\": [\n\t\t\t\t{\"value\": \"Last Year\", \"label\": \"Last Year\"},\n\t\t\t\t{\"value\": \"Last Quarter\", \"label\": \"Last Quarter\"},\n\t\t\t\t{\"value\": \"Last Month\", \"label\": \"Last Month\"},\n\t\t\t\t{\"value\": \"Last Week\", \"label\": \"Last Week\"}\n\t\t\t],\n\t\t\t\"reqd\": 1\n\t\t},\n\t\t{\n\t\t\t\"fieldname\": \"timegrain\",\n\t\t\t\"label\": \"Periodicity\",\n\t\t\t\"fieldtype\": \"Select\",\n\t\t\t\"options\": [\n\t\t\t\t{\"value\": \"Quarterly\", \"label\": \"Quarterly\"},\n\t\t\t\t{\"value\": \"Monthly\", \"label\": \"Monthly\"},\n\t\t\t\t{\"value\": \"Weekly\", \"label\": \"Weekly\"},\n\t\t\t\t{\"value\": \"Daily\", \"label\": \"Daily\"}\n\t\t\t],\n\t\t\t\"reqd\": 1\n\t\t}\n\t],\n\t\"is_time_series\": true\n}\n", + "creation": "2019-02-06 07:57:10.377718", + "docstatus": 0, + "doctype": "Dashboard Chart Source", + "idx": 0, + "modified": "2019-03-15 16:14:26.505986", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Account Balance Timeline", + "owner": "Administrator", + "source_name": "Account Balance Timeline" +} \ No newline at end of file diff --git a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py new file mode 100644 index 0000000000..52c202386c --- /dev/null +++ b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py @@ -0,0 +1,110 @@ +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +from itertools import groupby +from operator import itemgetter +import frappe +from frappe.core.page.dashboard.dashboard import cache_source +from frappe.utils import add_to_date, date_diff, getdate, nowdate +from erpnext.accounts.report.general_ledger.general_ledger import execute + +from frappe.utils.nestedset import get_descendants_of + +@frappe.whitelist() +@cache_source +def get(filters=None): + timespan = filters.get("timespan") + timegrain = filters.get("timegrain") + account = filters.get("account") + company = filters.get("company") + + from_date = get_from_date_from_timespan(timespan) + to_date = nowdate() + + # fetch dates to plot + dates = get_dates_from_timegrain(from_date, to_date, timegrain) + + # get all the entries for this account and its descendants + gl_entries = get_gl_entries(account, to_date) + + # compile balance values + result = build_result(account, dates, gl_entries) + + return { + "labels": [r[0].strftime('%Y-%m-%d') for r in result], + "datasets": [{ + "name": account, + "values": [r[1] for r in result] + }] + } + +def build_result(account, dates, gl_entries): + result = [[getdate(date), 0.0] for date in dates] + root_type = frappe.db.get_value('Account', account, 'root_type') + + # start with the first date + date_index = 0 + + # get balances in debit + for entry in gl_entries: + + # entry date is after the current pointer, so move the pointer forward + while getdate(entry.posting_date) > result[date_index][0]: + date_index += 1 + + result[date_index][1] += entry.debit - entry.credit + + # if account type is credit, switch balances + if root_type not in ('Asset', 'Expense'): + for r in result: + r[1] = -1 * r[1] + + # for balance sheet accounts, the totals are cumulative + if root_type in ('Asset', 'Liability', 'Equity'): + for i, r in enumerate(result): + if i < 0: + r[1] = r[1] + result[i-1][1] + + return result + +def get_gl_entries(account, to_date): + child_accounts = get_descendants_of('Account', account, ignore_permissions=True) + child_accounts.append(account) + + return frappe.db.get_all('GL Entry', + fields = ['posting_date', 'debit', 'credit'], + filters = [ + dict(posting_date = ('<', to_date)), + dict(account = ('in', child_accounts)) + ], + order_by = 'posting_date asc') + +def get_from_date_from_timespan(timespan): + days = months = years = 0 + if "Last Week" == timespan: + days = -7 + if "Last Month" == timespan: + months = -1 + elif "Last Quarter" == timespan: + months = -3 + elif "Last Year" == timespan: + years = -1 + return add_to_date(None, years=years, months=months, days=days, + as_string=True, as_datetime=True) + +def get_dates_from_timegrain(from_date, to_date, timegrain): + days = months = years = 0 + if "Daily" == timegrain: + days = 1 + elif "Weekly" == timegrain: + days = 7 + elif "Monthly" == timegrain: + months = 1 + elif "Quarterly" == timegrain: + months = 3 + + dates = [from_date] + while dates[-1] <= to_date: + dates.append(add_to_date(dates[-1], years=years, months=months, days=days)) + return dates diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py index e305652fbd..32485a3469 100644 --- a/erpnext/accounts/deferred_revenue.py +++ b/erpnext/accounts/deferred_revenue.py @@ -2,9 +2,9 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import date_diff, add_months, today, getdate, add_days, flt +from frappe.utils import date_diff, add_months, today, getdate, add_days, flt, get_last_day from erpnext.accounts.utils import get_account_currency -from erpnext.accounts.general_ledger import make_gl_entries +from frappe.email import sendmail_to_system_managers def validate_service_stop_date(doc): ''' Validates service_stop_date for Purchase Invoice and Sales Invoice ''' @@ -33,47 +33,49 @@ def validate_service_stop_date(doc): frappe.throw(_("Cannot change Service Stop Date for item in row {0}".format(item.idx))) def convert_deferred_expense_to_expense(start_date=None, end_date=None): + # book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM + if not start_date: + start_date = add_months(today(), -1) + if not end_date: + end_date = add_days(today(), -1) + # check for the purchase invoice for which GL entries has to be done invoices = frappe.db.sql_list(''' - select distinct parent from `tabPurchase Invoice Item` where service_start_date<=%s and service_end_date>=%s + select distinct parent from `tabPurchase Invoice Item` + where service_start_date<=%s and service_end_date>=%s and enable_deferred_expense = 1 and docstatus = 1 and ifnull(amount, 0) > 0 - ''', (end_date or today(), start_date or add_months(today(), -1))) + ''', (end_date, start_date)) # For each invoice, book deferred expense for invoice in invoices: doc = frappe.get_doc("Purchase Invoice", invoice) - book_deferred_income_or_expense(doc, start_date, end_date) + book_deferred_income_or_expense(doc, end_date) def convert_deferred_revenue_to_income(start_date=None, end_date=None): + # book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM + if not start_date: + start_date = add_months(today(), -1) + if not end_date: + end_date = add_days(today(), -1) + # check for the sales invoice for which GL entries has to be done invoices = frappe.db.sql_list(''' - select distinct parent from `tabSales Invoice Item` where service_start_date<=%s and service_end_date>=%s + select distinct parent from `tabSales Invoice Item` + where service_start_date<=%s and service_end_date>=%s and enable_deferred_revenue = 1 and docstatus = 1 and ifnull(amount, 0) > 0 - ''', (end_date or today(), start_date or add_months(today(), -1))) + ''', (end_date, start_date)) - # For each invoice, book deferred revenue for invoice in invoices: doc = frappe.get_doc("Sales Invoice", invoice) - book_deferred_income_or_expense(doc, start_date, end_date) + book_deferred_income_or_expense(doc, end_date) + +def get_booking_dates(doc, item, posting_date=None): + if not posting_date: + posting_date = add_days(today(), -1) + + last_gl_entry = False -def get_booking_dates(doc, item, start_date=None, end_date=None): deferred_account = "deferred_revenue_account" if doc.doctype=="Sales Invoice" else "deferred_expense_account" - last_gl_entry, skip = False, False - - booking_end_date = getdate(add_days(today(), -1) if not end_date else end_date) - if booking_end_date < item.service_start_date or \ - (item.service_stop_date and booking_end_date.month > item.service_stop_date.month): - return None, None, None, True - elif booking_end_date >= item.service_end_date: - last_gl_entry = True - booking_end_date = item.service_end_date - elif item.service_stop_date and item.service_stop_date <= booking_end_date: - last_gl_entry = True - booking_end_date = item.service_stop_date - - booking_start_date = getdate(add_months(today(), -1) if not start_date else start_date) - booking_start_date = booking_start_date \ - if booking_start_date > item.service_start_date else item.service_start_date prev_gl_entry = frappe.db.sql(''' select name, posting_date from `tabGL Entry` where company=%s and account=%s and @@ -81,17 +83,28 @@ def get_booking_dates(doc, item, start_date=None, end_date=None): order by posting_date desc limit 1 ''', (doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True) - if not prev_gl_entry and item.service_start_date < booking_start_date: - booking_start_date = item.service_start_date - elif prev_gl_entry: - booking_start_date = getdate(add_days(prev_gl_entry[0].posting_date, 1)) - skip = True if booking_start_date > booking_end_date else False + if prev_gl_entry: + start_date = getdate(add_days(prev_gl_entry[0].posting_date, 1)) + else: + start_date = item.service_start_date - return last_gl_entry, booking_start_date, booking_end_date, skip + end_date = get_last_day(start_date) + if end_date >= item.service_end_date: + end_date = item.service_end_date + last_gl_entry = True + elif item.service_stop_date and end_date >= item.service_stop_date: + end_date = item.service_stop_date + last_gl_entry = True -def calculate_amount_and_base_amount(doc, item, last_gl_entry, total_days, total_booking_days): - account_currency = get_account_currency(item.expense_account) + if end_date > getdate(posting_date): + end_date = posting_date + if getdate(start_date) <= getdate(end_date): + return start_date, end_date, last_gl_entry + else: + return None, None, None + +def calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, account_currency): if doc.doctype == "Sales Invoice": total_credit_debit, total_credit_debit_currency = "debit", "debit_in_account_currency" deferred_account = "deferred_revenue_account" @@ -123,28 +136,15 @@ def calculate_amount_and_base_amount(doc, item, last_gl_entry, total_days, total return amount, base_amount -def book_deferred_income_or_expense(doc, start_date=None, end_date=None): - # book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM - # start_date: 1st of the last month or the start date - # end_date: end_date or today-1 +def book_deferred_income_or_expense(doc, posting_date=None): enable_check = "enable_deferred_revenue" \ if doc.doctype=="Sales Invoice" else "enable_deferred_expense" - gl_entries = [] - for item in doc.get('items'): - if not item.get(enable_check): continue - - skip = False - last_gl_entry, booking_start_date, booking_end_date, skip = \ - get_booking_dates(doc, item, start_date, end_date) - - if skip: continue - total_days = date_diff(item.service_end_date, item.service_start_date) + 1 - total_booking_days = date_diff(booking_end_date, booking_start_date) + 1 + def _book_deferred_revenue_or_expense(item): + start_date, end_date, last_gl_entry = get_booking_dates(doc, item, posting_date=posting_date) + if not (start_date and end_date): return account_currency = get_account_currency(item.expense_account) - amount, base_amount = calculate_amount_and_base_amount(doc, item, last_gl_entry, total_days, total_booking_days) - if doc.doctype == "Sales Invoice": against, project = doc.customer, doc.project credit_account, debit_account = item.income_account, item.deferred_revenue_account @@ -152,36 +152,62 @@ def book_deferred_income_or_expense(doc, start_date=None, end_date=None): against, project = doc.supplier, item.project credit_account, debit_account = item.deferred_expense_account, item.expense_account - # GL Entry for crediting the amount in the deferred expense - gl_entries.append( - doc.get_gl_dict({ - "account": credit_account, - "against": against, - "credit": base_amount, - "credit_in_account_currency": amount, - "cost_center": item.cost_center, - "voucher_detail_no": item.name, - 'posting_date': booking_end_date, - 'project': project - }, account_currency) - ) - # GL Entry to debit the amount from the expense - gl_entries.append( - doc.get_gl_dict({ - "account": debit_account, - "against": against, - "debit": base_amount, - "debit_in_account_currency": amount, - "cost_center": item.cost_center, - "voucher_detail_no": item.name, - 'posting_date': booking_end_date, - 'project': project - }, account_currency) - ) + total_days = date_diff(item.service_end_date, item.service_start_date) + 1 + total_booking_days = date_diff(end_date, start_date) + 1 + + amount, base_amount = calculate_amount(doc, item, last_gl_entry, + total_days, total_booking_days, account_currency) + + make_gl_entries(doc, credit_account, debit_account, against, + amount, base_amount, end_date, project, account_currency, item.cost_center, item.name) + + if getdate(end_date) < getdate(posting_date) and not last_gl_entry: + _book_deferred_revenue_or_expense(item) + + + for item in doc.get('items'): + if item.get(enable_check): + _book_deferred_revenue_or_expense(item) + +def make_gl_entries(doc, credit_account, debit_account, against, + amount, base_amount, posting_date, project, account_currency, cost_center, voucher_detail_no): + # GL Entry for crediting the amount in the deferred expense + from erpnext.accounts.general_ledger import make_gl_entries + + gl_entries = [] + gl_entries.append( + doc.get_gl_dict({ + "account": credit_account, + "against": against, + "credit": base_amount, + "credit_in_account_currency": amount, + "cost_center": cost_center, + "voucher_detail_no": voucher_detail_no, + 'posting_date': posting_date, + 'project': project + }, account_currency) + ) + # GL Entry to debit the amount from the expense + gl_entries.append( + doc.get_gl_dict({ + "account": debit_account, + "against": against, + "debit": base_amount, + "debit_in_account_currency": amount, + "cost_center": cost_center, + "voucher_detail_no": voucher_detail_no, + 'posting_date': posting_date, + 'project': project + }, account_currency) + ) + if gl_entries: try: make_gl_entries(gl_entries, cancel=(doc.docstatus == 2), merge_entries=True) frappe.db.commit() except: frappe.db.rollback() - frappe.log_error(message = frappe.get_traceback(), title = _("Error while processing deferred accounting for {0}").format(doc.name)) \ No newline at end of file + title = _("Error while processing deferred accounting for {0}").format(doc.name) + traceback = frappe.get_traceback() + frappe.log_error(message=traceback , title=title) + sendmail_to_system_managers(title, traceback) \ No newline at end of file diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index 427f3dba20..3d9604d159 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -98,6 +98,8 @@ class Account(NestedSet): ancestors = get_root_company(self.company) if ancestors: + if frappe.get_value("Company", self.company, "allow_account_creation_against_child_company"): + return frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0])) else: descendants = get_descendants_of('Company', self.company) @@ -110,6 +112,8 @@ class Account(NestedSet): ["company", "name"], as_dict=True): acc_name_map[d["company"]] = d["name"] + if not acc_name_map: return + for company in descendants: doc = frappe.copy_doc(self) doc.flags.ignore_root_company_validation = True diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js index 03c98fadf2..dc4c69d9e8 100644 --- a/erpnext/accounts/doctype/account/account_tree.js +++ b/erpnext/accounts/doctype/account/account_tree.js @@ -23,6 +23,10 @@ frappe.treeview_settings["Account"] = { if(r.message) { let root_company = r.message.length ? r.message[0] : ""; me.page.fields_dict.root_company.set_value(root_company); + + frappe.db.get_value("Company", {"name": company}, "allow_account_creation_against_child_company", (r) => { + frappe.flags.ignore_root_company_validation = r.allow_account_creation_against_child_company; + }); } } }); @@ -133,9 +137,10 @@ 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.root_company.get_value() && - node.expandable && !node.hide_add; + return frappe.boot.user.can_create.indexOf("Account") !== -1 + && (!frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value() + || frappe.flags.ignore_root_company_validation) + && node.expandable && !node.hide_add; }, click: function() { var me = frappe.treeview_settings['Account'].treeview; diff --git a/erpnext/accounts/doctype/account/test_account.py b/erpnext/accounts/doctype/account/test_account.py index fc6f4e4eca..4ee55736fe 100644 --- a/erpnext/accounts/doctype/account/test_account.py +++ b/erpnext/accounts/doctype/account/test_account.py @@ -146,7 +146,7 @@ def _make_test_records(verbose): # related to Account Inventory Integration ["_Test Account Stock In Hand", "Current Assets", 0, None, None], - + # fixed asset depreciation ["_Test Fixed Asset", "Current Assets", 0, "Fixed Asset", None], ["_Test Accumulated Depreciations", "Current Assets", 0, None, None], @@ -183,13 +183,17 @@ def get_inventory_account(company, warehouse=None): return account def create_account(**kwargs): - account = frappe.get_doc(dict( - doctype = "Account", - account_name = kwargs.get('account_name'), - account_type = kwargs.get('account_type'), - parent_account = kwargs.get('parent_account'), - company = kwargs.get('company') - )) - - account.save() - return account.name + account = frappe.db.get_value("Account", filters={"account_name": kwargs.get("account_name"), "company": kwargs.get("company")}) + if account: + return account + else: + account = frappe.get_doc(dict( + doctype = "Account", + account_name = kwargs.get('account_name'), + account_type = kwargs.get('account_type'), + parent_account = kwargs.get('parent_account'), + company = kwargs.get('company') + )) + + account.save() + return account.name diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index 945d5d47f5..be5407b926 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -23,6 +23,7 @@ "columns": 0, "default": "1", "description": "If enabled, the system will post accounting entries for inventory automatically.", + "fetch_if_empty": 0, "fieldname": "auto_accounting_for_stock", "fieldtype": "Check", "hidden": 1, @@ -55,6 +56,7 @@ "collapsible": 0, "columns": 0, "description": "Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.", + "fetch_if_empty": 0, "fieldname": "acc_frozen_upto", "fieldtype": "Date", "hidden": 0, @@ -87,6 +89,7 @@ "collapsible": 0, "columns": 0, "description": "Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts", + "fetch_if_empty": 0, "fieldname": "frozen_accounts_modifier", "fieldtype": "Link", "hidden": 0, @@ -121,6 +124,7 @@ "columns": 0, "default": "Billing Address", "description": "Address used to determine Tax Category in transactions.", + "fetch_if_empty": 0, "fieldname": "determine_address_tax_category_from", "fieldtype": "Select", "hidden": 0, @@ -154,6 +158,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_4", "fieldtype": "Column Break", "hidden": 0, @@ -186,6 +191,7 @@ "collapsible": 0, "columns": 0, "description": "Role that is allowed to submit transactions that exceed credit limits set.", + "fetch_if_empty": 0, "fieldname": "credit_controller", "fieldtype": "Link", "hidden": 0, @@ -218,6 +224,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "check_supplier_invoice_uniqueness", "fieldtype": "Check", "hidden": 0, @@ -250,6 +257,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "make_payment_via_journal_entry", "fieldtype": "Check", "hidden": 0, @@ -283,6 +291,7 @@ "collapsible": 0, "columns": 0, "default": "1", + "fetch_if_empty": 0, "fieldname": "unlink_payment_on_cancellation_of_invoice", "fieldtype": "Check", "hidden": 0, @@ -316,6 +325,41 @@ "collapsible": 0, "columns": 0, "default": "1", + "fetch_if_empty": 0, + "fieldname": "unlink_advance_payment_on_cancelation_of_order", + "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": "Unlink Advance Payment on Cancelation of Order", + "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": "1", + "fetch_if_empty": 0, "fieldname": "book_asset_depreciation_entry_automatically", "fieldtype": "Check", "hidden": 0, @@ -348,6 +392,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "allow_cost_center_in_entry_of_bs_account", "fieldtype": "Check", "hidden": 0, @@ -381,6 +426,7 @@ "collapsible": 0, "columns": 0, "default": "1", + "fetch_if_empty": 0, "fieldname": "add_taxes_from_item_tax_template", "fieldtype": "Check", "hidden": 0, @@ -413,6 +459,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "print_settings", "fieldtype": "Section Break", "hidden": 0, @@ -445,6 +492,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "show_inclusive_tax_in_print", "fieldtype": "Check", "hidden": 0, @@ -477,6 +525,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_12", "fieldtype": "Column Break", "hidden": 0, @@ -508,6 +557,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "show_payment_schedule_in_print", "fieldtype": "Check", "hidden": 0, @@ -540,6 +590,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "currency_exchange_section", "fieldtype": "Section Break", "hidden": 0, @@ -573,6 +624,7 @@ "collapsible": 0, "columns": 0, "default": "1", + "fetch_if_empty": 0, "fieldname": "allow_stale", "fieldtype": "Check", "hidden": 0, @@ -607,6 +659,7 @@ "columns": 0, "default": "1", "depends_on": "eval:doc.allow_stale==0", + "fetch_if_empty": 0, "fieldname": "stale_days", "fieldtype": "Int", "hidden": 0, @@ -639,6 +692,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "report_settings_sb", "fieldtype": "Section Break", "hidden": 0, @@ -673,6 +727,7 @@ "columns": 0, "default": "0", "description": "Only select if you have setup Cash Flow Mapper documents", + "fetch_if_empty": 0, "fieldname": "use_custom_cash_flow", "fieldtype": "Check", "hidden": 0, @@ -700,17 +755,15 @@ } ], "has_web_view": 0, - "hide_heading": 0, "hide_toolbar": 0, "icon": "icon-cog", "idx": 1, - "image_view": 0, "in_create": 0, "is_submittable": 0, "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2019-01-07 00:42:34.510150", + "modified": "2019-04-06 12:28:43.026250", "modified_by": "Administrator", "module": "Accounts", "name": "Accounts Settings", @@ -776,10 +829,9 @@ ], "quick_entry": 1, "read_only": 0, - "read_only_onload": 0, "show_name_in_global_search": 0, "sort_order": "ASC", "track_changes": 1, "track_seen": 0, "track_views": 0 -} +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py index 917276293d..fae5213f23 100644 --- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py +++ b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py @@ -23,36 +23,36 @@ class BankReconciliation(Document): journal_entries = frappe.db.sql(""" - select - "Journal Entry" as payment_document, t1.name as payment_entry, - t1.cheque_no as cheque_number, t1.cheque_date, + select + "Journal Entry" as payment_document, t1.name as payment_entry, + t1.cheque_no as cheque_number, t1.cheque_date, sum(t2.debit_in_account_currency) as debit, sum(t2.credit_in_account_currency) as credit, - t1.posting_date, t2.against_account, t1.clearance_date, t2.account_currency + t1.posting_date, t2.against_account, t1.clearance_date, t2.account_currency from `tabJournal Entry` t1, `tabJournal Entry Account` t2 where t2.parent = t1.name and t2.account = %s and t1.docstatus=1 - and t1.posting_date >= %s and t1.posting_date <= %s + and t1.posting_date >= %s and t1.posting_date <= %s and ifnull(t1.is_opening, 'No') = 'No' {0} group by t2.account, t1.name order by t1.posting_date ASC, t1.name DESC """.format(condition), (self.bank_account, self.from_date, self.to_date), as_dict=1) payment_entries = frappe.db.sql(""" - select - "Payment Entry" as payment_document, name as payment_entry, - reference_no as cheque_number, reference_date as cheque_date, - if(paid_from=%(account)s, paid_amount, "") as credit, - if(paid_from=%(account)s, "", received_amount) as debit, + select + "Payment Entry" as payment_document, name as payment_entry, + reference_no as cheque_number, reference_date as cheque_date, + if(paid_from=%(account)s, paid_amount, 0) as credit, + if(paid_from=%(account)s, 0, received_amount) as debit, posting_date, ifnull(party,if(paid_from=%(account)s,paid_to,paid_from)) as against_account, clearance_date, if(paid_to=%(account)s, paid_to_account_currency, paid_from_account_currency) as account_currency from `tabPayment Entry` where (paid_from=%(account)s or paid_to=%(account)s) and docstatus=1 and posting_date >= %(from)s and posting_date <= %(to)s {0} - order by + order by posting_date ASC, name DESC - """.format(condition), + """.format(condition), {"account":self.bank_account, "from":self.from_date, "to":self.to_date}, as_dict=1) pos_entries = [] @@ -79,8 +79,12 @@ class BankReconciliation(Document): for d in entries: row = self.append('payment_entries', {}) - amount = d.debit if d.debit else d.credit - d.amount = fmt_money(amount, 2, d.account_currency) + " " + (_("Dr") if d.debit else _("Cr")) + + amount = flt(d.get('debit', 0)) - flt(d.get('credit', 0)) + + formatted_amount = fmt_money(abs(amount), 2, d.account_currency) + d.amount = formatted_amount + " " + (_("Dr") if amount > 0 else _("Cr")) + d.pop("credit") d.pop("debit") d.pop("account_currency") @@ -103,10 +107,10 @@ class BankReconciliation(Document): d.clearance_date = None frappe.db.set_value(d.payment_document, d.payment_entry, "clearance_date", d.clearance_date) - frappe.db.sql("""update `tab{0}` set clearance_date = %s, modified = %s - where name=%s""".format(d.payment_document), + frappe.db.sql("""update `tab{0}` set clearance_date = %s, modified = %s + where name=%s""".format(d.payment_document), (d.clearance_date, nowdate(), d.payment_entry)) - + clearance_date_updated = True if clearance_date_updated: diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 3a17ce5b4b..00aba41559 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -52,11 +52,6 @@ class JournalEntry(AccountsController): self.update_loan() self.update_inter_company_jv() - def before_print(self): - self.gl_entries = frappe.get_list("GL Entry",filters={"voucher_type": "Journal Entry", - "voucher_no": self.name} , - fields=["account", "party_type", "party", "debit", "credit", "remarks"] - ) def get_title(self): return self.pay_to_recd_from or self.accounts[0].account diff --git a/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py b/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py index 4fc43121f6..18f853cadc 100644 --- a/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py +++ b/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py @@ -3,8 +3,8 @@ from __future__ import unicode_literals import frappe -from frappe.utils import flt from frappe import _ +from frappe.utils import (flt, add_months) from frappe.model.document import Document class MonthlyDistribution(Document): @@ -25,3 +25,33 @@ class MonthlyDistribution(Document): if flt(total, 2) != 100.0: frappe.throw(_("Percentage Allocation should be equal to 100%") + \ " ({0}%)".format(str(flt(total, 2)))) + +def get_periodwise_distribution_data(distribution_id, period_list, periodicity): + doc = frappe.get_doc('Monthly Distribution', distribution_id) + + months_to_add = { + "Yearly": 12, + "Half-Yearly": 6, + "Quarterly": 3, + "Monthly": 1 + }[periodicity] + + period_dict = {} + + for d in period_list: + period_dict[d.key] = get_percentage(doc, d.from_date, months_to_add) + + return period_dict + +def get_percentage(doc, start_date, period): + percentage = 0 + months = [start_date.strftime("%B").title()] + + for r in range(1, period): + months.append(add_months(start_date, r).strftime("%B").title()) + + for d in doc.percentages: + if d.month in months: + percentage += d.percentage_allocation + + return percentage \ No newline at end of file diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 818b950336..b8073ce065 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -70,11 +70,6 @@ class PaymentEntry(AccountsController): self.update_advance_paid() self.update_expense_claim() - def before_print(self): - self.gl_entries = frappe.get_list("GL Entry",filters={"voucher_type": "Payment Entry", - "voucher_no": self.name} , - fields=["account", "party_type", "party", "debit", "credit", "remarks"] - ) def on_cancel(self): self.setup_party_account_field() @@ -754,7 +749,7 @@ def get_outstanding_on_journal_entry(name): @frappe.whitelist() def get_reference_details(reference_doctype, reference_name, party_account_currency): - total_amount = outstanding_amount = exchange_rate = None + total_amount = outstanding_amount = exchange_rate = bill_no = None ref_doc = frappe.get_doc(reference_doctype, reference_name) company_currency = ref_doc.get("company_currency") or erpnext.get_company_currency(ref_doc.company) @@ -788,6 +783,7 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre if reference_doctype in ("Sales Invoice", "Purchase Invoice"): outstanding_amount = ref_doc.get("outstanding_amount") + bill_no = ref_doc.get("bill_no") elif reference_doctype == "Expense Claim": outstanding_amount = flt(ref_doc.get("total_sanctioned_amount")) \ - flt(ref_doc.get("total_amount+reimbursed")) - flt(ref_doc.get("total_advance_amount")) @@ -804,7 +800,8 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre "due_date": ref_doc.get("due_date"), "total_amount": total_amount, "outstanding_amount": outstanding_amount, - "exchange_rate": exchange_rate + "exchange_rate": exchange_rate, + "bill_no": bill_no }) diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py index e64ad28cda..4f17e9f995 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.py +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py @@ -155,7 +155,6 @@ def pos_profile_query(doctype, txt, searchfield, start, page_len, filters): def set_default_profile(pos_profile, company): modified = now() user = frappe.session.user - company = frappe.db.escape(company) if pos_profile and company: frappe.db.sql(""" update `tabPOS Profile User` pfu, `tabPOS Profile` pf diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index 1e11c4e163..01b935c999 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -119,7 +119,7 @@ class PricingRule(Document): #-------------------------------------------------------------------------------- @frappe.whitelist() -def apply_pricing_rule(args): +def apply_pricing_rule(args, doc=None): """ args = { "items": [{"doctype": "", "name": "", "item_code": "", "brand": "", "item_group": ""}, ...], @@ -139,6 +139,7 @@ def apply_pricing_rule(args): "ignore_pricing_rule": "something" } """ + if isinstance(args, string_types): args = json.loads(args) @@ -161,10 +162,11 @@ def apply_pricing_rule(args): for item in item_list: args_copy = copy.deepcopy(args) args_copy.update(item) - data = get_pricing_rule_for_item(args_copy, item.get('price_list_rate')) + data = get_pricing_rule_for_item(args_copy, item.get('price_list_rate'), doc=doc) out.append(data) - if set_serial_nos_based_on_fifo and not args.get('is_return'): - out.append(get_serial_no_for_item(args_copy)) + if not item.get("serial_no") and set_serial_nos_based_on_fifo and not args.get('is_return'): + out[0].update(get_serial_no_for_item(args_copy)) + return out def get_serial_no_for_item(args): @@ -182,6 +184,12 @@ def get_serial_no_for_item(args): def get_pricing_rule_for_item(args, price_list_rate=0, doc=None): from erpnext.accounts.doctype.pricing_rule.utils import get_pricing_rules + if isinstance(doc, string_types): + doc = json.loads(doc) + + if doc: + doc = frappe.get_doc(doc) + if (args.get('is_free_item') or args.get("parenttype") == "Material Request"): return {} @@ -227,11 +235,11 @@ def get_pricing_rule_for_item(args, price_list_rate=0, doc=None): if pricing_rules: rules = [] - item_details.discount_percentage = 0 - item_details.discount_amount = 0 for pricing_rule in pricing_rules: if not pricing_rule or pricing_rule.get('suggestion'): continue + item_details.validate_applied_rule = pricing_rule.get("validate_applied_rule", 0) + rules.append(get_pricing_rule_details(args, pricing_rule)) if pricing_rule.mixed_conditions or pricing_rule.apply_rule_on_other: continue @@ -243,8 +251,8 @@ def get_pricing_rule_for_item(args, price_list_rate=0, doc=None): item_details.has_pricing_rule = 1 # if discount is applied on the rate and not on price list rate - if price_list_rate: - set_discount_amount(price_list_rate, item_details) + # if price_list_rate: + # set_discount_amount(price_list_rate, item_details) item_details.pricing_rules = ','.join([d.pricing_rule for d in rules]) @@ -264,7 +272,7 @@ def get_pricing_rule_details(args, pricing_rule): 'pricing_rule': pricing_rule.name, 'rate_or_discount': pricing_rule.rate_or_discount, 'margin_type': pricing_rule.margin_type, - 'item_code': pricing_rule.item_code, + 'item_code': pricing_rule.item_code or args.get("item_code"), 'child_docname': args.get('child_docname') }) @@ -296,6 +304,9 @@ def apply_price_discount_pricing_rule(pricing_rule, item_details, args): discount_field = "{0}_on_rate".format(field) item_details[discount_field].append(pricing_rule.get(field, 0)) else: + if field not in item_details: + item_details.setdefault(field, 0) + item_details[field] += (pricing_rule.get(field, 0) if pricing_rule else args.get(field, 0)) @@ -308,6 +319,7 @@ def set_discount_amount(rate, item_details): item_details.rate = rate def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None): + from erpnext.accounts.doctype.pricing_rule.utils import get_apply_on_and_items for d in pricing_rules.split(','): if not d: continue pricing_rule = frappe.get_doc('Pricing Rule', d) @@ -327,6 +339,11 @@ def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None): item_details.remove_free_item = (item_code if pricing_rule.get('same_item') else pricing_rule.get('free_item')) + if pricing_rule.get("mixed_conditions") or pricing_rule.get("apply_rule_on_other"): + apply_on, items = get_apply_on_and_items(pricing_rule, item_details) + item_details.apply_on = apply_on + item_details.applied_on_items = ','.join(items) + item_details.pricing_rules = '' return item_details @@ -368,35 +385,6 @@ def make_pricing_rule(doctype, docname): return doc -@frappe.whitelist() -def get_free_items(pricing_rules, item_row): - if isinstance(item_row, string_types): - item_row = json.loads(item_row) - - free_items = [] - pricing_rules = list(set(pricing_rules.split(','))) - - for d in pricing_rules: - pr_doc = frappe.get_doc('Pricing Rule', d) - if pr_doc.price_or_product_discount == 'Product': - item = (item_row.get('item_code') if pr_doc.same_item - else pr_doc.free_item) - if not item: return free_items - - doc = frappe.get_doc('Item', item) - - free_items.append({ - 'item_code': item, - 'item_name': doc.item_name, - 'description': doc.description, - 'qty': pr_doc.free_qty, - 'uom': pr_doc.free_item_uom, - 'rate': pr_doc.free_item_rate or 0, - 'is_free_item': 1 - }) - - return free_items - def get_item_uoms(doctype, txt, searchfield, start, page_len, filters): items = [filters.get('value')] if filters.get('apply_on') != 'Item Code': diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index e12771b8ba..d3db130f3a 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -4,490 +4,531 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe -import json -import copy +import frappe, copy, json from frappe import throw, _ +from six import string_types from frappe.utils import flt, cint, get_datetime from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses from erpnext.stock.get_item_details import get_conversion_factor class MultiplePricingRuleConflict(frappe.ValidationError): pass +apply_on_table = { + 'Item Code': 'items', + 'Item Group': 'item_groups', + 'Brand': 'brands' +} + def get_pricing_rules(args, doc=None): - pricing_rules = [] - values = {} + pricing_rules = [] + values = {} - for apply_on in ['Item Code', 'Item Group', 'Brand']: - pricing_rules.extend(_get_pricing_rules(apply_on, args, values)) - if pricing_rules and not apply_multiple_pricing_rules(pricing_rules): - break + for apply_on in ['Item Code', 'Item Group', 'Brand']: + pricing_rules.extend(_get_pricing_rules(apply_on, args, values)) + if pricing_rules and not apply_multiple_pricing_rules(pricing_rules): + break - rules = [] + rules = [] - if not pricing_rules: return [] + if not pricing_rules: return [] - if apply_multiple_pricing_rules(pricing_rules): - for pricing_rule in pricing_rules: - pricing_rule = filter_pricing_rules(args, pricing_rule, doc) - if pricing_rule: - rules.append(pricing_rule) - else: - rules.append(filter_pricing_rules(args, pricing_rules, doc)) + if apply_multiple_pricing_rules(pricing_rules): + for pricing_rule in pricing_rules: + pricing_rule = filter_pricing_rules(args, pricing_rule, doc) + if pricing_rule: + rules.append(pricing_rule) + else: + pricing_rule = filter_pricing_rules(args, pricing_rules, doc) + if pricing_rule: + rules.append(pricing_rule) - return rules + return rules def _get_pricing_rules(apply_on, args, values): - apply_on_field = frappe.scrub(apply_on) + apply_on_field = frappe.scrub(apply_on) - if not args.get(apply_on_field): return [] + if not args.get(apply_on_field): return [] - child_doc = '`tabPricing Rule {0}`'.format(apply_on) + child_doc = '`tabPricing Rule {0}`'.format(apply_on) - conditions = item_variant_condition = item_conditions = "" - values[apply_on_field] = args.get(apply_on_field) - if apply_on_field in ['item_code', 'brand']: - item_conditions = "{child_doc}.{apply_on_field}= %({apply_on_field})s".format(child_doc=child_doc, - apply_on_field = apply_on_field) + conditions = item_variant_condition = item_conditions = "" + values[apply_on_field] = args.get(apply_on_field) + if apply_on_field in ['item_code', 'brand']: + item_conditions = "{child_doc}.{apply_on_field}= %({apply_on_field})s".format(child_doc=child_doc, + apply_on_field = apply_on_field) - if apply_on_field == 'item_code': - if "variant_of" not in args: - args.variant_of = frappe.get_cached_value("Item", args.item_code, "variant_of") + if apply_on_field == 'item_code': + if "variant_of" not in args: + args.variant_of = frappe.get_cached_value("Item", args.item_code, "variant_of") - if args.variant_of: - item_variant_condition = ' or {child_doc}.item_code=%(variant_of)s '.format(child_doc=child_doc) - values['variant_of'] = args.variant_of - elif apply_on_field == 'item_group': - item_conditions = _get_tree_conditions(args, "Item Group", child_doc, False) + if args.variant_of: + item_variant_condition = ' or {child_doc}.item_code=%(variant_of)s '.format(child_doc=child_doc) + values['variant_of'] = args.variant_of + elif apply_on_field == 'item_group': + item_conditions = _get_tree_conditions(args, "Item Group", child_doc, False) - conditions += get_other_conditions(conditions, values, args) - warehouse_conditions = _get_tree_conditions(args, "Warehouse", '`tabPricing Rule`') - if warehouse_conditions: - warehouse_conditions = " and {0}".format(warehouse_conditions) + conditions += get_other_conditions(conditions, values, args) + warehouse_conditions = _get_tree_conditions(args, "Warehouse", '`tabPricing Rule`') + if warehouse_conditions: + warehouse_conditions = " and {0}".format(warehouse_conditions) - if not args.price_list: args.price_list = None + if not args.price_list: args.price_list = None - conditions += " and ifnull(`tabPricing Rule`.for_price_list, '') in (%(price_list)s, '')" - values["price_list"] = args.get("price_list") + conditions += " and ifnull(`tabPricing Rule`.for_price_list, '') in (%(price_list)s, '')" + values["price_list"] = args.get("price_list") - pricing_rules = frappe.db.sql("""select `tabPricing Rule`.*, - {child_doc}.{apply_on_field}, {child_doc}.uom - from `tabPricing Rule`, {child_doc} + pricing_rules = frappe.db.sql("""select `tabPricing Rule`.*, + {child_doc}.{apply_on_field}, {child_doc}.uom + from `tabPricing Rule`, {child_doc} where ({item_conditions} or (`tabPricing Rule`.apply_rule_on_other is not null - and `tabPricing Rule`.{apply_on_other_field}=%({apply_on_field})s) {item_variant_condition}) - and {child_doc}.parent = `tabPricing Rule`.name + and `tabPricing Rule`.{apply_on_other_field}=%({apply_on_field})s) {item_variant_condition}) + and {child_doc}.parent = `tabPricing Rule`.name and `tabPricing Rule`.disable = 0 and - `tabPricing Rule`.{transaction_type} = 1 {warehouse_cond} {conditions} + `tabPricing Rule`.{transaction_type} = 1 {warehouse_cond} {conditions} order by `tabPricing Rule`.priority desc, - `tabPricing Rule`.name desc""".format( - child_doc = child_doc, - apply_on_field = apply_on_field, + `tabPricing Rule`.name desc""".format( + child_doc = child_doc, + apply_on_field = apply_on_field, item_conditions = item_conditions, item_variant_condition = item_variant_condition, transaction_type = args.transaction_type, - warehouse_cond = warehouse_conditions, - apply_on_other_field = "other_{0}".format(apply_on_field), + warehouse_cond = warehouse_conditions, + apply_on_other_field = "other_{0}".format(apply_on_field), conditions = conditions), values, as_dict=1) or [] - return pricing_rules + return pricing_rules def apply_multiple_pricing_rules(pricing_rules): - apply_multiple_rule = [d.apply_multiple_pricing_rules - for d in pricing_rules if d.apply_multiple_pricing_rules] + apply_multiple_rule = [d.apply_multiple_pricing_rules + for d in pricing_rules if d.apply_multiple_pricing_rules] - if not apply_multiple_rule: return False + if not apply_multiple_rule: return False - if (apply_multiple_rule - and len(apply_multiple_rule) == len(pricing_rules)): - return True + if (apply_multiple_rule + and len(apply_multiple_rule) == len(pricing_rules)): + return True def _get_tree_conditions(args, parenttype, table, allow_blank=True): - field = frappe.scrub(parenttype) - condition = "" - if args.get(field): - if not frappe.flags.tree_conditions: - frappe.flags.tree_conditions = {} - key = (parenttype, args.get(field)) - if key in frappe.flags.tree_conditions: - return frappe.flags.tree_conditions[key] + field = frappe.scrub(parenttype) + condition = "" + if args.get(field): + if not frappe.flags.tree_conditions: + frappe.flags.tree_conditions = {} + key = (parenttype, args.get(field)) + if key in frappe.flags.tree_conditions: + return frappe.flags.tree_conditions[key] - try: - lft, rgt = frappe.db.get_value(parenttype, args.get(field), ["lft", "rgt"]) - except TypeError: - frappe.throw(_("Invalid {0}").format(args.get(field))) + try: + lft, rgt = frappe.db.get_value(parenttype, args.get(field), ["lft", "rgt"]) + except TypeError: + frappe.throw(_("Invalid {0}").format(args.get(field))) - parent_groups = frappe.db.sql_list("""select name from `tab%s` - where lft<=%s and rgt>=%s""" % (parenttype, '%s', '%s'), (lft, rgt)) + parent_groups = frappe.db.sql_list("""select name from `tab%s` + where lft<=%s and rgt>=%s""" % (parenttype, '%s', '%s'), (lft, rgt)) - if parent_groups: - if allow_blank: parent_groups.append('') - condition = "ifnull({table}.{field}, '') in ({parent_groups})".format( - table=table, - field=field, - parent_groups=", ".join([frappe.db.escape(d) for d in parent_groups]) - ) + if parent_groups: + if allow_blank: parent_groups.append('') + condition = "ifnull({table}.{field}, '') in ({parent_groups})".format( + table=table, + field=field, + parent_groups=", ".join([frappe.db.escape(d) for d in parent_groups]) + ) - frappe.flags.tree_conditions[key] = condition - return condition + frappe.flags.tree_conditions[key] = condition + return condition def get_other_conditions(conditions, values, args): - for field in ["company", "customer", "supplier", "campaign", "sales_partner"]: - if args.get(field): - conditions += " and ifnull(`tabPricing Rule`.{0}, '') in (%({1})s, '')".format(field, field) - values[field] = args.get(field) - else: - conditions += " and ifnull(`tabPricing Rule`.{0}, '') = ''".format(field) + for field in ["company", "customer", "supplier", "campaign", "sales_partner"]: + if args.get(field): + conditions += " and ifnull(`tabPricing Rule`.{0}, '') in (%({1})s, '')".format(field, field) + values[field] = args.get(field) + else: + conditions += " and ifnull(`tabPricing Rule`.{0}, '') = ''".format(field) - for parenttype in ["Customer Group", "Territory", "Supplier Group"]: - group_condition = _get_tree_conditions(args, parenttype, '`tabPricing Rule`') - if group_condition: - conditions += " and " + group_condition + for parenttype in ["Customer Group", "Territory", "Supplier Group"]: + group_condition = _get_tree_conditions(args, parenttype, '`tabPricing Rule`') + if group_condition: + conditions += " and " + group_condition - if args.get("transaction_date"): - conditions += """ and %(transaction_date)s between ifnull(`tabPricing Rule`.valid_from, '2000-01-01') - and ifnull(`tabPricing Rule`.valid_upto, '2500-12-31')""" - values['transaction_date'] = args.get('transaction_date') + if args.get("transaction_date"): + conditions += """ and %(transaction_date)s between ifnull(`tabPricing Rule`.valid_from, '2000-01-01') + and ifnull(`tabPricing Rule`.valid_upto, '2500-12-31')""" + values['transaction_date'] = args.get('transaction_date') - return conditions + return conditions def filter_pricing_rules(args, pricing_rules, doc=None): - if not isinstance(pricing_rules, list): - pricing_rules = [pricing_rules] + if not isinstance(pricing_rules, list): + pricing_rules = [pricing_rules] - original_pricing_rule = copy.copy(pricing_rules) + original_pricing_rule = copy.copy(pricing_rules) - # filter for qty - if pricing_rules: - stock_qty = flt(args.get('stock_qty')) - amount = flt(args.get('price_list_rate')) * flt(args.get('qty')) + # filter for qty + if pricing_rules: + stock_qty = flt(args.get('stock_qty')) + amount = flt(args.get('price_list_rate')) * flt(args.get('qty')) - if pricing_rules[0].apply_rule_on_other: - field = frappe.scrub(pricing_rules[0].apply_rule_on_other) + if pricing_rules[0].apply_rule_on_other: + field = frappe.scrub(pricing_rules[0].apply_rule_on_other) - if (field and pricing_rules[0].get('other_' + field) != args.get(field)): return + if (field and pricing_rules[0].get('other_' + field) != args.get(field)): return - pr_doc = frappe.get_doc('Pricing Rule', pricing_rules[0].name) + pr_doc = frappe.get_doc('Pricing Rule', pricing_rules[0].name) - if pricing_rules[0].mixed_conditions and doc: - stock_qty, amount = get_qty_and_rate_for_mixed_conditions(doc, pr_doc) + if pricing_rules[0].mixed_conditions and doc: + stock_qty, amount = get_qty_and_rate_for_mixed_conditions(doc, pr_doc, args) - elif pricing_rules[0].is_cumulative: - items = [args.get(frappe.scrub(pr_doc.get('apply_on')))] - data = get_qty_amount_data_for_cumulative(pr_doc, args, items) + elif pricing_rules[0].is_cumulative: + items = [args.get(frappe.scrub(pr_doc.get('apply_on')))] + data = get_qty_amount_data_for_cumulative(pr_doc, args, items) - if data: - stock_qty += data[0] - amount += data[1] + if data: + stock_qty += data[0] + amount += data[1] - if pricing_rules[0].apply_rule_on_other and not pricing_rules[0].mixed_conditions and doc: - pricing_rules = get_qty_and_rate_for_other_item(doc, pr_doc, pricing_rules) or [] - else: - pricing_rules = filter_pricing_rules_for_qty_amount(stock_qty, amount, pricing_rules, args) + if pricing_rules[0].apply_rule_on_other and not pricing_rules[0].mixed_conditions and doc: + pricing_rules = get_qty_and_rate_for_other_item(doc, pr_doc, pricing_rules) or [] + else: + pricing_rules = filter_pricing_rules_for_qty_amount(stock_qty, amount, pricing_rules, args) - if not pricing_rules: - for d in original_pricing_rule: - if not d.threshold_percentage: continue + if not pricing_rules: + for d in original_pricing_rule: + if not d.threshold_percentage: continue - msg = validate_quantity_and_amount_for_suggestion(d, stock_qty, - amount, args.get('item_code'), args.get('transaction_type')) + msg = validate_quantity_and_amount_for_suggestion(d, stock_qty, + amount, args.get('item_code'), args.get('transaction_type')) - if msg: - return {'suggestion': msg, 'item_code': args.get('item_code')} + if msg: + return {'suggestion': msg, 'item_code': args.get('item_code')} - # add variant_of property in pricing rule - for p in pricing_rules: - if p.item_code and args.variant_of: - p.variant_of = args.variant_of - else: - p.variant_of = None + # add variant_of property in pricing rule + for p in pricing_rules: + if p.item_code and args.variant_of: + p.variant_of = args.variant_of + else: + p.variant_of = None - # find pricing rule with highest priority - if pricing_rules: - max_priority = max([cint(p.priority) for p in pricing_rules]) - if max_priority: - pricing_rules = list(filter(lambda x: cint(x.priority)==max_priority, pricing_rules)) + # find pricing rule with highest priority + if pricing_rules: + max_priority = max([cint(p.priority) for p in pricing_rules]) + if max_priority: + pricing_rules = list(filter(lambda x: cint(x.priority)==max_priority, pricing_rules)) - # apply internal priority - all_fields = ["item_code", "item_group", "brand", "customer", "customer_group", "territory", - "supplier", "supplier_group", "campaign", "sales_partner", "variant_of"] + # apply internal priority + all_fields = ["item_code", "item_group", "brand", "customer", "customer_group", "territory", + "supplier", "supplier_group", "campaign", "sales_partner", "variant_of"] - if len(pricing_rules) > 1: - for field_set in [["item_code", "variant_of", "item_group", "brand"], - ["customer", "customer_group", "territory"], ["supplier", "supplier_group"]]: - remaining_fields = list(set(all_fields) - set(field_set)) - if if_all_rules_same(pricing_rules, remaining_fields): - pricing_rules = apply_internal_priority(pricing_rules, field_set, args) - break + if len(pricing_rules) > 1: + for field_set in [["item_code", "variant_of", "item_group", "brand"], + ["customer", "customer_group", "territory"], ["supplier", "supplier_group"]]: + remaining_fields = list(set(all_fields) - set(field_set)) + if if_all_rules_same(pricing_rules, remaining_fields): + pricing_rules = apply_internal_priority(pricing_rules, field_set, args) + break - if pricing_rules and not isinstance(pricing_rules, list): - pricing_rules = list(pricing_rules) + if pricing_rules and not isinstance(pricing_rules, list): + pricing_rules = list(pricing_rules) - if len(pricing_rules) > 1: - rate_or_discount = list(set([d.rate_or_discount for d in pricing_rules])) - if len(rate_or_discount) == 1 and rate_or_discount[0] == "Discount Percentage": - pricing_rules = filter(lambda x: x.for_price_list==args.price_list, pricing_rules) \ - or pricing_rules + if len(pricing_rules) > 1: + rate_or_discount = list(set([d.rate_or_discount for d in pricing_rules])) + if len(rate_or_discount) == 1 and rate_or_discount[0] == "Discount Percentage": + pricing_rules = filter(lambda x: x.for_price_list==args.price_list, pricing_rules) \ + or pricing_rules - if len(pricing_rules) > 1 and not args.for_shopping_cart: - frappe.throw(_("Multiple Price Rules exists with same criteria, please resolve conflict by assigning priority. Price Rules: {0}") - .format("\n".join([d.name for d in pricing_rules])), MultiplePricingRuleConflict) - elif pricing_rules: - return pricing_rules[0] + if len(pricing_rules) > 1 and not args.for_shopping_cart: + frappe.throw(_("Multiple Price Rules exists with same criteria, please resolve conflict by assigning priority. Price Rules: {0}") + .format("\n".join([d.name for d in pricing_rules])), MultiplePricingRuleConflict) + elif pricing_rules: + return pricing_rules[0] def validate_quantity_and_amount_for_suggestion(args, qty, amount, item_code, transaction_type): - fieldname, msg = '', '' - type_of_transaction = 'purcahse' if transaction_type == "buying" else "sale" + fieldname, msg = '', '' + type_of_transaction = 'purcahse' if transaction_type == "buying" else "sale" - for field, value in {'min_qty': qty, 'min_amt': amount}.items(): - if (args.get(field) and value < args.get(field) - and (args.get(field) - cint(args.get(field) * args.threshold_percentage * 0.01)) <= value): - fieldname = field + for field, value in {'min_qty': qty, 'min_amt': amount}.items(): + if (args.get(field) and value < args.get(field) + and (args.get(field) - cint(args.get(field) * args.threshold_percentage * 0.01)) <= value): + fieldname = field - for field, value in {'max_qty': qty, 'max_amt': amount}.items(): - if (args.get(field) and value > args.get(field) - and (args.get(field) + cint(args.get(field) * args.threshold_percentage * 0.01)) >= value): - fieldname = field + for field, value in {'max_qty': qty, 'max_amt': amount}.items(): + if (args.get(field) and value > args.get(field) + and (args.get(field) + cint(args.get(field) * args.threshold_percentage * 0.01)) >= value): + fieldname = field - if fieldname: - msg = _("""If you {0} {1} quantities of the item {2}, the scheme {3} - will be applied on the item.""").format(type_of_transaction, args.get(fieldname), item_code, args.rule_description) + if fieldname: + msg = _("""If you {0} {1} quantities of the item {2}, the scheme {3} + will be applied on the item.""").format(type_of_transaction, args.get(fieldname), item_code, args.rule_description) - if fieldname in ['min_amt', 'max_amt']: - msg = _("""If you {0} {1} worth item {2}, the scheme {3} will be applied on the item. - """).format(frappe.fmt_money(type_of_transaction, args.get(fieldname)), item_code, args.rule_description) + if fieldname in ['min_amt', 'max_amt']: + msg = _("""If you {0} {1} worth item {2}, the scheme {3} will be applied on the item. + """).format(frappe.fmt_money(type_of_transaction, args.get(fieldname)), item_code, args.rule_description) - frappe.msgprint(msg) + frappe.msgprint(msg) - return msg + return msg def filter_pricing_rules_for_qty_amount(qty, rate, pricing_rules, args=None): - rules = [] + rules = [] - for rule in pricing_rules: - status = False - conversion_factor = 1 + for rule in pricing_rules: + status = False + conversion_factor = 1 - if rule.get("uom"): - conversion_factor = get_conversion_factor(rule.item_code, rule.uom).get("conversion_factor", 1) + if rule.get("uom"): + conversion_factor = get_conversion_factor(rule.item_code, rule.uom).get("conversion_factor", 1) - if (flt(qty) >= (flt(rule.min_qty) * conversion_factor) - and (flt(qty)<= (rule.max_qty * conversion_factor) if rule.max_qty else True)): - status = True + if (flt(qty) >= (flt(rule.min_qty) * conversion_factor) + and (flt(qty)<= (rule.max_qty * conversion_factor) if rule.max_qty else True)): + status = True - # if user has created item price against the transaction UOM - if rule.get("uom") == args.get("uom"): - conversion_factor = 1.0 + # if user has created item price against the transaction UOM + if rule.get("uom") == args.get("uom"): + conversion_factor = 1.0 - if status and (flt(rate) >= (flt(rule.min_amt) * conversion_factor) - and (flt(rate)<= (rule.max_amt * conversion_factor) if rule.max_amt else True)): - status = True - else: - status = False + if status and (flt(rate) >= (flt(rule.min_amt) * conversion_factor) + and (flt(rate)<= (rule.max_amt * conversion_factor) if rule.max_amt else True)): + status = True + else: + status = False - if status: - rules.append(rule) + if status: + rules.append(rule) - return rules + return rules def if_all_rules_same(pricing_rules, fields): - all_rules_same = True - val = [pricing_rules[0].get(k) for k in fields] - for p in pricing_rules[1:]: - if val != [p.get(k) for k in fields]: - all_rules_same = False - break + all_rules_same = True + val = [pricing_rules[0].get(k) for k in fields] + for p in pricing_rules[1:]: + if val != [p.get(k) for k in fields]: + all_rules_same = False + break - return all_rules_same + return all_rules_same def apply_internal_priority(pricing_rules, field_set, args): - filtered_rules = [] - for field in field_set: - if args.get(field): - filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules) - if filtered_rules: break + filtered_rules = [] + for field in field_set: + if args.get(field): + filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules) + if filtered_rules: break - return filtered_rules or pricing_rules + return filtered_rules or pricing_rules -def get_qty_and_rate_for_mixed_conditions(doc, pr_doc): - sum_qty, sum_amt = [0, 0] - items = get_pricing_rule_items(pr_doc) or [] - apply_on = frappe.scrub(pr_doc.get('apply_on')) +def get_qty_and_rate_for_mixed_conditions(doc, pr_doc, args): + sum_qty, sum_amt = [0, 0] + items = get_pricing_rule_items(pr_doc) or [] + apply_on = frappe.scrub(pr_doc.get('apply_on')) - if items and doc.get("items"): - for row in doc.get('items'): - if row.get(apply_on) not in items: continue + if items and doc.get("items"): + for row in doc.get('items'): + if row.get(apply_on) not in items: continue - if pr_doc.mixed_conditions: - sum_qty += row.stock_qty - sum_amt += row.amount + if pr_doc.mixed_conditions: + amt = args.get('qty') * args.get("price_list_rate") + if args.get("item_code") != row.get("item_code"): + amt = row.get('qty') * row.get("price_list_rate") - if pr_doc.is_cumulative: - data = get_qty_amount_data_for_cumulative(pr_doc, doc, items) + sum_qty += row.get("stock_qty") or args.get("stock_qty") + sum_amt += amt - if data and data[0]: - sum_qty += data[0] - sum_amt += data[1] + if pr_doc.is_cumulative: + data = get_qty_amount_data_for_cumulative(pr_doc, doc, items) - return sum_qty, sum_amt + if data and data[0]: + sum_qty += data[0] + sum_amt += data[1] + + return sum_qty, sum_amt def get_qty_and_rate_for_other_item(doc, pr_doc, pricing_rules): - for d in get_pricing_rule_items(pr_doc): - for row in doc.items: - if d == row.get(frappe.scrub(pr_doc.apply_on)): - pricing_rules = filter_pricing_rules_for_qty_amount(row.stock_qty, - row.amount, pricing_rules, row) + for d in get_pricing_rule_items(pr_doc): + for row in doc.items: + if d == row.get(frappe.scrub(pr_doc.apply_on)): + pricing_rules = filter_pricing_rules_for_qty_amount(row.get("stock_qty"), + row.get("amount"), pricing_rules, row) - if pricing_rules and pricing_rules[0]: - return pricing_rules + if pricing_rules and pricing_rules[0]: + return pricing_rules def get_qty_amount_data_for_cumulative(pr_doc, doc, items=[]): - sum_qty, sum_amt = [0, 0] - doctype = doc.get('parenttype') or doc.doctype + sum_qty, sum_amt = [0, 0] + doctype = doc.get('parenttype') or doc.doctype - date_field = ('transaction_date' - if doc.get('transaction_date') else 'posting_date') + date_field = ('transaction_date' + if doc.get('transaction_date') else 'posting_date') - child_doctype = '{0} Item'.format(doctype) - apply_on = frappe.scrub(pr_doc.get('apply_on')) + child_doctype = '{0} Item'.format(doctype) + apply_on = frappe.scrub(pr_doc.get('apply_on')) - values = [pr_doc.valid_from, pr_doc.valid_upto] - condition = "" + values = [pr_doc.valid_from, pr_doc.valid_upto] + condition = "" - if pr_doc.warehouse: - warehouses = get_child_warehouses(pr_doc.warehouse) + if pr_doc.warehouse: + warehouses = get_child_warehouses(pr_doc.warehouse) - condition += """ and `tab{child_doc}`.warehouse in ({warehouses}) - """.format(child_doc=child_doctype, warehouses = ','.join(['%s'] * len(warehouses))) + condition += """ and `tab{child_doc}`.warehouse in ({warehouses}) + """.format(child_doc=child_doctype, warehouses = ','.join(['%s'] * len(warehouses))) - values.extend(warehouses) + values.extend(warehouses) - if items: - condition = " and `tab{child_doc}`.{apply_on} in ({items})".format(child_doc = child_doctype, - apply_on = apply_on, items = ','.join(['%s'] * len(items))) + if items: + condition = " and `tab{child_doc}`.{apply_on} in ({items})".format(child_doc = child_doctype, + apply_on = apply_on, items = ','.join(['%s'] * len(items))) - values.extend(items) + values.extend(items) - data_set = frappe.db.sql(""" SELECT `tab{child_doc}`.stock_qty, - `tab{child_doc}`.amount - FROM `tab{child_doc}`, `tab{parent_doc}` - WHERE - `tab{child_doc}`.parent = `tab{parent_doc}`.name and {date_field} - between %s and %s and `tab{parent_doc}`.docstatus = 1 - {condition} group by `tab{child_doc}`.name - """.format(parent_doc = doctype, - child_doc = child_doctype, - condition = condition, - date_field = date_field - ), tuple(values), as_dict=1) + data_set = frappe.db.sql(""" SELECT `tab{child_doc}`.stock_qty, + `tab{child_doc}`.amount + FROM `tab{child_doc}`, `tab{parent_doc}` + WHERE + `tab{child_doc}`.parent = `tab{parent_doc}`.name and {date_field} + between %s and %s and `tab{parent_doc}`.docstatus = 1 + {condition} group by `tab{child_doc}`.name + """.format(parent_doc = doctype, + child_doc = child_doctype, + condition = condition, + date_field = date_field + ), tuple(values), as_dict=1) - for data in data_set: - sum_qty += data.get('stock_qty') - sum_amt += data.get('amount') + for data in data_set: + sum_qty += data.get('stock_qty') + sum_amt += data.get('amount') - return [sum_qty, sum_amt] + return [sum_qty, sum_amt] def validate_pricing_rules(doc): - validate_pricing_rule_on_transactions(doc) + validate_pricing_rule_on_transactions(doc) - if not doc.pricing_rules: return + for d in doc.items: + validate_pricing_rule_on_items(doc, d) - for d in doc.items: - validate_pricing_rule_on_items(doc, d) + doc.calculate_taxes_and_totals() - doc.calculate_taxes_and_totals() +def validate_pricing_rule_on_items(doc, item_row, do_not_validate = False): + value = 0 + for pricing_rule in get_applied_pricing_rules(doc, item_row): + pr_doc = frappe.get_doc('Pricing Rule', pricing_rule) -def validate_pricing_rule_on_items(doc, item_row): - value = 0 - for pr_row in get_applied_pricing_rules(doc, item_row): - pr_doc = frappe.get_doc('Pricing Rule', pr_row.pricing_rule) + if pr_doc.get('apply_on') == 'Transaction': continue - if pr_doc.get('apply_on') == 'Transaction': continue + if pr_doc.get('price_or_product_discount') == 'Product': + apply_pricing_rule_for_free_items(doc, pr_doc) + else: + for field in ['discount_percentage', 'discount_amount', 'rate']: + if not pr_doc.get(field): continue - if pr_doc.get('price_or_product_discount') == 'Product': - apply_pricing_rule_for_free_items(doc, pr_doc) - else: - for field in ['discount_percentage', 'discount_amount', 'rate']: - if not pr_doc.get(field): continue - - value += pr_doc.get(field) - apply_pricing_rule(doc, pr_doc, pr_row, item_row, value) + value += pr_doc.get(field) + apply_pricing_rule(doc, pr_doc, item_row, value, do_not_validate) def validate_pricing_rule_on_transactions(doc): - conditions = "apply_on = 'Transaction'" + conditions = "apply_on = 'Transaction'" - values = {} - conditions = get_other_conditions(conditions, values, doc) + values = {} + conditions = get_other_conditions(conditions, values, doc) - pricing_rules = frappe.db.sql(""" Select `tabPricing Rule`.* from `tabPricing Rule` - where {conditions} """.format(conditions = conditions), values, as_dict=1) + pricing_rules = frappe.db.sql(""" Select `tabPricing Rule`.* from `tabPricing Rule` + where {conditions} """.format(conditions = conditions), values, as_dict=1) - if pricing_rules: - pricing_rules = filter_pricing_rules_for_qty_amount(doc.total_qty, - doc.total, pricing_rules) + if pricing_rules: + pricing_rules = filter_pricing_rules_for_qty_amount(doc.total_qty, + doc.total, pricing_rules) - for d in pricing_rules: - if d.price_or_product_discount == 'Price': - if d.apply_discount_on: - doc.set('apply_discount_on', d.apply_discount_on) + for d in pricing_rules: + if d.price_or_product_discount == 'Price': + if d.apply_discount_on: + doc.set('apply_discount_on', d.apply_discount_on) - for field in ['additional_discount_percentage', 'discount_amount']: - if not d.get(field): continue + for field in ['additional_discount_percentage', 'discount_amount']: + if not d.get(field): continue - pr_field = ('discount_percentage' - if field == 'additional_discount_percentage' else field) + pr_field = ('discount_percentage' + if field == 'additional_discount_percentage' else field) - if d.validate_applied_rule and doc.get(field) < d.get(pr_field): - frappe.msgprint(_("User has not applied rule on the invoice {0}") - .format(doc.name)) - else: - doc.set(field, d.get(pr_field)) - elif d.price_or_product_discount == 'Product': - apply_pricing_rule_for_free_items(doc, d) + if d.validate_applied_rule and doc.get(field) < d.get(pr_field): + frappe.msgprint(_("User has not applied rule on the invoice {0}") + .format(doc.name)) + else: + doc.set(field, d.get(pr_field)) + elif d.price_or_product_discount == 'Product': + apply_pricing_rule_for_free_items(doc, d) def get_applied_pricing_rules(doc, item_row): - return [d for d in doc.pricing_rules - if d.child_docname == item_row.name] + return (item_row.get("pricing_rules").split(',') + if item_row.get("pricing_rules") else []) def apply_pricing_rule_for_free_items(doc, pricing_rule): - if pricing_rule.get('free_item'): - items = [d.item_code for d in doc.items - if d.item_code == (d.item_code - if pricing_rule.get('same_item') else pricing_rule.get('free_item')) and d.is_free_item] + if pricing_rule.get('free_item'): + items = [d.item_code for d in doc.items + if d.item_code == (d.item_code + if pricing_rule.get('same_item') else pricing_rule.get('free_item')) and d.is_free_item] - if not items: - doc.append('items', { - 'item_code': pricing_rule.get('free_item'), - 'qty': pricing_rule.get('free_qty'), - 'uom': pricing_rule.get('free_item_uom'), - 'rate': pricing_rule.get('free_item_rate'), - 'is_free_item': 1 - }) + if not items: + doc.append('items', { + 'item_code': pricing_rule.get('free_item'), + 'qty': pricing_rule.get('free_qty'), + 'uom': pricing_rule.get('free_item_uom'), + 'rate': pricing_rule.get('free_item_rate'), + 'is_free_item': 1 + }) - doc.set_missing_values() + doc.set_missing_values() -def apply_pricing_rule(doc, pr_doc, pr_row, item_row, value): - apply_on = frappe.scrub(pr_doc.get('apply_on')) - items = (get_pricing_rule_items(pr_doc) - if pr_doc.mixed_conditions else [item_row.get(apply_on)]) +def apply_pricing_rule(doc, pr_doc, item_row, value, do_not_validate=False): + apply_on, items = get_apply_on_and_items(pr_doc, item_row) - if pr_doc.apply_rule_on_other: - apply_on = frappe.scrub(pr_doc.apply_rule_on_other) - items = [pr_doc.get(apply_on)] + rule_applied = {} - rule_applied = 1 - if item_row.get(apply_on) in items: - for field in ['discount_percentage', 'discount_amount', 'rate']: - if not pr_doc.get(field): continue + for item in doc.get("items"): + if not item.pricing_rules: + item.pricing_rules = item_row.pricing_rules - if not pr_doc.validate_applied_rule: - item_row.set(field, value) - elif item_row.get(field) < value: - rule_applied = 0 - frappe.msgprint(_("Row {0}: user has not applied rule {1} on the item {2}") - .format(item_row.idx, pr_doc.title, item_row.item_code)) + if item.get(apply_on) in items: + for field in ['discount_percentage', 'discount_amount', 'rate']: + if not pr_doc.get(field): continue - pr_row.rule_applied = rule_applied + key = (item.name, item.pricing_rules) + if not pr_doc.validate_applied_rule: + rule_applied[key] = 1 + item.set(field, value) + elif item.get(field) < value: + if not do_not_validate and item.idx == item_row.idx: + rule_applied[key] = 0 + frappe.msgprint(_("Row {0}: user has not applied rule {1} on the item {2}") + .format(item.idx, pr_doc.title, item.item_code)) + + if rule_applied and doc.get("pricing_rules"): + for d in doc.get("pricing_rules"): + key = (d.child_docname, d.pricing_rule) + if key in rule_applied: + d.rule_applied = 1 + +def get_apply_on_and_items(pr_doc, item_row): + # for mixed or other items conditions + apply_on = frappe.scrub(pr_doc.get('apply_on')) + items = (get_pricing_rule_items(pr_doc) + if pr_doc.mixed_conditions else [item_row.get(apply_on)]) + + if pr_doc.apply_rule_on_other: + apply_on = frappe.scrub(pr_doc.apply_rule_on_other) + items = [pr_doc.get(apply_on)] + + return apply_on, items def get_pricing_rule_items(pr_doc): - apply_on = frappe.scrub(pr_doc.get('apply_on')) - return [item.get(apply_on) for item in pr_doc.items] or [] \ No newline at end of file + apply_on = frappe.scrub(pr_doc.get('apply_on')) + + pricing_rule_apply_on = apply_on_table.get(pr_doc.get('apply_on')) + + return [item.get(apply_on) for item in pr_doc.get(pricing_rule_apply_on)] or [] + +@frappe.whitelist() +def validate_pricing_rule_for_different_cond(doc): + if isinstance(doc, string_types): + doc = json.loads(doc) + + doc = frappe.get_doc(doc) + for d in doc.get("items"): + validate_pricing_rule_on_items(doc, d, True) + + return doc \ No newline at end of file diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index ac2ce8e6d8..6ca31e727d 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -468,7 +468,7 @@ cur_frm.fields_dict["items"].grid.get_field("cost_center").get_query = function( cur_frm.cscript.cost_center = function(doc, cdt, cdn){ var d = locals[cdt][cdn]; - if(d.idx == 1 && d.cost_center){ + if(d.cost_center){ var cl = doc.items || []; for(var i = 0; i < cl.length; i++){ if(!cl[i].cost_center) cl[i].cost_center = d.cost_center; diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 53eb73191d..896eab8a4a 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -55,11 +55,6 @@ class PurchaseInvoice(BuyingController): if not self.on_hold: self.release_date = '' - def before_print(self): - self.gl_entries = frappe.get_list("GL Entry",filters={"voucher_type": "Purchase Invoice", - "voucher_no": self.name} , - fields=["account", "party_type", "party", "debit", "credit"] - ) def invoice_is_blocked(self): return self.on_hold and (not self.release_date or self.release_date > getdate(nowdate())) @@ -770,10 +765,6 @@ class PurchaseInvoice(BuyingController): self.update_status_updater_args() if not self.is_return: - from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries - if frappe.db.get_single_value('Accounts Settings', 'unlink_payment_on_cancellation_of_invoice'): - unlink_ref_doc_from_payment_entries(self) - self.update_prevdoc_status() self.update_billing_status_for_zero_amount_refdoc("Purchase Order") self.update_billing_status_in_pr() diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index ab7dc9cd7d..44af743ebf 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -89,6 +89,12 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte }, __('Create')); } + if (doc.docstatus === 1) { + cur_frm.add_custom_button(__('Maintenance Schedule'), function () { + cur_frm.cscript.make_maintenance_schedule(); + }, __('Create')); + } + if(!doc.auto_repeat) { cur_frm.add_custom_button(__('Subscription'), function() { erpnext.utils.make_subscription(doc.doctype, doc.name) @@ -118,6 +124,13 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte } }, + make_maintenance_schedule: function() { + frappe.model.open_mapped_doc({ + method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_maintenance_schedule", + frm: cur_frm + }) + }, + on_submit: function(doc, dt, dn) { var me = this; diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 0b4c405aca..2089f15c7c 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -205,18 +205,11 @@ class SalesInvoice(SellingController): def before_cancel(self): self.update_time_sheet(None) - def before_print(self): - self.gl_entries = frappe.get_list("GL Entry",filters={"voucher_type": "Sales Invoice", - "voucher_no": self.name} , - fields=["account", "party_type", "party", "debit", "credit"] - ) def on_cancel(self): - self.check_sales_order_on_hold_or_close("sales_order") + super(SalesInvoice, self).on_cancel() - from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries - if frappe.db.get_single_value('Accounts Settings', 'unlink_payment_on_cancellation_of_invoice'): - unlink_ref_doc_from_payment_entries(self) + self.check_sales_order_on_hold_or_close("sales_order") if self.is_return and not self.update_billed_amount_in_sales_order: # NOTE status updating bypassed for is_return @@ -1230,6 +1223,22 @@ def get_bank_cash_account(mode_of_payment, company): "account": account } +@frappe.whitelist() +def make_maintenance_schedule(source_name, target_doc=None): + doclist = get_mapped_doc("Sales Invoice", source_name, { + "Sales Invoice": { + "doctype": "Maintenance Schedule", + "validation": { + "docstatus": ["=", 1] + } + }, + "Sales Invoice Item": { + "doctype": "Maintenance Schedule Item", + }, + }, target_doc) + + return doclist + @frappe.whitelist() def make_delivery_note(source_name, target_doc=None): def set_missing_values(source, target): @@ -1388,4 +1397,4 @@ def get_loyalty_programs(customer): frappe.db.set(customer, 'loyalty_program', lp_details[0]) return [] else: - return lp_details + return lp_details \ No newline at end of file diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 801d620223..bb18dfff32 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -14,8 +14,9 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_per from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError from frappe.model.naming import make_autoname -from erpnext.accounts.doctype.account.test_account import get_inventory_account +from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data +from erpnext.stock.doctype.item.test_item import create_item from six import iteritems class TestSalesInvoice(unittest.TestCase): def make(self): @@ -1572,6 +1573,56 @@ class TestSalesInvoice(unittest.TestCase): accounts_settings.allow_cost_center_in_entry_of_bs_account = 0 accounts_settings.save() + def test_deferred_revenue(self): + deferred_account = create_account(account_name="Deferred Revenue", + parent_account="Current Liabilities - _TC", company="_Test Company") + + item = create_item("_Test Item for Deferred Accounting") + item.enable_deferred_revenue = 1 + item.deferred_revenue_account = deferred_account + item.no_of_months = 12 + item.save() + + si = create_sales_invoice(item=item.name, posting_date="2019-01-10", do_not_submit=True) + si.items[0].enable_deferred_revenue = 1 + si.items[0].service_start_date = "2019-01-10" + si.items[0].service_end_date = "2019-03-15" + si.items[0].deferred_revenue_account = deferred_account + si.save() + si.submit() + + from erpnext.accounts.deferred_revenue import convert_deferred_revenue_to_income + convert_deferred_revenue_to_income(start_date="2019-01-01", end_date="2019-01-31") + + expected_gle = [ + [deferred_account, 33.85, 0.0, "2019-01-31"], + ["Sales - _TC", 0.0, 33.85, "2019-01-31"] + ] + + self.check_gl_entries(si.name, expected_gle, "2019-01-10") + + convert_deferred_revenue_to_income(start_date="2019-01-01", end_date="2019-03-31") + + expected_gle = [ + [deferred_account, 43.08, 0.0, "2019-02-28"], + ["Sales - _TC", 0.0, 43.08, "2019-02-28"], + [deferred_account, 23.07, 0.0, "2019-03-15"], + ["Sales - _TC", 0.0, 23.07, "2019-03-15"] + ] + + self.check_gl_entries(si.name, expected_gle, "2019-01-31") + + def check_gl_entries(self, voucher_no, expected_gle, posting_date): + gl_entries = frappe.db.sql("""select account, debit, credit, posting_date + from `tabGL Entry` + where voucher_type='Sales Invoice' and voucher_no=%s and posting_date > %s + order by posting_date asc, account asc""", (voucher_no, posting_date), as_dict=1) + + for i, gle in enumerate(gl_entries): + self.assertEqual(expected_gle[i][0], gle.account) + self.assertEqual(expected_gle[i][1], gle.debit) + self.assertEqual(expected_gle[i][2], gle.credit) + self.assertEqual(getdate(expected_gle[i][3]), gle.posting_date) def create_sales_invoice(**args): si = frappe.new_doc("Sales Invoice") @@ -1669,4 +1720,4 @@ def get_outstanding_amount(against_voucher_type, against_voucher, account, party if against_voucher_type == 'Purchase Invoice': bal = bal * -1 - return bal + return bal \ No newline at end of file diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index c3274b9fb5..4550dedba9 100755 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -333,6 +333,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ var me = this; this.frm = {} this.load_data(true); + this.frm.doc.offline_pos_name = ''; this.setup(); this.set_default_customer() }, @@ -345,7 +346,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ if (load_doc) { this.frm.doc = JSON.parse(localStorage.getItem('doc')); - this.frm.doc.offline_pos_name = null; } $.each(this.meta, function (i, data) { @@ -641,7 +641,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ me.list_customers_btn.toggleClass("view_customer"); me.pos_bill.show(); me.list_customers_btn.show(); - me.frm.doc.offline_pos_name = $(this).parents().attr('invoice-name') + me.frm.doc.offline_pos_name = $(this).parents().attr('invoice-name'); me.edit_record(); }) @@ -984,7 +984,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ } if(!this.customer_doc.fields_dict.customer_pos_id.value) { - this.customer_doc.set_value("customer_pos_id", $.now()) + this.customer_doc.set_value("customer_pos_id", frappe.datetime.now_datetime()) } }, @@ -1686,10 +1686,18 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ create_invoice: function () { var me = this; + var existing_pos_list = []; var invoice_data = {}; this.si_docs = this.get_doc_from_localstorage(); - if (this.frm.doc.offline_pos_name) { + if(this.si_docs) { + this.si_docs.forEach((row) => { + existing_pos_list.push(Object.keys(row)); + }); + } + + if (this.frm.doc.offline_pos_name + && in_list(existing_pos_list, this.frm.doc.offline_pos_name)) { this.update_invoice() //to retrieve and set the default payment invoice_data[this.frm.doc.offline_pos_name] = this.frm.doc; @@ -1698,8 +1706,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ this.frm.doc.paid_amount = this.frm.doc.net_total this.frm.doc.outstanding_amount = 0 - } else { - this.frm.doc.offline_pos_name = $.now(); + } else if(!this.frm.doc.offline_pos_name) { + this.frm.doc.offline_pos_name = frappe.datetime.now_datetime(); this.frm.doc.posting_date = frappe.datetime.get_today(); this.frm.doc.posting_time = frappe.datetime.now_time(); this.frm.doc.pos_total_qty = this.frm.doc.qty_total; diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 686579be92..f25473e308 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -592,13 +592,17 @@ def get_party_shipping_address(doctype, name): else: return '' -def get_partywise_advanced_payment_amount(party_type="Customer"): +def get_partywise_advanced_payment_amount(party_type, posting_date = None): + cond = "1=1" + if posting_date: + cond = "posting_date <= '{0}'".format(posting_date) + data = frappe.db.sql(""" SELECT party, sum({0}) as amount FROM `tabGL Entry` WHERE party_type = %s and against_voucher is null - GROUP BY party""" - .format(("credit") if party_type == "Customer" else "debit") , party_type) + and {1} GROUP BY party""" + .format(("credit") if party_type == "Customer" else "debit", cond) , party_type) if data: return frappe._dict(data) \ No newline at end of file diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py index 8cb5ac1090..244aa8af6a 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py @@ -136,7 +136,8 @@ class AccountsReceivableSummary(ReceivablePayableReport): partywise_total = self.get_partywise_total(party_naming_by, args) - partywise_advance_amount = get_partywise_advanced_payment_amount(args.get("party_type")) or {} + partywise_advance_amount = get_partywise_advanced_payment_amount(args.get("party_type"), + self.filters.get("report_date")) or {} for party, party_dict in iteritems(partywise_total): row = [party] @@ -144,7 +145,10 @@ class AccountsReceivableSummary(ReceivablePayableReport): row += [self.get_party_name(args.get("party_type"), party)] row += [partywise_advance_amount.get(party, 0)] - paid_amt = flt(party_dict.paid_amt - partywise_advance_amount.get(party, 0)) + + paid_amt = 0 + if party_dict.paid_amt > 0: + paid_amt = flt(party_dict.paid_amt - partywise_advance_amount.get(party, 0)) row += [ party_dict.invoiced_amt, paid_amt, party_dict.credit_amt, party_dict.outstanding_amt, diff --git a/erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.py b/erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.py index 9bf851df41..3ffb3ac1df 100644 --- a/erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.py +++ b/erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.py @@ -14,13 +14,13 @@ def execute(filters=None): def get_column(): return [ - _("Delivery Note") + ":Link/Delivery Note:120", _("Date") + ":Date:100", + _("Delivery Note") + ":Link/Delivery Note:120", _("Status") + "::120", _("Date") + ":Date:100", _("Suplier") + ":Link/Customer:120", _("Customer Name") + "::120", - _("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120", + _("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120", _("Amount") + ":Currency:100", _("Billed Amount") + ":Currency:100", _("Pending Amount") + ":Currency:100", _("Item Name") + "::120", _("Description") + "::120", _("Company") + ":Link/Company:120", ] def get_args(): - return {'doctype': 'Delivery Note', 'party': 'customer', + return {'doctype': 'Delivery Note', 'party': 'customer', 'date': 'posting_date', 'order': 'name', 'order_by': 'desc'} \ No newline at end of file diff --git a/erpnext/accounts/report/non_billed_report.py b/erpnext/accounts/report/non_billed_report.py index 41ec9b7466..c238606443 100644 --- a/erpnext/accounts/report/non_billed_report.py +++ b/erpnext/accounts/report/non_billed_report.py @@ -12,14 +12,14 @@ def get_ordered_to_be_billed_data(args): child_tab = doctype + " Item" precision = get_field_precision(frappe.get_meta(child_tab).get_field("billed_amt"), currency=get_default_currency()) or 2 - + project_field = get_project_field(doctype, party) return frappe.db.sql(""" Select - `{parent_tab}`.name, `{parent_tab}`.{date_field}, `{parent_tab}`.{party}, `{parent_tab}`.{party}_name, + `{parent_tab}`.name, `{parent_tab}`.status, `{parent_tab}`.{date_field}, `{parent_tab}`.{party}, `{parent_tab}`.{party}_name, {project_field}, `{child_tab}`.item_code, `{child_tab}`.base_amount, - (`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)), + (`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)), (`{child_tab}`.base_amount - (`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1))), `{child_tab}`.item_name, `{child_tab}`.description, `{parent_tab}`.company from diff --git a/erpnext/accounts/report/ordered_items_to_be_billed/ordered_items_to_be_billed.py b/erpnext/accounts/report/ordered_items_to_be_billed/ordered_items_to_be_billed.py index 5765266f1c..ec0d2f39f3 100644 --- a/erpnext/accounts/report/ordered_items_to_be_billed/ordered_items_to_be_billed.py +++ b/erpnext/accounts/report/ordered_items_to_be_billed/ordered_items_to_be_billed.py @@ -14,13 +14,13 @@ def execute(filters=None): def get_column(): return [ - _("Sales Order") + ":Link/Sales Order:120", _("Date") + ":Date:100", + _("Sales Order") + ":Link/Sales Order:120", _("Status") + "::120", _("Date") + ":Date:100", _("Suplier") + ":Link/Customer:120", _("Customer Name") + "::120", - _("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120", + _("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120", _("Amount") + ":Currency:100", _("Billed Amount") + ":Currency:100", _("Pending Amount") + ":Currency:100", _("Item Name") + "::120", _("Description") + "::120", _("Company") + ":Link/Company:120", ] def get_args(): - return {'doctype': 'Sales Order', 'party': 'customer', + return {'doctype': 'Sales Order', 'party': 'customer', 'date': 'transaction_date', 'order': 'transaction_date', 'order_by': 'asc'} \ No newline at end of file diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.py b/erpnext/accounts/report/profitability_analysis/profitability_analysis.py index 39706acde0..a0d8c5f0e4 100644 --- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.py +++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.py @@ -133,6 +133,13 @@ def get_columns(filters): "options": filters.get("based_on"), "width": 300 }, + { + "fieldname": "currency", + "label": _("Currency"), + "fieldtype": "Link", + "options": "Currency", + "hidden": 1 + }, { "fieldname": "income", "label": _("Income"), @@ -153,13 +160,6 @@ def get_columns(filters): "fieldtype": "Currency", "options": "currency", "width": 120 - }, - { - "fieldname": "currency", - "label": _("Currency"), - "fieldtype": "Link", - "options": "Currency", - "hidden": 1 } ] @@ -191,4 +191,4 @@ def set_gl_entries_by_account(company, from_date, to_date, based_on, gl_entries_ for entry in gl_entries: gl_entries_by_account.setdefault(entry.based_on, []).append(entry) - return gl_entries_by_account \ No newline at end of file + return gl_entries_by_account diff --git a/erpnext/accounts/report/purchase_order_items_to_be_billed/purchase_order_items_to_be_billed.py b/erpnext/accounts/report/purchase_order_items_to_be_billed/purchase_order_items_to_be_billed.py index 5aed93d348..99d0a36813 100644 --- a/erpnext/accounts/report/purchase_order_items_to_be_billed/purchase_order_items_to_be_billed.py +++ b/erpnext/accounts/report/purchase_order_items_to_be_billed/purchase_order_items_to_be_billed.py @@ -14,13 +14,13 @@ def execute(filters=None): def get_column(): return [ - _("Purchase Order") + ":Link/Purchase Order:120", _("Date") + ":Date:100", + _("Purchase Order") + ":Link/Purchase Order:120", _("Status") + "::120", _("Date") + ":Date:100", _("Suplier") + ":Link/Supplier:120", _("Suplier Name") + "::120", - _("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120", + _("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120", _("Amount") + ":Currency:100", _("Billed Amount") + ":Currency:100", _("Amount to Bill") + ":Currency:100", _("Item Name") + "::120", _("Description") + "::120", _("Company") + ":Link/Company:120", ] def get_args(): - return {'doctype': 'Purchase Order', 'party': 'supplier', + return {'doctype': 'Purchase Order', 'party': 'supplier', 'date': 'transaction_date', 'order': 'transaction_date', 'order_by': 'asc'} diff --git a/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.py b/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.py index 73e8b25a3a..5e8d7730b7 100644 --- a/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.py +++ b/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.py @@ -14,7 +14,7 @@ def execute(filters=None): def get_column(): return [ - _("Purchase Receipt") + ":Link/Purchase Receipt:120", _("Date") + ":Date:100", + _("Purchase Receipt") + ":Link/Purchase Receipt:120", _("Status") + "::120", _("Date") + ":Date:100", _("Supplier") + ":Link/Supplier:120", _("Supplier Name") + "::120", _("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120", _("Amount") + ":Currency:100", _("Billed Amount") + ":Currency:100", _("Amount to Bill") + ":Currency:100", diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index b2c1de57f2..cf4ec49a78 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -25,9 +25,6 @@ frappe.ui.form.on("Purchase Order", { frm.set_indicator_formatter('item_code', function(doc) { return (doc.qty<=doc.received_qty) ? "green" : "orange" }) - frm.set_indicator_formatter('pricing_rule', - function(doc) { return (doc.rule_applied) ? "green" : "red" }) - frm.set_query("blanket_order", "items", function() { return { filters: { diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 34bb80330d..b7450744da 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -444,7 +444,7 @@ def make_rm_stock_entry(purchase_order, rm_items): item_wh = get_item_details(items) stock_entry = frappe.new_doc("Stock Entry") - stock_entry.purpose = "Subcontract" + stock_entry.purpose = "Send to Subcontractor" stock_entry.purchase_order = purchase_order.name stock_entry.supplier = purchase_order.supplier stock_entry.supplier_name = purchase_order.supplier_name @@ -452,6 +452,7 @@ def make_rm_stock_entry(purchase_order, rm_items): stock_entry.address_display = purchase_order.address_display stock_entry.company = purchase_order.company stock_entry.to_warehouse = purchase_order.supplier_warehouse + stock_entry.set_stock_entry_type() for item_code in fg_items: for rm_item_data in rm_items_list: diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index f1507364df..774156eda4 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -465,6 +465,33 @@ class TestPurchaseOrder(unittest.TestCase): self.assertEquals(se_items, supplied_items) update_backflush_based_on("BOM") + def test_advance_payment_entry_unlink_against_purchase_order(self): + from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry + frappe.db.set_value("Accounts Settings", "Accounts Settings", + "unlink_advance_payment_on_cancelation_of_order", 1) + + po_doc = create_purchase_order() + + pe = get_payment_entry("Purchase Order", po_doc.name, bank_account="_Test Bank - _TC") + pe.reference_no = "1" + pe.reference_date = nowdate() + pe.paid_from_account_currency = po_doc.currency + pe.paid_to_account_currency = po_doc.currency + pe.source_exchange_rate = 1 + pe.target_exchange_rate = 1 + pe.paid_amount = po_doc.grand_total + pe.save(ignore_permissions=True) + pe.submit() + + po_doc = frappe.get_doc('Purchase Order', po_doc.name) + po_doc.cancel() + + pe_doc = frappe.get_doc('Payment Entry', pe.name) + pe_doc.cancel() + + frappe.db.set_value("Accounts Settings", "Accounts Settings", + "unlink_advance_payment_on_cancelation_of_order", 0) + def make_subcontracted_item(item_code): from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom diff --git a/erpnext/config/desktop.py b/erpnext/config/desktop.py index 6dc95b242c..8ce096499d 100644 --- a/erpnext/config/desktop.py +++ b/erpnext/config/desktop.py @@ -81,9 +81,9 @@ def get_data(): "description": "Sales pipeline, leads, opportunities and customers." }, { - "module_name": "Help Desk", + "module_name": "Support", "category": "Modules", - "label": _("Help Desk"), + "label": _("Support"), "color": "#1abc9c", "icon": "fa fa-check-square-o", "type": "module", diff --git a/erpnext/config/help_desk.py b/erpnext/config/help_desk.py deleted file mode 100644 index c19dd423e6..0000000000 --- a/erpnext/config/help_desk.py +++ /dev/null @@ -1,82 +0,0 @@ -from __future__ import unicode_literals -from frappe import _ - -def get_data(): - return [ - { - "label": _("Issues"), - "items": [ - { - "type": "doctype", - "name": "Issue", - "description": _("Support queries from customers."), - "onboard": 1, - }, - { - "type": "doctype", - "name": "Communication", - "description": _("Communication log."), - "onboard": 1, - }, - ] - }, - { - "label": _("Warranty"), - "items": [ - { - "type": "doctype", - "name": "Warranty Claim", - "description": _("Warranty Claim against Serial No."), - }, - { - "type": "doctype", - "name": "Serial No", - "description": _("Single unit of an Item."), - }, - ] - }, - { - "label": _("Service Level Agreement"), - "items": [ - { - "type": "doctype", - "name": "Employee Group", - "description": _("Support Team."), - }, - { - "type": "doctype", - "name": "Service Level", - "description": _("Service Level."), - }, - { - "type": "doctype", - "name": "Service Level Agreement", - "description": _("Service Level Agreement."), - } - ] - }, - { - "label": _("Reports"), - "icon": "fa fa-list", - "items": [ - { - "type": "page", - "name": "support-analytics", - "label": _("Support Analytics"), - "icon": "fa fa-bar-chart" - }, - { - "type": "report", - "name": "Minutes to First Response for Issues", - "doctype": "Issue", - "is_query_report": True - }, - { - "type": "report", - "name": "Support Hours", - "doctype": "Issue", - "is_query_report": True - }, - ] - }, - ] \ No newline at end of file diff --git a/erpnext/config/hr.py b/erpnext/config/hr.py index f517a5e7c0..0f009b826f 100644 --- a/erpnext/config/hr.py +++ b/erpnext/config/hr.py @@ -287,6 +287,11 @@ def get_data(): "name": "Employee Advance", "dependencies": ["Employee"] }, + { + "type": "doctype", + "name": "Expense Claim", + "dependencies": ["Employee"] + }, { "type": "doctype", "name": "Loan Type", @@ -296,6 +301,10 @@ def get_data(): "name": "Loan Application", "dependencies": ["Employee"] }, + { + "type": "doctype", + "name": "Loan" + } ] }, { diff --git a/erpnext/config/selling.py b/erpnext/config/selling.py index 4a65af36a2..400f6be826 100644 --- a/erpnext/config/selling.py +++ b/erpnext/config/selling.py @@ -27,6 +27,13 @@ def get_data(): "onboard": 1, "dependencies": ["Item", "Customer"], }, + { + "type": "doctype", + "name": "Sales Invoice", + "description": _("Invoices for Costumers."), + "onboard": 1, + "dependencies": ["Item", "Customer"], + }, { "type": "doctype", "name": "Sales Partner", diff --git a/erpnext/config/support.py b/erpnext/config/support.py index 3980b4210a..c19dd423e6 100644 --- a/erpnext/config/support.py +++ b/erpnext/config/support.py @@ -10,11 +10,13 @@ def get_data(): "type": "doctype", "name": "Issue", "description": _("Support queries from customers."), + "onboard": 1, }, { "type": "doctype", "name": "Communication", "description": _("Communication log."), + "onboard": 1, }, ] }, @@ -33,6 +35,26 @@ def get_data(): }, ] }, + { + "label": _("Service Level Agreement"), + "items": [ + { + "type": "doctype", + "name": "Employee Group", + "description": _("Support Team."), + }, + { + "type": "doctype", + "name": "Service Level", + "description": _("Service Level."), + }, + { + "type": "doctype", + "name": "Service Level Agreement", + "description": _("Service Level Agreement."), + } + ] + }, { "label": _("Reports"), "icon": "fa fa-list", @@ -57,24 +79,4 @@ def get_data(): }, ] }, - { - "label": _("Service Level Agreement"), - "items": [ - { - "type": "doctype", - "name": "Employee Group", - "description": _("Support Team."), - }, - { - "type": "doctype", - "name": "Service Level", - "description": _("Service Level."), - }, - { - "type": "doctype", - "name": "Service Level Agreement", - "description": _("Service Level Agreement."), - } - ] - }, - ] + ] \ No newline at end of file diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index a4c6628ecd..7bb71ec9b5 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -119,6 +119,12 @@ class AccountsController(TransactionBase): self.validate_non_invoice_documents_schedule() def before_print(self): + if self.doctype in ['Journal Entry', 'Payment Entry', 'Sales Invoice', 'Purchase Invoice']: + self.gl_entries = frappe.get_list("GL Entry", filters={ + "voucher_type": self.doctype, + "voucher_no": self.name + }, fields=["account", "party_type", "party", "debit", "credit", "remarks"]) + if self.doctype in ['Purchase Order', 'Sales Order', 'Sales Invoice', 'Purchase Invoice', 'Supplier Quotation', 'Purchase Receipt', 'Delivery Note', 'Quotation']: if self.get("group_same_items"): @@ -276,7 +282,7 @@ class AccountsController(TransactionBase): if self.doctype in ["Purchase Invoice", "Sales Invoice"] and item.meta.get_field('is_fixed_asset'): item.set('is_fixed_asset', ret.get('is_fixed_asset', 0)) - if ret.get("pricing_rules"): + if ret.get("pricing_rules") and not ret.get("validate_applied_rule", 0): # if user changed the discount percentage then set user's discount percentage ? item.set("pricing_rules", ret.get("pricing_rules")) item.set("discount_percentage", ret.get("discount_percentage")) @@ -546,6 +552,19 @@ class AccountsController(TransactionBase): from erpnext.accounts.utils import reconcile_against_document reconcile_against_document(lst) + def on_cancel(self): + from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries + + if self.doctype in ["Sales Invoice", "Purchase Invoice"]: + if self.is_return: return + + if frappe.db.get_single_value('Accounts Settings', 'unlink_payment_on_cancellation_of_invoice'): + unlink_ref_doc_from_payment_entries(self) + + elif self.doctype in ["Sales Order", "Purchase Order"]: + if frappe.db.get_single_value('Accounts Settings', 'unlink_advance_payment_on_cancelation_of_order'): + unlink_ref_doc_from_payment_entries(self) + def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield): from erpnext.controllers.status_updater import get_tolerance_for item_tolerance = {} diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 388079291f..fed1fdd01f 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -538,6 +538,8 @@ class BuyingController(StockController): update_last_purchase_rate(self, is_submit = 1) def on_cancel(self): + super(BuyingController, self).on_cancel() + if self.get('is_return'): return @@ -736,7 +738,7 @@ def get_subcontracted_raw_materials_from_se(purchase_orders): sed.stock_uom, sed.subcontracted_item as main_item_code, sed.serial_no, sed.batch_no from `tabStock Entry` se,`tabStock Entry Detail` sed where - se.name = sed.parent and se.docstatus=1 and se.purpose='Subcontract' + se.name = sed.parent and se.docstatus=1 and se.purpose='Send to Subcontractor' and se.purchase_order in (%s) and ifnull(sed.t_warehouse, '') != '' group by sed.item_code, sed.t_warehouse """ % (','.join(['%s'] * len(purchase_orders))), tuple(purchase_orders), as_dict=1) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index c1ac407d77..608e8b2225 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -152,7 +152,6 @@ standard_portal_menu_items = [ {"title": _("Issues"), "route": "/issues", "reference_doctype": "Issue", "role":"Customer"}, {"title": _("Addresses"), "route": "/addresses", "reference_doctype": "Address"}, {"title": _("Timesheets"), "route": "/timesheets", "reference_doctype": "Timesheet", "role":"Customer"}, - {"title": _("Timesheets"), "route": "/timesheets", "reference_doctype": "Timesheet", "role":"Customer"}, {"title": _("Lab Test"), "route": "/lab-test", "reference_doctype": "Lab Test", "role":"Patient"}, {"title": _("Prescription"), "route": "/prescription", "reference_doctype": "Patient Encounter", "role":"Patient"}, {"title": _("Patient Appointment"), "route": "/patient-appointments", "reference_doctype": "Patient Appointment", "role":"Patient"}, @@ -241,8 +240,7 @@ scheduler_events = { "erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_mws_settings.schedule_get_order_details", "erpnext.accounts.doctype.gl_entry.gl_entry.rename_gle_sle_docs", "erpnext.projects.doctype.project.project.hourly_reminder", - "erpnext.projects.doctype.project.project.collect_project_status", - "erpnext.support.doctype.issue.issue.update_support_timer", + "erpnext.projects.doctype.project.project.collect_project_status" ], "daily": [ "erpnext.stock.reorder_item.reorder_item", @@ -333,4 +331,4 @@ user_privacy_documents = [ 'match_field': 'contact_email', 'personal_fields': ['contact_mobile', 'contact_display', 'customer_name'], } -] \ No newline at end of file +] diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py index b50b534275..7c47d0e4c9 100755 --- a/erpnext/hr/doctype/leave_application/leave_application.py +++ b/erpnext/hr/doctype/leave_application/leave_application.py @@ -400,6 +400,19 @@ def get_leave_balance_on(employee, leave_type, date, allocation_records=None, do return flt(allocation.total_leaves_allocated) - (flt(leaves_taken) + flt(leaves_encashed)) +def get_total_allocated_leaves(employee, leave_type, date): + filters= { + 'from_date': ['<=', date], + 'to_date': ['>=', date], + 'docstatus': 1, + 'leave_type': leave_type, + 'employee': employee + } + + leave_allocation_records = frappe.db.get_all('Leave Allocation', filters=filters, fields=['total_leaves_allocated']) + + return flt(leave_allocation_records[0]['total_leaves_allocated']) if leave_allocation_records else flt(0) + def get_leaves_for_period(employee, leave_type, from_date, to_date, status, docname=None): leave_applications = frappe.db.sql(""" select name, employee, leave_type, from_date, to_date, total_leave_days diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 3fd266b4bb..eb7cb113fc 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -441,7 +441,7 @@ class SalarySlip(TransactionBase): def calculate_net_pay(self): if self.salary_structure: self.calculate_component_amounts() - + disable_rounded_total = cint(frappe.db.get_value("Global Defaults", None, "disable_rounded_total")) precision = frappe.defaults.get_global_default("currency_precision") self.total_deduction = 0 @@ -452,10 +452,13 @@ class SalarySlip(TransactionBase): self.set_loan_repayment() - self.net_pay = flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment)) + self.net_pay = 0 + if self.total_working_days: + self.net_pay = (flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment))) * flt(self.payment_days / self.total_working_days) + self.rounded_total = rounded(self.net_pay, self.precision("net_pay") if disable_rounded_total else 0) - + if self.net_pay < 0: frappe.throw(_("Net Pay cannnot be negative")) diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py index ed44d639f5..95cb30b791 100644 --- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py +++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py @@ -5,21 +5,21 @@ from __future__ import unicode_literals import frappe from frappe import _ from erpnext.hr.doctype.leave_application.leave_application \ - import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period + import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period, get_total_allocated_leaves def execute(filters=None): leave_types = frappe.db.sql_list("select name from `tabLeave Type` order by name asc") - + columns = get_columns(leave_types) data = get_data(filters, leave_types) - + return columns, data - + def get_columns(leave_types): columns = [ - _("Employee") + ":Link/Employee:150", - _("Employee Name") + "::200", + _("Employee") + ":Link/Employee:150", + _("Employee Name") + "::200", _("Department") +"::150" ] @@ -27,18 +27,18 @@ def get_columns(leave_types): columns.append(_(leave_type) + " " + _("Opening") + ":Float:160") columns.append(_(leave_type) + " " + _("Taken") + ":Float:160") columns.append(_(leave_type) + " " + _("Balance") + ":Float:160") - + return columns - + def get_data(filters, leave_types): user = frappe.session.user allocation_records_based_on_to_date = get_leave_allocation_records(filters.to_date) allocation_records_based_on_from_date = get_leave_allocation_records(filters.from_date) - active_employees = frappe.get_all("Employee", - filters = { "status": "Active", "company": filters.company}, + active_employees = frappe.get_all("Employee", + filters = { "status": "Active", "company": filters.company}, fields = ["name", "employee_name", "department", "user_id"]) - + data = [] for employee in active_employees: leave_approvers = get_approvers(employee.department) @@ -51,8 +51,7 @@ def get_data(filters, leave_types): filters.from_date, filters.to_date) # opening balance - opening = get_leave_balance_on(employee.name, leave_type, filters.from_date, - allocation_records_based_on_from_date.get(employee.name, frappe._dict())) + opening = get_total_allocated_leaves(employee.name, leave_type, filters.to_date) # closing balance closing = get_leave_balance_on(employee.name, leave_type, filters.to_date, @@ -61,7 +60,7 @@ def get_data(filters, leave_types): row += [opening, leaves_taken, closing] data.append(row) - + return data def get_approvers(department): diff --git a/erpnext/hr/report/salary_register/salary_register.py b/erpnext/hr/report/salary_register/salary_register.py index 0c421502f1..586ca67273 100644 --- a/erpnext/hr/report/salary_register/salary_register.py +++ b/erpnext/hr/report/salary_register/salary_register.py @@ -14,11 +14,11 @@ def execute(filters=None): columns, earning_types, ded_types = get_columns(salary_slips) ss_earning_map = get_ss_earning_map(salary_slips) ss_ded_map = get_ss_ded_map(salary_slips) - + doj_map = get_employee_doj_map() data = [] for ss in salary_slips: - row = [ss.name, ss.employee, ss.employee_name, ss.branch, ss.department, ss.designation, + row = [ss.name, ss.employee, ss.employee_name, doj_map.get(ss.employee), ss.branch, ss.department, ss.designation, ss.company, ss.start_date, ss.end_date, ss.leave_without_pay, ss.payment_days] if not ss.branch == None:columns[3] = columns[3].replace('-1','120') @@ -44,17 +44,17 @@ def execute(filters=None): def get_columns(salary_slips): """ columns = [ - _("Salary Slip ID") + ":Link/Salary Slip:150",_("Employee") + ":Link/Employee:120", _("Employee Name") + "::140", _("Branch") + ":Link/Branch:120", - _("Department") + ":Link/Department:120", _("Designation") + ":Link/Designation:120", - _("Company") + ":Link/Company:120", _("Start Date") + "::80", _("End Date") + "::80", _("Leave Without Pay") + ":Float:130", - _("Payment Days") + ":Float:120" + _("Salary Slip ID") + ":Link/Salary Slip:150",_("Employee") + ":Link/Employee:120", _("Employee Name") + "::140", + _("Date of Joining") + "::80", _("Branch") + ":Link/Branch:120", _("Department") + ":Link/Department:120", + _("Designation") + ":Link/Designation:120", _("Company") + ":Link/Company:120", _("Start Date") + "::80", + _("End Date") + "::80", _("Leave Without Pay") + ":Float:130", _("Payment Days") + ":Float:120" ] """ columns = [ - _("Salary Slip ID") + ":Link/Salary Slip:150",_("Employee") + ":Link/Employee:120", _("Employee Name") + "::140", _("Branch") + ":Link/Branch:-1", - _("Department") + ":Link/Department:-1", _("Designation") + ":Link/Designation:-1", - _("Company") + ":Link/Company:120", _("Start Date") + "::80", _("End Date") + "::80", _("Leave Without Pay") + ":Float:-1", - _("Payment Days") + ":Float:120" + _("Salary Slip ID") + ":Link/Salary Slip:150",_("Employee") + ":Link/Employee:120", _("Employee Name") + "::140", + _("Date of Joining") + "::80", _("Branch") + ":Link/Branch:-1", _("Department") + ":Link/Department:-1", + _("Designation") + ":Link/Designation:-1", _("Company") + ":Link/Company:120", _("Start Date") + "::80", + _("End Date") + "::80", _("Leave Without Pay") + ":Float:-1", _("Payment Days") + ":Float:120" ] salary_components = {_("Earning"): [], _("Deduction"): []} @@ -93,6 +93,16 @@ def get_conditions(filters): return conditions, filters +def get_employee_doj_map(): + return frappe._dict(frappe.db.sql(""" + SELECT + employee, + date_of_joining + FROM `tabEmployee` + WHERE + `status`='Active' + """)) + def get_ss_earning_map(salary_slips): ss_earnings = frappe.db.sql("""select parent, salary_component, amount from `tabSalary Detail` where parent in (%s)""" % @@ -115,4 +125,4 @@ def get_ss_ded_map(salary_slips): ss_ded_map.setdefault(d.parent, frappe._dict()).setdefault(d.salary_component, []) ss_ded_map[d.parent][d.salary_component] = flt(d.amount) - return ss_ded_map + return ss_ded_map \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py index 976b24f16a..67930629f5 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.py +++ b/erpnext/manufacturing/doctype/production_order/production_order.py @@ -568,6 +568,7 @@ def make_stock_entry(production_order_id, purpose, qty=None): stock_entry.bom_no = production_order.bom_no stock_entry.use_multi_level_bom = production_order.use_multi_level_bom stock_entry.fg_completed_qty = qty or (flt(production_order.qty) - flt(production_order.produced_qty)) + stock_entry.set_stock_entry_type() if purpose=="Material Transfer for Manufacture": stock_entry.to_warehouse = wip_warehouse diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 694c4d160b..0e8f69145b 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -631,6 +631,7 @@ def make_stock_entry(work_order_id, purpose, qty=None): additional_costs = get_additional_costs(work_order, fg_qty=stock_entry.fg_completed_qty) stock_entry.set("additional_costs", additional_costs) + stock_entry.set_stock_entry_type() stock_entry.get_items() return stock_entry.as_dict() diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 7d54e3f45b..7bdde548e2 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -586,8 +586,12 @@ execute:frappe.delete_doc('DocType', 'Notification Control') erpnext.patches.v12_0.set_gst_category erpnext.patches.v11_0.remove_barcodes_field_from_copy_fields_to_variants erpnext.patches.v12_0.set_task_status -erpnext.patches.v11_0.make_italian_localization_fields # 01-03-2019 +erpnext.patches.v11_0.make_italian_localization_fields # 26-03-2019 erpnext.patches.v12_0.add_item_name_in_work_orders erpnext.patches.v12_0.update_pricing_rule_fields erpnext.patches.v11_1.make_job_card_time_logs -erpnext.patches.v12_0.rename_pricing_rule_child_doctypes \ No newline at end of file +erpnext.patches.v12_0.rename_pricing_rule_child_doctypes +erpnext.patches.v12_0.move_target_distribution_from_parent_to_child +erpnext.patches.v12_0.stock_entry_enhancements +erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019 +erpnext.patches.v12_0.move_item_tax_to_item_tax_template diff --git a/erpnext/patches/v11_0/make_italian_localization_fields.py b/erpnext/patches/v11_0/make_italian_localization_fields.py index d9a7b35e77..29d25c9a2d 100644 --- a/erpnext/patches/v11_0/make_italian_localization_fields.py +++ b/erpnext/patches/v11_0/make_italian_localization_fields.py @@ -6,7 +6,6 @@ from erpnext.regional.italy.setup import make_custom_fields, setup_report from erpnext.regional.italy import state_codes import frappe - def execute(): company = frappe.get_all('Company', filters = {'country': 'Italy'}) if not company: @@ -27,4 +26,12 @@ def execute(): frappe.db.sql(""" UPDATE tabAddress set {condition} country_code = UPPER(ifnull((select code from `tabCountry` where name = `tabAddress`.country), '')) + where country_code is null and state_code is null """.format(condition=condition)) + + frappe.db.sql(""" + UPDATE `tabSales Invoice Item` si, `tabSales Order` so + set si.customer_po_no = so.po_no, si.customer_po_date = so.po_date + WHERE + si.sales_order = so.name and so.po_no is not null + """) diff --git a/erpnext/patches/v11_0/update_backflush_subcontract_rm_based_on_bom.py b/erpnext/patches/v11_0/update_backflush_subcontract_rm_based_on_bom.py index f71d9b43cf..f2eeadac60 100644 --- a/erpnext/patches/v11_0/update_backflush_subcontract_rm_based_on_bom.py +++ b/erpnext/patches/v11_0/update_backflush_subcontract_rm_based_on_bom.py @@ -7,13 +7,13 @@ import frappe def execute(): frappe.reload_doc('buying', 'doctype', 'buying_settings') frappe.db.set_value('Buying Settings', None, 'backflush_raw_materials_of_subcontract_based_on', 'BOM') - + frappe.reload_doc('stock', 'doctype', 'stock_entry_detail') - frappe.db.sql(""" update `tabStock Entry Detail` as sed, + frappe.db.sql(""" update `tabStock Entry Detail` as sed, `tabStock Entry` as se, `tabPurchase Order Item Supplied` as pois set sed.subcontracted_item = pois.main_item_code where - se.purpose = 'Subcontract' and sed.parent = se.name + se.purpose = 'Send to Subcontractor' and sed.parent = se.name and pois.rm_item_code = sed.item_code and se.docstatus = 1 and pois.parenttype = 'Purchase Order'""") \ No newline at end of file diff --git a/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py index 68db59193c..575ebebadb 100644 --- a/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py +++ b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py @@ -3,6 +3,8 @@ import json from six import iteritems def execute(): + if "tax_type" not in frappe.db.get_table_columns("Item Tax"): + return old_item_taxes = {} item_tax_templates = {} rename_template_to_untitled = [] @@ -40,7 +42,7 @@ def execute(): item.set("taxes", []) item.append("taxes", {"item_tax_template": item_tax_template_name, "tax_category": ""}) item.save() - + doctypes = [ 'Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice', 'Supplier Quotation', 'Purchase Order', 'Purchase Receipt', 'Purchase Invoice' diff --git a/erpnext/patches/v12_0/move_target_distribution_from_parent_to_child.py b/erpnext/patches/v12_0/move_target_distribution_from_parent_to_child.py new file mode 100644 index 0000000000..548c1a4717 --- /dev/null +++ b/erpnext/patches/v12_0/move_target_distribution_from_parent_to_child.py @@ -0,0 +1,22 @@ +# Copyright (c) 2017, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doc("setup", "doctype", "target_detail") + + for d in ['Sales Person', 'Sales Partner', 'Territory']: + frappe.db.sql(""" + UPDATE `tab{child_doc}`, `tab{parent_doc}` + SET + `tab{child_doc}`.distribution_id = `tab{parent_doc}`.distribution_id + WHERE + `tab{child_doc}`.parent = `tab{parent_doc}`.name + and `tab{parent_doc}`.distribution_id is not null and `tab{parent_doc}`.distribution_id != '' + """.format(parent_doc = d, child_doc = "Target Detail")) + + frappe.delete_doc("Report", "Sales Partner-wise Transaction Summary") + frappe.delete_doc("Report", "Sales Person Target Variance Item Group-Wise") + frappe.delete_doc("Report", "Territory Target Variance Item Group-Wise") \ No newline at end of file diff --git a/erpnext/patches/v12_0/stock_entry_enhancements.py b/erpnext/patches/v12_0/stock_entry_enhancements.py new file mode 100644 index 0000000000..d04b3d3862 --- /dev/null +++ b/erpnext/patches/v12_0/stock_entry_enhancements.py @@ -0,0 +1,52 @@ +# 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 +from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + +def execute(): + create_stock_entry_types() + + company = frappe.db.get_value("Company", {'country': 'India'}, 'name') + if company: + add_gst_hsn_code_field() + +def create_stock_entry_types(): + frappe.reload_doc('stock', 'doctype', 'stock_entry_type') + frappe.reload_doc('stock', 'doctype', 'stock_entry') + + for purpose in ["Material Issue", "Material Receipt", "Material Transfer", + "Material Transfer for Manufacture", "Material Consumption for Manufacture", "Manufacture", + "Repack", "Send to Subcontractor", "Send to Warehouse", "Receive at Warehouse"]: + + ste_type = frappe.get_doc({ + 'doctype': 'Stock Entry Type', + 'name': purpose, + 'purpose': purpose + }) + + try: + ste_type.insert() + except frappe.DuplicateEntryError: + pass + + frappe.db.sql(" UPDATE `tabStock Entry` set purpose = 'Send to Subcontractor' where purpose = 'Subcontract'") + frappe.db.sql(" UPDATE `tabStock Entry` set stock_entry_type = purpose ") + +def add_gst_hsn_code_field(): + custom_fields = { + 'Stock Entry Detail': [dict(fieldname='gst_hsn_code', label='HSN/SAC', + fieldtype='Data', fetch_from='item_code.gst_hsn_code', + insert_after='description', allow_on_submit=1, print_hide=0)] + } + + create_custom_fields(custom_fields, ignore_validate = frappe.flags.in_patch, update=True) + + frappe.db.sql(""" update `tabStock Entry Detail`, `tabItem` + SET + `tabStock Entry Detail`.gst_hsn_code = `tabItem`.gst_hsn_code + Where + `tabItem`.name = `tabStock Entry Detail`.item_code and `tabItem`.gst_hsn_code is not null + """) \ No newline at end of file diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 845d3a02c4..2686e58294 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -165,6 +165,13 @@ class Task(NestedSet): self.update_nsm_model() + def update_status(self): + if self.status not in ('Cancelled', 'Completed') and self.exp_end_date: + from datetime import datetime + if self.exp_end_date < datetime.now().date(): + self.db_set('status', 'Overdue') + self.update_project() + @frappe.whitelist() def check_if_child_exists(name): child_tasks = frappe.get_all("Task", filters={"parent_task": name}) @@ -196,10 +203,9 @@ def set_multiple_status(names, status): task.save() def set_tasks_as_overdue(): - frappe.db.sql("""update tabTask set `status`='Overdue' - where exp_end_date is not null - and exp_end_date < CURDATE() - and `status` not in ('Completed', 'Cancelled')""") + tasks = frappe.get_all("Task", filters={'status':['not in',['Cancelled', 'Completed']]}) + for task in tasks: + frappe.get_doc("Task", task.name).update_status() @frappe.whitelist() def get_children(doctype, parent, task=None, project=None, is_root=False): diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js index 375731517d..101d903bed 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.js +++ b/erpnext/projects/doctype/timesheet/timesheet.js @@ -10,8 +10,8 @@ frappe.ui.form.on("Timesheet", { filters:{ 'status': 'Active' } - } - } + }; + }; frm.fields_dict['time_logs'].grid.get_field('task').get_query = function(frm, cdt, cdn) { var child = locals[cdt][cdn]; @@ -20,22 +20,26 @@ frappe.ui.form.on("Timesheet", { 'project': child.project, 'status': ["!=", "Cancelled"] } - } - } + }; + }; frm.fields_dict['time_logs'].grid.get_field('project').get_query = function() { return{ filters: { 'company': frm.doc.company } - } - } + }; + }; }, onload: function(frm){ if (frm.doc.__islocal && frm.doc.time_logs) { calculate_time_and_amount(frm); } + + if (frm.is_new()) { + set_employee_and_company(frm); + } }, refresh: function(frm) { @@ -58,7 +62,7 @@ frappe.ui.form.on("Timesheet", { if ((row.from_time <= frappe.datetime.now_datetime()) && !row.completed) { button = 'Resume Timer'; } - }) + }); frm.add_custom_button(__(button), function() { var flag = true; @@ -77,7 +81,7 @@ frappe.ui.form.on("Timesheet", { erpnext.timesheet.timer(frm, row, timestamp); flag = false; } - }) + }); // If no activities found to start a timer, create new if (flag) { erpnext.timesheet.timer(frm); @@ -94,7 +98,7 @@ frappe.ui.form.on("Timesheet", { frappe.db.get_value('Company', { 'company_name' : frm.doc.company }, 'standard_working_hours') .then(({ message }) => { (frappe.working_hours = message.standard_working_hours || 0); - }); + }); }, make_invoice: function(frm) { @@ -125,8 +129,8 @@ frappe.ui.form.on("Timesheet", { frappe.set_route("Form", r.message.doctype, r.message.name); } } - }) - }) + }); + }); dialog.show(); }, @@ -136,7 +140,7 @@ frappe.ui.form.on("Timesheet", { frm: frm }); }, -}) +}); frappe.ui.form.on("Timesheet Detail", { time_logs_remove: function(frm) { @@ -171,22 +175,22 @@ frappe.ui.form.on("Timesheet Detail", { .find('[data-fieldname="timer"]') .append(frappe.render_template("timesheet")); frm.trigger("control_timer"); - }) + }); }, hours: function(frm, cdt, cdn) { - calculate_end_time(frm, cdt, cdn) + calculate_end_time(frm, cdt, cdn); }, billing_hours: function(frm, cdt, cdn) { - calculate_billing_costing_amount(frm, cdt, cdn) + calculate_billing_costing_amount(frm, cdt, cdn); }, billing_rate: function(frm, cdt, cdn) { - calculate_billing_costing_amount(frm, cdt, cdn) + calculate_billing_costing_amount(frm, cdt, cdn); }, costing_rate: function(frm, cdt, cdn) { - calculate_billing_costing_amount(frm, cdt, cdn) + calculate_billing_costing_amount(frm, cdt, cdn); }, billable: function(frm, cdt, cdn) { @@ -212,7 +216,7 @@ frappe.ui.form.on("Timesheet Detail", { calculate_billing_costing_amount(frm, cdt, cdn); } } - }) + }); } }); @@ -240,23 +244,23 @@ var calculate_end_time = function(frm, cdt, cdn) { frm._setting_hours = true; frappe.model.set_value(cdt, cdn, "to_time", d.format(frappe.defaultDatetimeFormat)).then(() => { - frm._setting_hours = false; - }); + frm._setting_hours = false; + }); } } -} +}; var update_billing_hours = function(frm, cdt, cdn){ var child = locals[cdt][cdn]; if(!child.billable) frappe.model.set_value(cdt, cdn, 'billing_hours', 0.0); -} +}; var update_time_rates = function(frm, cdt, cdn){ var child = locals[cdt][cdn]; if(!child.billable){ frappe.model.set_value(cdt, cdn, 'billing_rate', 0.0); } -} +}; var calculate_billing_costing_amount = function(frm, cdt, cdn){ var child = locals[cdt][cdn]; @@ -270,7 +274,7 @@ var calculate_billing_costing_amount = function(frm, cdt, cdn){ frappe.model.set_value(cdt, cdn, 'billing_amount', billing_amount); frappe.model.set_value(cdt, cdn, 'costing_amount', costing_amount); calculate_time_and_amount(frm); -} +}; var calculate_time_and_amount = function(frm) { var tl = frm.doc.time_logs || []; @@ -294,4 +298,17 @@ var calculate_time_and_amount = function(frm) { frm.set_value("total_hours", total_working_hr); frm.set_value("total_billable_amount", total_billable_amount); frm.set_value("total_costing_amount", total_costing_amount); -} \ No newline at end of file +}; + +// set employee (and company) to the one that's currently logged in +const set_employee_and_company = function(frm) { + const options = { user_id: frappe.session.user }; + const fields = ['name', 'company']; + frappe.db.get_value('Employee', options, fields).then(({ message }) => { + if (message) { + // there is an employee with the currently logged in user_id + frm.set_value("employee", message.name); + frm.set_value("company", message.company); + } + }); +}; diff --git a/erpnext/public/.gitignore b/erpnext/public/.gitignore new file mode 100644 index 0000000000..3c3629e647 --- /dev/null +++ b/erpnext/public/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index f64791325e..1bfcd6f47c 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -158,6 +158,12 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ }; }); } + + if(frappe.meta.get_docfield(this.frm.doc.doctype, "pricing_rules")) { + this.frm.set_indicator_formatter('pricing_rule', function(doc) { + return (doc.rule_applied) ? "green" : "red"; + }); + } }, onload: function() { var me = this; @@ -422,6 +428,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ method: "erpnext.stock.get_item_details.get_item_details", child: item, args: { + doc: me.frm.doc, args: { item_code: item.item_code, barcode: item.barcode, @@ -456,7 +463,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ cost_center: item.cost_center, tax_category: me.frm.doc.tax_category, item_tax_template: item.item_tax_template, - child_docname: item.name + child_docname: item.name, } }, @@ -482,7 +489,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ } }, () => me.conversion_factor(doc, cdt, cdn, true), - () => me.update_free_items(item) + () => me.validate_pricing_rule(item) ]); } } @@ -1116,7 +1123,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ callback: function(r) { if (!r.exc && r.message) { r.message.forEach(row_item => { - me.update_free_items(row_item); + me.validate_pricing_rule(row_item); }); me._set_values_for_item_list(r.message); me.calculate_taxes_and_totals(); @@ -1139,14 +1146,12 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ return this.frm.call({ method: "erpnext.accounts.doctype.pricing_rule.pricing_rule.apply_pricing_rule", - args: { args: args }, + args: { args: args, doc: me.frm.doc }, callback: function(r) { if (!r.exc && r.message) { me._set_values_for_item_list(r.message); if(item) me.set_gross_profit(item); - if(calculate_taxes_and_totals) me.calculate_taxes_and_totals(); if(me.frm.doc.apply_discount_on) me.frm.trigger("apply_discount_on") - me.update_free_items(item); } } }); @@ -1200,7 +1205,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ "warehouse": d.warehouse, "serial_no": d.serial_no, "price_list_rate": d.price_list_rate, - "discount_percentage": d.discount_percentage || 0.0, "conversion_factor": d.conversion_factor || 1.0 }); @@ -1241,6 +1245,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ // if pricing rule set as blank from an existing value, apply price_list if(!me.frm.doc.ignore_pricing_rule && existing_pricing_rule && !d.pricing_rules) { me.apply_price_list(frappe.get_doc(d.doctype, d.name)); + } else { + me.validate_pricing_rule(frappe.get_doc(d.doctype, d.name)); } } @@ -1288,41 +1294,29 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ }); }, - update_free_items: function(item) { - var me = this; + validate_pricing_rule: function(item) { + let me = this; + const fields = ["discount_percentage", "discount_amount", "pricing_rules"]; if (item.pricing_rules) { frappe.call({ - method: "erpnext.accounts.doctype.pricing_rule.pricing_rule.get_free_items", + method: "erpnext.accounts.doctype.pricing_rule.utils.validate_pricing_rule_for_different_cond", args: { - pricing_rules: item.pricing_rules, - item_row: item + doc: me.frm.doc }, callback: function(r) { - let items = []; - let child = ''; - - me.frm.doc.items.map(d => { - items[d.item_code] = d; - }); - - if(r.message && r.message.length) { - r.message.forEach(d => { - // If free item is already exists - - if(d.item_code in items && - d.is_free_item && items[d.item_code].is_free_item) { - child = items[d.item_code]; - } else { - child = frappe.model.add_child(me.frm.doc, item.doctype, "items"); - } - - $.each(d, function(k, v) { - child[k] = v; + if (r.message) { + r.message.items.forEach(d => { + me.frm.doc.items.forEach(row => { + if(d.name == row.name) { + fields.forEach(f => { + row[f] = d[f]; + }); + } }); - - me.frm.script_manager.trigger("price_list_rate", child.doctype, child.name); }); + + me.trigger_price_list_rate(); } } }); @@ -1337,9 +1331,29 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ me.frm.doc.items = items; refresh_field('items'); + } else if(item.applied_on_items && item.apply_on) { + const applied_on_items = item.applied_on_items.split(','); + me.frm.doc.items.forEach(row => { + if(applied_on_items.includes(row[item.apply_on])) { + fields.forEach(f => { + row[f] = 0; + }); + } + }); + + me.trigger_price_list_rate(); } }, + trigger_price_list_rate: function() { + var me = this; + + this.frm.doc.items.forEach(child_row => { + me.frm.script_manager.trigger("price_list_rate", + child_row.doctype, child_row.name); + }) + }, + validate_company_and_party: function() { var me = this; var valid = true; @@ -1379,7 +1393,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ }, callback: function(r) { if(!r.exc) { - me.frm.set_value("taxes", r.message); + for (let tax of r.message) { + me.frm.add_child("taxes", tax); + } me.calculate_taxes_and_totals(); } } diff --git a/erpnext/public/js/hub/components/DetailView.vue b/erpnext/public/js/hub/components/DetailView.vue index cc0998212a..942c1ebdb3 100644 --- a/erpnext/public/js/hub/components/DetailView.vue +++ b/erpnext/public/js/hub/components/DetailView.vue @@ -31,7 +31,7 @@ -
+

{{ title }}

diff --git a/erpnext/public/node_modules b/erpnext/public/node_modules deleted file mode 120000 index 903b09c1de..0000000000 --- a/erpnext/public/node_modules +++ /dev/null @@ -1 +0,0 @@ -/Users/netchampfaris/frappe-bench/apps/erpnext/node_modules \ No newline at end of file diff --git a/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py index 2e9f53685e..d50eaebefc 100644 --- a/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py +++ b/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe import unittest +from frappe.utils import getdate from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice from erpnext.stock.doctype.item.test_item import make_item @@ -12,10 +13,27 @@ import json class TestGSTR3BReport(unittest.TestCase): def test_gstr_3b_report(self): + + month_number_mapping = { + 1: "January", + 2: "February", + 3: "March", + 4: "April", + 5: "May", + 6: "June", + 7: "July", + 8: "August", + 9: "September", + 10: "October", + 11: "November", + 12: "December" + } + frappe.set_user("Administrator") frappe.db.sql("delete from `tabSales Invoice` where company='_Test Company GST'") frappe.db.sql("delete from `tabPurchase Invoice` where company='_Test Company GST'") + frappe.db.sql("delete from `tabGSTR 3B Report` where company='_Test Company GST'") make_company() make_item("Milk", properties = {"is_nil_exempt": 1, "standard_rate": 0.000000}) @@ -33,8 +51,8 @@ class TestGSTR3BReport(unittest.TestCase): "doctype": "GSTR 3B Report", "company": "_Test Company GST", "company_address": "_Test Address-Billing", - "year": "2019", - "month": "March" + "year": getdate().year, + "month": month_number_mapping.get(getdate().month) }).insert() output = json.loads(report.json_output) @@ -55,7 +73,6 @@ def make_sales_invoice(): income_account = 'Sales - _GST', expense_account = 'Cost of Goods Sold - _GST', cost_center = 'Main - _GST', - posting_date = '2019-03-10', do_not_save=1 ) @@ -77,7 +94,6 @@ def make_sales_invoice(): income_account = 'Sales - _GST', expense_account = 'Cost of Goods Sold - _GST', cost_center = 'Main - _GST', - posting_date = '2019-03-10', do_not_save=1 ) @@ -99,7 +115,6 @@ def make_sales_invoice(): income_account = 'Sales - _GST', expense_account = 'Cost of Goods Sold - _GST', cost_center = 'Main - _GST', - posting_date = '2019-03-10', do_not_save=1 ) @@ -122,7 +137,6 @@ def make_sales_invoice(): income_account = 'Sales - _GST', expense_account = 'Cost of Goods Sold - _GST', cost_center = 'Main - _GST', - posting_date = '2019-03-10', do_not_save=1 ) si3.submit() @@ -135,7 +149,6 @@ def create_purchase_invoices(): currency = 'INR', warehouse = 'Finished Goods - _GST', cost_center = 'Main - _GST', - posting_date = '2019-03-10', do_not_save=1, ) @@ -157,7 +170,6 @@ def create_purchase_invoices(): currency = 'INR', warehouse = 'Finished Goods - _GST', cost_center = 'Main - _GST', - posting_date = '2019-03-10', item = "Milk", do_not_save=1 ) diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index f7057aa846..bad99ba3af 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -265,6 +265,7 @@ def make_custom_fields(update=True): 'Purchase Order Item': [hsn_sac_field, nil_rated_exempt, is_non_gst], 'Purchase Receipt Item': [hsn_sac_field, nil_rated_exempt, is_non_gst], 'Purchase Invoice Item': [hsn_sac_field, nil_rated_exempt, is_non_gst], + 'Material Request Item': [hsn_sac_field, nil_rated_exempt, is_non_gst], 'Employee': [ dict(fieldname='ifsc_code', label='IFSC Code', fieldtype='Data', insert_after='bank_ac_no', print_hide=1, diff --git a/erpnext/regional/italy/e-invoice.xml b/erpnext/regional/italy/e-invoice.xml index c886ee9aa8..935077b7be 100644 --- a/erpnext/regional/italy/e-invoice.xml +++ b/erpnext/regional/italy/e-invoice.xml @@ -95,13 +95,12 @@ {{ doc.customer_data.last_name }} {%- else %} - {%- if doc.customer_data.is_public_administration %} - {{ doc.customer_data.fiscal_code }} - {%- else %} {{ doc.customer_address_data.country_code }} {{ doc.tax_id | replace("IT","") }} + {%- if doc.customer_data.fiscal_code %} + {{ doc.customer_data.fiscal_code }} {%- endif %} {{ doc.customer_name }} @@ -128,22 +127,42 @@ {{ format_float(doc.stamp_duty) }} {%- endif %} - {{ format_float(doc.grand_total) }} + {%- if doc.discount_amount %} + + {%- if doc.discount_amount > 0.0 %} + SC + {%- else %} + MG + {%- endif %} + {%- if doc.additional_discount_percentage > 0.0 %} + {{ format_float(doc.additional_discount_percentage) }} + {%- endif %} + {{ format_float(doc.discount_amount) }} + + {%- endif %} + {{ format_float(doc.rounded_total or doc.grand_total) }} VENDITA - {%- if doc.po_no %} - - {{ doc.po_no }} - {%- if doc.po_date %} - {{ doc.po_date }} - {%- endif %} - - {%- endif %} + {%- for po_no, po_date in doc.customer_po_data.items() %} + + {{ po_no }} + {{ po_date }} + + {%- endfor %} {%- if doc.is_return and doc.return_against_unamended %} {{ doc.return_against_unamended }} {%- endif %} + {%- for row in doc.e_invoice_items %} + {%- if row.delivery_note %} + + {{ row.delivery_note }} + {{ frappe.db.get_value('Delivery Note', row.delivery_note, 'posting_date') }} + {{ row.idx }} + + {%- endif %} + {%- endfor %} {%- if doc.shipping_address_data %} @@ -165,7 +184,11 @@ {{ item.stock_uom }} {{ format_float(item.price_list_rate or item.rate) }} {{ render_discount_or_margin(item) }} - {{ format_float(item.amount) }} + {%- if (item.discount_amount or item.rate_with_margin) %} + {{ format_float(item.net_amount) }} + {%- else %} + {{ format_float(item.amount) }} + {%- endif %} {{ format_float(item.tax_rate) }} {%- if item.tax_exemption_reason %} {{ item.tax_exemption_reason.split("-")[0] }} @@ -199,7 +222,9 @@ {{ payment_term.mode_of_payment_code.split("-")[0] }} {{ payment_term.due_date }} {{ format_float(payment_term.payment_amount) }} - {{ payment_term.bank_account_name }} + {%- if payment_term.bank_account_name %} + {{ payment_term.bank_account_name }} + {%- endif %} {%- if payment_term.bank_account_iban %} {{ payment_term.bank_account_iban }} {{ payment_term.bank_account_iban[5:10] }} diff --git a/erpnext/regional/italy/sales_invoice.js b/erpnext/regional/italy/sales_invoice.js index 3457f7161e..586a52937b 100644 --- a/erpnext/regional/italy/sales_invoice.js +++ b/erpnext/regional/italy/sales_invoice.js @@ -3,15 +3,26 @@ erpnext.setup_e_invoice_button = (doctype) => { refresh: (frm) => { if(frm.doc.docstatus == 1) { frm.add_custom_button('Generate E-Invoice', () => { - var w = window.open( - frappe.urllib.get_full_url( - "/api/method/erpnext.regional.italy.utils.generate_single_invoice?" - + "docname=" + frm.doc.name - ) - ) - if (!w) { - frappe.msgprint(__("Please enable pop-ups")); return; - } + frm.call({ + method: "erpnext.regional.italy.utils.generate_single_invoice", + args: { + docname: frm.doc.name + }, + callback: function(r) { + frm.reload_doc(); + if(r.message) { + var w = window.open( + frappe.urllib.get_full_url( + "/api/method/erpnext.regional.italy.utils.download_e_invoice_file?" + + "file_name=" + r.message + ) + ) + if (!w) { + frappe.msgprint(__("Please enable pop-ups")); return; + } + } + } + }); }); } } diff --git a/erpnext/regional/italy/setup.py b/erpnext/regional/italy/setup.py index 2b6e3af52a..1526d6f62f 100644 --- a/erpnext/regional/italy/setup.py +++ b/erpnext/regional/italy/setup.py @@ -26,6 +26,22 @@ def make_custom_fields(update=True): print_hide=1, hidden=1, read_only=1, options="currency") ] + customer_po_fields = [ + dict(fieldname='customer_po_details', label='Customer PO', + fieldtype='Section Break', insert_after='image'), + dict(fieldname='customer_po_no', label='Customer PO No', + fieldtype='Data', insert_after='customer_po_details', + fetch_from = 'sales_order.po_no', + print_hide=1, allow_on_submit=1, fetch_if_empty= 1, read_only=1, no_copy=1), + dict(fieldname='customer_po_clm_brk', label='', + fieldtype='Column Break', insert_after='customer_po_no', + print_hide=1, read_only=1), + dict(fieldname='customer_po_date', label='Customer PO Date', + fieldtype='Date', insert_after='customer_po_clm_brk', + fetch_from = 'sales_order.po_date', + print_hide=1, allow_on_submit=1, fetch_if_empty= 1, read_only=1, no_copy=1) + ] + custom_fields = { 'Company': [ dict(fieldname='sb_e_invoicing', label='E-Invoicing', @@ -128,7 +144,7 @@ def make_custom_fields(update=True): 'Purchase Invoice Item': invoice_item_fields, 'Sales Order Item': invoice_item_fields, 'Delivery Note Item': invoice_item_fields, - 'Sales Invoice Item': invoice_item_fields, + 'Sales Invoice Item': invoice_item_fields + customer_po_fields, 'Quotation Item': invoice_item_fields, 'Purchase Order Item': invoice_item_fields, 'Purchase Receipt Item': invoice_item_fields, diff --git a/erpnext/regional/italy/utils.py b/erpnext/regional/italy/utils.py index 52a5ddcfd9..876bdcf459 100644 --- a/erpnext/regional/italy/utils.py +++ b/erpnext/regional/italy/utils.py @@ -5,6 +5,7 @@ from frappe.utils import flt, cstr from erpnext.controllers.taxes_and_totals import get_itemised_tax from frappe import _ from frappe.core.doctype.file.file import remove_file +from six import string_types from frappe.desk.form.load import get_attachments from erpnext.regional.italy import state_codes @@ -82,6 +83,14 @@ def prepare_invoice(invoice, progressive_number): if item.tax_rate == 0.0 and item.tax_amount == 0.0: item.tax_exemption_reason = tax_data["0.0"]["tax_exemption_reason"] + customer_po_data = {} + for d in invoice.e_invoice_items: + if (d.customer_po_no and d.customer_po_date + and d.customer_po_no not in customer_po_data): + customer_po_data[d.customer_po_no] = d.customer_po_date + + invoice.customer_po_data = customer_po_data + return invoice def get_conditions(filters): @@ -134,6 +143,7 @@ def get_invoice_summary(items, taxes): idx=len(items)+1, item_code=reference_row.description, item_name=reference_row.description, + description=reference_row.description, rate=reference_row.tax_amount, qty=1.0, amount=reference_row.tax_amount, @@ -142,7 +152,7 @@ def get_invoice_summary(items, taxes): tax_amount=(reference_row.tax_amount * tax.rate) / 100, net_amount=reference_row.tax_amount, taxable_amount=reference_row.tax_amount, - item_tax_rate="{}", + item_tax_rate={tax.account_head: tax.rate}, charges=True ) ) @@ -150,10 +160,16 @@ def get_invoice_summary(items, taxes): #Check item tax rates if tax rate is zero. if tax.rate == 0: for item in items: - item_tax_rate = json.loads(item.item_tax_rate) - if tax.account_head in item_tax_rate: + item_tax_rate = item.item_tax_rate + if isinstance(item.item_tax_rate, string_types): + item_tax_rate = json.loads(item.item_tax_rate) + + if item_tax_rate and tax.account_head in item_tax_rate: key = cstr(item_tax_rate[tax.account_head]) - summary_data.setdefault(key, {"tax_amount": 0.0, "taxable_amount": 0.0, "tax_exemption_reason": "", "tax_exemption_law": ""}) + if key not in summary_data: + summary_data.setdefault(key, {"tax_amount": 0.0, "taxable_amount": 0.0, + "tax_exemption_reason": "", "tax_exemption_law": ""}) + summary_data[key]["tax_amount"] += item.tax_amount summary_data[key]["taxable_amount"] += item.net_amount if key == "0.0": @@ -198,19 +214,25 @@ def sales_invoice_validate(doc): else: doc.company_fiscal_regime = company_fiscal_regime + doc.company_tax_id = frappe.get_cached_value("Company", doc.company, 'tax_id') + doc.company_fiscal_code = frappe.get_cached_value("Company", doc.company, 'fiscal_code') if not doc.company_tax_id and not doc.company_fiscal_code: frappe.throw(_("Please set either the Tax ID or Fiscal Code on Company '%s'" % doc.company), title=_("E-Invoicing Information Missing")) #Validate customer details - customer_type, is_public_administration = frappe.db.get_value("Customer", doc.customer, ["customer_type", "is_public_administration"]) - if customer_type == _("Individual"): + customer = frappe.get_doc("Customer", doc.customer) + + if customer.customer_type == _("Individual"): + doc.customer_fiscal_code = customer.fiscal_code if not doc.customer_fiscal_code: frappe.throw(_("Please set Fiscal Code for the customer '%s'" % doc.customer), title=_("E-Invoicing Information Missing")) else: - if is_public_administration: + if customer.is_public_administration: + doc.customer_fiscal_code = customer.fiscal_code if not doc.customer_fiscal_code: frappe.throw(_("Please set Fiscal Code for the public administration '%s'" % doc.customer), title=_("E-Invoicing Information Missing")) else: + doc.tax_id = customer.tax_id if not doc.tax_id: frappe.throw(_("Please set Tax ID for the customer '%s'" % doc.customer), title=_("E-Invoicing Information Missing")) @@ -276,13 +298,18 @@ def prepare_and_attach_invoice(doc, replace=False): def generate_single_invoice(docname): doc = frappe.get_doc("Sales Invoice", docname) + e_invoice = prepare_and_attach_invoice(doc, True) + return e_invoice.file_name + +@frappe.whitelist() +def download_e_invoice_file(file_name): content = None - with open(frappe.get_site_path('private', 'files', e_invoice.file_name), "r") as f: + with open(frappe.get_site_path('private', 'files', file_name), "r") as f: content = f.read() - frappe.local.response.filename = e_invoice.file_name + frappe.local.response.filename = file_name frappe.local.response.filecontent = content frappe.local.response.type = "download" diff --git a/erpnext/regional/report/gstr_1/gstr_1.js b/erpnext/regional/report/gstr_1/gstr_1.js index 9246aa6724..9682768280 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.js +++ b/erpnext/regional/report/gstr_1/gstr_1.js @@ -4,7 +4,7 @@ frappe.query_reports["GSTR-1"] = { "filters": [ { - "fieldname":"company", + "fieldname": "company", "label": __("Company"), "fieldtype": "Link", "options": "Company", @@ -12,22 +12,22 @@ frappe.query_reports["GSTR-1"] = { "default": frappe.defaults.get_user_default("Company") }, { - "fieldname":"company_address", + "fieldname": "company_address", "label": __("Address"), "fieldtype": "Link", "options": "Address", - "get_query": function() { + "get_query": function () { var company = frappe.query_report.get_filter_value('company'); if (company) { return { "query": 'frappe.contacts.doctype.address.address.address_query', - "filters": { link_doctype: 'Company', link_name: company} + "filters": { link_doctype: 'Company', link_name: company } }; } } }, { - "fieldname":"from_date", + "fieldname": "from_date", "label": __("From Date"), "fieldtype": "Date", "reqd": 1, @@ -35,19 +35,34 @@ frappe.query_reports["GSTR-1"] = { "width": "80" }, { - "fieldname":"to_date", + "fieldname": "to_date", "label": __("To Date"), "fieldtype": "Date", "reqd": 1, "default": frappe.datetime.get_today() }, { - "fieldname":"type_of_business", + "fieldname": "type_of_business", "label": __("Type of Business"), "fieldtype": "Select", "reqd": 1, - "options": ["B2B", "B2C Large", "B2C Small","CDNR", "EXPORT"], + "options": ["B2B", "B2C Large", "B2C Small", "CDNR", "EXPORT"], "default": "B2B" } - ] + ], + onload: function (report) { + + report.page.add_inner_button(__("Download as Json"), function () { + var filters = report.get_values(); + + const args = { + cmd: 'erpnext.regional.report.gstr_1.gstr_1.get_json', + data: report.data, + report_name: report.report_name, + filters: filters + }; + + open_url_post(frappe.request.url, args); + }); + } } diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index b01abce3cd..24bd6cf11c 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -4,9 +4,10 @@ from __future__ import unicode_literals import frappe, json from frappe import _ -from frappe.utils import flt, formatdate +from frappe.utils import flt, formatdate, now_datetime, getdate from datetime import date from six import iteritems +from erpnext.regional.doctype.gstr_3b_report.gstr_3b_report import get_period def execute(filters=None): return Gstr1Report(filters).run() @@ -38,7 +39,7 @@ class Gstr1Report(object): shipping_bill_date, reason_for_issuing_document """ - self.customer_type = "Company" if self.filters.get("type_of_business") == "B2B" else "Individual" + # self.customer_type = "Company" if self.filters.get("type_of_business") == "B2B" else "Individual" def run(self): self.get_columns() @@ -113,9 +114,14 @@ class Gstr1Report(object): if self.filters.get(opts[0]): conditions += opts[1] - customers = frappe.get_all("Customer", filters={"customer_type": self.customer_type}) + # customers = frappe.get_all("Customer", filters={"customer_type": self.customer_type}) if self.filters.get("type_of_business") == "B2B": + customers = frappe.get_all("Customer", + filters={ + "gst_category": ["in", ["Registered Regular", "Deemed Export", "SEZ"]] + }) + conditions += """ and ifnull(gst_category, '') != 'Overseas' and is_return != 1 and customer in ({0})""".format(", ".join([frappe.db.escape(c.name) for c in customers])) @@ -124,6 +130,11 @@ class Gstr1Report(object): if not b2c_limit: frappe.throw(_("Please set B2C Limit in GST Settings.")) + customers = frappe.get_all("Customer", + filters={ + "gst_category": ["in", ["Unregistered"]] + }) + if self.filters.get("type_of_business") == "B2C Large": conditions += """ and SUBSTR(place_of_supply, 1, 2) != SUBSTR(company_gstin, 1, 2) and grand_total > {0} and is_return != 1 and customer in ({1})""".\ @@ -494,3 +505,158 @@ class Gstr1Report(object): } ] self.columns = self.invoice_columns + self.tax_columns + self.other_columns + +@frappe.whitelist() +def get_json(): + data = frappe._dict(frappe.local.form_dict) + + del data["cmd"] + if "csrf_token" in data: + del data["csrf_token"] + + filters = json.loads(data["filters"]) + report_data = json.loads(data["data"]) + report_name = data["report_name"] + gstin = get_company_gstin_number(filters["company"]) + + fp = "%02d%s" % (getdate(filters["to_date"]).month, getdate(filters["to_date"]).year) + + gst_json = {"gstin": "", "version": "GST2.2.9", + "hash": "hash", "gstin": gstin, "fp": fp} + + res = {} + if filters["type_of_business"] == "B2B": + for item in report_data: + res.setdefault(item["customer_gstin"], {}).setdefault(item["invoice_number"],[]).append(item) + + out = get_b2b_json(res, gstin) + gst_json["b2b"] = out + elif filters["type_of_business"] == "B2C Large": + for item in report_data: + res.setdefault(item["place_of_supply"], []).append(item) + + out = get_b2cl_json(res, gstin) + gst_json["b2cl"] = out + elif filters["type_of_business"] == "EXPORT": + for item in report_data: + res.setdefault(item["export_type"], []).append(item) + + out = get_export_json(res) + gst_json["exp"] = out + + download_json_file(report_name, filters["type_of_business"], gst_json) + +def get_b2b_json(res, gstin): + inv_type, out = {"Registered Regular": "R", "Deemed Export": "DE", "URD": "URD", "SEZ": "SEZ"}, [] + for gst_in in res: + b2b_item, inv = {"ctin": gst_in, "inv": []}, [] + if not gst_in: continue + + for number, invoice in iteritems(res[gst_in]): + inv_item = get_basic_invoice_detail(invoice[0]) + inv_item["pos"] = "%02d" % int(invoice[0]["place_of_supply"].split('-')[0]) + inv_item["rchrg"] = invoice[0]["reverse_charge"] + inv_item["inv_typ"] = inv_type.get(invoice[0].get("gst_category", ""),"") + + if inv_item["pos"]=="00": continue + inv_item["itms"] = [] + + for item in invoice: + inv_item["itms"].append(get_rate_and_tax_details(item, gstin)) + + inv.append(inv_item) + + if not inv: continue + b2b_item["inv"] = inv + out.append(b2b_item) + + return out + +def get_b2cl_json(res, gstin): + out = [] + for pos in res: + b2cl_item, inv = {"pos": "%02d" % int(pos.split('-')[0]), "inv": []}, [] + + for row in res[pos]: + inv_item = get_basic_invoice_detail(row) + if row.get("sale_from_bonded_wh"): + inv_item["inv_typ"] = "CBW" + + inv_item["itms"] = [get_rate_and_tax_details(row, gstin)] + + inv.append(inv_item) + + b2cl_item["inv"] = inv + out.append(b2cl_item) + + return out + +def get_export_json(res): + out = [] + for exp_type in res: + exp_item, inv = {"exp_typ": exp_type, "inv": []}, [] + + for row in res[exp_type]: + inv_item = get_basic_invoice_detail(row) + inv_item["itms"] = [{ + "txval": flt(row["taxable_value"], 2), + "rt": row["rate"] or 0, + "iamt": 0, + "csamt": 0 + }] + + inv.append(inv_item) + + exp_item["inv"] = inv + out.append(exp_item) + + return out + +def get_basic_invoice_detail(row): + return { + "inum": row["invoice_number"], + "idt": getdate(row["posting_date"]).strftime('%d-%m-%Y'), + "val": flt(row["invoice_value"], 2) + } + +def get_rate_and_tax_details(row, gstin): + itm_det = {"txval": flt(row["taxable_value"], 2), + "rt": row["rate"], + "csamt": (flt(row.get("cess_amount"), 2) or 0) + } + + # calculate rate + num = 1 if not row["rate"] else "%d%02d" % (row["rate"], 1) + rate = row.get("rate") or 0 + + # calculate tax amount added + tax = flt((row["taxable_value"]*rate)/100.0, 2) + frappe.errprint([tax, tax/2]) + if row.get("customer_gstin") and gstin[0:2] == row["customer_gstin"][0:2]: + itm_det.update({"camt": flt(tax/2.0, 2), "samt": flt(tax/2.0, 2)}) + else: + itm_det.update({"iamt": tax}) + + return {"num": int(num), "itm_det": itm_det} + +def get_company_gstin_number(company): + filters = [ + ["is_your_company_address", "=", 1], + ["Dynamic Link", "link_doctype", "=", "Company"], + ["Dynamic Link", "link_name", "=", company], + ["Dynamic Link", "parenttype", "=", "Address"], + ] + + gstin = frappe.get_all("Address", filters=filters, fields=["gstin"]) + + if gstin: + return gstin[0]["gstin"] + else: + frappe.throw(_("No GST No. found for the Company.")) + +def download_json_file(filename, report_type, data): + ''' download json content in a file ''' + frappe.response['filename'] = frappe.scrub("{0} {1}".format(filename, report_type)) + '.json' + frappe.response['filecontent'] = json.dumps(data) + frappe.response['content_type'] = 'application/json' + frappe.response['type'] = 'download' diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index c85065cf12..ad151bef00 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -97,6 +97,8 @@ class Quotation(SellingController): self.update_lead() def on_cancel(self): + super(Quotation, self).on_cancel() + #update enquiry status self.set_status(update=True) self.update_opportunity() diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 2725009d86..b874fe8fcb 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -183,6 +183,8 @@ class SalesOrder(SellingController): self.update_blanket_order() def on_cancel(self): + super(SalesOrder, self).on_cancel() + # Cannot cancel closed SO if self.status == 'Closed': frappe.throw(_("Closed order cannot be cancelled. Unclose to cancel.")) diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index 5c375543f4..4fca15b707 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -2,7 +2,7 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals import frappe -from frappe.utils import flt, add_days +from frappe.utils import flt, add_days, nowdate import frappe.permissions import unittest from erpnext.selling.doctype.sales_order.sales_order \ @@ -13,7 +13,6 @@ from erpnext.controllers.accounts_controller import update_child_qty_rate import json from erpnext.selling.doctype.sales_order.sales_order import make_raw_material_request - class TestSalesOrder(unittest.TestCase): def tearDown(self): frappe.set_user("Administrator") @@ -710,6 +709,28 @@ class TestSalesOrder(unittest.TestCase): se.cancel() self.assertFalse(frappe.db.exists("Serial No", {"sales_order": so.name})) + def test_advance_payment_entry_unlink_against_sales_order(self): + from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry + frappe.db.set_value("Accounts Settings", "Accounts Settings", + "unlink_advance_payment_on_cancelation_of_order", 0) + + so = make_sales_order() + + pe = get_payment_entry("Sales Order", so.name, bank_account="_Test Bank - _TC") + pe.reference_no = "1" + pe.reference_date = nowdate() + pe.paid_from_account_currency = so.currency + pe.paid_to_account_currency = so.currency + pe.source_exchange_rate = 1 + pe.target_exchange_rate = 1 + pe.paid_amount = so.grand_total + pe.save(ignore_permissions=True) + pe.submit() + + so_doc = frappe.get_doc('Sales Order', so.name) + + self.assertRaises(frappe.LinkExistsError, so_doc.cancel) + def test_request_for_raw_materials(self): from erpnext.stock.doctype.item.test_item import make_item item = make_item("_Test Finished Item", {"is_stock_item": 1, diff --git a/erpnext/selling/doctype/sales_team/sales_team.json b/erpnext/selling/doctype/sales_team/sales_team.json index 04027b2396..876789135c 100644 --- a/erpnext/selling/doctype/sales_team/sales_team.json +++ b/erpnext/selling/doctype/sales_team/sales_team.json @@ -244,4 +244,4 @@ "track_changes": 1, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js index c54430fd56..4c0f42d22e 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.js +++ b/erpnext/selling/page/point_of_sale/point_of_sale.js @@ -233,9 +233,21 @@ erpnext.pos.PointOfSale = class PointOfSale { } else { this.update_item_in_frm(item, field, value) .then(() => { - // update cart - this.update_cart_data(item); - this.set_form_action(); + frappe.dom.unfreeze(); + frappe.run_serially([ + () => { + let items = this.frm.doc.items.map(item => item.name); + if (items && items.length > 0 && items.includes(item.name)) { + this.frm.doc.items.forEach(item_row => { + // update cart + this.on_qty_change(item_row); + }); + } else { + this.on_qty_change(item); + } + }, + () => this.post_qty_change(item) + ]); }); } return; @@ -251,7 +263,28 @@ erpnext.pos.PointOfSale = class PointOfSale { frappe.flags.hide_serial_batch_dialog = true; frappe.run_serially([ - () => this.frm.script_manager.trigger('item_code', item.doctype, item.name), + () => { + this.frm.script_manager.trigger('item_code', item.doctype, item.name) + .then(() => { + this.frm.script_manager.trigger('qty', item.doctype, item.name) + .then(() => { + frappe.run_serially([ + () => { + let items = this.frm.doc.items.map(i => i.name); + if (items && items.length > 0 && items.includes(item.name)) { + this.frm.doc.items.forEach(item_row => { + // update cart + this.on_qty_change(item_row); + }); + } else { + this.on_qty_change(item); + } + }, + () => this.post_qty_change(item) + ]); + }); + }); + }, () => { const show_dialog = item.has_serial_no || item.has_batch_no; @@ -261,14 +294,25 @@ erpnext.pos.PointOfSale = class PointOfSale { (item.has_serial_no) || (item.actual_batch_qty != item.actual_qty)) ) { // check has serial no/batch no and update cart this.select_batch_and_serial_no(item); - } else { - // update cart - this.update_cart_data(item); } } ]); } + on_qty_change(item) { + frappe.run_serially([ + () => this.update_cart_data(item), + ]); + } + + post_qty_change(item) { + this.cart.update_taxes_and_totals(); + this.cart.update_grand_total(); + this.cart.update_qty_total(); + this.cart.scroll_to_item(item.item_code); + this.set_form_action(); + } + select_batch_and_serial_no(row) { frappe.dom.unfreeze(); @@ -283,7 +327,8 @@ erpnext.pos.PointOfSale = class PointOfSale { frappe.model.clear_doc(item.doctype, item.name); } }, - () => this.update_cart_data(item) + () => this.update_cart_data(item), + () => this.post_qty_change(item) ]); }); }) @@ -300,9 +345,6 @@ erpnext.pos.PointOfSale = class PointOfSale { update_cart_data(item) { this.cart.add_item(item); - this.cart.update_taxes_and_totals(); - this.cart.update_grand_total(); - this.cart.update_qty_total(); frappe.dom.unfreeze(); } @@ -446,16 +488,15 @@ erpnext.pos.PointOfSale = class PointOfSale { } setup_company() { - this.company = frappe.sys_defaults.company; return new Promise(resolve => { - if(!this.company) { + if(!frappe.sys_defaults.company) { frappe.prompt({fieldname:"company", options: "Company", fieldtype:"Link", label: __("Select Company"), reqd: 1}, (data) => { this.company = data.company; resolve(this.company); }, __("Select Company")); } else { - resolve(this.company); + resolve(); } }) } @@ -509,7 +550,9 @@ erpnext.pos.PointOfSale = class PointOfSale { } set_pos_profile_data() { - this.frm.doc.company = this.company; + if (this.company) { + this.frm.doc.company = this.company; + } return new Promise(resolve => { return this.frm.call({ @@ -953,7 +996,6 @@ class POSCart { $item.appendTo(this.$cart_items); } this.highlight_item(item.item_code); - this.scroll_to_item(item.item_code); } update_item(item) { @@ -1206,7 +1248,10 @@ class POSItems { clearTimeout(this.last_search); this.last_search = setTimeout(() => { const search_term = e.target.value; - this.filter_items({ search_term }); + const item_group = this.item_group_field ? + this.item_group_field.get_value() : ''; + + this.filter_items({ search_term:search_term, item_group: item_group}); }, 300); }); diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py index ced6540e21..7c3cf5b039 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.py +++ b/erpnext/selling/page/point_of_sale/point_of_sale.py @@ -29,7 +29,7 @@ def get_items(start, page_length, price_list, item_group, search_value="", pos_p batch_no = data.get("batch_no") if data.get("batch_no") else "" barcode = data.get("barcode") if data.get("barcode") else "" - item_code, condition = get_conditions(item_code, serial_no, batch_no, barcode) + condition = get_conditions(item_code, serial_no, batch_no, barcode) if pos_profile: condition += get_item_group_condition(pos_profile) @@ -86,7 +86,6 @@ def get_items(start, page_length, price_list, item_group, search_value="", pos_p and {condition} limit {start}, {page_length}""".format (start=start,page_length=page_length,lft=lft, rgt=rgt, condition=condition), { - 'item_code': item_code, 'price_list': price_list, 'warehouse': warehouse } , as_dict=1) @@ -133,12 +132,10 @@ def search_serial_or_batch_or_barcode_number(search_value): def get_conditions(item_code, serial_no, batch_no, barcode): if serial_no or batch_no or barcode: - return frappe.db.escape(item_code), "i.name = %(item_code)s" + return "i.name = {0}".format(frappe.db.escape(item_code)) - condition = """(i.name like %(item_code)s - or i.item_name like %(item_code)s)""" - - return frappe.db.escape('%' + item_code + '%'), condition + return """(i.name like {item_code} + or i.item_name like {item_code})""".format(item_code = frappe.db.escape('%' + item_code + '%')) def get_item_group_condition(pos_profile): cond = "and 1=1" diff --git a/erpnext/selling/report/territory_target_variance_item_group_wise/__init__.py b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/__init__.py similarity index 100% rename from erpnext/selling/report/territory_target_variance_item_group_wise/__init__.py rename to erpnext/selling/report/sales_partner_target_variance_based_on_item_group/__init__.py diff --git a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py new file mode 100644 index 0000000000..d7ebafc217 --- /dev/null +++ b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py @@ -0,0 +1,211 @@ +# 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 +from frappe import _ +from frappe.utils import flt +from erpnext.accounts.utils import get_fiscal_year +from erpnext.accounts.report.financial_statements import get_period_list +from erpnext.accounts.doctype.monthly_distribution.monthly_distribution import get_periodwise_distribution_data + +def get_data_column(filters, partner_doctype): + data = [] + period_list = get_period_list(filters.fiscal_year, filters.fiscal_year, + filters.period, company=filters.company) + + rows = get_data(filters, period_list, partner_doctype) + columns = get_columns(filters, period_list, partner_doctype) + + if not rows: + return columns, data + + for key, value in rows.items(): + value.update({ + frappe.scrub(partner_doctype): key[0], + 'item_group': key[1] + }) + + data.append(value) + + return columns, data + +def get_data(filters, period_list, partner_doctype): + sales_field = frappe.scrub(partner_doctype) + sales_users_data = get_parents_data(filters, partner_doctype) + + if not sales_users_data: return + sales_users, item_groups = [], [] + + for d in sales_users_data: + if d.parent not in sales_users: + sales_users.append(d.parent) + + if d.item_group not in item_groups: + item_groups.append(d.item_group) + + date_field = ("transaction_date" + if filters.get('doctype') == "Sales Order" else "posting_date") + + actual_data = get_actual_data(filters, item_groups, sales_users, date_field, sales_field) + + return prepare_data(filters, sales_users_data, + actual_data, date_field, period_list, sales_field) + +def get_columns(filters, period_list, partner_doctype): + fieldtype, options = "Currency", "currency" + + if filters.get("target_on") == 'Quantity': + fieldtype, options = "Float", "" + + columns = [{ + "fieldname": frappe.scrub(partner_doctype), + "label": _(partner_doctype), + "fieldtype": "Link", + "options": partner_doctype, + "width": 100 + }, { + "fieldname": "item_group", + "label": _("Item Group"), + "fieldtype": "Link", + "options": "Item Group", + "width": 100 + }] + + for period in period_list: + target_key = 'target_{}'.format(period.key) + variance_key = 'variance_{}'.format(period.key) + + columns.extend([{ + "fieldname": target_key, + "label": _("Target ({})".format(period.label)), + "fieldtype": fieldtype, + "options": options, + "width": 100 + }, { + "fieldname": period.key, + "label": _("Achieved ({})".format(period.label)), + "fieldtype": fieldtype, + "options": options, + "width": 100 + }, { + "fieldname": variance_key, + "label": _("Variance ({})".format(period.label)), + "fieldtype": fieldtype, + "options": options, + "width": 100 + }]) + + columns.extend([{ + "fieldname": "total_target", + "label": _("Total Target"), + "fieldtype": fieldtype, + "options": options, + "width": 100 + }, { + "fieldname": "total_achieved", + "label": _("Total Achieved"), + "fieldtype": fieldtype, + "options": options, + "width": 100 + }, { + "fieldname": "total_variance", + "label": _("Total Variance"), + "fieldtype": fieldtype, + "options": options, + "width": 100 + }]) + + return columns + +def prepare_data(filters, sales_users_data, actual_data, date_field, period_list, sales_field): + rows = {} + + target_qty_amt_field = ("target_qty" + if filters.get("target_on") == 'Quantity' else "target_amount") + + qty_or_amount_field = ("stock_qty" + if filters.get("target_on") == 'Quantity' else "base_net_amount") + + for d in sales_users_data: + key = (d.parent, d.item_group) + dist_data = get_periodwise_distribution_data(d.distribution_id, period_list, filters.get("period")) + + if key not in rows: + rows.setdefault(key,{ + 'total_target': 0, + 'total_achieved': 0, + 'total_variance': 0 + }) + + details = rows[key] + for period in period_list: + p_key = period.key + if p_key not in details: + details[p_key] = 0 + + target_key = 'target_{}'.format(p_key) + variance_key = 'variance_{}'.format(p_key) + details[target_key] = (d.get(target_qty_amt_field) * dist_data.get(p_key)) / 100 + details[variance_key] = 0 + details["total_target"] += details[target_key] + + for r in actual_data: + if (r.get(sales_field) == d.parent and r.item_group == d.item_group and + period.from_date <= r.get(date_field) and r.get(date_field) <= period.to_date): + details[p_key] += r.get(qty_or_amount_field, 0) + details[variance_key] = details.get(target_key) - details.get(p_key) + + details["total_achieved"] += details.get(p_key) + details["total_variance"] = details.get("total_target") - details.get("total_achieved") + + return rows + +def get_actual_data(filters, item_groups, sales_users_or_territory_data, date_field, sales_field): + fiscal_year = get_fiscal_year(fiscal_year=filters.get("fiscal_year"), as_dict=1) + dates = [fiscal_year.year_start_date, fiscal_year.year_end_date] + + select_field = "`tab{0}`.{1}".format(filters.get("doctype"), sales_field) + child_table = "`tab{0}`".format(filters.get("doctype") + ' Item') + + if sales_field == 'sales_person': + select_field = "`tabSales Team`.sales_person" + child_table = "`tab{0}`, `tabSales Team`".format(filters.get("doctype") + ' Item') + cond = """`tabSales Team`.parent = `tab{0}`.name and + `tabSales Team`.sales_person in ({1}) """.format(filters.get("doctype"), + ','.join(['%s'] * len(sales_users_or_territory_data))) + else: + cond = "`tab{0}`.{1} in ({2})".format(filters.get("doctype"), sales_field, + ','.join(['%s'] * len(sales_users_or_territory_data))) + + return frappe.db.sql(""" SELECT `tab{child_doc}`.item_group, + `tab{child_doc}`.stock_qty, `tab{child_doc}`.base_net_amount, + {select_field}, `tab{parent_doc}`.{date_field} + FROM `tab{parent_doc}`, {child_table} + WHERE + `tab{child_doc}`.parent = `tab{parent_doc}`.name + and `tab{parent_doc}`.docstatus = 1 and {cond} + and `tab{child_doc}`.item_group in ({item_groups}) + and `tab{parent_doc}`.{date_field} between %s and %s""" + .format( + cond = cond, + date_field = date_field, + select_field = select_field, + child_table = child_table, + parent_doc = filters.get("doctype"), + child_doc = filters.get("doctype") + ' Item', + item_groups = ','.join(['%s'] * len(item_groups)) + ), tuple(sales_users_or_territory_data + item_groups + dates), as_dict=1) + +def get_parents_data(filters, partner_doctype): + filters_dict = {'parenttype': partner_doctype} + + target_qty_amt_field = ("target_qty" + if filters.get("target_on") == 'Quantity' else "target_amount") + + if filters.get("fiscal_year"): + filters_dict["fiscal_year"] = filters.get("fiscal_year") + + return frappe.get_all('Target Detail', + filters = filters_dict, + fields = ["parent", "item_group", target_qty_amt_field, "fiscal_year", "distribution_id"]) \ No newline at end of file diff --git a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.js b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.js new file mode 100644 index 0000000000..f99f68c524 --- /dev/null +++ b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.js @@ -0,0 +1,48 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Sales Partner Target Variance based on Item Group"] = { + "filters": [ + { + fieldname:"company", + label: __("Company"), + fieldtype: "Link", + options: "Company", + default: frappe.defaults.get_user_default("Company") + }, + { + fieldname: "fiscal_year", + label: __("Fiscal Year"), + fieldtype: "Link", + options: "Fiscal Year", + default: frappe.sys_defaults.fiscal_year + }, + { + fieldname: "doctype", + label: __("Document Type"), + fieldtype: "Select", + options: "Sales Order\nDelivery Note\nSales Invoice", + default: "Sales Order" + }, + { + fieldname: "period", + label: __("Period"), + fieldtype: "Select", + options: [ + { "value": "Monthly", "label": __("Monthly") }, + { "value": "Quarterly", "label": __("Quarterly") }, + { "value": "Half-Yearly", "label": __("Half-Yearly") }, + { "value": "Yearly", "label": __("Yearly") } + ], + default: "Monthly" + }, + { + fieldname: "target_on", + label: __("Target On"), + fieldtype: "Select", + options: "Quantity\nAmount", + default: "Quantity" + }, + ] +} diff --git a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.json b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.json new file mode 100644 index 0000000000..1cc7e961d3 --- /dev/null +++ b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.json @@ -0,0 +1,37 @@ +{ + "add_total_row": 0, + "creation": "2019-03-25 18:22:37.323995", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "letter_head": "Gadgets International", + "modified": "2019-03-25 18:22:37.323995", + "modified_by": "Administrator", + "module": "Selling", + "name": "Sales Partner Target Variance based on Item Group", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Sales Order", + "report_name": "Sales Partner Target Variance based on Item Group", + "report_type": "Script Report", + "roles": [ + { + "role": "Sales User" + }, + { + "role": "Sales Manager" + }, + { + "role": "Maintenance User" + }, + { + "role": "Accounts User" + }, + { + "role": "Stock User" + } + ] +} \ No newline at end of file diff --git a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.py b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.py new file mode 100644 index 0000000000..e41011fba2 --- /dev/null +++ b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.py @@ -0,0 +1,12 @@ +# 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 +from erpnext.selling.report.sales_partner_target_variance_based_on_item_group.item_group_wise_sales_target_variance import get_data_column + +def execute(filters=None): + data = [] + + return get_data_column(filters, "Sales Partner") + diff --git a/erpnext/selling/report/sales_partner_transaction_summary/__init__.py b/erpnext/selling/report/sales_partner_transaction_summary/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/selling/report/sales_partner_wise_transaction_summary/sales_partner_wise_transaction_summary.js b/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.js similarity index 95% rename from erpnext/selling/report/sales_partner_wise_transaction_summary/sales_partner_wise_transaction_summary.js rename to erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.js index 7e99dd4da6..e404233953 100644 --- a/erpnext/selling/report/sales_partner_wise_transaction_summary/sales_partner_wise_transaction_summary.js +++ b/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.js @@ -2,7 +2,7 @@ // For license information, please see license.txt /* eslint-disable */ -frappe.query_reports["Sales Partner-wise Transaction Summary"] = { +frappe.query_reports["Sales Partner Transaction Summary"] = { "filters": [ { fieldname: "sales_partner", diff --git a/erpnext/selling/report/sales_partner_wise_transaction_summary/sales_partner_wise_transaction_summary.json b/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.json similarity index 73% rename from erpnext/selling/report/sales_partner_wise_transaction_summary/sales_partner_wise_transaction_summary.json rename to erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.json index 9384bfb23d..b518b42be3 100644 --- a/erpnext/selling/report/sales_partner_wise_transaction_summary/sales_partner_wise_transaction_summary.json +++ b/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.json @@ -1,6 +1,6 @@ { "add_total_row": 1, - "creation": "2019-03-15 16:21:16.088831", + "creation": "2019-03-25 18:15:09.920739", "disable_prepared_report": 0, "disabled": 0, "docstatus": 0, @@ -8,14 +8,14 @@ "idx": 0, "is_standard": "Yes", "letter_head": "Gadgets International", - "modified": "2019-03-15 16:21:16.088831", + "modified": "2019-03-25 18:15:09.920739", "modified_by": "Administrator", "module": "Selling", - "name": "Sales Partner-wise Transaction Summary", + "name": "Sales Partner Transaction Summary", "owner": "Administrator", "prepared_report": 0, "ref_doctype": "Sales Order", - "report_name": "Sales Partner-wise Transaction Summary", + "report_name": "Sales Partner Transaction Summary", "report_type": "Script Report", "roles": [ { diff --git a/erpnext/selling/report/sales_partner_wise_transaction_summary/sales_partner_wise_transaction_summary.py b/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py similarity index 100% rename from erpnext/selling/report/sales_partner_wise_transaction_summary/sales_partner_wise_transaction_summary.py rename to erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py diff --git a/erpnext/selling/report/sales_person_target_variance_based_on_item_group/__init__.py b/erpnext/selling/report/sales_person_target_variance_based_on_item_group/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.js b/erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.js similarity index 55% rename from erpnext/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.js rename to erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.js index 55a13d9680..9f6bfc41df 100644 --- a/erpnext/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.js +++ b/erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.js @@ -1,8 +1,16 @@ -// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -// License: GNU General Public License v3. See license.txt +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ -frappe.query_reports["Territory Target Variance Item Group-Wise"] = { +frappe.query_reports["Sales Person Target Variance Based On Item Group"] = { "filters": [ + { + fieldname:"company", + label: __("Company"), + fieldtype: "Link", + options: "Company", + default: frappe.defaults.get_user_default("Company") + }, { fieldname: "fiscal_year", label: __("Fiscal Year"), @@ -10,6 +18,13 @@ frappe.query_reports["Territory Target Variance Item Group-Wise"] = { options: "Fiscal Year", default: frappe.sys_defaults.fiscal_year }, + { + fieldname: "doctype", + label: __("Document Type"), + fieldtype: "Select", + options: "Sales Order\nDelivery Note\nSales Invoice", + default: "Sales Order" + }, { fieldname: "period", label: __("Period"), diff --git a/erpnext/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.json b/erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.json similarity index 57% rename from erpnext/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.json rename to erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.json index 2cb548fc45..84cd27eb34 100644 --- a/erpnext/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.json +++ b/erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.json @@ -1,19 +1,21 @@ { "add_total_row": 0, - "apply_user_permissions": 1, - "creation": "2013-06-21 12:15:00", + "creation": "2019-03-25 22:16:49.040998", + "disable_prepared_report": 0, "disabled": 0, "docstatus": 0, "doctype": "Report", - "idx": 3, + "idx": 0, "is_standard": "Yes", - "modified": "2017-02-24 20:13:29.705321", + "letter_head": "Gadgets International", + "modified": "2019-03-25 22:16:49.040998", "modified_by": "Administrator", "module": "Selling", - "name": "Territory Target Variance Item Group-Wise", + "name": "Sales Person Target Variance Based On Item Group", "owner": "Administrator", + "prepared_report": 0, "ref_doctype": "Sales Order", - "report_name": "Territory Target Variance Item Group-Wise", + "report_name": "Sales Person Target Variance Based On Item Group", "report_type": "Script Report", "roles": [ { diff --git a/erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.py b/erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.py new file mode 100644 index 0000000000..5166cc808e --- /dev/null +++ b/erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.py @@ -0,0 +1,11 @@ +# 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 +from erpnext.selling.report.sales_partner_target_variance_based_on_item_group.item_group_wise_sales_target_variance import get_data_column + +def execute(filters=None): + data = [] + + return get_data_column(filters, "Sales Person") \ No newline at end of file diff --git a/erpnext/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py b/erpnext/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py deleted file mode 100644 index fd5bc4ec5b..0000000000 --- a/erpnext/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py +++ /dev/null @@ -1,178 +0,0 @@ -# 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 -from frappe import _, msgprint -from frappe.utils import flt -from erpnext.accounts.utils import get_fiscal_year -from erpnext.controllers.trends import get_period_date_ranges, get_period_month_ranges - -def execute(filters=None): - if not filters: filters = {} - - columns = get_columns(filters) - period_month_ranges = get_period_month_ranges(filters["period"], filters["fiscal_year"]) - sim_map = get_salesperson_item_month_map(filters) - - data = [] - for salesperson, salesperson_items in sim_map.items(): - for item_group, monthwise_data in salesperson_items.items(): - row = [salesperson, item_group] - totals = [0, 0, 0] - for relevant_months in period_month_ranges: - period_data = [0, 0, 0] - for month in relevant_months: - month_data = monthwise_data.get(month, {}) - for i, fieldname in enumerate(["target", "achieved", "variance"]): - value = flt(month_data.get(fieldname)) - period_data[i] += value - totals[i] += value - period_data[2] = period_data[0] - period_data[1] - row += period_data - totals[2] = totals[0] - totals[1] - row += totals - data.append(row) - - return columns, sorted(data, key=lambda x: (x[0], x[1])) - -def get_columns(filters): - for fieldname in ["fiscal_year", "period", "target_on"]: - if not filters.get(fieldname): - label = (" ".join(fieldname.split("_"))).title() - msgprint(_("Please specify") + ": " + label, - raise_exception=True) - - columns = [_("Sales Person") + ":Link/Sales Person:120", _("Item Group") + ":Link/Item Group:120"] - - group_months = False if filters["period"] == "Monthly" else True - - for from_date, to_date in get_period_date_ranges(filters["period"], filters["fiscal_year"]): - for label in [_("Target") + " (%s)", _("Achieved") + " (%s)", _("Variance") + " (%s)"]: - if group_months: - label = label % (_(from_date.strftime("%b")) + " - " + _(to_date.strftime("%b"))) - else: - label = label % _(from_date.strftime("%b")) - - columns.append(label+":Float:120") - - return columns + [_("Total Target") + ":Float:120", _("Total Achieved") + ":Float:120", - _("Total Variance") + ":Float:120"] - -#Get sales person & item group details -def get_salesperson_details(filters): - return frappe.db.sql(""" - select - sp.name, td.item_group, td.target_qty, td.target_amount, sp.distribution_id - from - `tabSales Person` sp, `tabTarget Detail` td - where - td.parent=sp.name and td.fiscal_year=%s order by sp.name - """, (filters["fiscal_year"]), as_dict=1) - -#Get target distribution details of item group -def get_target_distribution_details(filters): - target_details = {} - - for d in frappe.db.sql(""" - select - md.name, mdp.month, mdp.percentage_allocation - from - `tabMonthly Distribution Percentage` mdp, `tabMonthly Distribution` md - where - mdp.parent=md.name and md.fiscal_year=%s - """, (filters["fiscal_year"]), as_dict=1): - target_details.setdefault(d.name, {}).setdefault(d.month, flt(d.percentage_allocation)) - - return target_details - -#Get achieved details from sales order -def get_achieved_details(filters, sales_person, all_sales_persons, target_item_group, item_groups): - start_date, end_date = get_fiscal_year(fiscal_year = filters["fiscal_year"])[1:] - - item_details = frappe.db.sql(""" - SELECT st.sales_person, MONTHNAME(so.transaction_date) as month_name, - CASE - WHEN so.status = "Closed" THEN sum(soi.delivered_qty * soi.conversion_factor * (st.allocated_percentage/100)) - ELSE sum(soi.stock_qty * (st.allocated_percentage/100)) - END as qty, - CASE - WHEN so.status = "Closed" THEN sum(soi.delivered_qty * soi.conversion_factor * soi.base_net_rate * (st.allocated_percentage/100)) - ELSE sum(soi.base_net_amount * (st.allocated_percentage/100)) - END as amount - from - `tabSales Order Item` soi, `tabSales Order` so, `tabSales Team` st - where - soi.parent=so.name and so.docstatus=1 and st.parent=so.name - and so.transaction_date>=%s and so.transaction_date<=%s - and exists(SELECT name from `tabSales Person` where lft >= %s and rgt <= %s and name=st.sales_person) - and exists(SELECT name from `tabItem Group` where lft >= %s and rgt <= %s and name=soi.item_group) - group by - sales_person, month_name - """, - (start_date, end_date, all_sales_persons[sales_person].lft, all_sales_persons[sales_person].rgt, - item_groups[target_item_group].lft, item_groups[target_item_group].rgt), as_dict=1) - - actual_details = {} - for d in item_details: - actual_details.setdefault(d.month_name, frappe._dict({ - "quantity" : 0, - "amount" : 0 - })) - - value_dict = actual_details[d.month_name] - value_dict.quantity += flt(d.qty) - value_dict.amount += flt(d.amount) - - return actual_details - -def get_salesperson_item_month_map(filters): - import datetime - salesperson_details = get_salesperson_details(filters) - tdd = get_target_distribution_details(filters) - item_groups = get_item_groups() - sales_persons = get_sales_persons() - - sales_person_achievement_dict = {} - for sd in salesperson_details: - achieved_details = get_achieved_details(filters, sd.name, sales_persons, sd.item_group, item_groups) - - for month_id in range(1, 13): - month = datetime.date(2013, month_id, 1).strftime('%B') - sales_person_achievement_dict.setdefault(sd.name, {}).setdefault(sd.item_group, {})\ - .setdefault(month, frappe._dict({ - "target": 0.0, "achieved": 0.0 - })) - - sales_target_achieved = sales_person_achievement_dict[sd.name][sd.item_group][month] - month_percentage = tdd.get(sd.distribution_id, {}).get(month, 0) \ - if sd.distribution_id else 100.0/12 - - if (filters["target_on"] == "Quantity"): - sales_target_achieved.target = flt(sd.target_qty) * month_percentage / 100 - else: - sales_target_achieved.target = flt(sd.target_amount) * month_percentage / 100 - - sales_target_achieved.achieved = achieved_details.get(month, frappe._dict())\ - .get(filters["target_on"].lower()) - - return sales_person_achievement_dict - -def get_item_groups(): - item_groups = frappe._dict() - for d in frappe.get_all("Item Group", fields=["name", "lft", "rgt"]): - item_groups.setdefault(d.name, frappe._dict({ - "lft": d.lft, - "rgt": d.rgt - })) - return item_groups - -def get_sales_persons(): - sales_persons = frappe._dict() - for d in frappe.get_all("Sales Person", fields=["name", "lft", "rgt"]): - sales_persons.setdefault(d.name, frappe._dict({ - "lft": d.lft, - "rgt": d.rgt - })) - return sales_persons - \ No newline at end of file diff --git a/erpnext/selling/report/territory_target_variance_based_on_item_group/__init__.py b/erpnext/selling/report/territory_target_variance_based_on_item_group/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.js b/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.js similarity index 55% rename from erpnext/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.js rename to erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.js index 8987a74ff8..dd9607ffbd 100644 --- a/erpnext/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.js +++ b/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.js @@ -1,8 +1,16 @@ -// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -// License: GNU General Public License v3. See license.txt +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ -frappe.query_reports["Sales Person Target Variance Item Group-Wise"] = { +frappe.query_reports["Territory Target Variance Based On Item Group"] = { "filters": [ + { + fieldname:"company", + label: __("Company"), + fieldtype: "Link", + options: "Company", + default: frappe.defaults.get_user_default("Company") + }, { fieldname: "fiscal_year", label: __("Fiscal Year"), @@ -10,6 +18,13 @@ frappe.query_reports["Sales Person Target Variance Item Group-Wise"] = { options: "Fiscal Year", default: frappe.sys_defaults.fiscal_year }, + { + fieldname: "doctype", + label: __("Document Type"), + fieldtype: "Select", + options: "Sales Order\nDelivery Note\nSales Invoice", + default: "Sales Order" + }, { fieldname: "period", label: __("Period"), diff --git a/erpnext/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.json b/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.json similarity index 58% rename from erpnext/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.json rename to erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.json index 452caf9d46..d3b05ba57d 100644 --- a/erpnext/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.json +++ b/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.json @@ -1,19 +1,21 @@ { "add_total_row": 0, - "apply_user_permissions": 1, - "creation": "2013-06-21 12:14:15", + "creation": "2019-03-25 22:20:59.033199", + "disable_prepared_report": 0, "disabled": 0, "docstatus": 0, "doctype": "Report", - "idx": 3, + "idx": 0, "is_standard": "Yes", - "modified": "2017-02-24 20:14:50.589149", + "letter_head": "Gadgets International", + "modified": "2019-03-25 22:20:59.033199", "modified_by": "Administrator", "module": "Selling", - "name": "Sales Person Target Variance Item Group-Wise", + "name": "Territory Target Variance Based On Item Group", "owner": "Administrator", + "prepared_report": 0, "ref_doctype": "Sales Order", - "report_name": "Sales Person Target Variance Item Group-Wise", + "report_name": "Territory Target Variance Based On Item Group", "report_type": "Script Report", "roles": [ { diff --git a/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.py b/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.py new file mode 100644 index 0000000000..b1d89cc3fb --- /dev/null +++ b/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.py @@ -0,0 +1,11 @@ +# 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 +from erpnext.selling.report.sales_partner_target_variance_based_on_item_group.item_group_wise_sales_target_variance import get_data_column + +def execute(filters=None): + data = [] + + return get_data_column(filters, "Territory") diff --git a/erpnext/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py b/erpnext/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py deleted file mode 100644 index 7caed9bc46..0000000000 --- a/erpnext/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py +++ /dev/null @@ -1,157 +0,0 @@ -# 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 -from frappe import _, msgprint -from frappe.utils import flt -from erpnext.accounts.utils import get_fiscal_year -from erpnext.controllers.trends import get_period_date_ranges, get_period_month_ranges - -def execute(filters=None): - if not filters: filters = {} - - columns = get_columns(filters) - period_month_ranges = get_period_month_ranges(filters["period"], filters["fiscal_year"]) - territory_item_group_dict = get_territory_item_month_map(filters) - - data = [] - for territory, territory_items in territory_item_group_dict.items(): - for item_group, monthwise_data in territory_items.items(): - row = [territory, item_group] - totals = [0, 0, 0] - for relevant_months in period_month_ranges: - period_data = [0, 0, 0] - for month in relevant_months: - month_data = monthwise_data.get(month, {}) - for i, fieldname in enumerate(["target", "achieved", "variance"]): - value = flt(month_data.get(fieldname)) - period_data[i] += value - totals[i] += value - period_data[2] = period_data[0] - period_data[1] - row += period_data - totals[2] = totals[0] - totals[1] - row += totals - data.append(row) - - return columns, sorted(data, key=lambda x: (x[0], x[1])) - -def get_columns(filters): - for fieldname in ["fiscal_year", "period", "target_on"]: - if not filters.get(fieldname): - label = (" ".join(fieldname.split("_"))).title() - msgprint(_("Please specify") + ": " + label, raise_exception=True) - - columns = [_("Territory") + ":Link/Territory:120", _("Item Group") + ":Link/Item Group:120"] - - group_months = False if filters["period"] == "Monthly" else True - - for from_date, to_date in get_period_date_ranges(filters["period"], filters["fiscal_year"]): - for label in [_("Target") +" (%s)", _("Achieved") + " (%s)", _("Variance") + " (%s)"]: - if group_months: - label = label % (_(from_date.strftime("%b")) + " - " + _(to_date.strftime("%b"))) - else: - label = label % _(from_date.strftime("%b")) - columns.append(label+":Float:120") - - return columns + [_("Total Target") + ":Float:120", _("Total Achieved") + ":Float:120", - _("Total Variance") + ":Float:120"] - -#Get territory & item group details -def get_territory_details(filters): - return frappe.db.sql(""" - select - t.name, td.item_group, td.target_qty, td.target_amount, t.distribution_id - from - `tabTerritory` t, `tabTarget Detail` td - where - td.parent=t.name and td.fiscal_year=%s order by t.name - """, (filters["fiscal_year"]), as_dict=1) - -#Get target distribution details of item group -def get_target_distribution_details(filters): - target_details = {} - - for d in frappe.db.sql(""" - select - md.name, mdp.month, mdp.percentage_allocation - from - `tabMonthly Distribution Percentage` mdp, `tabMonthly Distribution` md - where - mdp.parent=md.name and md.fiscal_year=%s - """, (filters["fiscal_year"]), as_dict=1): - target_details.setdefault(d.name, {}).setdefault(d.month, flt(d.percentage_allocation)) - - return target_details - -#Get achieved details from sales order -def get_achieved_details(filters, territory, item_groups): - start_date, end_date = get_fiscal_year(fiscal_year = filters["fiscal_year"])[1:] - - lft, rgt = frappe.db.get_value("Territory", territory, ["lft", "rgt"]) - - item_details = frappe.db.sql(""" - select - soi.item_code, sum(soi.stock_qty) as qty, sum(soi.base_net_amount) as amount, - MONTHNAME(so.transaction_date) as month_name - from - `tabSales Order Item` soi, `tabSales Order` so - where - soi.parent=so.name and so.docstatus=1 - and so.transaction_date>=%s and so.transaction_date<=%s - and exists(select name from `tabTerritory` where lft >=%s and rgt <= %s and name=so.territory) - group by - month_name, item_code - """, (start_date, end_date, lft, rgt), as_dict=1) - - item_actual_details = {} - for d in item_details: - item_group = item_groups[d.item_code] - item_actual_details.setdefault(item_group, frappe._dict())\ - .setdefault(d.month_name, frappe._dict({ - "quantity": 0, - "amount": 0 - })) - - value_dict = item_actual_details[item_group][d.month_name] - value_dict.quantity += flt(d.qty) - value_dict.amount += flt(d.amount) - - return item_actual_details - -def get_territory_item_month_map(filters): - import datetime - territory_details = get_territory_details(filters) - tdd = get_target_distribution_details(filters) - item_groups = get_item_groups() - - territory_item_group_dict = {} - - for td in territory_details: - achieved_details = get_achieved_details(filters, td.name, item_groups) - - for month_id in range(1, 13): - month = datetime.date(2013, month_id, 1).strftime('%B') - - territory_item_group_dict.setdefault(td.name, {}).setdefault(td.item_group, {})\ - .setdefault(month, frappe._dict({ - "target": 0.0, "achieved": 0.0 - })) - - target_achieved = territory_item_group_dict[td.name][td.item_group][month] - month_percentage = tdd.get(td.distribution_id, {}).get(month, 0) \ - if td.distribution_id else 100.0/12 - - - if (filters["target_on"] == "Quantity"): - target_achieved.target = flt(td.target_qty) * month_percentage / 100 - else: - target_achieved.target = flt(td.target_amount) * month_percentage / 100 - - target_achieved.achieved = achieved_details.get(td.item_group, {}).get(month, {})\ - .get(filters["target_on"].lower()) - - return territory_item_group_dict - -def get_item_groups(): - return dict(frappe.get_all("Item", fields=["name", "item_group"], as_list=1)) diff --git a/erpnext/setup/doctype/brand/test_records.json b/erpnext/setup/doctype/brand/test_records.json index 17b5a6b0a3..eeed9e7733 100644 --- a/erpnext/setup/doctype/brand/test_records.json +++ b/erpnext/setup/doctype/brand/test_records.json @@ -1,6 +1,6 @@ [ { - "brand": "_Test Brand", + "brand": "_Test Brand", "doctype": "Brand" }, { diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index 77c371e0cd..dbd7c4149f 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -22,6 +22,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "details", "fieldtype": "Section Break", "hidden": 0, @@ -54,6 +55,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company_name", "fieldtype": "Data", "hidden": 0, @@ -88,6 +90,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "abbr", "fieldtype": "Data", "hidden": 0, @@ -122,6 +125,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal && in_list(frappe.user_roles, \"System Manager\")", + "fetch_if_empty": 0, "fieldname": "change_abbr", "fieldtype": "Button", "hidden": 0, @@ -153,6 +157,7 @@ "bold": 1, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "is_group", "fieldtype": "Check", "hidden": 0, @@ -185,6 +190,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_finance_book", "fieldtype": "Link", "hidden": 0, @@ -218,6 +224,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "cb0", "fieldtype": "Column Break", "hidden": 0, @@ -248,6 +255,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "domain", "fieldtype": "Link", "hidden": 0, @@ -280,6 +288,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "parent_company", "fieldtype": "Link", "hidden": 0, @@ -313,6 +322,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sb_about", "fieldtype": "Section Break", "hidden": 0, @@ -345,6 +355,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company_logo", "fieldtype": "Attach Image", "hidden": 0, @@ -377,6 +388,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company_description", "fieldtype": "Text Editor", "hidden": 0, @@ -409,6 +421,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sales_settings", "fieldtype": "Section Break", "hidden": 0, @@ -441,6 +454,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sales_monthly_history", "fieldtype": "Small Text", "hidden": 1, @@ -473,6 +487,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "transactions_annual_history", "fieldtype": "Code", "hidden": 1, @@ -505,6 +520,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "monthly_sales_target", "fieldtype": "Currency", "hidden": 0, @@ -538,6 +554,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_goals", "fieldtype": "Column Break", "hidden": 0, @@ -569,6 +586,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_monthly_sales", "fieldtype": "Currency", "hidden": 0, @@ -602,6 +620,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "charts_section", "fieldtype": "Section Break", "hidden": 0, @@ -633,6 +652,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_currency", "fieldtype": "Link", "hidden": 0, @@ -665,6 +685,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_letter_head", "fieldtype": "Link", "hidden": 0, @@ -698,6 +719,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_holiday_list", "fieldtype": "Link", "hidden": 0, @@ -731,6 +753,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "standard_working_hours", "fieldtype": "Float", "hidden": 0, @@ -763,6 +786,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_terms", "fieldtype": "Link", "hidden": 0, @@ -795,6 +819,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_10", "fieldtype": "Column Break", "hidden": 0, @@ -826,6 +851,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "country", "fieldtype": "Link", "hidden": 0, @@ -858,6 +884,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "create_chart_of_accounts_based_on", "fieldtype": "Select", "hidden": 0, @@ -892,6 +919,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.create_chart_of_accounts_based_on===\"Standard Template\"", + "fetch_if_empty": 0, "fieldname": "chart_of_accounts", "fieldtype": "Select", "hidden": 0, @@ -926,6 +954,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.create_chart_of_accounts_based_on===\"Existing Company\"", + "fetch_if_empty": 0, "fieldname": "existing_company", "fieldtype": "Link", "hidden": 0, @@ -959,6 +988,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "tax_id", "fieldtype": "Data", "hidden": 0, @@ -991,6 +1021,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "date_of_establishment", "fieldtype": "Date", "hidden": 0, @@ -1023,6 +1054,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_settings", "fieldtype": "Section Break", "hidden": 0, @@ -1056,6 +1088,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_bank_account", "fieldtype": "Link", "hidden": 0, @@ -1091,6 +1124,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_cash_account", "fieldtype": "Link", "hidden": 0, @@ -1124,6 +1158,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_receivable_account", "fieldtype": "Link", "hidden": 0, @@ -1158,6 +1193,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "round_off_account", "fieldtype": "Link", "hidden": 0, @@ -1191,6 +1227,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "round_off_cost_center", "fieldtype": "Link", "hidden": 0, @@ -1224,6 +1261,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "write_off_account", "fieldtype": "Link", "hidden": 0, @@ -1257,6 +1295,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "discount_allowed_account", "fieldtype": "Link", "hidden": 0, @@ -1290,6 +1329,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "discount_received_account", "fieldtype": "Link", "hidden": 0, @@ -1323,6 +1363,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "exchange_gain_loss_account", "fieldtype": "Link", "hidden": 0, @@ -1356,6 +1397,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "unrealized_exchange_gain_loss_account", "fieldtype": "Link", "hidden": 0, @@ -1389,6 +1431,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break0", "fieldtype": "Column Break", "hidden": 0, @@ -1414,6 +1457,40 @@ "unique": 0, "width": "50%" }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.parent_company", + "fetch_if_empty": 0, + "fieldname": "allow_account_creation_against_child_company", + "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 Account Creation Against Child Company", + "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, @@ -1422,6 +1499,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_payable_account", "fieldtype": "Link", "hidden": 0, @@ -1456,6 +1534,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_employee_advance_account", "fieldtype": "Link", "hidden": 0, @@ -1490,6 +1569,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_expense_account", "fieldtype": "Link", "hidden": 0, @@ -1523,6 +1603,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_income_account", "fieldtype": "Link", "hidden": 0, @@ -1556,6 +1637,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_deferred_revenue_account", "fieldtype": "Link", "hidden": 0, @@ -1590,6 +1672,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_deferred_expense_account", "fieldtype": "Link", "hidden": 0, @@ -1624,6 +1707,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_payroll_payable_account", "fieldtype": "Link", "hidden": 0, @@ -1658,6 +1742,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_expense_claim_payable_account", "fieldtype": "Link", "hidden": 0, @@ -1691,6 +1776,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_22", "fieldtype": "Section Break", "hidden": 0, @@ -1723,6 +1809,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "cost_center", "fieldtype": "Link", "hidden": 0, @@ -1755,6 +1842,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_26", "fieldtype": "Column Break", "hidden": 0, @@ -1787,6 +1875,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "credit_limit", "fieldtype": "Currency", "hidden": 0, @@ -1822,6 +1911,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "payment_terms", "fieldtype": "Link", "hidden": 0, @@ -1856,6 +1946,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "auto_accounting_for_stock_settings", "fieldtype": "Section Break", "hidden": 0, @@ -1888,6 +1979,7 @@ "collapsible": 0, "columns": 0, "default": "1", + "fetch_if_empty": 0, "fieldname": "enable_perpetual_inventory", "fieldtype": "Check", "hidden": 0, @@ -1920,6 +2012,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_inventory_account", "fieldtype": "Link", "hidden": 0, @@ -1953,6 +2046,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "stock_adjustment_account", "fieldtype": "Link", "hidden": 0, @@ -1985,6 +2079,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_32", "fieldtype": "Column Break", "hidden": 0, @@ -2016,6 +2111,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "stock_received_but_not_billed", "fieldtype": "Link", "hidden": 0, @@ -2048,6 +2144,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "expenses_included_in_valuation", "fieldtype": "Link", "hidden": 0, @@ -2080,6 +2177,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "fixed_asset_depreciation_settings", "fieldtype": "Section Break", "hidden": 0, @@ -2112,6 +2210,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "accumulated_depreciation_account", "fieldtype": "Link", "hidden": 0, @@ -2145,6 +2244,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "depreciation_expense_account", "fieldtype": "Link", "hidden": 0, @@ -2178,6 +2278,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "series_for_depreciation_entry", "fieldtype": "Data", "hidden": 0, @@ -2210,6 +2311,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "expenses_included_in_asset_valuation", "fieldtype": "Link", "hidden": 0, @@ -2243,6 +2345,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_40", "fieldtype": "Column Break", "hidden": 0, @@ -2274,6 +2377,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "disposal_account", "fieldtype": "Link", "hidden": 0, @@ -2307,6 +2411,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "depreciation_cost_center", "fieldtype": "Link", "hidden": 0, @@ -2340,6 +2445,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "capital_work_in_progress_account", "fieldtype": "Link", "hidden": 0, @@ -2373,6 +2479,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "asset_received_but_not_billed", "fieldtype": "Link", "hidden": 0, @@ -2406,6 +2513,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "budget_detail", "fieldtype": "Section Break", "hidden": 0, @@ -2438,6 +2546,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "exception_budget_approver_role", "fieldtype": "Link", "hidden": 0, @@ -2472,6 +2581,7 @@ "collapsible": 0, "columns": 0, "description": "For reference only.", + "fetch_if_empty": 0, "fieldname": "company_info", "fieldtype": "Section Break", "hidden": 0, @@ -2503,6 +2613,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "date_of_incorporation", "fieldtype": "Date", "hidden": 0, @@ -2535,6 +2646,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "address_html", "fieldtype": "HTML", "hidden": 0, @@ -2566,6 +2678,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break1", "fieldtype": "Column Break", "hidden": 0, @@ -2599,6 +2712,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.date_of_incorporation", + "fetch_if_empty": 0, "fieldname": "date_of_commencement", "fieldtype": "Date", "hidden": 0, @@ -2631,6 +2745,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "phone_no", "fieldtype": "Data", "hidden": 0, @@ -2665,6 +2780,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "fax", "fieldtype": "Data", "hidden": 0, @@ -2699,6 +2815,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "email", "fieldtype": "Data", "hidden": 0, @@ -2733,6 +2850,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "website", "fieldtype": "Data", "hidden": 0, @@ -2767,6 +2885,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "registration_info", "fieldtype": "Section Break", "hidden": 0, @@ -2801,6 +2920,7 @@ "collapsible": 0, "columns": 0, "description": "Company registration numbers for your reference. Tax numbers etc.", + "fetch_if_empty": 0, "fieldname": "registration_details", "fieldtype": "Code", "hidden": 0, @@ -2834,6 +2954,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "delete_company_transactions", "fieldtype": "Button", "hidden": 0, @@ -2866,6 +2987,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "lft", "fieldtype": "Int", "hidden": 1, @@ -2898,6 +3020,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "rgt", "fieldtype": "Int", "hidden": 1, @@ -2930,6 +3053,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "old_parent", "fieldtype": "Data", "hidden": 1, @@ -2969,7 +3093,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2019-01-15 13:29:54.510379", + "modified": "2019-03-26 17:15:50.390548", "modified_by": "Administrator", "module": "Setup", "name": "Company", diff --git a/erpnext/setup/doctype/sales_partner/sales_partner.js b/erpnext/setup/doctype/sales_partner/sales_partner.js index 30c2c91d6f..7164add495 100644 --- a/erpnext/setup/doctype/sales_partner/sales_partner.js +++ b/erpnext/setup/doctype/sales_partner/sales_partner.js @@ -13,5 +13,16 @@ frappe.ui.form.on('Sales Partner', { unhide_field(['address_html', 'contact_html', 'address_contacts']); frappe.contacts.render_address_and_contact(frm); } + }, + + setup: function(frm) { + frm.fields_dict["targets"].grid.get_field("distribution_id").get_query = function(doc, cdt, cdn){ + var row = locals[cdt][cdn]; + return { + filters: { + 'fiscal_year': row.fiscal_year + } + } + }; } }); diff --git a/erpnext/setup/doctype/sales_partner/sales_partner.json b/erpnext/setup/doctype/sales_partner/sales_partner.json index 351aba210c..28cdd3e10c 100644 --- a/erpnext/setup/doctype/sales_partner/sales_partner.json +++ b/erpnext/setup/doctype/sales_partner/sales_partner.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 1, @@ -21,6 +22,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "partner_name", "fieldtype": "Data", "hidden": 0, @@ -45,7 +47,7 @@ "search_index": 0, "set_only_once": 0, "translatable": 0, - "unique": 0 + "unique": 1 }, { "allow_bulk_edit": 0, @@ -54,6 +56,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "partner_type", "fieldtype": "Link", "hidden": 0, @@ -89,6 +92,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "territory", "fieldtype": "Link", "hidden": 0, @@ -121,6 +125,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break0", "fieldtype": "Column Break", "hidden": 0, @@ -153,6 +158,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "commission_rate", "fieldtype": "Float", "hidden": 0, @@ -186,6 +192,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "address_contacts", "fieldtype": "Section Break", "hidden": 0, @@ -218,6 +225,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.__islocal", + "fetch_if_empty": 0, "fieldname": "address_desc", "fieldtype": "HTML", "hidden": 0, @@ -249,6 +257,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "address_html", "fieldtype": "HTML", "hidden": 0, @@ -280,6 +289,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break1", "fieldtype": "Column Break", "hidden": 0, @@ -311,6 +321,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.__islocal", + "fetch_if_empty": 0, "fieldname": "contact_desc", "fieldtype": "HTML", "hidden": 0, @@ -342,6 +353,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "contact_html", "fieldtype": "HTML", "hidden": 0, @@ -373,6 +385,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "partner_target_details_section_break", "fieldtype": "Section Break", "hidden": 0, @@ -405,6 +418,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "targets", "fieldtype": "Table", "hidden": 0, @@ -439,41 +453,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "description": "Select Monthly Distribution to unevenly distribute targets across months.", - "fieldname": "distribution_id", - "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 Distribution", - "length": 0, - "no_copy": 0, - "oldfieldname": "distribution_id", - "oldfieldtype": "Link", - "options": "Monthly Distribution", - "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, + "fetch_if_empty": 0, "fieldname": "website", "fieldtype": "Section Break", "hidden": 0, @@ -505,6 +485,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "show_in_website", "fieldtype": "Check", "hidden": 0, @@ -537,6 +518,7 @@ "collapsible": 0, "columns": 0, "depends_on": "show_in_website", + "fetch_if_empty": 0, "fieldname": "section_break_17", "fieldtype": "Section Break", "hidden": 0, @@ -567,6 +549,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "route", "fieldtype": "Data", "hidden": 0, @@ -599,6 +582,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_20", "fieldtype": "Column Break", "hidden": 0, @@ -629,6 +613,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "logo", "fieldtype": "Attach", "hidden": 0, @@ -661,6 +646,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "partner_website", "fieldtype": "Data", "hidden": 0, @@ -693,6 +679,7 @@ "collapsible": 0, "columns": 0, "depends_on": "show_in_website", + "fetch_if_empty": 0, "fieldname": "section_break_22", "fieldtype": "Section Break", "hidden": 0, @@ -723,6 +710,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "introduction", "fieldtype": "Text", "hidden": 0, @@ -754,6 +742,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "description", "fieldtype": "Text Editor", "hidden": 0, @@ -790,7 +779,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-06-11 13:47:04.182339", + "modified": "2019-03-21 16:26:45.447265", "modified_by": "Administrator", "module": "Setup", "name": "Sales Partner", @@ -860,5 +849,6 @@ "show_name_in_global_search": 1, "sort_order": "ASC", "track_changes": 0, - "track_seen": 0 + "track_seen": 0, + "track_views": 0 } \ No newline at end of file diff --git a/erpnext/setup/doctype/sales_person/sales_person.js b/erpnext/setup/doctype/sales_person/sales_person.js index 584f879431..9ff37fa4e8 100644 --- a/erpnext/setup/doctype/sales_person/sales_person.js +++ b/erpnext/setup/doctype/sales_person/sales_person.js @@ -8,6 +8,17 @@ frappe.ui.form.on('Sales Person', { frm.dashboard.add_indicator(__('Total Contribution Amount: {0}', [format_currency(info.allocated_amount, info.currency)]), 'blue'); } + }, + + setup: function(frm) { + frm.fields_dict["targets"].grid.get_field("distribution_id").get_query = function(doc, cdt, cdn){ + var row = locals[cdt][cdn]; + return { + filters: { + 'fiscal_year': row.fiscal_year + } + } + }; } }); diff --git a/erpnext/setup/doctype/sales_person/sales_person.json b/erpnext/setup/doctype/sales_person/sales_person.json index 73f7623ba0..5a32028dac 100644 --- a/erpnext/setup/doctype/sales_person/sales_person.json +++ b/erpnext/setup/doctype/sales_person/sales_person.json @@ -22,6 +22,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "name_and_employee_id", "fieldtype": "Section Break", "hidden": 0, @@ -54,6 +55,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sales_person_name", "fieldtype": "Data", "hidden": 0, @@ -88,6 +90,7 @@ "collapsible": 0, "columns": 0, "description": "Select company name first.", + "fetch_if_empty": 0, "fieldname": "parent_sales_person", "fieldtype": "Link", "hidden": 0, @@ -122,6 +125,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "commission_rate", "fieldtype": "Data", "hidden": 0, @@ -154,6 +158,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "is_group", "fieldtype": "Check", "hidden": 0, @@ -189,6 +194,7 @@ "collapsible": 0, "columns": 0, "default": "1", + "fetch_if_empty": 0, "fieldname": "enabled", "fieldtype": "Check", "hidden": 0, @@ -221,6 +227,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "cb0", "fieldtype": "Column Break", "hidden": 0, @@ -251,6 +258,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "employee", "fieldtype": "Link", "hidden": 0, @@ -284,6 +292,7 @@ "collapsible": 0, "columns": 0, "fetch_from": "employee.department", + "fetch_if_empty": 0, "fieldname": "department", "fieldtype": "Link", "hidden": 0, @@ -317,6 +326,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "lft", "fieldtype": "Int", "hidden": 1, @@ -350,6 +360,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "rgt", "fieldtype": "Int", "hidden": 1, @@ -383,6 +394,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "old_parent", "fieldtype": "Data", "hidden": 1, @@ -417,6 +429,7 @@ "collapsible": 0, "columns": 0, "description": "Set targets Item Group-wise for this Sales Person.", + "fetch_if_empty": 0, "fieldname": "target_details_section_break", "fieldtype": "Section Break", "hidden": 0, @@ -450,6 +463,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "targets", "fieldtype": "Table", "hidden": 0, @@ -476,41 +490,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, - "description": "Select Monthly Distribution to unevenly distribute targets across months.", - "fieldname": "distribution_id", - "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 Distribution", - "length": 0, - "no_copy": 0, - "oldfieldname": "distribution_id", - "oldfieldtype": "Link", - "options": "Monthly Distribution", - "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 } ], "has_web_view": 0, @@ -524,7 +503,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2019-01-30 11:28:16.966735", + "modified": "2019-03-21 16:26:01.706129", "modified_by": "Administrator", "module": "Setup", "name": "Sales Person", diff --git a/erpnext/setup/doctype/target_detail/target_detail.json b/erpnext/setup/doctype/target_detail/target_detail.json index 55d437cbd0..768cf9f83a 100644 --- a/erpnext/setup/doctype/target_detail/target_detail.json +++ b/erpnext/setup/doctype/target_detail/target_detail.json @@ -19,6 +19,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "item_group", "fieldtype": "Link", "hidden": 0, @@ -53,6 +54,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "fiscal_year", "fieldtype": "Link", "hidden": 0, @@ -87,6 +89,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "target_qty", "fieldtype": "Float", "hidden": 0, @@ -120,6 +123,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "target_amount", "fieldtype": "Float", "hidden": 0, @@ -145,6 +149,40 @@ "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": "distribution_id", + "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": "Target Distribution", + "length": 0, + "no_copy": 0, + "options": "Monthly Distribution", + "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, @@ -157,7 +195,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2019-01-07 16:56:48.179709", + "modified": "2019-03-20 16:59:03.578274", "modified_by": "Administrator", "module": "Setup", "name": "Target Detail", diff --git a/erpnext/setup/doctype/territory/territory.js b/erpnext/setup/doctype/territory/territory.js index 69f761a687..1eb9958ce7 100644 --- a/erpnext/setup/doctype/territory/territory.js +++ b/erpnext/setup/doctype/territory/territory.js @@ -1,6 +1,18 @@ // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // License: GNU General Public License v3. See license.txt +frappe.ui.form.on("Territory", { + setup: function(frm) { + frm.fields_dict["targets"].grid.get_field("distribution_id").get_query = function(doc, cdt, cdn){ + var row = locals[cdt][cdn]; + return { + filters: { + 'fiscal_year': row.fiscal_year + } + } + }; + } +}); cur_frm.cscript.refresh = function(doc, cdt, cdn) { cur_frm.cscript.set_root_readonly(doc); diff --git a/erpnext/setup/doctype/territory/territory.json b/erpnext/setup/doctype/territory/territory.json index 38d0e0fc80..beadb48377 100644 --- a/erpnext/setup/doctype/territory/territory.json +++ b/erpnext/setup/doctype/territory/territory.json @@ -1,511 +1,487 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 1, - "autoname": "field:territory_name", - "beta": 0, - "creation": "2013-01-10 16:34:24", - "custom": 0, - "description": "Classification of Customers by region", - "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": 1, + "autoname": "field:territory_name", + "beta": 0, + "creation": "2013-01-10 16:34:24", + "custom": 0, + "description": "Classification of Customers by region", + "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": "territory_name", - "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": "Territory Name", - "length": 0, - "no_copy": 1, - "oldfieldname": "territory_name", - "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, + "fetch_if_empty": 0, + "fieldname": "territory_name", + "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": "Territory Name", + "length": 0, + "no_copy": 1, + "oldfieldname": "territory_name", + "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": 1, - "collapsible": 0, - "columns": 0, - "description": "", - "fieldname": "parent_territory", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Parent Territory", - "length": 0, - "no_copy": 0, - "oldfieldname": "parent_territory", - "oldfieldtype": "Link", - "options": "Territory", - "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": 1, + "collapsible": 0, + "columns": 0, + "description": "", + "fetch_if_empty": 0, + "fieldname": "parent_territory", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Parent Territory", + "length": 0, + "no_copy": 0, + "oldfieldname": "parent_territory", + "oldfieldtype": "Link", + "options": "Territory", + "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": 1, - "collapsible": 0, - "columns": 0, - "description": "", - "fieldname": "is_group", - "fieldtype": "Check", - "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": "Is Group", - "length": 0, - "no_copy": 0, - "oldfieldname": "is_group", - "oldfieldtype": "Select", - "options": "", - "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": 1, + "collapsible": 0, + "columns": 0, + "description": "", + "fetch_if_empty": 0, + "fieldname": "is_group", + "fieldtype": "Check", + "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": "Is Group", + "length": 0, + "no_copy": 0, + "oldfieldname": "is_group", + "oldfieldtype": "Select", + "options": "", + "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": "cb0", - "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, + "fetch_if_empty": 0, + "fieldname": "cb0", + "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, - "description": "For reference", - "fieldname": "territory_manager", - "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": "Territory Manager", - "length": 0, - "no_copy": 0, - "oldfieldname": "territory_manager", - "oldfieldtype": "Link", - "options": "Sales Person", - "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": 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, + "description": "For reference", + "fetch_if_empty": 0, + "fieldname": "territory_manager", + "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": "Territory Manager", + "length": 0, + "no_copy": 0, + "oldfieldname": "territory_manager", + "oldfieldtype": "Link", + "options": "Sales Person", + "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": 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": "lft", - "fieldtype": "Int", - "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": "lft", - "length": 0, - "no_copy": 1, - "oldfieldname": "lft", - "oldfieldtype": "Int", - "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": 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, + "fetch_if_empty": 0, + "fieldname": "lft", + "fieldtype": "Int", + "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": "lft", + "length": 0, + "no_copy": 1, + "oldfieldname": "lft", + "oldfieldtype": "Int", + "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": 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": "rgt", - "fieldtype": "Int", - "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": "rgt", - "length": 0, - "no_copy": 1, - "oldfieldname": "rgt", - "oldfieldtype": "Int", - "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": 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, + "fetch_if_empty": 0, + "fieldname": "rgt", + "fieldtype": "Int", + "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": "rgt", + "length": 0, + "no_copy": 1, + "oldfieldname": "rgt", + "oldfieldtype": "Int", + "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": 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, - "description": "", - "fieldname": "old_parent", - "fieldtype": "Link", - "hidden": 1, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "old_parent", - "length": 0, - "no_copy": 1, - "oldfieldname": "old_parent", - "oldfieldtype": "Data", - "options": "Territory", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 1, - "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": "", + "fetch_if_empty": 0, + "fieldname": "old_parent", + "fieldtype": "Link", + "hidden": 1, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "old_parent", + "length": 0, + "no_copy": 1, + "oldfieldname": "old_parent", + "oldfieldtype": "Data", + "options": "Territory", + "permlevel": 0, + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 1, + "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": "Set Item Group-wise budgets on this Territory. You can also include seasonality by setting the Distribution.", - "fieldname": "target_details_section_break", - "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": "Territory Targets", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section 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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "Set Item Group-wise budgets on this Territory. You can also include seasonality by setting the Distribution.", + "fetch_if_empty": 0, + "fieldname": "target_details_section_break", + "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": "Territory Targets", + "length": 0, + "no_copy": 0, + "oldfieldtype": "Section 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, - "fieldname": "targets", - "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": "Targets", - "length": 0, - "no_copy": 0, - "oldfieldname": "target_details", - "oldfieldtype": "Table", - "options": "Target Detail", - "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": "Select Monthly Distribution to unevenly distribute targets across months.", - "fieldname": "distribution_id", - "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 Distribution", - "length": 0, - "no_copy": 0, - "oldfieldname": "distribution_id", - "oldfieldtype": "Link", - "options": "Monthly Distribution", - "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, + "fetch_if_empty": 0, + "fieldname": "targets", + "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": "Targets", + "length": 0, + "no_copy": 0, + "oldfieldname": "target_details", + "oldfieldtype": "Table", + "options": "Target Detail", + "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 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-map-marker", - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-08-29 06:26:38.918259", - "modified_by": "Administrator", - "module": "Setup", - "name": "Territory", - "name_case": "Title Case", - "owner": "Administrator", + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "icon": "fa fa-map-marker", + "idx": 1, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2019-03-21 16:26:58.581431", + "modified_by": "Administrator", + "module": "Setup", + "name": "Territory", + "name_case": "Title Case", + "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": "Sales Master Manager", - "set_user_permissions": 1, - "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": "Sales Master Manager", + "set_user_permissions": 1, + "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": "Sales Manager", - "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 Manager", + "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": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 0, - "read": 1, - "report": 0, - "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": 0, + "role": "Stock User", + "set_user_permissions": 0, + "share": 0, + "submit": 0, "write": 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": 0, - "role": "Maintenance 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": 0, + "role": "Maintenance User", + "set_user_permissions": 0, + "share": 0, + "submit": 0, "write": 0 } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "search_fields": "parent_territory,territory_manager", - "show_name_in_global_search": 1, - "sort_order": "DESC", - "track_changes": 0, - "track_seen": 0, + ], + "quick_entry": 1, + "read_only": 0, + "read_only_onload": 0, + "search_fields": "parent_territory,territory_manager", + "show_name_in_global_search": 1, + "sort_order": "DESC", + "track_changes": 0, + "track_seen": 0, "track_views": 0 } \ No newline at end of file diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py index d21de0ef36..66871dbd5a 100644 --- a/erpnext/setup/setup_wizard/operations/install_fixtures.py +++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py @@ -82,6 +82,19 @@ def install(country=None): {'doctype': 'Employment Type', 'employee_type_name': _('Intern')}, {'doctype': 'Employment Type', 'employee_type_name': _('Apprentice')}, + + # Stock Entry Type + {'doctype': 'Stock Entry Type', 'name': 'Material Issue', 'purpose': 'Material Issue'}, + {'doctype': 'Stock Entry Type', 'name': 'Material Receipt', 'purpose': 'Material Receipt'}, + {'doctype': 'Stock Entry Type', 'name': 'Material Transfer', 'purpose': 'Material Transfer'}, + {'doctype': 'Stock Entry Type', 'name': 'Manufacture', 'purpose': 'Manufacture'}, + {'doctype': 'Stock Entry Type', 'name': 'Repack', 'purpose': 'Repack'}, + {'doctype': 'Stock Entry Type', 'name': 'Send to Subcontractor', 'purpose': 'Send to Subcontractor'}, + {'doctype': 'Stock Entry Type', 'name': 'Material Transfer for Manufacture', 'purpose': 'Material Transfer for Manufacture'}, + {'doctype': 'Stock Entry Type', 'name': 'Material Consumption for Manufacture', 'purpose': 'Material Consumption for Manufacture'}, + {'doctype': 'Stock Entry Type', 'name': 'Send to Warehouse', 'purpose': 'Send to Warehouse'}, + {'doctype': 'Stock Entry Type', 'name': 'Receive at Warehouse', 'purpose': 'Receive at Warehouse'}, + # Designation {'doctype': 'Designation', 'designation_name': _('CEO')}, {'doctype': 'Designation', 'designation_name': _('Manager')}, diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index 71fd82181e..4881983b8e 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -202,6 +202,7 @@ def split_batch(batch_no, item_code, warehouse, qty, new_batch_id=None): ), ] )) + stock_entry.set_stock_entry_type() stock_entry.insert() stock_entry.submit() diff --git a/erpnext/stock/doctype/batch/test_batch.py b/erpnext/stock/doctype/batch/test_batch.py index 343d517c23..737f528761 100644 --- a/erpnext/stock/doctype/batch/test_batch.py +++ b/erpnext/stock/doctype/batch/test_batch.py @@ -67,7 +67,10 @@ class TestBatch(unittest.TestCase): rate = 10 ) ] - )).insert() + )) + + stock_entry.set_stock_entry_type() + stock_entry.insert() stock_entry.submit() self.assertTrue(stock_entry.items[0].batch_no) @@ -136,7 +139,10 @@ class TestBatch(unittest.TestCase): s_warehouse=receipt.items[0].warehouse, ) ] - )).insert() + )) + + stock_entry.set_stock_entry_type() + stock_entry.insert() stock_entry.submit() # assert same batch is selected @@ -193,7 +199,10 @@ class TestBatch(unittest.TestCase): allow_zero_valuation_rate = 1 ) ] - )).insert() + )) + + stock_entry.set_stock_entry_type() + stock_entry.insert() stock_entry.submit() def test_batch_name_with_naming_series(self): diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py index aa5c69e64f..97a84726da 100644 --- a/erpnext/stock/doctype/bin/bin.py +++ b/erpnext/stock/doctype/bin/bin.py @@ -106,7 +106,7 @@ class Bin(Document): `tabStock Entry` se, `tabStock Entry Detail` sed, `tabPurchase Order` po where se.docstatus=1 - and se.purpose='Subcontract' + and se.purpose='Send to Subcontractor' and ifnull(se.purchase_order, '') !='' and (sed.item_code = %(item)s or sed.original_item = %(item)s) and se.name = sed.parent diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index b39abdbeb3..90d1d0a401 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -177,7 +177,7 @@ class DeliveryNote(SellingController): frappe.msgprint(_("Note: Item {0} entered multiple times").format(d.item_code)) else: chk_dupl_itm.append(f) - #Customer Provided parts will have zero valuation rate + #Customer Provided parts will have zero valuation rate if frappe.db.get_value('Item', d.item_code, 'is_customer_provided_item'): d.allow_zero_valuation_rate = 1 @@ -223,6 +223,8 @@ class DeliveryNote(SellingController): self.make_gl_entries() def on_cancel(self): + super(DeliveryNote, self).on_cancel() + self.check_sales_order_on_hold_or_close("against_sales_order") self.check_next_docstatus() diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 73c009c7fb..a1083051f1 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -118,7 +118,6 @@ class Item(WebsiteGenerator): self.validate_has_variants() self.validate_stock_exists_for_template_item() - self.validate_asset_exists_for_serialized_asset() self.validate_attributes() self.validate_variant_attributes() self.validate_website_image() @@ -128,6 +127,7 @@ class Item(WebsiteGenerator): self.validate_uom_conversion_factor() self.validate_item_defaults() self.validate_customer_provided_part() + self.validate_stock_for_has_batch_and_has_serial() if not self.get("__islocal"): self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group") @@ -759,12 +759,6 @@ class Item(WebsiteGenerator): frappe.throw( _('Cannot change Attributes after stock transaction. Make a new Item and transfer stock to the new Item')) - def validate_asset_exists_for_serialized_asset(self): - if (not self.get("__islocal") and self.asset_exists() and - cint(self.has_serial_no) != cint(frappe.db.get_value('Item', self.name, 'has_serial_no'))): - frappe.throw(_("Asset is already exists against the item {0}, you cannot change the has serial no value") - .format(self.name)) - def asset_exists(self): if not hasattr(self, '_asset_created'): self._asset_created = frappe.db.get_all("Asset", @@ -791,6 +785,9 @@ class Item(WebsiteGenerator): d.conversion_factor = value def validate_attributes(self): + if not self.variant_based_on: + self.variant_based_on = 'Item Attribute' + if (self.has_variants or self.variant_of) and self.variant_based_on == 'Item Attribute': attributes = [] if not self.attributes: @@ -813,7 +810,7 @@ class Item(WebsiteGenerator): variant = get_variant(self.variant_of, args, self.name) if variant: frappe.throw(_("Item variant {0} exists with same attributes") - .format(variant), ItemVariantExistsError) + .format(variant), ItemVariantExistsError) validate_item_variant_attributes(self, args) @@ -821,6 +818,11 @@ class Item(WebsiteGenerator): for d in self.attributes: d.variant_of = self.variant_of + def validate_stock_for_has_batch_and_has_serial(self): + if self.stock_ledger_created(): + for value in ["has_batch_no", "has_serial_no"]: + if frappe.db.get_value("Item", self.name, value) != self.get_value(value): + frappe.throw(_("Cannot change {0} as Stock Transaction for Item {1} exist.".format(value, self.name))) def get_timeline_data(doctype, name): '''returns timeline data based on stock ledger entry''' diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index 1a94d5a680..da53d8d6b1 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -18,7 +18,7 @@ from erpnext.stock.get_item_details import get_item_details from six import iteritems test_ignore = ["BOM"] -test_dependencies = ["Warehouse", "Item Group", "Item Tax Template"] +test_dependencies = ["Warehouse", "Item Group", "Item Tax Template", "Brand"] def make_item(item_code, properties=None): if frappe.db.exists("Item", item_code): @@ -513,3 +513,6 @@ def create_item(item_code, is_stock_item=None, valuation_rate=0, warehouse=None, "company": "_Test Company" }) item.save() + else: + item = frappe.get_doc("Item", item_code) + return item diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index ec10367a49..86baeae60e 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -428,6 +428,7 @@ def make_stock_entry(source_name, target_doc=None): target.purpose = "Material Receipt" target.run_method("calculate_rate_and_amount") + target.set_stock_entry_type() target.set_job_card_data() doclist = get_mapped_doc("Material Request", source_name, { diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py index 69bd43927c..7dc54d0e33 100644 --- a/erpnext/stock/doctype/material_request/test_material_request.py +++ b/erpnext/stock/doctype/material_request/test_material_request.py @@ -96,6 +96,8 @@ class TestMaterialRequest(unittest.TestCase): } ] }) + + se.set_stock_entry_type() se.insert() se.submit() @@ -388,6 +390,7 @@ class TestMaterialRequest(unittest.TestCase): # check for stopped status of Material Request se = frappe.copy_doc(se_doc) + se.set_stock_entry_type() se.insert() mr.update_status('Stopped') self.assertRaises(frappe.InvalidStatusError, se.submit) @@ -395,6 +398,7 @@ class TestMaterialRequest(unittest.TestCase): mr.update_status('Submitted') se = frappe.copy_doc(se_doc) + se.set_stock_entry_type() se.insert() se.submit() @@ -528,7 +532,7 @@ class TestMaterialRequest(unittest.TestCase): #testing bin requested qty after issuing stock against material request self.assertEqual(_get_requested_qty(), existing_requested_qty) - + def test_material_request_type_manufacture(self): mr = frappe.copy_doc(test_records[1]).insert() mr = frappe.get_doc("Material Request", mr.name) @@ -541,20 +545,20 @@ class TestMaterialRequest(unittest.TestCase): po = frappe.get_doc("Work Order", prod_order[0]) po.wip_warehouse = "_Test Warehouse 1 - _TC" po.submit() - + mr = frappe.get_doc("Material Request", mr.name) self.assertEqual(completed_qty + po.qty, mr.items[0].ordered_qty) new_requested_qty = frappe.db.sql("""select indented_qty from `tabBin` where \ item_code= %s and warehouse= %s """, (mr.items[0].item_code, mr.items[0].warehouse))[0][0] - + self.assertEqual(requested_qty - po.qty, new_requested_qty) - + po.cancel() mr = frappe.get_doc("Material Request", mr.name) self.assertEqual(completed_qty, mr.items[0].ordered_qty) - + new_requested_qty = frappe.db.sql("""select indented_qty from `tabBin` where \ item_code= %s and warehouse= %s """, (mr.items[0].item_code, mr.items[0].warehouse))[0][0] self.assertEqual(requested_qty, new_requested_qty) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 6039939755..bfbcb3cf8d 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -14,6 +14,16 @@ frappe.ui.form.on('Stock Entry', { } }); + frm.set_query('outgoing_stock_entry', function() { + return { + filters: [ + ['Stock Entry', 'docstatus', '=', 1], + ['Stock Entry', 'per_transferred', '<','100'], + ['Stock Entry', 'purpose', '=', 'Send to Warehouse'] + ] + } + }); + frappe.db.get_value('Stock Settings', {name: 'Stock Settings'}, 'sample_retention_warehouse', (r) => { if (r.sample_retention_warehouse) { var filters = [ @@ -39,7 +49,7 @@ frappe.ui.form.on('Stock Entry', { if(!item.item_code) { frappe.throw(__("Please enter Item Code to get Batch Number")); } else { - if (in_list(["Material Transfer for Manufacture", "Manufacture", "Repack", "Subcontract"], doc.purpose)) { + if (in_list(["Material Transfer for Manufacture", "Manufacture", "Repack", "Send to Subcontractor"], doc.purpose)) { var filters = { 'item_code': item.item_code, 'posting_date': frm.doc.posting_date || frappe.datetime.nowdate() @@ -92,6 +102,16 @@ frappe.ui.form.on('Stock Entry', { }); }, + outgoing_stock_entry: function(frm) { + frappe.call({ + doc: frm.doc, + method: "set_items_for_stock_in", + callback: function() { + refresh_field('items'); + } + }); + }, + refresh: function(frm) { if(!frm.doc.docstatus) { frm.trigger('validate_purpose_consumption'); @@ -139,6 +159,28 @@ frappe.ui.form.on('Stock Entry', { } } + if (frm.doc.docstatus === 1 && frm.doc.purpose == 'Send to Warehouse') { + if (frm.doc.per_transferred < 100) { + frm.add_custom_button(__('Receive at Warehouse Entry'), function() { + frappe.model.open_mapped_doc({ + method: "erpnext.stock.doctype.stock_entry.stock_entry.make_stock_in_entry", + frm: frm + }) + }); + } + + if (frm.doc.per_transferred > 0) { + frm.add_custom_button(__('Received Stock Entries'), function() { + frappe.route_options = { + 'outgoing_stock_entry': frm.doc.name, + 'docstatus': ['!=', 2] + }; + + frappe.set_route('List', 'Stock Entry'); + }, __("View")); + } + } + if (frm.doc.docstatus===0) { frm.add_custom_button(__('Purchase Invoice'), function() { erpnext.utils.map_current_doc({ @@ -154,6 +196,23 @@ frappe.ui.form.on('Stock Entry', { } }) }, __("Get items from")); + + frm.add_custom_button(__('Material Request'), function() { + erpnext.utils.map_current_doc({ + method: "erpnext.stock.doctype.material_request.material_request.make_stock_entry", + source_doctype: "Material Request", + target: frm, + date_field: "schedule_date", + setters: { + company: frm.doc.company, + }, + get_query_filters: { + docstatus: 1, + material_request_type: "Material Transfer", + status: ['!=', 'Transferred'] + } + }) + }, __("Get items from")); } if (frm.doc.docstatus===0 && frm.doc.purpose == "Material Issue") { frm.add_custom_button(__('Expired Batches'), function() { @@ -457,6 +516,7 @@ frappe.ui.form.on('Stock Entry Detail', { 'voucher_no' : d.name, 'allow_zero_valuation': 1, }; + return frappe.call({ doc: frm.doc, method: "get_item_details", @@ -721,8 +781,10 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ if(!row.t_warehouse) row.t_warehouse = this.frm.doc.to_warehouse; }, - source_mandatory: ["Material Issue", "Material Transfer", "Subcontract", "Material Transfer for Manufacture"], - target_mandatory: ["Material Receipt", "Material Transfer", "Subcontract", "Material Transfer for Manufacture"], + source_mandatory: ["Material Issue", "Material Transfer", "Send to Subcontractor", + "Material Transfer for Manufacture", "Send to Warehouse", "Receive at Warehouse"], + target_mandatory: ["Material Receipt", "Material Transfer", "Send to Subcontractor", + "Material Transfer for Manufacture", "Send to Warehouse", "Receive at Warehouse"], from_warehouse: function(doc) { var me = this; @@ -769,7 +831,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ this.frm.cscript.toggle_enable_bom(); - if (doc.purpose == 'Subcontract') { + if (doc.purpose == 'Send to Subcontractor') { doc.customer = doc.customer_name = doc.customer_address = doc.delivery_note_no = doc.sales_invoice_no = null; } else { @@ -787,6 +849,8 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ doc.purpose!='Material Issue'); this.frm.fields_dict["items"].grid.set_column_disp("additional_cost", doc.purpose!='Material Issue'); + this.frm.toggle_reqd("outgoing_stock_entry", + doc.purpose == 'Receive at Warehouse' ? 1: 0); }, supplier: function(doc) { diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json index 6a925adef1..4a2ae538ae 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.json +++ b/erpnext/stock/doctype/stock_entry/stock_entry.json @@ -1,2178 +1,2342 @@ { - "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-04-09 11:43:55", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Document", - "editable_grid": 0, - "engine": "InnoDB", + "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-04-09 11:43:55", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Document", + "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": "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": "", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section 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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "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": "", + "length": 0, + "no_copy": 0, + "oldfieldtype": "Section 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": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "{purpose}", - "fieldname": "title", - "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": "Title", - "length": 0, - "no_copy": 1, - "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": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "{purpose}", + "fetch_if_empty": 0, + "fieldname": "title", + "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": "Title", + "length": 0, + "no_copy": 1, + "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, - "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": 1, - "oldfieldname": "naming_series", - "oldfieldtype": "Select", - "options": "MAT-STE-.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": "", + "fetch_if_empty": 0, + "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": 1, + "oldfieldname": "naming_series", + "oldfieldtype": "Select", + "options": "MAT-STE-.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": 1, - "collapsible": 0, - "columns": 0, - "default": "Material Issue", - "fieldname": "purpose", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Purpose", - "length": 0, - "no_copy": 0, - "oldfieldname": "purpose", - "oldfieldtype": "Select", - "options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSubcontract", - "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, + "fetch_if_empty": 0, + "fieldname": "stock_entry_type", + "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": 1, + "label": "Stock Entry Type", + "length": 0, + "no_copy": 0, + "options": "Stock Entry Type", + "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": "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": 1, - "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, + "depends_on": "eval:doc.purpose == 'Receive at Warehouse'", + "fetch_if_empty": 0, + "fieldname": "outgoing_stock_entry", + "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 Entry (Outward GIT)", + "length": 0, + "no_copy": 0, + "options": "Stock Entry", + "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:in_list([\"Material Transfer for Manufacture\", \"Manufacture\", \"Material Consumption for Manufacture\"], doc.purpose)", - "fieldname": "work_order", - "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 Order", - "length": 0, - "no_copy": 0, - "oldfieldname": "production_order", - "oldfieldtype": "Link", - "options": "Work Order", - "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": 1, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 0, + "default": "", + "fetch_from": "stock_entry_type.purpose", + "fetch_if_empty": 0, + "fieldname": "purpose", + "fieldtype": "Select", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Purpose", + "length": 0, + "no_copy": 0, + "oldfieldname": "purpose", + "oldfieldtype": "Select", + "options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor\nSend to Warehouse\nReceive at Warehouse", + "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": "eval:doc.purpose==\"Subcontract\"", - "fieldname": "purchase_order", - "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": "Purchase Order", - "length": 0, - "no_copy": 0, - "options": "Purchase Order", - "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, + "fetch_if_empty": 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": 1, + "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": "eval:doc.purpose==\"Sales Return\"", - "fieldname": "delivery_note_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": "Delivery Note No", - "length": 0, - "no_copy": 1, - "oldfieldname": "delivery_note_no", - "oldfieldtype": "Link", - "options": "Delivery Note", - "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": 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, + "depends_on": "eval:in_list([\"Material Transfer for Manufacture\", \"Manufacture\", \"Material Consumption for Manufacture\"], doc.purpose)", + "fetch_if_empty": 0, + "fieldname": "work_order", + "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 Order", + "length": 0, + "no_copy": 0, + "oldfieldname": "production_order", + "oldfieldtype": "Link", + "options": "Work Order", + "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": 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, - "depends_on": "eval:doc.purpose==\"Sales Return\"", - "fieldname": "sales_invoice_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": "Sales Invoice No", - "length": 0, - "no_copy": 1, - "options": "Sales Invoice", - "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, + "depends_on": "eval:doc.purpose==\"Send to Subcontractor\"", + "fetch_if_empty": 0, + "fieldname": "purchase_order", + "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": "Purchase Order", + "length": 0, + "no_copy": 0, + "options": "Purchase Order", + "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.purpose==\"Purchase Return\"", - "fieldname": "purchase_receipt_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": "Purchase Receipt No", - "length": 0, - "no_copy": 1, - "oldfieldname": "purchase_receipt_no", - "oldfieldtype": "Link", - "options": "Purchase Receipt", - "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": 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, + "depends_on": "eval:doc.purpose==\"Sales Return\"", + "fetch_if_empty": 0, + "fieldname": "delivery_note_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": "Delivery Note No", + "length": 0, + "no_copy": 1, + "oldfieldname": "delivery_note_no", + "oldfieldtype": "Link", + "options": "Delivery Note", + "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": 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, - "depends_on": "eval:in_list([\"Material Issue\", \"Material Transfer\", \"Manufacture\", \"Repack\", \t\t\t\t\t\"Subcontract\", \"Material Transfer for Manufacture\", \"Material Consumption for Manufacture\"], doc.purpose)", - "fieldname": "from_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": "From BOM", - "length": 0, - "no_copy": 0, - "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, + "depends_on": "eval:doc.purpose==\"Sales Return\"", + "fetch_if_empty": 0, + "fieldname": "sales_invoice_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": "Sales Invoice No", + "length": 0, + "no_copy": 1, + "options": "Sales Invoice", + "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": "inspection_required", - "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": "Inspection Required", - "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": "eval:doc.purpose==\"Purchase Return\"", + "fetch_if_empty": 0, + "fieldname": "purchase_receipt_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": "Purchase Receipt No", + "length": 0, + "no_copy": 1, + "oldfieldname": "purchase_receipt_no", + "oldfieldtype": "Link", + "options": "Purchase Receipt", + "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": 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": "col2", - "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, - "print_width": "50%", - "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": "col2", + "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, + "print_width": "50%", + "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, - "default": "Today", - "depends_on": "", - "fieldname": "posting_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": "Posting Date", - "length": 0, - "no_copy": 1, - "oldfieldname": "posting_date", - "oldfieldtype": "Date", - "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": 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": "Today", + "depends_on": "", + "fetch_if_empty": 0, + "fieldname": "posting_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": "Posting Date", + "length": 0, + "no_copy": 1, + "oldfieldname": "posting_date", + "oldfieldtype": "Date", + "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": 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, - "depends_on": "", - "fieldname": "posting_time", - "fieldtype": "Time", - "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": "Posting Time", - "length": 0, - "no_copy": 1, - "oldfieldname": "posting_time", - "oldfieldtype": "Time", - "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, + "depends_on": "", + "fetch_if_empty": 0, + "fieldname": "posting_time", + "fieldtype": "Time", + "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": "Posting Time", + "length": 0, + "no_copy": 1, + "oldfieldname": "posting_time", + "oldfieldtype": "Time", + "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, - "depends_on": "eval:doc.docstatus==0", - "fieldname": "set_posting_time", - "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": "Edit Posting Date and Time", - "length": 0, - "no_copy": 0, - "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, + "depends_on": "eval:doc.docstatus==0", + "fetch_if_empty": 0, + "fieldname": "set_posting_time", + "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": "Edit Posting Date and Time", + "length": 0, + "no_copy": 0, + "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, - "depends_on": "eval: doc.from_bom && (doc.purpose!==\"Sales Return\" && doc.purpose!==\"Purchase Return\")", - "fieldname": "sb1", - "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, - "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, + "fetch_if_empty": 0, + "fieldname": "inspection_required", + "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": "Inspection Required", + "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, - "depends_on": "from_bom", - "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, - "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": 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": "eval:in_list([\"Material Issue\", \"Material Transfer\", \"Manufacture\", \"Repack\", \t\t\t\t\t\"Send to Subcontractor\", \"Material Transfer for Manufacture\", \"Material Consumption for Manufacture\"], doc.purpose)", + "fetch_if_empty": 0, + "fieldname": "from_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": "From BOM", + "length": 0, + "no_copy": 0, + "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, - "depends_on": "from_bom", - "description": "As per Stock UOM", - "fieldname": "fg_completed_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": "For Quantity", - "length": 0, - "no_copy": 0, - "oldfieldname": "fg_completed_qty", - "oldfieldtype": "Currency", - "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, + "depends_on": "eval: doc.from_bom && (doc.purpose!==\"Sales Return\" && doc.purpose!==\"Purchase Return\")", + "fetch_if_empty": 0, + "fieldname": "sb1", + "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, + "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": "cb1", - "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, + "depends_on": "from_bom", + "fetch_if_empty": 0, + "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, + "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": 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": "1", - "depends_on": "from_bom", - "description": "Including items 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, + "depends_on": "from_bom", + "description": "As per Stock UOM", + "fetch_if_empty": 0, + "fieldname": "fg_completed_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": "For Quantity", + "length": 0, + "no_copy": 0, + "oldfieldname": "fg_completed_qty", + "oldfieldtype": "Currency", + "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, - "depends_on": "from_bom", - "fieldname": "get_items", - "fieldtype": "Button", - "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": "Get Items", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Button", - "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, + "fetch_if_empty": 0, + "fieldname": "cb1", + "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": "section_break_12", - "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": "1", + "depends_on": "from_bom", + "description": "Including items for sub assemblies", + "fetch_if_empty": 0, + "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": "from_warehouse", - "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": 1, - "label": "Default Source Warehouse", - "length": 0, - "no_copy": 1, - "oldfieldname": "from_warehouse", - "oldfieldtype": "Link", - "options": "Warehouse", - "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, + "depends_on": "from_bom", + "fetch_if_empty": 0, + "fieldname": "get_items", + "fieldtype": "Button", + "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": "Get Items", + "length": 0, + "no_copy": 0, + "oldfieldtype": "Button", + "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, - "depends_on": "from_warehouse", - "fieldname": "source_warehouse_address", - "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": "Source Warehouse Address", - "length": 0, - "no_copy": 0, - "options": "Address", - "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, + "fetch_if_empty": 0, + "fieldname": "section_break_12", + "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, - "fieldname": "source_address_display", - "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": "Source Warehouse Address", - "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, + "fetch_if_empty": 0, + "fieldname": "from_warehouse", + "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": 1, + "label": "Default Source Warehouse", + "length": 0, + "no_copy": 1, + "oldfieldname": "from_warehouse", + "oldfieldtype": "Link", + "options": "Warehouse", + "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": "cb0", - "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, + "depends_on": "from_warehouse", + "fetch_if_empty": 0, + "fieldname": "source_warehouse_address", + "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": "Source Warehouse Address", + "length": 0, + "no_copy": 0, + "options": "Address", + "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": "to_warehouse", - "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": 1, - "label": "Default Target Warehouse", - "length": 0, - "no_copy": 1, - "oldfieldname": "to_warehouse", - "oldfieldtype": "Link", - "options": "Warehouse", - "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, + "fetch_if_empty": 0, + "fieldname": "source_address_display", + "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": "Source Warehouse Address", + "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, - "depends_on": "to_warehouse", - "fieldname": "target_warehouse_address", - "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 Name", - "length": 0, - "no_copy": 0, - "options": "Address", - "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, + "fetch_if_empty": 0, + "fieldname": "cb0", + "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": "target_address_display", - "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": "Target Warehouse Address", - "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, + "fetch_if_empty": 0, + "fieldname": "to_warehouse", + "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": 1, + "label": "Default Target Warehouse", + "length": 0, + "no_copy": 1, + "oldfieldname": "to_warehouse", + "oldfieldtype": "Link", + "options": "Warehouse", + "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": "sb0", - "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, - "options": "Simple", - "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": "to_warehouse", + "fetch_if_empty": 0, + "fieldname": "target_warehouse_address", + "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 Name", + "length": 0, + "no_copy": 0, + "options": "Address", + "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": "scan_barcode", - "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": "Scan Barcode", - "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, + "fetch_if_empty": 0, + "fieldname": "target_address_display", + "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": "Target Warehouse Address", + "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": "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": "Items", - "length": 0, - "no_copy": 0, - "oldfieldname": "mtn_details", - "oldfieldtype": "Table", - "options": "Stock Entry Detail", - "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, + "fetch_if_empty": 0, + "fieldname": "sb0", + "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, + "options": "Simple", + "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": "", - "fieldname": "get_stock_and_rate", - "fieldtype": "Button", - "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": "Update Rate and Availability", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Button", - "options": "get_stock_and_rate", - "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, + "fetch_if_empty": 0, + "fieldname": "scan_barcode", + "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": "Scan Barcode", + "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_19", - "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": 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, + "fetch_if_empty": 0, + "fieldname": "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": "Items", + "length": 0, + "no_copy": 0, + "oldfieldname": "mtn_details", + "oldfieldtype": "Table", + "options": "Stock Entry Detail", + "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, - "fieldname": "total_incoming_value", - "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 Incoming Value", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "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, + "description": "", + "fetch_if_empty": 0, + "fieldname": "get_stock_and_rate", + "fieldtype": "Button", + "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": "Update Rate and Availability", + "length": 0, + "no_copy": 0, + "oldfieldtype": "Button", + "options": "get_stock_and_rate", + "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_break_22", - "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, + "fetch_if_empty": 0, + "fieldname": "section_break_19", + "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": 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": "total_outgoing_value", - "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 Outgoing Value", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "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, + "fetch_if_empty": 0, + "fieldname": "total_incoming_value", + "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 Incoming Value", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "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": "value_difference", - "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 Value Difference (Out - In)", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 1, - "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, + "fetch_if_empty": 0, + "fieldname": "column_break_22", + "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": 1, - "collapsible_depends_on": "total_additional_costs", - "columns": 0, - "fieldname": "additional_costs_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": "Additional Costs", - "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, + "fetch_if_empty": 0, + "fieldname": "total_outgoing_value", + "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 Outgoing Value", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "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": "additional_costs", - "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": "Additional Costs", - "length": 0, - "no_copy": 0, - "options": "Landed Cost Taxes and Charges", - "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, + "fetch_if_empty": 0, + "fieldname": "value_difference", + "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 Value Difference (Out - In)", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 1, + "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": "total_additional_costs", - "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 Additional Costs", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 1, - "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": 1, + "collapsible_depends_on": "total_additional_costs", + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "additional_costs_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": "Additional Costs", + "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": 1, - "columns": 0, - "depends_on": "eval: in_list([\"Sales Return\", \"Purchase Return\", \"Subcontract\"], doc.purpose)", - "fieldname": "contact_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": "Customer or Supplier Details", - "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, + "fetch_if_empty": 0, + "fieldname": "additional_costs", + "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": "Additional Costs", + "length": 0, + "no_copy": 0, + "options": "Landed Cost Taxes and Charges", + "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.purpose==\"Purchase Return\" || doc.purpose==\"Subcontract\"", - "fieldname": "supplier", - "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": "Supplier", - "length": 0, - "no_copy": 1, - "oldfieldname": "supplier", - "oldfieldtype": "Link", - "options": "Supplier", - "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, + "fetch_if_empty": 0, + "fieldname": "total_additional_costs", + "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 Additional Costs", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 1, + "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": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.purpose==\"Purchase Return\" || doc.purpose==\"Subcontract\"", - "fieldname": "supplier_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": "Supplier Name", - "length": 0, - "no_copy": 1, - "oldfieldname": "supplier_name", - "oldfieldtype": "Data", - "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": 1, + "columns": 0, + "depends_on": "eval: in_list([\"Sales Return\", \"Purchase Return\", \"Send to Subcontractor\"], doc.purpose)", + "fetch_if_empty": 0, + "fieldname": "contact_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": "Customer or Supplier Details", + "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": "eval:doc.purpose==\"Purchase Return\" || doc.purpose==\"Subcontract\"", - "fieldname": "supplier_address", - "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": "Supplier Address", - "length": 0, - "no_copy": 1, - "oldfieldname": "supplier_address", - "oldfieldtype": "Small Text", - "options": "Address", - "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": "eval:doc.purpose==\"Purchase Return\" || doc.purpose==\"Send to Subcontractor\"", + "fetch_if_empty": 0, + "fieldname": "supplier", + "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": "Supplier", + "length": 0, + "no_copy": 1, + "oldfieldname": "supplier", + "oldfieldtype": "Link", + "options": "Supplier", + "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": "address_display", - "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": "Address", - "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": 1, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.purpose==\"Purchase Return\" || doc.purpose==\"Send to Subcontractor\"", + "fetch_if_empty": 0, + "fieldname": "supplier_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": "Supplier Name", + "length": 0, + "no_copy": 1, + "oldfieldname": "supplier_name", + "oldfieldtype": "Data", + "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_break_39", - "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, + "depends_on": "eval:doc.purpose==\"Purchase Return\" || doc.purpose==\"Send to Subcontractor\"", + "fetch_if_empty": 0, + "fieldname": "supplier_address", + "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": "Supplier Address", + "length": 0, + "no_copy": 1, + "oldfieldname": "supplier_address", + "oldfieldtype": "Small Text", + "options": "Address", + "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": "eval:doc.purpose==\"Sales Return\"", - "fieldname": "customer", - "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": "Customer", - "length": 0, - "no_copy": 1, - "oldfieldname": "customer", - "oldfieldtype": "Link", - "options": "Customer", - "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, + "fetch_if_empty": 0, + "fieldname": "address_display", + "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": "Address", + "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": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.purpose==\"Sales Return\"", - "fieldname": "customer_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": "Customer Name", - "length": 0, - "no_copy": 1, - "oldfieldname": "customer_name", - "oldfieldtype": "Data", - "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, + "fetch_if_empty": 0, + "fieldname": "column_break_39", + "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, - "depends_on": "eval:doc.purpose==\"Sales Return\"", - "fieldname": "customer_address", - "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": "Customer Address", - "length": 0, - "no_copy": 1, - "oldfieldname": "customer_address", - "oldfieldtype": "Small 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": 0, + "columns": 0, + "depends_on": "eval:doc.purpose==\"Sales Return\"", + "fetch_if_empty": 0, + "fieldname": "customer", + "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": "Customer", + "length": 0, + "no_copy": 1, + "oldfieldname": "customer", + "oldfieldtype": "Link", + "options": "Customer", + "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": 1, - "columns": 0, - "fieldname": "printing_settings", - "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": "Printing Settings", - "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": 1, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.purpose==\"Sales Return\"", + "fetch_if_empty": 0, + "fieldname": "customer_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": "Customer Name", + "length": 0, + "no_copy": 1, + "oldfieldname": "customer_name", + "oldfieldtype": "Data", + "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, - "fieldname": "select_print_heading", - "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": "Print Heading", - "length": 0, - "no_copy": 0, - "oldfieldname": "select_print_heading", - "oldfieldtype": "Link", - "options": "Print Heading", - "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": "eval:doc.purpose==\"Sales Return\"", + "fetch_if_empty": 0, + "fieldname": "customer_address", + "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": "Customer Address", + "length": 0, + "no_copy": 1, + "oldfieldname": "customer_address", + "oldfieldtype": "Small 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": "letter_head", - "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": "Letter Head", - "length": 0, - "no_copy": 0, - "options": "Letter Head", - "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": 1, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "printing_settings", + "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": "Printing Settings", + "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": 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, - "oldfieldtype": "Section 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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "select_print_heading", + "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": "Print Heading", + "length": 0, + "no_copy": 0, + "oldfieldname": "select_print_heading", + "oldfieldtype": "Link", + "options": "Print Heading", + "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, - "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, + "fetch_if_empty": 0, + "fieldname": "letter_head", + "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": "Letter Head", + "length": 0, + "no_copy": 0, + "options": "Letter Head", + "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": "remarks", - "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": "Remarks", - "length": 0, - "no_copy": 1, - "oldfieldname": "remarks", - "oldfieldtype": "Text", - "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": 1, + "columns": 0, + "fetch_if_empty": 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, + "oldfieldtype": "Section 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, - "fieldname": "col5", - "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, - "print_width": "50%", - "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": "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, + "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, + "fetch_if_empty": 0, + "fieldname": "remarks", + "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": "Remarks", + "length": 0, + "no_copy": 1, + "oldfieldname": "remarks", + "oldfieldtype": "Text", + "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, + "fetch_if_empty": 0, + "fieldname": "col5", + "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, + "print_width": "50%", + "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, - "depends_on": "total_amount", - "fieldname": "total_amount", - "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 Amount", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 1, - "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": "", + "fetch_if_empty": 0, + "fieldname": "per_transferred", + "fieldtype": "Percent", + "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": "Per Transferred", + "length": 0, + "no_copy": 1, + "options": "", + "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": "job_card", - "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": "Job Card", - "length": 0, - "no_copy": 0, - "options": "Job Card", - "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, + "depends_on": "total_amount", + "fetch_if_empty": 0, + "fieldname": "total_amount", + "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 Amount", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 1, + "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": "Link", - "options": "Stock Entry", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "job_card", + "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": "Job Card", + "length": 0, + "no_copy": 0, + "options": "Job Card", + "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": "credit_note", - "fieldtype": "Link", - "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": "Credit Note", - "length": 0, - "no_copy": 0, - "options": "Journal Entry", - "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, + "fetch_if_empty": 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": "Link", + "options": "Stock Entry", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "credit_note", + "fieldtype": "Link", + "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": "Credit Note", + "length": 0, + "no_copy": 0, + "options": "Journal Entry", + "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-file-text", - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-10-18 04:42:41.452572", - "modified_by": "Administrator", - "module": "Stock", - "name": "Stock Entry", - "owner": "Administrator", + ], + "has_web_view": 0, + "hide_toolbar": 0, + "icon": "fa fa-file-text", + "idx": 1, + "in_create": 0, + "is_submittable": 1, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2019-03-26 12:24:46.439626", + "modified_by": "Administrator", + "module": "Stock", + "name": "Stock Entry", + "owner": "Administrator", "permissions": [ { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "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": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "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": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Manufacturing User", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Manufacturing User", + "set_user_permissions": 0, + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Manufacturing Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Manufacturing Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 1, "write": 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": "Stock Manager", - "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": "Stock Manager", + "set_user_permissions": 1, + "share": 1, + "submit": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "search_fields": "posting_date, from_warehouse, to_warehouse, purpose, remarks", - "show_name_in_global_search": 1, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "title", - "track_changes": 1, - "track_seen": 0, + ], + "quick_entry": 0, + "read_only": 0, + "search_fields": "posting_date, from_warehouse, to_warehouse, purpose, remarks", + "show_name_in_global_search": 1, + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "title", + "track_changes": 1, + "track_seen": 0, "track_views": 0 } \ No newline at end of file diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 1149c3d16a..da2d09ff95 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -15,6 +15,7 @@ from erpnext.stock.doctype.batch.batch import get_batch_no, set_batch_nos, get_b from erpnext.stock.doctype.item.item import get_item_defaults from erpnext.manufacturing.doctype.bom.bom import validate_bom_no, add_additional_cost from erpnext.stock.utils import get_bin +from frappe.model.mapper import get_mapped_doc from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit, get_serial_nos import json @@ -61,6 +62,7 @@ class StockEntry(StockController): self.validate_inspection() self.validate_fg_completed_qty() self.set_job_card_data() + self.set_purpose_for_stock_entry() if not self.from_bom: self.fg_completed_qty = 0.0 @@ -81,17 +83,18 @@ class StockEntry(StockController): update_serial_nos_after_submit(self, "items") self.update_work_order() self.validate_purchase_order() - if self.purchase_order and self.purpose == "Subcontract": + if self.purchase_order and self.purpose == "Send to Subcontractor": self.update_purchase_order_supplied_items() self.make_gl_entries() self.update_cost_in_project() self.validate_reserved_serial_no_consumption() + self.update_transferred_qty() if self.work_order and self.purpose == "Manufacture": self.update_so_in_serial_number() def on_cancel(self): - if self.purchase_order and self.purpose == "Subcontract": + if self.purchase_order and self.purpose == "Send to Subcontractor": self.update_purchase_order_supplied_items() if self.work_order and self.purpose == "Material Consumption for Manufacture": @@ -102,6 +105,7 @@ class StockEntry(StockController): self.update_stock_ledger() self.make_gl_entries_on_cancel() self.update_cost_in_project() + self.update_transferred_qty() def set_job_card_data(self): if self.job_card and not self.work_order: @@ -118,8 +122,10 @@ class StockEntry(StockController): frappe.throw(_("Cannot cancel transaction for Completed Work Order.")) def validate_purpose(self): - valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer", "Material Transfer for Manufacture", - "Manufacture", "Repack", "Subcontract", "Material Consumption for Manufacture"] + valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer", + "Material Transfer for Manufacture", "Manufacture", "Repack", "Send to Subcontractor", + "Material Consumption for Manufacture", "Send to Warehouse", "Receive at Warehouse"] + if self.purpose not in valid_purposes: frappe.throw(_("Purpose must be one of {0}").format(comma_or(valid_purposes))) @@ -221,9 +227,11 @@ class StockEntry(StockController): def validate_warehouse(self): """perform various (sometimes conditional) validations on warehouse""" - source_mandatory = ["Material Issue", "Material Transfer", "Subcontract", "Material Transfer for Manufacture", - "Material Consumption for Manufacture"] - target_mandatory = ["Material Receipt", "Material Transfer", "Subcontract", "Material Transfer for Manufacture",] + source_mandatory = ["Material Issue", "Material Transfer", "Send to Subcontractor", "Material Transfer for Manufacture", + "Material Consumption for Manufacture", "Send to Warehouse", "Receive at Warehouse"] + + target_mandatory = ["Material Receipt", "Material Transfer", "Send to Subcontractor", + "Material Transfer for Manufacture", "Send to Warehouse", "Receive at Warehouse"] validate_for_manufacture_repack = any([d.bom_no for d in self.get("items")]) @@ -478,13 +486,23 @@ class StockEntry(StockController): if self.purpose not in ['Manufacture', 'Repack']: self.total_amount = sum([flt(item.amount) for item in self.get("items")]) + def set_stock_entry_type(self): + if self.purpose: + self.stock_entry_type = frappe.get_cached_value('Stock Entry Type', + {'purpose': self.purpose}, 'name') + + def set_purpose_for_stock_entry(self): + if self.stock_entry_type and not self.purpose: + self.purpose = frappe.get_cached_value('Stock Entry Type', + self.stock_entry_type, 'purpose') + def validate_purchase_order(self): """Throw exception if more raw material is transferred against Purchase Order than in the raw materials supplied table""" backflush_raw_materials_based_on = frappe.db.get_single_value("Buying Settings", "backflush_raw_materials_of_subcontract_based_on") - if (self.purpose == "Subcontract" and self.purchase_order and + if (self.purpose == "Send to Subcontractor" and self.purchase_order and backflush_raw_materials_based_on == 'BOM'): purchase_order = frappe.get_doc("Purchase Order", self.purchase_order) for se_item in self.items: @@ -520,7 +538,7 @@ class StockEntry(StockController): "overproduction_percentage_for_work_order")) for d in self.get('items'): - if self.purpose != "Subcontract" and d.bom_no and flt(d.transfer_qty) > flt(self.fg_completed_qty) and (d.t_warehouse != getattr(self, "pro_doc", frappe._dict()).scrap_warehouse): + if self.purpose != "Send to Subcontractor" and d.bom_no and flt(d.transfer_qty) > flt(self.fg_completed_qty) and (d.t_warehouse != getattr(self, "pro_doc", frappe._dict()).scrap_warehouse): frappe.throw(_("Quantity in row {0} ({1}) must be same as manufactured quantity {2}"). \ format(d.idx, d.transfer_qty, self.fg_completed_qty)) @@ -684,6 +702,30 @@ class StockEntry(StockController): return ret + def set_items_for_stock_in(self): + self.items = [] + + if self.outgoing_stock_entry and self.purpose == 'Receive at Warehouse': + doc = frappe.get_doc('Stock Entry', self.outgoing_stock_entry) + + if doc.per_transferred == 100: + frappe.throw(_("Goods are already received against the outward entry {0}") + .format(doc.name)) + + for d in doc.items: + self.append('items', { + 's_warehouse': d.t_warehouse, + 'item_code': d.item_code, + 'qty': d.qty, + 'uom': d.uom, + 'against_stock_entry': d.parent, + 'ste_detail': d.name, + 'stock_uom': d.stock_uom, + 'conversion_factor': d.conversion_factor, + 'serial_no': d.serial_no, + 'batch_no': d.batch_no + }) + def get_items(self): self.set('items', []) self.validate_work_order() @@ -696,7 +738,7 @@ class StockEntry(StockController): if self.bom_no: if self.purpose in ["Material Issue", "Material Transfer", "Manufacture", "Repack", - "Subcontract", "Material Transfer for Manufacture", "Material Consumption for Manufacture"]: + "Send to Subcontractor", "Material Transfer for Manufacture", "Material Consumption for Manufacture"]: if self.work_order and self.purpose == "Material Transfer for Manufacture": item_dict = self.get_pending_raw_materials() @@ -722,7 +764,7 @@ class StockEntry(StockController): item_dict = self.get_bom_raw_materials(self.fg_completed_qty) #Get PO Supplied Items Details - if self.purchase_order and self.purpose == "Subcontract": + if self.purchase_order and self.purpose == "Send to Subcontractor": #Get PO Supplied Items Details item_wh = frappe._dict(frappe.db.sql(""" select rm_item_code, reserve_warehouse @@ -734,13 +776,13 @@ class StockEntry(StockController): if self.pro_doc and (cint(self.pro_doc.from_wip_warehouse) or not self.pro_doc.skip_transfer): item["from_warehouse"] = self.pro_doc.wip_warehouse #Get Reserve Warehouse from PO - if self.purchase_order and self.purpose=="Subcontract": + if self.purchase_order and self.purpose=="Send to Subcontractor": item["from_warehouse"] = item_wh.get(item.item_code) - item["to_warehouse"] = self.to_warehouse if self.purpose=="Subcontract" else "" + item["to_warehouse"] = self.to_warehouse if self.purpose=="Send to Subcontractor" else "" self.add_to_stock_entry_detail(item_dict) - if self.purpose != "Subcontract": + if self.purpose != "Send to Subcontractor": scrap_item_dict = self.get_bom_scrap_material(self.fg_completed_qty) for item in itervalues(scrap_item_dict): if self.pro_doc and self.pro_doc.scrap_warehouse: @@ -1074,7 +1116,7 @@ class StockEntry(StockController): frappe.MappingMismatchError) def validate_batch(self): - if self.purpose in ["Material Transfer for Manufacture", "Manufacture", "Repack", "Subcontract", "Material Issue"]: + if self.purpose in ["Material Transfer for Manufacture", "Manufacture", "Repack", "Send to Subcontractor", "Material Issue"]: for item in self.get("items"): if item.batch_no: disabled = frappe.db.get_value("Batch", item.batch_no, "disabled") @@ -1130,6 +1172,52 @@ class StockEntry(StockController): frappe.throw(_("Item {0} (Serial No: {1}) cannot be consumed as is reserverd\ to fullfill Sales Order {2}.").format(item.item_code, sr, sales_order)) + def update_transferred_qty(self): + if self.purpose == 'Receive at Warehouse': + stock_entries = {} + stock_entries_child_list = [] + for d in self.items: + if not (d.against_stock_entry and d.ste_detail): + continue + + stock_entries_child_list.append(d.ste_detail) + transferred_qty = frappe.get_all("Stock Entry Detail", fields = ["sum(qty) as qty"], + filters = { 'against_stock_entry': d.against_stock_entry, + 'ste_detail': d.ste_detail,'docstatus': 1}) + + stock_entries[(d.against_stock_entry, d.ste_detail)] = (transferred_qty[0].qty + if transferred_qty and transferred_qty[0] else 0.0) or 0.0 + + if not stock_entries: return None + + cond = '' + for data, transferred_qty in stock_entries.items(): + cond += """ WHEN (parent = %s and name = %s) THEN %s + """ %(frappe.db.escape(data[0]), frappe.db.escape(data[1]), transferred_qty) + + if cond and stock_entries_child_list: + frappe.db.sql(""" UPDATE `tabStock Entry Detail` + SET + transferred_qty = CASE {cond} END + WHERE + name in ({ste_details}) """.format(cond=cond, + ste_details = ','.join(['%s'] * len(stock_entries_child_list))), + tuple(stock_entries_child_list)) + + args = { + 'source_dt': 'Stock Entry Detail', + 'target_field': 'transferred_qty', + 'target_ref_field': 'qty', + 'target_dt': 'Stock Entry Detail', + 'join_field': 'ste_detail', + 'target_parent_dt': 'Stock Entry', + 'target_parent_field': 'per_transferred', + 'source_field': 'qty', + 'percent_join_field': 'against_stock_entry' + } + + self._update_percent_field_in_targets(args, update_modified=True) + @frappe.whitelist() def move_sample_to_retention_warehouse(company, items): if isinstance(items, string_types): @@ -1138,6 +1226,7 @@ def move_sample_to_retention_warehouse(company, items): stock_entry = frappe.new_doc("Stock Entry") stock_entry.company = company stock_entry.purpose = "Material Transfer" + stock_entry.set_stock_entry_type() for item in items: if item.get('sample_quantity') and item.get('batch_no'): sample_quantity = validate_sample_quantity(item.get('item_code'), item.get('sample_quantity'), @@ -1165,6 +1254,42 @@ def move_sample_to_retention_warehouse(company, items): if stock_entry.get('items'): return stock_entry.as_dict() +@frappe.whitelist() +def make_stock_in_entry(source_name, target_doc=None): + def set_missing_values(source, target): + target.purpose = 'Receive at Warehouse' + target.set_stock_entry_type() + + def update_item(source_doc, target_doc, source_parent): + target_doc.t_warehouse = '' + target_doc.s_warehouse = source_doc.t_warehouse + target_doc.qty = source_doc.qty - source_doc.transferred_qty + + doclist = get_mapped_doc("Stock Entry", source_name, { + "Stock Entry": { + "doctype": "Stock Entry", + "field_map": { + "name": "outgoing_stock_entry" + }, + "validation": { + "docstatus": ["=", 1] + } + }, + "Stock Entry Detail": { + "doctype": "Stock Entry Detail", + "field_map": { + "name": "ste_detail", + "parent": "against_stock_entry", + "serial_no": "serial_no", + "batch_no": "batch_no" + }, + "postprocess": update_item, + "condition": lambda doc: flt(doc.qty) - flt(doc.transferred_qty) > 0.01 + }, + }, target_doc, set_missing_values) + + return doclist + @frappe.whitelist() def get_work_order_details(work_order): work_order = frappe.get_doc("Work Order", work_order) @@ -1224,7 +1349,7 @@ def get_used_alternative_items(purchase_order=None, work_order=None): cond = "" if purchase_order: - cond = "and ste.purpose = 'Subcontract' and ste.purchase_order = '{0}'".format(purchase_order) + cond = "and ste.purpose = 'Send to Subcontractor' and ste.purchase_order = '{0}'".format(purchase_order) elif work_order: cond = "and ste.purpose = 'Material Transfer for Manufacture' and ste.work_order = '{0}'".format(work_order) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_list.js b/erpnext/stock/doctype/stock_entry/stock_entry_list.js index 0f84b6da8d..cbc3491eba 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry_list.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry_list.js @@ -1,6 +1,22 @@ frappe.listview_settings['Stock Entry'] = { add_fields: ["`tabStock Entry`.`from_warehouse`", "`tabStock Entry`.`to_warehouse`", "`tabStock Entry`.`purpose`", "`tabStock Entry`.`work_order`", "`tabStock Entry`.`bom_no`"], + get_indicator: function (doc) { + if (doc.docstatus === 0) { + return [__("Draft"), "red", "docstatus,=,0"]; + + } else if (doc.purpose === 'Send to Warehouse' && doc.per_transferred < 100) { + // not delivered & overdue + return [__("Goods In Transit"), "grey", "per_transferred,<,100"]; + + } else if (doc.purpose === 'Send to Warehouse' && doc.per_transferred === 100) { + return [__("Goods Transferred"), "green", "per_transferred,=,100"]; + } else if (doc.docstatus === 2) { + return [__("Canceled"), "red", "docstatus,=,2"]; + } else { + return [__("Submitted"), "blue", "docstatus,=,1"]; + } + }, column_render: { "from_warehouse": function(doc) { var html = ""; diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py index 7a3433819d..49a30951fc 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py @@ -124,6 +124,7 @@ def make_stock_entry(**args): 'expense_account': args.expense_account }) + s.set_stock_entry_type() if not args.do_not_save: s.insert() if not args.do_not_submit: diff --git a/erpnext/stock/doctype/stock_entry/test_records.json b/erpnext/stock/doctype/stock_entry/test_records.json index b1daf12ea3..cfbdce4d77 100644 --- a/erpnext/stock/doctype/stock_entry/test_records.json +++ b/erpnext/stock/doctype/stock_entry/test_records.json @@ -1,109 +1,107 @@ [ - { - "company": "_Test Company", - "doctype": "Stock Entry", - "items": [ - { - "conversion_factor": 1.0, - "cost_center": "_Test Cost Center - _TC", - "doctype": "Stock Entry Detail", - "expense_account": "Stock Adjustment - _TC", - "basic_rate": 100, - "item_code": "_Test Item", - "parentfield": "items", - "qty": 50.0, - "stock_uom": "_Test UOM", - "t_warehouse": "_Test Warehouse - _TC", - "transfer_qty": 50.0, - "uom": "_Test UOM" - } - ], - "purpose": "Material Receipt" - }, - - - { - "company": "_Test Company", - "doctype": "Stock Entry", - "items": [ - { - "conversion_factor": 1.0, - "cost_center": "_Test Cost Center - _TC", - "doctype": "Stock Entry Detail", - "expense_account": "Stock Adjustment - _TC", - "basic_rate": 100, - "item_code": "_Test Item", - "parentfield": "items", - "qty": 40.0, - "s_warehouse": "_Test Warehouse - _TC", - "stock_uom": "_Test UOM", - "transfer_qty": 40.0, - "uom": "_Test UOM" - } - ], - "posting_date": "2013-01-25", - "purpose": "Material Issue" - }, - - - { - "company": "_Test Company", - "doctype": "Stock Entry", - "items": [ - { - "conversion_factor": 1.0, - "cost_center": "_Test Cost Center - _TC", - "doctype": "Stock Entry Detail", - "expense_account": "Stock Adjustment - _TC", - "basic_rate": 100, - "item_code": "_Test Item", - "parentfield": "items", - "qty": 45.0, - "s_warehouse": "_Test Warehouse - _TC", - "stock_uom": "_Test UOM", - "t_warehouse": "_Test Warehouse 1 - _TC", - "transfer_qty": 45.0, - "uom": "_Test UOM" - } - ], - "posting_date": "2013-01-25", - "purpose": "Material Transfer" - }, - - - { - "company": "_Test Company", - "doctype": "Stock Entry", - "items": [ - { - "conversion_factor": 1.0, - "cost_center": "_Test Cost Center - _TC", - "doctype": "Stock Entry Detail", - "expense_account": "Stock Adjustment - _TC", - "basic_rate": 100, - "item_code": "_Test Item", - "parentfield": "items", - "qty": 50.0, - "s_warehouse": "_Test Warehouse - _TC", - "stock_uom": "_Test UOM", - "transfer_qty": 50.0, - "uom": "_Test UOM" - }, - { - "conversion_factor": 1.0, - "cost_center": "_Test Cost Center - _TC", - "doctype": "Stock Entry Detail", - "expense_account": "Stock Adjustment - _TC", - "basic_rate": 5000, - "item_code": "_Test Item Home Desktop 100", - "parentfield": "items", - "qty": 1, - "stock_uom": "_Test UOM", - "t_warehouse": "_Test Warehouse - _TC", - "transfer_qty": 1, - "uom": "_Test UOM" - } - ], - "purpose": "Repack" - } + { + "company": "_Test Company", + "doctype": "Stock Entry", + "stock_entry_type": "Material Receipt", + "purpose": "Material Receipt", + "items": [ + { + "conversion_factor": 1.0, + "cost_center": "_Test Cost Center - _TC", + "doctype": "Stock Entry Detail", + "expense_account": "Stock Adjustment - _TC", + "basic_rate": 100, + "item_code": "_Test Item", + "parentfield": "items", + "qty": 50.0, + "stock_uom": "_Test UOM", + "t_warehouse": "_Test Warehouse - _TC", + "transfer_qty": 50.0, + "uom": "_Test UOM" + } + ] + }, + { + "company": "_Test Company", + "doctype": "Stock Entry", + "posting_date": "2013-01-25", + "purpose": "Material Issue", + "stock_entry_type": "Material Issue", + "items": [ + { + "conversion_factor": 1.0, + "cost_center": "_Test Cost Center - _TC", + "doctype": "Stock Entry Detail", + "expense_account": "Stock Adjustment - _TC", + "basic_rate": 100, + "item_code": "_Test Item", + "parentfield": "items", + "qty": 40.0, + "s_warehouse": "_Test Warehouse - _TC", + "stock_uom": "_Test UOM", + "transfer_qty": 40.0, + "uom": "_Test UOM" + } + ] + }, + { + "company": "_Test Company", + "doctype": "Stock Entry", + "posting_date": "2013-01-25", + "purpose": "Material Transfer", + "stock_entry_type": "Material Transfer", + "items": [ + { + "conversion_factor": 1.0, + "cost_center": "_Test Cost Center - _TC", + "doctype": "Stock Entry Detail", + "expense_account": "Stock Adjustment - _TC", + "basic_rate": 100, + "item_code": "_Test Item", + "parentfield": "items", + "qty": 45.0, + "s_warehouse": "_Test Warehouse - _TC", + "stock_uom": "_Test UOM", + "t_warehouse": "_Test Warehouse 1 - _TC", + "transfer_qty": 45.0, + "uom": "_Test UOM" + } + ] + }, + { + "company": "_Test Company", + "doctype": "Stock Entry", + "purpose": "Repack", + "stock_entry_type": "Repack", + "items": [ + { + "conversion_factor": 1.0, + "cost_center": "_Test Cost Center - _TC", + "doctype": "Stock Entry Detail", + "expense_account": "Stock Adjustment - _TC", + "basic_rate": 100, + "item_code": "_Test Item", + "parentfield": "items", + "qty": 50.0, + "s_warehouse": "_Test Warehouse - _TC", + "stock_uom": "_Test UOM", + "transfer_qty": 50.0, + "uom": "_Test UOM" + }, + { + "conversion_factor": 1.0, + "cost_center": "_Test Cost Center - _TC", + "doctype": "Stock Entry Detail", + "expense_account": "Stock Adjustment - _TC", + "basic_rate": 5000, + "item_code": "_Test Item Home Desktop 100", + "parentfield": "items", + "qty": 1, + "stock_uom": "_Test UOM", + "t_warehouse": "_Test Warehouse - _TC", + "transfer_qty": 1, + "uom": "_Test UOM" + } + ] + } ] diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index 448e2db76d..d7808c2695 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -15,7 +15,7 @@ from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import from erpnext.stock.doctype.item.test_item import set_item_variant_settings, make_item_variant, create_item from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry from erpnext.accounts.doctype.account.test_account import get_inventory_account -from erpnext.stock.doctype.stock_entry.stock_entry import move_sample_to_retention_warehouse +from erpnext.stock.doctype.stock_entry.stock_entry import move_sample_to_retention_warehouse, make_stock_in_entry from six import iteritems @@ -239,6 +239,7 @@ class TestStockEntry(unittest.TestCase): repack = frappe.copy_doc(test_records[3]) repack.posting_date = nowdate() repack.posting_time = nowtime() + repack.set_stock_entry_type() repack.insert() repack.submit() @@ -272,6 +273,8 @@ class TestStockEntry(unittest.TestCase): "amount": 200 }, ]) + + repack.set_stock_entry_type() repack.insert() repack.submit() @@ -327,6 +330,7 @@ class TestStockEntry(unittest.TestCase): def test_serial_no_not_reqd(self): se = frappe.copy_doc(test_records[0]) se.get("items")[0].serial_no = "ABCD" + se.set_stock_entry_type() se.insert() self.assertRaises(SerialNoNotRequiredError, se.submit) @@ -335,6 +339,7 @@ class TestStockEntry(unittest.TestCase): se.get("items")[0].item_code = "_Test Serialized Item" se.get("items")[0].qty = 2 se.get("items")[0].transfer_qty = 2 + se.set_stock_entry_type() se.insert() self.assertRaises(SerialNoRequiredError, se.submit) @@ -344,6 +349,7 @@ class TestStockEntry(unittest.TestCase): se.get("items")[0].qty = 2 se.get("items")[0].serial_no = "ABCD\nEFGH\nXYZ" se.get("items")[0].transfer_qty = 2 + se.set_stock_entry_type() se.insert() self.assertRaises(SerialNoQtyError, se.submit) @@ -353,6 +359,7 @@ class TestStockEntry(unittest.TestCase): se.get("items")[0].qty = 2 se.get("items")[0].serial_no = "ABCD" se.get("items")[0].transfer_qty = 2 + se.set_stock_entry_type() se.insert() self.assertRaises(SerialNoQtyError, se.submit) @@ -362,6 +369,7 @@ class TestStockEntry(unittest.TestCase): se.get("items")[0].qty = 2 se.get("items")[0].serial_no = "ABCD\nEFGH" se.get("items")[0].transfer_qty = 2 + se.set_stock_entry_type() se.insert() se.submit() @@ -382,6 +390,7 @@ class TestStockEntry(unittest.TestCase): se.get("items")[0].t_warehouse = None se.get("items")[0].serial_no = "ABCD\nEFGH" se.get("items")[0].transfer_qty = 2 + se.set_stock_entry_type() se.insert() self.assertRaises(SerialNoNotExistsError, se.submit) @@ -394,6 +403,7 @@ class TestStockEntry(unittest.TestCase): se.get("items")[0].qty = 1 se.get("items")[0].serial_no = serial_nos[0] se.get("items")[0].transfer_qty = 1 + se.set_stock_entry_type() se.insert() self.assertRaises(SerialNoDuplicateError, se.submit) @@ -420,6 +430,7 @@ class TestStockEntry(unittest.TestCase): se.get("items")[0].serial_no = serial_nos[0] se.get("items")[0].s_warehouse = "_Test Warehouse - _TC" se.get("items")[0].t_warehouse = "_Test Warehouse 1 - _TC" + se.set_stock_entry_type() se.insert() self.assertRaises(SerialNoItemError, se.submit) @@ -435,6 +446,7 @@ class TestStockEntry(unittest.TestCase): se.get("items")[0].serial_no = serial_no se.get("items")[0].s_warehouse = "_Test Warehouse - _TC" se.get("items")[0].t_warehouse = "_Test Warehouse 1 - _TC" + se.set_stock_entry_type() se.insert() se.submit() self.assertTrue(frappe.db.get_value("Serial No", serial_no, "warehouse"), "_Test Warehouse 1 - _TC") @@ -456,6 +468,7 @@ class TestStockEntry(unittest.TestCase): se.get("items")[0].serial_no = serial_nos[0] se.get("items")[0].s_warehouse = "_Test Warehouse 1 - _TC" se.get("items")[0].t_warehouse = "_Test Warehouse - _TC" + se.set_stock_entry_type() se.insert() self.assertRaises(SerialNoWarehouseError, se.submit) @@ -476,6 +489,7 @@ class TestStockEntry(unittest.TestCase): from erpnext.stock.utils import InvalidWarehouseCompany st1 = frappe.copy_doc(test_records[0]) st1.get("items")[0].t_warehouse="_Test Warehouse 2 - _TC1" + st1.set_stock_entry_type() st1.insert() self.assertRaises(InvalidWarehouseCompany, st1.submit) @@ -506,6 +520,7 @@ class TestStockEntry(unittest.TestCase): st1.get("items")[0].t_warehouse="_Test Warehouse 2 - _TC1" st1.get("items")[0].expense_account = "Stock Adjustment - _TC1" st1.get("items")[0].cost_center = "Main - _TC1" + st1.set_stock_entry_type() st1.insert() st1.submit() @@ -529,6 +544,7 @@ class TestStockEntry(unittest.TestCase): se = frappe.copy_doc(test_records[0]) se.set_posting_time = 1 se.posting_date = add_days(nowdate(), -15) + se.set_stock_entry_type() se.insert() self.assertRaises(StockFreezeError, se.submit) frappe.db.set_value("Stock Settings", None, "stock_frozen_upto_days", 0) @@ -644,6 +660,7 @@ class TestStockEntry(unittest.TestCase): "cost_center": "_Test Cost Center - _TC", "sample_quantity": 4 }) + receipt_entry.set_stock_entry_type() receipt_entry.insert() receipt_entry.submit() @@ -660,6 +677,7 @@ class TestStockEntry(unittest.TestCase): "cost_center": "_Test Cost Center - _TC", "batch_no": receipt_entry.get("items")[0].batch_no }) + retention_entry.set_stock_entry_type() retention_entry.insert() retention_entry.submit() @@ -726,6 +744,33 @@ class TestStockEntry(unittest.TestCase): self.assertEqual(se.get("items")[0].allow_zero_valuation_rate, 1) self.assertEqual(se.get("items")[0].amount, 0) + def test_goods_in_transit(self): + from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse + warehouse = "_Test Warehouse FG 1 - _TC" + + if not frappe.db.exists('Warehouse', warehouse): + create_warehouse("_Test Warehouse FG 1") + + outward_entry = make_stock_entry(item_code="_Test Item", + purpose="Send to Warehouse", + source="_Test Warehouse - _TC", + target="_Test Warehouse 1 - _TC", qty=50, basic_rate=100) + + inward_entry1 = make_stock_in_entry(outward_entry.name) + inward_entry1.items[0].t_warehouse = warehouse + inward_entry1.items[0].qty = 25 + inward_entry1.submit() + + doc = frappe.get_doc('Stock Entry', outward_entry.name) + self.assertEqual(doc.per_transferred, 50) + + inward_entry2 = make_stock_in_entry(outward_entry.name) + inward_entry2.items[0].t_warehouse = warehouse + inward_entry2.items[0].qty = 25 + inward_entry2.submit() + + doc = frappe.get_doc('Stock Entry', outward_entry.name) + self.assertEqual(doc.per_transferred, 100) def make_serialized_item(item_code=None, serial_no=None, target_warehouse=None): se = frappe.copy_doc(test_records[0]) @@ -737,6 +782,7 @@ def make_serialized_item(item_code=None, serial_no=None, target_warehouse=None): if target_warehouse: se.get("items")[0].t_warehouse = target_warehouse + se.set_stock_entry_type() se.insert() se.submit() return se diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_subcontract.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_subcontract.js index 131d3ca1de..770f886d04 100644 --- a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_subcontract.js +++ b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_subcontract.js @@ -6,7 +6,7 @@ QUnit.test("test material Transfer to manufacture", function(assert) { frappe.run_serially([ () => { return frappe.tests.make('Stock Entry', [ - {purpose:'Subcontract'}, + {purpose:'Send to Subcontractor'}, {from_warehouse:'Work In Progress - '+frappe.get_abbr(frappe.defaults.get_default('Company'))}, {to_warehouse:'Finished Goods - '+frappe.get_abbr(frappe.defaults.get_default('Company'))}, {items: [ diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json index 00ca024156..5b6244183c 100644 --- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json +++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json @@ -1,1567 +1,1779 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "hash", - "beta": 0, - "creation": "2013-03-29 18:22:12", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Other", - "editable_grid": 1, - "engine": "InnoDB", + "allow_copy": 0, + "allow_events_in_timeline": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "hash", + "beta": 0, + "creation": "2013-03-29 18:22:12", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Other", + "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": "barcode", - "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": "Barcode", - "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, + "fetch_if_empty": 0, + "fieldname": "barcode", + "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": "Barcode", + "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_2", - "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, + "fetch_if_empty": 0, + "fieldname": "section_break_2", + "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": 2, - "fieldname": "s_warehouse", - "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": "Source Warehouse", - "length": 0, - "no_copy": 0, - "oldfieldname": "s_warehouse", - "oldfieldtype": "Link", - "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": 2, + "fetch_if_empty": 0, + "fieldname": "s_warehouse", + "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": "Source Warehouse", + "length": 0, + "no_copy": 0, + "oldfieldname": "s_warehouse", + "oldfieldtype": "Link", + "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": "col_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, - "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, + "fetch_if_empty": 0, + "fieldname": "col_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, + "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": 2, - "fieldname": "t_warehouse", - "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": "Target Warehouse", - "length": 0, - "no_copy": 0, - "oldfieldname": "t_warehouse", - "oldfieldtype": "Link", - "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": 2, + "fetch_if_empty": 0, + "fieldname": "t_warehouse", + "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": "Target Warehouse", + "length": 0, + "no_copy": 0, + "oldfieldname": "t_warehouse", + "oldfieldtype": "Link", + "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": "sec_break1", - "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, - "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, + "fetch_if_empty": 0, + "fieldname": "sec_break1", + "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, + "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": 1, - "collapsible": 0, - "columns": 3, - "fieldname": "item_code", - "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": 0, - "label": "Item Code", - "length": 0, - "no_copy": 0, - "oldfieldname": "item_code", - "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": 1, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 3, + "fetch_if_empty": 0, + "fieldname": "item_code", + "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": 0, + "label": "Item Code", + "length": 0, + "no_copy": 0, + "oldfieldname": "item_code", + "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": 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": "col_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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "col_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": "item_name", - "fieldtype": "Data", - "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": "Item Name", - "length": 0, - "no_copy": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "item_name", + "fieldtype": "Data", + "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": "Item Name", + "length": 0, + "no_copy": 0, + "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 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "section_break_8", - "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": "Description", - "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": 1, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "section_break_8", + "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": "Description", + "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": "description", - "fieldtype": "Text Editor", - "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": "Description", - "length": 0, - "no_copy": 0, - "oldfieldname": "description", - "oldfieldtype": "Text", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": "300px", - "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": "description", + "fieldtype": "Text Editor", + "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": "Description", + "length": 0, + "no_copy": 0, + "oldfieldname": "description", + "oldfieldtype": "Text", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "300px", + "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": "column_break_10", - "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, + "fetch_if_empty": 0, + "fieldname": "column_break_10", + "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": "image", - "fieldtype": "Attach", - "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": "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "image", + "fieldtype": "Attach", + "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": "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": "image_view", - "fieldtype": "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 View", - "length": 0, - "no_copy": 0, - "options": "image", - "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, + "fetch_if_empty": 0, + "fieldname": "image_view", + "fieldtype": "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 View", + "length": 0, + "no_copy": 0, + "options": "image", + "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": "quantity_and_rate", - "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": "Quantity and Rate", - "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, + "fetch_if_empty": 0, + "fieldname": "quantity_and_rate", + "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": "Quantity and Rate", + "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": 1, - "collapsible": 0, - "columns": 3, - "fieldname": "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": "Qty", - "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": 1, + "collapsible": 0, + "columns": 3, + "fetch_if_empty": 0, + "fieldname": "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": "Qty", + "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": 1, - "collapsible": 0, - "columns": 0, - "fieldname": "basic_rate", - "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": "Basic Rate (as per Stock UOM)", - "length": 0, - "no_copy": 0, - "oldfieldname": "incoming_rate", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "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": 1, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "basic_rate", + "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": "Basic Rate (as per Stock UOM)", + "length": 0, + "no_copy": 0, + "oldfieldname": "incoming_rate", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "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": "basic_amount", - "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": "Basic Amount", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "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, + "fetch_if_empty": 0, + "fieldname": "basic_amount", + "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": "Basic Amount", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "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": "additional_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 Cost", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "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, + "fetch_if_empty": 0, + "fieldname": "additional_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 Cost", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "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": "amount", - "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": "Amount", - "length": 0, - "no_copy": 0, - "oldfieldname": "amount", - "oldfieldtype": "Currency", - "options": "Company:company:default_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, + "fetch_if_empty": 0, + "fieldname": "amount", + "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": "Amount", + "length": 0, + "no_copy": 0, + "oldfieldname": "amount", + "oldfieldtype": "Currency", + "options": "Company:company:default_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": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "valuation_rate", - "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": "Valuation Rate", - "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, + "fetch_if_empty": 0, + "fieldname": "valuation_rate", + "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": "Valuation Rate", + "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": "col_break3", - "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, + "fetch_if_empty": 0, + "fieldname": "col_break3", + "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": "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": "UOM", - "length": 0, - "no_copy": 0, - "oldfieldname": "uom", - "oldfieldtype": "Link", - "options": "UOM", - "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, + "fetch_if_empty": 0, + "fieldname": "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": "UOM", + "length": 0, + "no_copy": 0, + "oldfieldname": "uom", + "oldfieldtype": "Link", + "options": "UOM", + "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, - "fieldname": "conversion_factor", - "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": "Conversion Factor", - "length": 0, - "no_copy": 0, - "oldfieldname": "conversion_factor", - "oldfieldtype": "Currency", - "permlevel": 0, - "print_hide": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "conversion_factor", + "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": "Conversion Factor", + "length": 0, + "no_copy": 0, + "oldfieldname": "conversion_factor", + "oldfieldtype": "Currency", + "permlevel": 0, + "print_hide": 1, + "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, - "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": "Link", - "options": "UOM", - "permlevel": 0, - "print_hide": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "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": "Link", + "options": "UOM", + "permlevel": 0, + "print_hide": 1, + "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, - "fieldname": "transfer_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 as per Stock UOM", - "length": 0, - "no_copy": 0, - "oldfieldname": "transfer_qty", - "oldfieldtype": "Currency", - "permlevel": 0, - "print_hide": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "transfer_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 as per Stock UOM", + "length": 0, + "no_copy": 0, + "oldfieldname": "transfer_qty", + "oldfieldtype": "Currency", + "permlevel": 0, + "print_hide": 1, + "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, - "fetch_from": "item_code.retain_sample", - "fieldname": "retain_sample", - "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": "Retain Sample", - "length": 0, - "no_copy": 0, - "options": "", - "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, + "fetch_from": "item_code.retain_sample", + "fetch_if_empty": 0, + "fieldname": "retain_sample", + "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": "Retain Sample", + "length": 0, + "no_copy": 0, + "options": "", + "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": "retain_sample", - "fieldname": "sample_quantity", - "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": "Sample Quantity", - "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": "retain_sample", + "fetch_if_empty": 0, + "fieldname": "sample_quantity", + "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": "Sample Quantity", + "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": "serial_no_batch", - "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": "Serial No / Batch", - "length": 0, - "no_copy": 1, - "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, + "fetch_if_empty": 0, + "fieldname": "serial_no_batch", + "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": "Serial No / Batch", + "length": 0, + "no_copy": 1, + "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": "serial_no", - "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": "Serial No", - "length": 0, - "no_copy": 1, - "oldfieldname": "serial_no", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "serial_no", + "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": "Serial No", + "length": 0, + "no_copy": 1, + "oldfieldname": "serial_no", + "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": "col_break4", - "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, + "fetch_if_empty": 0, + "fieldname": "col_break4", + "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": "batch_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": "Batch No", - "length": 0, - "no_copy": 1, - "oldfieldname": "batch_no", - "oldfieldtype": "Link", - "options": "Batch", - "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, + "fetch_if_empty": 0, + "fieldname": "batch_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": "Batch No", + "length": 0, + "no_copy": 1, + "oldfieldname": "batch_no", + "oldfieldtype": "Link", + "options": "Batch", + "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": "eval:parent.inspection_required && doc.t_warehouse", - "fieldname": "quality_inspection", - "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": "Quality Inspection", - "length": 0, - "no_copy": 0, - "options": "Quality Inspection", - "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": "eval:parent.inspection_required && doc.t_warehouse", + "fetch_if_empty": 0, + "fieldname": "quality_inspection", + "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": "Quality Inspection", + "length": 0, + "no_copy": 0, + "options": "Quality Inspection", + "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": "accounting", - "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": "Accounting", - "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, + "fetch_if_empty": 0, + "fieldname": "accounting", + "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": "Accounting", + "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": "eval:cint(erpnext.is_perpetual_inventory_enabled(parent.company))", - "fieldname": "expense_account", - "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": "Difference Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "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, + "depends_on": "eval:cint(erpnext.is_perpetual_inventory_enabled(parent.company))", + "fetch_if_empty": 0, + "fieldname": "expense_account", + "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": "Difference Account", + "length": 0, + "no_copy": 0, + "options": "Account", + "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": "col_break5", - "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, + "fetch_if_empty": 0, + "fieldname": "col_break5", + "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, - "default": ":Company", - "depends_on": "eval:cint(erpnext.is_perpetual_inventory_enabled(parent.company))", - "fieldname": "cost_center", - "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": "Cost Center", - "length": 0, - "no_copy": 0, - "options": "Cost Center", - "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, + "default": ":Company", + "depends_on": "eval:cint(erpnext.is_perpetual_inventory_enabled(parent.company))", + "fetch_if_empty": 0, + "fieldname": "cost_center", + "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": "Cost Center", + "length": 0, + "no_copy": 0, + "options": "Cost Center", + "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": "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, - "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, + "fetch_if_empty": 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, + "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": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "allow_zero_valuation_rate", - "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 Zero Valuation Rate", - "length": 0, - "no_copy": 1, - "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": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "allow_zero_valuation_rate", + "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 Zero Valuation Rate", + "length": 0, + "no_copy": 1, + "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": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "actual_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": "Actual Qty (at source/target)", - "length": 0, - "no_copy": 1, - "oldfieldname": "actual_qty", - "oldfieldtype": "Read Only", - "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": 1, - "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, + "fetch_if_empty": 0, + "fieldname": "actual_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": "Actual Qty (at source/target)", + "length": 0, + "no_copy": 1, + "oldfieldname": "actual_qty", + "oldfieldtype": "Read Only", + "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": 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, - "description": "BOM No. for a Finished Good Item", - "fieldname": "bom_no", - "fieldtype": "Link", - "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": "BOM No", - "length": 0, - "no_copy": 0, - "options": "BOM", - "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, + "description": "BOM No. for a Finished Good Item", + "fetch_if_empty": 0, + "fieldname": "bom_no", + "fieldtype": "Link", + "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": "BOM No", + "length": 0, + "no_copy": 0, + "options": "BOM", + "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, - "depends_on": "s_warehouse", - "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": 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, + "depends_on": "s_warehouse", + "fetch_if_empty": 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": 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": "col_break6", - "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, + "fetch_if_empty": 0, + "fieldname": "col_break6", + "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, - "description": "Material Request used to make this Stock Entry", - "fieldname": "material_request", - "fieldtype": "Link", - "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", - "length": 0, - "no_copy": 1, - "options": "Material Request", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "Material Request used to make this Stock Entry", + "fetch_if_empty": 0, + "fieldname": "material_request", + "fieldtype": "Link", + "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", + "length": 0, + "no_copy": 1, + "options": "Material Request", + "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 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "material_request_item", - "fieldtype": "Link", - "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": 1, - "options": "Material Request Item", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "material_request_item", + "fieldtype": "Link", + "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": 1, + "options": "Material Request Item", + "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 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "original_item", - "fieldtype": "Link", - "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": "Original 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, + "fetch_if_empty": 0, + "fieldname": "original_item", + "fieldtype": "Link", + "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": "Original 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": "subcontracted_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": "Subcontracted Item", - "length": 0, - "no_copy": 0, - "options": "Item", - "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, + "fetch_if_empty": 0, + "fieldname": "subcontracted_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": "Subcontracted Item", + "length": 0, + "no_copy": 0, + "options": "Item", + "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": "reference_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": "Reference", + "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": "against_stock_entry", + "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": "Against Stock Entry", + "length": 0, + "no_copy": 1, + "options": "Stock Entry", + "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": "ste_detail", + "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": "Stock Entry Child", + "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": "column_break_51", + "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": "transferred_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": "Transferred Qty", + "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 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2019-01-07 16:58:58.769285", - "modified_by": "Administrator", - "module": "Stock", - "name": "Stock Entry Detail", - "owner": "Administrator", - "permissions": [], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_order": "ASC", - "track_changes": 0, - "track_seen": 0, + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 1, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 1, + "max_attachments": 0, + "modified": "2019-03-13 19:15:04.678398", + "modified_by": "Administrator", + "module": "Stock", + "name": "Stock Entry Detail", + "owner": "Administrator", + "permissions": [], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_order": "ASC", + "track_changes": 0, + "track_seen": 0, "track_views": 0 } \ No newline at end of file diff --git a/erpnext/stock/doctype/stock_entry_type/__init__.py b/erpnext/stock/doctype/stock_entry_type/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.js b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.js new file mode 100644 index 0000000000..c554278334 --- /dev/null +++ b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.js @@ -0,0 +1,8 @@ +// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Stock Entry Type', { + // refresh: function(frm) { + + // } +}); diff --git a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.json b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.json new file mode 100644 index 0000000000..edee3c7dc9 --- /dev/null +++ b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.json @@ -0,0 +1,156 @@ +{ + "allow_copy": 0, + "allow_events_in_timeline": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "Prompt", + "beta": 0, + "creation": "2019-03-13 16:23:46.636769", + "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": "Material Issue", + "fetch_if_empty": 0, + "fieldname": "purpose", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Purpose", + "length": 0, + "no_copy": 0, + "options": "\nMaterial Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor\nSend to Warehouse\nReceive at 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": 1, + "search_index": 0, + "set_only_once": 1, + "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": 0, + "max_attachments": 0, + "modified": "2019-03-26 12:02:42.144377", + "modified_by": "Administrator", + "module": "Stock", + "name": "Stock Entry Type", + "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": 0, + "write": 1 + }, + { + "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": "Manufacturing Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "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": "Stock Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "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": "Stock User", + "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": "ASC", + "track_changes": 1, + "track_seen": 0, + "track_views": 0 +} \ No newline at end of file diff --git a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py new file mode 100644 index 0000000000..a4116aba2c --- /dev/null +++ b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +# import frappe +from frappe.model.document import Document + +class StockEntryType(Document): + pass diff --git a/erpnext/stock/doctype/stock_entry_type/test_stock_entry_type.py b/erpnext/stock/doctype/stock_entry_type/test_stock_entry_type.py new file mode 100644 index 0000000000..4fa73fd2dc --- /dev/null +++ b/erpnext/stock/doctype/stock_entry_type/test_stock_entry_type.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest + +class TestStockEntryType(unittest.TestCase): + pass diff --git a/erpnext/stock/doctype/warehouse/warehouse.json b/erpnext/stock/doctype/warehouse/warehouse.json index 0d60a5ca38..63e374f6d7 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.json +++ b/erpnext/stock/doctype/warehouse/warehouse.json @@ -51,6 +51,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "description": "If blank, parent Warehouse Account or company default will be considered", "fieldname": "warehouse_name", "fieldtype": "Data", "hidden": 0, @@ -870,7 +871,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-08-29 06:26:48.647225", + "modified": "2018-08-29 06:26:49.647225", "modified_by": "Administrator", "module": "Stock", "name": "Warehouse", diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 6d75314638..4d8022c24f 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -667,28 +667,39 @@ def get_pos_profile_item_details(company, args, pos_profile=None, update_data=Fa @frappe.whitelist() def get_pos_profile(company, pos_profile=None, user=None): - if pos_profile: - return frappe.get_cached_doc('POS Profile', pos_profile) + if pos_profile: return frappe.get_cached_doc('POS Profile', pos_profile) if not user: user = frappe.session['user'] + condition = "pfu.user = %(user)s AND pfu.default=1" + if user and company: + condition = "pfu.user = %(user)s AND pf.company = %(company)s AND pfu.default=1" + pos_profile = frappe.db.sql("""SELECT pf.* FROM `tabPOS Profile` pf LEFT JOIN `tabPOS Profile User` pfu ON pf.name = pfu.parent WHERE - ( - (pfu.user = %(user)s AND pf.company = %(company)s AND pfu.default=1) - OR (pfu.user = %(user)s AND pfu.default=1) - OR (ifnull(pfu.user, '') = '' AND pf.company = %(company)s) - ) AND pf.disabled = 0 - """, { + {cond} AND pf.disabled = 0 + """.format(cond = condition), { 'user': user, 'company': company }, as_dict=1) + if not pos_profile and company: + pos_profile = frappe.db.sql("""SELECT pf.* + FROM + `tabPOS Profile` pf LEFT JOIN `tabPOS Profile User` pfu + ON + pf.name = pfu.parent + WHERE + pf.company = %(company)s AND pf.disabled = 0 + """, { + 'company': company + }, as_dict=1) + return pos_profile and pos_profile[0] or None def get_serial_nos_by_fifo(args, sales_order=None): diff --git a/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py b/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py index 618fd152ff..c5cf6c4243 100644 --- a/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py +++ b/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py @@ -59,7 +59,7 @@ def get_consumed_items(condition): sum(se_item.transfer_qty) as 'consume_qty' from `tabStock Entry` se, `tabStock Entry Detail` se_item where se.name = se_item.parent and se.docstatus = 1 - and (ifnull(se_item.t_warehouse, '') = '' or se.purpose = 'Subcontract') %s + and (ifnull(se_item.t_warehouse, '') = '' or se.purpose = 'Send to Subcontractor') %s group by se_item.item_code""" % (condition), as_dict=1) cn_items_map = {} diff --git a/erpnext/stock/report/ordered_items_to_be_delivered/ordered_items_to_be_delivered.json b/erpnext/stock/report/ordered_items_to_be_delivered/ordered_items_to_be_delivered.json index 2dd5b7a4c6..aa5fd0f165 100644 --- a/erpnext/stock/report/ordered_items_to_be_delivered/ordered_items_to_be_delivered.json +++ b/erpnext/stock/report/ordered_items_to_be_delivered/ordered_items_to_be_delivered.json @@ -1,31 +1,32 @@ { - "add_total_row": 1, - "apply_user_permissions": 1, - "creation": "2018-01-09 18:38:23.540100", - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "idx": 0, - "is_standard": "Yes", - "modified": "2018-01-15 15:04:15.340151", - "modified_by": "Administrator", - "module": "Stock", - "name": "Ordered Items To Be Delivered", - "owner": "Administrator", - "query": "select \n `tabSales Order`.`name` as \"Sales Order:Link/Sales Order:120\",\n `tabSales Order`.`customer` as \"Customer:Link/Customer:120\",\n `tabSales Order`.`customer_name` as \"Customer Name::150\",\n `tabSales Order`.`transaction_date` as \"Date:Date\",\n `tabSales Order`.`project` as \"Project:Link/Project:120\",\n `tabSales Order Item`.item_code as \"Item:Link/Item:120\",\n `tabSales Order Item`.qty as \"Qty:Float:140\",\n `tabSales Order Item`.delivered_qty as \"Delivered Qty:Float:140\",\n (`tabSales Order Item`.qty - ifnull(`tabSales Order Item`.delivered_qty, 0)) as \"Qty to Deliver:Float:140\",\n `tabSales Order Item`.base_rate as \"Rate:Float:140\",\n `tabSales Order Item`.base_amount as \"Amount:Float:140\",\n ((`tabSales Order Item`.qty - ifnull(`tabSales Order Item`.delivered_qty, 0))*`tabSales Order Item`.base_rate) as \"Amount to Deliver:Float:140\",\n `tabBin`.actual_qty as \"Available Qty:Float:120\",\n `tabBin`.projected_qty as \"Projected Qty:Float:120\",\n `tabSales Order Item`.`delivery_date` as \"Item Delivery Date:Date:120\",\n DATEDIFF(CURDATE(),`tabSales Order Item`.`delivery_date`) as \"Delay Days:Int:120\",\n `tabSales Order Item`.item_name as \"Item Name::150\",\n `tabSales Order Item`.description as \"Description::200\",\n `tabSales Order Item`.item_group as \"Item Group:Link/Item Group:120\",\n `tabSales Order Item`.warehouse as \"Warehouse:Link/Warehouse:200\"\nfrom\n `tabSales Order` JOIN `tabSales Order Item` \n LEFT JOIN `tabBin` ON (`tabBin`.item_code = `tabSales Order Item`.item_code\n and `tabBin`.warehouse = `tabSales Order Item`.warehouse)\nwhere\n `tabSales Order Item`.`parent` = `tabSales Order`.`name`\n and `tabSales Order`.docstatus = 1\n and `tabSales Order`.status not in (\"Stopped\", \"Closed\")\n and ifnull(`tabSales Order Item`.delivered_qty,0) < ifnull(`tabSales Order Item`.qty,0)\norder by `tabSales Order`.transaction_date asc", - "ref_doctype": "Delivery Note", - "report_name": "Ordered Items To Be Delivered", - "report_type": "Query Report", + "add_total_row": 1, + "creation": "2018-01-09 18:38:23.540100", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "modified": "2019-04-01 22:10:09.829361", + "modified_by": "Administrator", + "module": "Stock", + "name": "Ordered Items To Be Delivered", + "owner": "Administrator", + "prepared_report": 0, + "query": "select \n `tabSales Order`.`name` as \"Sales Order:Link/Sales Order:120\",\n `tabSales Order`.`status` as \"Status:Data:120\",\n `tabSales Order`.`customer` as \"Customer:Link/Customer:120\",\n `tabSales Order`.`customer_name` as \"Customer Name::150\",\n `tabSales Order`.`transaction_date` as \"Date:Date\",\n `tabSales Order`.`project` as \"Project:Link/Project:120\",\n `tabSales Order Item`.item_code as \"Item:Link/Item:120\",\n `tabSales Order Item`.qty as \"Qty:Float:140\",\n `tabSales Order Item`.delivered_qty as \"Delivered Qty:Float:140\",\n (`tabSales Order Item`.qty - ifnull(`tabSales Order Item`.delivered_qty, 0)) as \"Qty to Deliver:Float:140\",\n `tabSales Order Item`.base_rate as \"Rate:Float:140\",\n `tabSales Order Item`.base_amount as \"Amount:Float:140\",\n ((`tabSales Order Item`.qty - ifnull(`tabSales Order Item`.delivered_qty, 0))*`tabSales Order Item`.base_rate) as \"Amount to Deliver:Float:140\",\n `tabBin`.actual_qty as \"Available Qty:Float:120\",\n `tabBin`.projected_qty as \"Projected Qty:Float:120\",\n `tabSales Order Item`.`delivery_date` as \"Item Delivery Date:Date:120\",\n DATEDIFF(CURDATE(),`tabSales Order Item`.`delivery_date`) as \"Delay Days:Int:120\",\n `tabSales Order Item`.item_name as \"Item Name::150\",\n `tabSales Order Item`.description as \"Description::200\",\n `tabSales Order Item`.item_group as \"Item Group:Link/Item Group:120\",\n `tabSales Order Item`.warehouse as \"Warehouse:Link/Warehouse:200\"\nfrom\n `tabSales Order` JOIN `tabSales Order Item` \n LEFT JOIN `tabBin` ON (`tabBin`.item_code = `tabSales Order Item`.item_code\n and `tabBin`.warehouse = `tabSales Order Item`.warehouse)\nwhere\n `tabSales Order Item`.`parent` = `tabSales Order`.`name`\n and `tabSales Order`.docstatus = 1\n and `tabSales Order`.status not in (\"Stopped\", \"Closed\")\n and ifnull(`tabSales Order Item`.delivered_qty,0) < ifnull(`tabSales Order Item`.qty,0)\norder by `tabSales Order`.transaction_date asc", + "ref_doctype": "Delivery Note", + "report_name": "Ordered Items To Be Delivered", + "report_type": "Query Report", "roles": [ { "role": "Stock User" - }, + }, { "role": "Stock Manager" - }, + }, { "role": "Sales User" - }, + }, { "role": "Accounts User" } diff --git a/erpnext/stock/report/purchase_order_items_to_be_received/purchase_order_items_to_be_received.json b/erpnext/stock/report/purchase_order_items_to_be_received/purchase_order_items_to_be_received.json index 3c440f44ad..dfaa9ed6cc 100644 --- a/erpnext/stock/report/purchase_order_items_to_be_received/purchase_order_items_to_be_received.json +++ b/erpnext/stock/report/purchase_order_items_to_be_received/purchase_order_items_to_be_received.json @@ -1,31 +1,32 @@ { - "add_total_row": 1, - "apply_user_permissions": 1, - "creation": "2013-02-22 18:01:55", - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "idx": 3, - "is_standard": "Yes", - "modified": "2017-02-24 20:04:20.699195", - "modified_by": "Administrator", - "module": "Stock", - "name": "Purchase Order Items To Be Received", - "owner": "Administrator", - "query": "select \n `tabPurchase Order`.`name` as \"Purchase Order:Link/Purchase Order:120\",\n\t`tabPurchase Order`.`transaction_date` as \"Date:Date:100\",\n\t`tabPurchase Order Item`.`schedule_date` as \"Reqd by Date:Date:110\",\n\t`tabPurchase Order`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Order`.`supplier_name` as \"Supplier Name::150\",\n\t`tabPurchase Order Item`.`project` as \"Project\",\n\t`tabPurchase Order Item`.item_code as \"Item Code:Link/Item:120\",\n\t`tabPurchase Order Item`.qty as \"Qty:Float:100\",\n\t`tabPurchase Order Item`.received_qty as \"Received Qty:Float:100\", \n\t(`tabPurchase Order Item`.qty - ifnull(`tabPurchase Order Item`.received_qty, 0)) as \"Qty to Receive:Float:100\",\n `tabPurchase Order Item`.warehouse as \"Warehouse:Link/Warehouse:150\",\n\t`tabPurchase Order Item`.item_name as \"Item Name::150\",\n\t`tabPurchase Order Item`.description as \"Description::200\",\n `tabPurchase Order Item`.brand as \"Brand::100\",\n\t`tabPurchase Order`.`company` as \"Company:Link/Company:\"\nfrom\n\t`tabPurchase Order`, `tabPurchase Order Item`\nwhere\n\t`tabPurchase Order Item`.`parent` = `tabPurchase Order`.`name`\n\tand `tabPurchase Order`.docstatus = 1\n\tand `tabPurchase Order`.status not in (\"Stopped\", \"Closed\")\n\tand ifnull(`tabPurchase Order Item`.received_qty, 0) < ifnull(`tabPurchase Order Item`.qty, 0)\norder by `tabPurchase Order`.transaction_date asc", - "ref_doctype": "Purchase Receipt", - "report_name": "Purchase Order Items To Be Received", - "report_type": "Query Report", + "add_total_row": 1, + "creation": "2013-02-22 18:01:55", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 3, + "is_standard": "Yes", + "modified": "2019-04-01 22:12:05.573343", + "modified_by": "Administrator", + "module": "Stock", + "name": "Purchase Order Items To Be Received", + "owner": "Administrator", + "prepared_report": 0, + "query": "select \n `tabPurchase Order`.`name` as \"Purchase Order:Link/Purchase Order:120\",\n `tabPurchase Order`.`status` as \"Status:Data:120\",\n\t`tabPurchase Order`.`transaction_date` as \"Date:Date:100\",\n\t`tabPurchase Order Item`.`schedule_date` as \"Reqd by Date:Date:110\",\n\t`tabPurchase Order`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Order`.`supplier_name` as \"Supplier Name::150\",\n\t`tabPurchase Order Item`.`project` as \"Project\",\n\t`tabPurchase Order Item`.item_code as \"Item Code:Link/Item:120\",\n\t`tabPurchase Order Item`.qty as \"Qty:Float:100\",\n\t`tabPurchase Order Item`.received_qty as \"Received Qty:Float:100\", \n\t(`tabPurchase Order Item`.qty - ifnull(`tabPurchase Order Item`.received_qty, 0)) as \"Qty to Receive:Float:100\",\n `tabPurchase Order Item`.warehouse as \"Warehouse:Link/Warehouse:150\",\n\t`tabPurchase Order Item`.item_name as \"Item Name::150\",\n\t`tabPurchase Order Item`.description as \"Description::200\",\n `tabPurchase Order Item`.brand as \"Brand::100\",\n\t`tabPurchase Order`.`company` as \"Company:Link/Company:\"\nfrom\n\t`tabPurchase Order`, `tabPurchase Order Item`\nwhere\n\t`tabPurchase Order Item`.`parent` = `tabPurchase Order`.`name`\n\tand `tabPurchase Order`.docstatus = 1\n\tand `tabPurchase Order`.status not in (\"Stopped\", \"Closed\")\n\tand ifnull(`tabPurchase Order Item`.received_qty, 0) < ifnull(`tabPurchase Order Item`.qty, 0)\norder by `tabPurchase Order`.transaction_date asc", + "ref_doctype": "Purchase Receipt", + "report_name": "Purchase Order Items To Be Received", + "report_type": "Query Report", "roles": [ { "role": "Stock Manager" - }, + }, { "role": "Stock User" - }, + }, { "role": "Purchase User" - }, + }, { "role": "Accounts User" } diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.js b/erpnext/stock/report/stock_ageing/stock_ageing.js index 60e64b77f4..aad8df426a 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.js +++ b/erpnext/stock/report/stock_ageing/stock_ageing.js @@ -13,7 +13,7 @@ frappe.query_reports["Stock Ageing"] = { }, { "fieldname":"to_date", - "label": __("To Date"), + "label": __("As On Date"), "fieldtype": "Date", "default": frappe.datetime.get_today(), "reqd": 1 @@ -35,6 +35,12 @@ frappe.query_reports["Stock Ageing"] = { "label": __("Brand"), "fieldtype": "Link", "options": "Brand" + }, + { + "fieldname":"show_ageing_warehouse_wise", + "label": __("Show Ageing Warehouse-wise"), + "fieldtype": "Check", + "default": 0 } ] } \ No newline at end of file diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index ae3d72ee4f..969284598c 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -9,7 +9,7 @@ from six import iteritems def execute(filters=None): - columns = get_columns() + columns = get_columns(filters) item_details = get_fifo_queue(filters) to_date = filters["to_date"] data = [] @@ -22,8 +22,16 @@ def execute(filters=None): earliest_age = date_diff(to_date, fifo_queue[0][1]) latest_age = date_diff(to_date, fifo_queue[-1][1]) - data.append([item, details.item_name, details.description, details.item_group, - details.brand, average_age, earliest_age, latest_age, details.stock_uom]) + row = [details.name, details.item_name, + details.description, details.item_group, details.brand] + + if filters.get("show_ageing_warehouse_wise"): + row.append(details.warehouse) + + row.extend([item_dict.get("total_qty"), average_age, + earliest_age, latest_age, details.stock_uom]) + + data.append(row) return columns, data @@ -36,19 +44,27 @@ def get_average_age(fifo_queue, to_date): return (age_qty / total_qty) if total_qty else 0.0 -def get_columns(): - return [_("Item Code") + ":Link/Item:100", _("Item Name") + "::100", _("Description") + "::200", - _("Item Group") + ":Link/Item Group:100", _("Brand") + ":Link/Brand:100", _("Average Age") + ":Float:100", - _("Earliest") + ":Int:80", _("Latest") + ":Int:80", _("UOM") + ":Link/UOM:100"] +def get_columns(filters): + columns = [_("Item Code") + ":Link/Item:100", _("Item Name") + "::100", _("Description") + "::200", + _("Item Group") + ":Link/Item Group:100", _("Brand") + ":Link/Brand:100"] + + if filters.get("show_ageing_warehouse_wise"): + columns.extend([_("Warehouse") + ":Link/Warehouse:100"]) + + columns.extend([_("Available Qty") + ":Float:100", _("Average Age") + ":Float:100", + _("Earliest") + ":Int:80", _("Latest") + ":Int:80", _("UOM") + ":Link/UOM:100"]) + + return columns def get_fifo_queue(filters): item_details = {} for d in get_stock_ledger_entries(filters): - item_details.setdefault(d.name, {"details": d, "fifo_queue": []}) - fifo_queue = item_details[d.name]["fifo_queue"] + key = (d.name, d.warehouse) if filters.get('show_ageing_warehouse_wise') else d.name + item_details.setdefault(key, {"details": d, "fifo_queue": []}) + fifo_queue = item_details[key]["fifo_queue"] if d.voucher_type == "Stock Reconciliation": - d.actual_qty = flt(d.qty_after_transaction) - flt(item_details[d.name].get("qty_after_transaction", 0)) + d.actual_qty = flt(d.qty_after_transaction) - flt(item_details[key].get("qty_after_transaction", 0)) if d.actual_qty > 0: fifo_queue.append([d.actual_qty, d.posting_date]) @@ -66,14 +82,19 @@ def get_fifo_queue(filters): batch[0] -= qty_to_pop qty_to_pop = 0 - item_details[d.name]["qty_after_transaction"] = d.qty_after_transaction + item_details[key]["qty_after_transaction"] = d.qty_after_transaction + + if "total_qty" not in item_details[key]: + item_details[key]["total_qty"] = d.actual_qty + else: + item_details[key]["total_qty"] += d.actual_qty return item_details def get_stock_ledger_entries(filters): return frappe.db.sql("""select item.name, item.item_name, item_group, brand, description, item.stock_uom, - actual_qty, posting_date, voucher_type, qty_after_transaction + actual_qty, posting_date, voucher_type, qty_after_transaction, warehouse from `tabStock Ledger Entry` sle, (select name, item_name, description, stock_uom, brand, item_group from `tabItem` {item_conditions}) item diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index 5d7c582609..0c71f9182e 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -225,16 +225,15 @@ def get_item_details(items, sle, filters): cf_join = "left join `tabUOM Conversion Detail` ucd on ucd.parent=item.name and ucd.uom='%s'" \ % frappe.db.escape(filters.get("include_uom")) - item_codes = ', '.join(['"' + frappe.db.escape(i, percent=False) + '"' for i in items]) res = frappe.db.sql(""" select - item.name, item.item_name, item.description, item.item_group, item.brand, item.stock_uom {cf_field} + item.name, item.item_name, item.description, item.item_group, item.brand, item.stock_uom %s from `tabItem` item - {cf_join} + %s where - item.name in ({item_codes}) and ifnull(item.disabled, 0) = 0 - """.format(cf_field=cf_field, cf_join=cf_join, item_codes=item_codes), as_dict=1) + item.name in (%s) and ifnull(item.disabled, 0) = 0 + """ % (cf_field, cf_join, ','.join(['%s'] *len(items))), items, as_dict=1) for item in res: item_details.setdefault(item.name, item) diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py index 46c55d2ff3..20b5e45e19 100644 --- a/erpnext/stock/report/stock_ledger/stock_ledger.py +++ b/erpnext/stock/report/stock_ledger/stock_ledger.py @@ -113,7 +113,6 @@ def get_item_details(items, sl_entries, include_uom): cf_join = "left join `tabUOM Conversion Detail` ucd on ucd.parent=item.name and ucd.uom='%s'" \ % frappe.db.escape(include_uom) - item_codes = ', '.join([frappe.db.escape(i, percent=False) for i in items]) res = frappe.db.sql(""" select item.name, item.item_name, item.description, item.item_group, item.brand, item.stock_uom {cf_field} @@ -122,7 +121,7 @@ def get_item_details(items, sl_entries, include_uom): {cf_join} where item.name in ({item_codes}) - """.format(cf_field=cf_field, cf_join=cf_join, item_codes=item_codes), as_dict=1) + """.format(cf_field=cf_field, cf_join=cf_join, item_codes=','.join(['%s'] *len(items))), items, as_dict=1) for item in res: item_details.setdefault(item.name, item) diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js index dba111d8d8..97b34e9401 100644 --- a/erpnext/support/doctype/issue/issue.js +++ b/erpnext/support/doctype/issue/issue.js @@ -1,7 +1,9 @@ frappe.ui.form.on("Issue", { onload: function(frm) { frm.email_field = "raised_by"; - set_time_to_resolve_and_response(frm); + if (frm.doc.service_level_agreement) { + set_time_to_resolve_and_response(frm); + } }, refresh: function (frm) { @@ -84,15 +86,16 @@ function set_time_to_resolve_and_response(frm) { const email_account = frm.fields_dict['email_account'].$wrapper; const time_to_respond = $(get_time_left_element(__('Time To Respond'), frm.doc.response_by)); - const time_to_resolve = $(get_time_left_element(__('Time To Resolve'), frm.doc.resolve_by)); + const time_to_resolve = $(get_time_left_element(__('Time To Resolve'), frm.doc.resolution_by)); time_to_respond.insertAfter(customer); time_to_resolve.insertAfter(email_account); } function get_time_left_element(label, timestamp) { + $('.'+ frappe.scrub(label) +'').remove(); return ` -
+