From a5002525704d5e9d4a33913143f49a355ac20f16 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Tue, 12 Oct 2021 13:25:55 +0530 Subject: [PATCH 01/23] perf: skip get_pricing_rules if no pricing rule exists --- erpnext/accounts/doctype/pricing_rule/utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index 0637fdaef0..ef44b41476 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -29,6 +29,9 @@ def get_pricing_rules(args, doc=None): pricing_rules = [] values = {} + if not frappe.db.exists('Pricing Rule', {'disable': 0, args.transaction_type: 1}): + return + 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): From 7b691beabb40cdf3156a5cf81355d8d4c6b8bd7b Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Tue, 12 Oct 2021 13:28:31 +0530 Subject: [PATCH 02/23] perf: fetch mode of payments data in single query --- .../doctype/sales_invoice/sales_invoice.py | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index d909814921..0c3eff2a03 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1951,22 +1951,23 @@ def update_multi_mode_option(doc, pos_profile): def append_payment(payment_mode): payment = doc.append('payments', {}) payment.default = payment_mode.default - payment.mode_of_payment = payment_mode.parent + payment.mode_of_payment = payment_mode.mop payment.account = payment_mode.default_account payment.type = payment_mode.type doc.set('payments', []) invalid_modes = [] - for pos_payment_method in pos_profile.get('payments'): - pos_payment_method = pos_payment_method.as_dict() + mode_of_payments = [d.mode_of_payment for d in pos_profile.get('payments')] + mode_of_payments_info = get_mode_of_payments_info(mode_of_payments, doc.company) - payment_mode = get_mode_of_payment_info(pos_payment_method.mode_of_payment, doc.company) + for row in pos_profile.get('payments'): + payment_mode = mode_of_payments_info.get(row.mode_of_payment) if not payment_mode: - invalid_modes.append(get_link_to_form("Mode of Payment", pos_payment_method.mode_of_payment)) + invalid_modes.append(get_link_to_form("Mode of Payment", row.mode_of_payment)) continue - payment_mode[0].default = pos_payment_method.default - append_payment(payment_mode[0]) + payment_mode.default = row.default + append_payment(payment_mode) if invalid_modes: if invalid_modes == 1: @@ -1982,6 +1983,25 @@ def get_all_mode_of_payments(doc): where mpa.parent = mp.name and mpa.company = %(company)s and mp.enabled = 1""", {'company': doc.company}, as_dict=1) +def get_mode_of_payments_info(mode_of_payments, company): + data = frappe.db.sql( + """ + select + mpa.default_account, mpa.parent as mop, mp.type as type + from + `tabMode of Payment Account` mpa,`tabMode of Payment` mp + where + mpa.parent = mp.name and + mpa.company = %s and + mp.enabled = 1 and + mp.name in (%s) + group by + mp.name + """, + (company, mode_of_payments), as_dict=1) + + return {row.get('mop'): row for row in data} + def get_mode_of_payment_info(mode_of_payment, company): return frappe.db.sql(""" select mpa.default_account, mpa.parent, mp.type as type From eb3aae870f92e73b2b7babdb1bba01aaebf6e854 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Tue, 12 Oct 2021 13:29:32 +0530 Subject: [PATCH 03/23] perf: get total company stock only for purchase order --- erpnext/stock/get_item_details.py | 36 ++++++++++++++++++------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index cbff2149d6..e0190b64a7 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -89,7 +89,13 @@ def get_item_details(args, doc=None, for_validate=False, overwrite_warehouse=Tru out.update(get_bin_details(args.item_code, args.get("from_warehouse"))) elif out.get("warehouse"): - out.update(get_bin_details(args.item_code, out.warehouse, args.company)) + if doc and doc.get('doctype') == 'Purchase Order': + # calculate company_total_stock only for po + bin_details = get_bin_details(args.item_code, out.warehouse, args.company) + else: + bin_details = get_bin_details(args.item_code, out.warehouse) + + out.update(bin_details) # update args with out, if key or value not exists for key, value in iteritems(out): @@ -485,8 +491,9 @@ def get_item_tax_template(args, item, out): "item_tax_template": None } """ - item_tax_template = args.get("item_tax_template") - item_tax_template = _get_item_tax_template(args, item.taxes, out) + item_tax_template = None + if item.taxes: + item_tax_template = _get_item_tax_template(args, item.taxes, out) if not item_tax_template: item_group = item.item_group @@ -502,17 +509,17 @@ def _get_item_tax_template(args, taxes, out=None, for_validate=False): taxes_with_no_validity = [] for tax in taxes: - tax_company = frappe.get_value("Item Tax Template", tax.item_tax_template, 'company') - if (tax.valid_from or tax.maximum_net_rate) and tax_company == args['company']: - # In purchase Invoice first preference will be given to supplier invoice date - # if supplier date is not present then posting date - validation_date = args.get('transaction_date') or args.get('bill_date') or args.get('posting_date') + tax_company = frappe.get_cached_value("Item Tax Template", tax.item_tax_template, 'company') + if tax_company == args['company']: + if (tax.valid_from or tax.maximum_net_rate): + # In purchase Invoice first preference will be given to supplier invoice date + # if supplier date is not present then posting date + validation_date = args.get('transaction_date') or args.get('bill_date') or args.get('posting_date') - if getdate(tax.valid_from) <= getdate(validation_date) \ - and is_within_valid_range(args, tax): - taxes_with_validity.append(tax) - else: - if tax_company == args['company']: + if getdate(tax.valid_from) <= getdate(validation_date) \ + and is_within_valid_range(args, tax): + taxes_with_validity.append(tax) + else: taxes_with_no_validity.append(tax) if taxes_with_validity: @@ -890,8 +897,7 @@ def get_pos_profile_item_details(company, args, pos_profile=None, update_data=Fa res[fieldname] = pos_profile.get(fieldname) if res.get("warehouse"): - res.actual_qty = get_bin_details(args.item_code, - res.warehouse).get("actual_qty") + res.actual_qty = get_bin_details(args.item_code, res.warehouse).get("actual_qty") return res From c7fc609236aeaada0375e90b664c041bdbc52570 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Tue, 12 Oct 2021 13:30:40 +0530 Subject: [PATCH 04/23] perf: skip insertion of stock ledger entry --- erpnext/stock/stock_ledger.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 1b5b792f94..bff7880fd6 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -123,12 +123,11 @@ def set_as_cancel(voucher_type, voucher_no): (now(), frappe.session.user, voucher_type, voucher_no)) def make_entry(args, allow_negative_stock=False, via_landed_cost_voucher=False): - args.update({"doctype": "Stock Ledger Entry"}) + args["doctype"] = "Stock Ledger Entry" sle = frappe.get_doc(args) sle.flags.ignore_permissions = 1 sle.allow_negative_stock=allow_negative_stock sle.via_landed_cost_voucher = via_landed_cost_voucher - sle.insert() sle.submit() return sle @@ -240,8 +239,7 @@ class update_entries_after(object): self.verbose = verbose self.allow_zero_rate = allow_zero_rate self.via_landed_cost_voucher = via_landed_cost_voucher - self.allow_negative_stock = allow_negative_stock \ - or cint(frappe.db.get_single_value("Stock Settings", "allow_negative_stock")) + self.allow_negative_stock = True self.args = frappe._dict(args) self.item_code = args.get("item_code") From 7bafa11d5758c40496898cd0151efde4ff358946 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 12 Oct 2021 20:39:10 +0530 Subject: [PATCH 05/23] fix: undo changes to allow negative stock flag --- erpnext/stock/stock_ledger.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index bff7880fd6..2b6eefb5cc 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -239,7 +239,8 @@ class update_entries_after(object): self.verbose = verbose self.allow_zero_rate = allow_zero_rate self.via_landed_cost_voucher = via_landed_cost_voucher - self.allow_negative_stock = True + self.allow_negative_stock = allow_negative_stock \ + or cint(frappe.db.get_single_value("Stock Settings", "allow_negative_stock")) self.args = frappe._dict(args) self.item_code = args.get("item_code") From ac381d21fe94b99406b4d7d332a6356a41bd8e26 Mon Sep 17 00:00:00 2001 From: Saqib Date: Mon, 18 Oct 2021 10:43:15 +0530 Subject: [PATCH 06/23] fix: sider --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 0c3eff2a03..290c7fe60b 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1997,8 +1997,7 @@ def get_mode_of_payments_info(mode_of_payments, company): mp.name in (%s) group by mp.name - """, - (company, mode_of_payments), as_dict=1) + """, (company, mode_of_payments), as_dict=1) return {row.get('mop'): row for row in data} From c6d06816cfbafef05d79c26df166cc6cd7c18b48 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 21 Oct 2021 15:37:59 +0530 Subject: [PATCH 07/23] fix: Auto update company address check on linking with company --- erpnext/accounts/custom/address.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/erpnext/accounts/custom/address.py b/erpnext/accounts/custom/address.py index a6d08d8ff6..551048e50b 100644 --- a/erpnext/accounts/custom/address.py +++ b/erpnext/accounts/custom/address.py @@ -10,6 +10,7 @@ from frappe.contacts.doctype.address.address import ( class ERPNextAddress(Address): def validate(self): self.validate_reference() + self.update_compnay_address() super(ERPNextAddress, self).validate() def link_address(self): @@ -19,6 +20,11 @@ class ERPNextAddress(Address): return super(ERPNextAddress, self).link_address() + def update_compnay_address(self): + for link in self.get('links'): + if link.link_doctype == 'Company': + self.is_your_company_address = 1 + def validate_reference(self): if self.is_your_company_address and not [ row for row in self.links if row.link_doctype == "Company" From 7733afc0ae7e5e3a67b8e498a282ac5fb54afabf Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 21 Oct 2021 16:13:00 +0530 Subject: [PATCH 08/23] fix(minor): Filters and fixes in Tax Withholding Category --- .../tax_withholding_category/tax_withholding_category.js | 3 ++- .../tax_withholding_category/tax_withholding_category.py | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.js b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.js index b8d6c9af3a..7b47974946 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.js +++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.js @@ -8,7 +8,8 @@ frappe.ui.form.on('Tax Withholding Category', { if (child.company) { return { filters: { - 'company': child.company + 'company': child.company, + 'root_type': ['in', ['Asset', 'Liability']] } }; } diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py index c3cb8396d0..c36f3cb201 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py @@ -13,6 +13,7 @@ from frappe.utils import cint, getdate class TaxWithholdingCategory(Document): def validate(self): self.validate_dates() + self.validate_accounts() self.validate_thresholds() def validate_dates(self): @@ -25,6 +26,14 @@ class TaxWithholdingCategory(Document): if last_date and getdate(d.to_date) < getdate(last_date): frappe.throw(_("Row #{0}: Dates overlapping with other row").format(d.idx)) + def validate_accounts(self): + existing_accounts = [] + for d in self.get('accounts'): + if d.get('account') in existing_accounts: + frappe.throw(_("Account {0} added multiple times").format(frappe.bold(d.get('account')))) + + existing_accounts.append(d.get('account')) + def validate_thresholds(self): for d in self.get('rates'): if d.cumulative_threshold and d.cumulative_threshold < d.single_threshold: From a20058a3436f63afb4c537916aeffacdac14c786 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 21 Oct 2021 17:52:13 +0530 Subject: [PATCH 09/23] fix(minor): Add mandatory depends on condition for reference no and date fields --- .../doctype/payment_entry/payment_entry.json | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json index 6f362c1fbb..ee2e319a6f 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.json +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json @@ -27,10 +27,12 @@ "payment_accounts_section", "party_balance", "paid_from", + "paid_from_account_type", "paid_from_account_currency", "paid_from_account_balance", "column_break_18", "paid_to", + "paid_to_account_type", "paid_to_account_currency", "paid_to_account_balance", "payment_amounts_section", @@ -440,7 +442,8 @@ "depends_on": "eval:(doc.paid_from && doc.paid_to)", "fieldname": "reference_no", "fieldtype": "Data", - "label": "Cheque/Reference No" + "label": "Cheque/Reference No", + "mandatory_depends_on": "eval:(doc.paid_from_account_type == 'Bank' || doc.paid_to_account_type == 'Bank')" }, { "fieldname": "column_break_23", @@ -452,6 +455,7 @@ "fieldname": "reference_date", "fieldtype": "Date", "label": "Cheque/Reference Date", + "mandatory_depends_on": "eval:(doc.paid_from_account_type == 'Bank' || doc.paid_to_account_type == 'Bank')", "search_index": 1 }, { @@ -707,15 +711,30 @@ "label": "Received Amount After Tax (Company Currency)", "options": "Company:company:default_currency", "read_only": 1 + }, + { + "fetch_from": "paid_from.account_type", + "fieldname": "paid_from_account_type", + "fieldtype": "Data", + "hidden": 1, + "label": "Paid From Account Type" + }, + { + "fetch_from": "paid_to.account_type", + "fieldname": "paid_to_account_type", + "fieldtype": "Data", + "hidden": 1, + "label": "Paid To Account Type" } ], "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2021-07-09 08:58:15.008761", + "modified": "2021-10-22 17:50:24.632806", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Entry", + "naming_rule": "By \"Naming Series\" field", "owner": "Administrator", "permissions": [ { From 65025fb628d55a97d3c2281760d7d5954ac44912 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 21 Oct 2021 19:29:18 +0530 Subject: [PATCH 10/23] fix: Update receivable/payable account on company change --- .../accounts/doctype/purchase_invoice/purchase_invoice.js | 6 ++++++ erpnext/accounts/doctype/sales_invoice/sales_invoice.js | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index 6c74d2b438..3526e488e1 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -590,5 +590,11 @@ frappe.ui.form.on("Purchase Invoice", { company: function(frm) { erpnext.accounts.dimensions.update_dimension(frm, frm.doctype); + + if (frm.doc.company) { + frappe.db.get_value('Company', frm.doc.company, 'default_payable_account', (r) => { + frm.set_value('credit_to', r.default_payable_account); + }); + } }, }) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 73e1284304..bee153b7b8 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -12,6 +12,13 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e } company() { erpnext.accounts.dimensions.update_dimension(this.frm, this.frm.doctype); + + let me = this; + if (this.frm.doc.company) { + frappe.db.get_value('Company', this.frm.doc.company, 'default_receivable_account', (r) => { + me.frm.set_value('debit_to', r.default_receivable_account); + }); + } } onload() { var me = this; From e3ae8d5a1e6bc1251feae63f51215e9ce3c2365a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 20 Oct 2021 22:10:21 +0530 Subject: [PATCH 11/23] fix: Move PAN field from standard doctype to fixtures for India --- erpnext/buying/doctype/supplier/supplier.json | 9 ++----- erpnext/patches.txt | 1 + .../v13_0/create_pan_field_for_india.py | 25 +++++++++++++++++++ erpnext/regional/india/setup.py | 16 ++++++++++-- .../selling/doctype/customer/customer.json | 12 +++------ 5 files changed, 45 insertions(+), 18 deletions(-) create mode 100644 erpnext/patches/v13_0/create_pan_field_for_india.py diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json index 12a09cdd0e..a57d9a92bb 100644 --- a/erpnext/buying/doctype/supplier/supplier.json +++ b/erpnext/buying/doctype/supplier/supplier.json @@ -25,7 +25,6 @@ "column_break0", "supplier_group", "supplier_type", - "pan", "allow_purchase_invoice_creation_without_purchase_order", "allow_purchase_invoice_creation_without_purchase_receipt", "disabled", @@ -176,11 +175,6 @@ "options": "Company\nIndividual", "reqd": 1 }, - { - "fieldname": "pan", - "fieldtype": "Data", - "label": "PAN" - }, { "fieldname": "language", "fieldtype": "Link", @@ -438,11 +432,12 @@ "link_fieldname": "party" } ], - "modified": "2021-09-06 17:37:56.522233", + "modified": "2021-10-20 22:03:33.147249", "modified_by": "Administrator", "module": "Buying", "name": "Supplier", "name_case": "Title Case", + "naming_rule": "By \"Naming Series\" field", "owner": "Administrator", "permissions": [ { diff --git a/erpnext/patches.txt b/erpnext/patches.txt index e446d6be42..9bcab5e74a 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -310,3 +310,4 @@ erpnext.patches.v13_0.enable_scheduler_job_for_item_reposting erpnext.patches.v13_0.requeue_failed_reposts erpnext.patches.v13_0.healthcare_deprecation_warning erpnext.patches.v14_0.delete_healthcare_doctypes +erpnext.patches.v13_0.create_pan_field_for_india diff --git a/erpnext/patches/v13_0/create_pan_field_for_india.py b/erpnext/patches/v13_0/create_pan_field_for_india.py new file mode 100644 index 0000000000..e94a9d93b3 --- /dev/null +++ b/erpnext/patches/v13_0/create_pan_field_for_india.py @@ -0,0 +1,25 @@ +import frappe +from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + + +def execute(): + custom_fields = { + 'Supplier': [ + { + 'fieldname': 'pan', + 'label': 'PAN', + 'fieldtype': 'Data', + 'insert_after': 'supplier_type' + } + ], + 'Customer': [ + { + 'fieldname': 'pan', + 'label': 'PAN', + 'fieldtype': 'Data', + 'insert_after': 'customer_type' + } + ] + } + + create_custom_fields(custom_fields, update=True) diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index afb1b07ccc..1cbb154125 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -614,11 +614,17 @@ def get_custom_fields(): fieldtype='Currency', insert_after='monthly_hra_exemption', read_only=1, depends_on='house_rent_payment_amount') ], 'Supplier': [ + { + 'fieldname': 'pan', + 'label': 'PAN', + 'fieldtype': 'Data', + 'insert_after': 'supplier_type' + }, { 'fieldname': 'gst_transporter_id', 'label': 'GST Transporter ID', 'fieldtype': 'Data', - 'insert_after': 'supplier_type', + 'insert_after': 'pan', 'depends_on': 'eval:doc.is_transporter' }, { @@ -640,11 +646,17 @@ def get_custom_fields(): } ], 'Customer': [ + { + 'fieldname': 'pan', + 'label': 'PAN', + 'fieldtype': 'Data', + 'insert_after': 'customer_type' + }, { 'fieldname': 'gst_category', 'label': 'GST Category', 'fieldtype': 'Select', - 'insert_after': 'customer_type', + 'insert_after': 'pan', 'options': 'Registered Regular\nRegistered Composition\nUnregistered\nSEZ\nOverseas\nConsumer\nDeemed Export\nUIN Holders', 'default': 'Unregistered' }, diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json index e811435e66..fa6e932d9e 100644 --- a/erpnext/selling/doctype/customer/customer.json +++ b/erpnext/selling/doctype/customer/customer.json @@ -16,7 +16,6 @@ "customer_name", "gender", "customer_type", - "pan", "tax_withholding_category", "default_bank_account", "lead_name", @@ -213,8 +212,7 @@ "fieldtype": "Link", "ignore_user_permissions": 1, "label": "Represents Company", - "options": "Company", - "unique": 1 + "options": "Company" }, { "depends_on": "represents_company", @@ -486,11 +484,6 @@ "fieldtype": "Check", "label": "Allow Sales Invoice Creation Without Delivery Note" }, - { - "fieldname": "pan", - "fieldtype": "Data", - "label": "PAN" - }, { "fieldname": "tax_withholding_category", "fieldtype": "Link", @@ -517,11 +510,12 @@ "link_fieldname": "party" } ], - "modified": "2021-09-06 17:38:54.196663", + "modified": "2021-10-20 22:07:52.485809", "modified_by": "Administrator", "module": "Selling", "name": "Customer", "name_case": "Title Case", + "naming_rule": "By \"Naming Series\" field", "owner": "Administrator", "permissions": [ { From cd4b20313e69affe3a5074a0c514f1a96ece0f6f Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 25 Oct 2021 11:21:55 +0530 Subject: [PATCH 12/23] fix: Test case fixes and linting issues --- erpnext/patches/v13_0/create_pan_field_for_india.py | 1 - erpnext/regional/india/utils.py | 2 +- erpnext/selling/doctype/customer/customer.json | 3 ++- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/patches/v13_0/create_pan_field_for_india.py b/erpnext/patches/v13_0/create_pan_field_for_india.py index e94a9d93b3..01d4305bc4 100644 --- a/erpnext/patches/v13_0/create_pan_field_for_india.py +++ b/erpnext/patches/v13_0/create_pan_field_for_india.py @@ -1,4 +1,3 @@ -import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index 0e4128024d..1733220c0a 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -62,7 +62,7 @@ def validate_gstin_for_india(doc, method): .format(doc.gst_state_number), title=_("Invalid GSTIN")) def validate_pan_for_india(doc, method): - if doc.get('country') != 'India' or not doc.pan: + if doc.get('country') != 'India' or not doc.get('pan'): return if not PAN_NUMBER_FORMAT.match(doc.pan): diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json index fa6e932d9e..ae40630617 100644 --- a/erpnext/selling/doctype/customer/customer.json +++ b/erpnext/selling/doctype/customer/customer.json @@ -212,7 +212,8 @@ "fieldtype": "Link", "ignore_user_permissions": 1, "label": "Represents Company", - "options": "Company" + "options": "Company", + "unique": 1 }, { "depends_on": "represents_company", From 9c1705205f4597639c800b04eaf421bb7e987844 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 25 Oct 2021 20:06:24 +0530 Subject: [PATCH 13/23] fix: Payment Terms validation precision --- erpnext/controllers/accounts_controller.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 88c439b4f6..b05d1b6f6d 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1354,8 +1354,8 @@ class AccountsController(TransactionBase): total = 0 base_total = 0 for d in self.get("payment_schedule"): - total += flt(d.payment_amount) - base_total += flt(d.base_payment_amount) + total += flt(d.payment_amount, d.precision("payment_amount")) + base_total += flt(d.base_payment_amount, d.precision("base_payment_amount")) base_grand_total = self.get("base_rounded_total") or self.base_grand_total grand_total = self.get("rounded_total") or self.grand_total @@ -1371,8 +1371,9 @@ class AccountsController(TransactionBase): else: grand_total -= self.get("total_advance") base_grand_total = flt(grand_total * self.get("conversion_rate"), self.precision("base_grand_total")) - if total != flt(grand_total, self.precision("grand_total")) or \ - base_total != flt(base_grand_total, self.precision("base_grand_total")): + + if flt(total, self.precision("grand_total")) != flt(grand_total, self.precision("grand_total")) or \ + flt(base_total, self.precision("base_grand_total")) != flt(base_grand_total, self.precision("base_grand_total")): frappe.throw(_("Total Payment Amount in Payment Schedule must be equal to Grand / Rounded Total")) def is_rounded_total_disabled(self): From 07a3be6f6124ddc9db97a0f22d9c1c886f1782ab Mon Sep 17 00:00:00 2001 From: Kenneth Sequeira <33246109+kennethsequeira@users.noreply.github.com> Date: Mon, 25 Oct 2021 20:10:52 +0530 Subject: [PATCH 14/23] fix: remove VM from installation (#28075) --- README.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/README.md b/README.md index 6fad8f4fcd..1105a97005 100644 --- a/README.md +++ b/README.md @@ -55,14 +55,6 @@ The Easy Way: our install script for bench will install all dependencies (e.g. M New passwords will be created for the ERPNext "Administrator" user, the MariaDB root user, and the frappe user (the script displays the passwords and saves them to ~/frappe_passwords.txt). -### Virtual Image - -You can download a virtual image to run ERPNext in a virtual machine on your local system. - -- [ERPNext Download](http://erpnext.com/download) - -System and user credentials are listed on the download page. - --- ## License From 89d5e494ddbe82912a65400ebf7f7b4ff565a8b0 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 26 Oct 2021 19:51:03 +0530 Subject: [PATCH 15/23] fix: Reload customer and supplier doctype --- erpnext/patches.txt | 2 +- erpnext/patches/v13_0/create_pan_field_for_india.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 9bcab5e74a..20e54e08e6 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -310,4 +310,4 @@ erpnext.patches.v13_0.enable_scheduler_job_for_item_reposting erpnext.patches.v13_0.requeue_failed_reposts erpnext.patches.v13_0.healthcare_deprecation_warning erpnext.patches.v14_0.delete_healthcare_doctypes -erpnext.patches.v13_0.create_pan_field_for_india +erpnext.patches.v13_0.create_pan_field_for_india #2 diff --git a/erpnext/patches/v13_0/create_pan_field_for_india.py b/erpnext/patches/v13_0/create_pan_field_for_india.py index 01d4305bc4..c37651aaa3 100644 --- a/erpnext/patches/v13_0/create_pan_field_for_india.py +++ b/erpnext/patches/v13_0/create_pan_field_for_india.py @@ -1,7 +1,11 @@ +import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields def execute(): + frappe.reload_doc('buying', 'doctype', 'supplier', force=True) + frappe.reload_doc('selling', 'doctype', 'customer', force=True) + custom_fields = { 'Supplier': [ { From 6ec047cba9418815712efbe71abc147677ebfc0e Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 27 Oct 2021 10:30:05 +0530 Subject: [PATCH 16/23] fix(ux): overbiling message in SO->SI, PO->PI (#28088) --- erpnext/controllers/accounts_controller.py | 2 +- erpnext/controllers/status_updater.py | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 88c439b4f6..904f221718 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1032,7 +1032,7 @@ class AccountsController(TransactionBase): if role_allowed_to_over_bill in user_roles and total_overbilled_amt > 0.1: frappe.msgprint(_("Overbilling of {} ignored because you have {} role.") - .format(total_overbilled_amt, role_allowed_to_over_bill), title=_("Warning"), indicator="orange") + .format(total_overbilled_amt, role_allowed_to_over_bill), indicator="orange", alert=True) def throw_overbill_exception(self, item, max_allowed_amt): frappe.throw(_("Cannot overbill for Item {0} in row {1} more than {2}. To allow over-billing, please set allowance in Accounts Settings") diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index 8738204ce0..49a76da697 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -216,11 +216,14 @@ class StatusUpdater(Document): overflow_percent = ((item[args['target_field']] - item[args['target_ref_field']]) / item[args['target_ref_field']]) * 100 - if overflow_percent - allowance > 0.01 and role not in frappe.get_roles(): + if overflow_percent - allowance > 0.01: item['max_allowed'] = flt(item[args['target_ref_field']] * (100+allowance)/100) item['reduce_by'] = item[args['target_field']] - item['max_allowed'] - self.limits_crossed_error(args, item, qty_or_amount) + if role not in frappe.get_roles(): + self.limits_crossed_error(args, item, qty_or_amount) + else: + self.warn_about_bypassing_with_role(item, qty_or_amount, role) def limits_crossed_error(self, args, item, qty_or_amount): '''Raise exception for limits crossed''' @@ -238,6 +241,19 @@ class StatusUpdater(Document): frappe.bold(item.get('item_code')) ) + '

' + action_msg, OverAllowanceError, title = _('Limit Crossed')) + def warn_about_bypassing_with_role(self, item, qty_or_amount, role): + action = _("Over Receipt/Delivery") if qty_or_amount == "qty" else _("Overbilling") + + msg = (_("{} of {} {} ignored for item {} because you have {} role.") + .format( + action, + _(item["target_ref_field"].title()), + frappe.bold(item["reduce_by"]), + frappe.bold(item.get('item_code')), + role) + ) + frappe.msgprint(msg, indicator="orange", alert=True) + def update_qty(self, update_modified=True): """Updates qty or amount at row level From f2d136e57475421694c12c97b9eba6ccb8e45f76 Mon Sep 17 00:00:00 2001 From: Diksha Jadhav Date: Tue, 5 Oct 2021 14:50:29 +0530 Subject: [PATCH 17/23] feat(pick list): group items based on item code and warehouse before printing picklist --- .../stock/doctype/pick_list/pick_list.json | 22 +++++++++++++--- erpnext/stock/doctype/pick_list/pick_list.py | 26 +++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/pick_list/pick_list.json b/erpnext/stock/doctype/pick_list/pick_list.json index 2146793537..c604c711ef 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.json +++ b/erpnext/stock/doctype/pick_list/pick_list.json @@ -18,7 +18,9 @@ "get_item_locations", "section_break_6", "locations", - "amended_from" + "amended_from", + "print_settings_section", + "group_same_items" ], "fields": [ { @@ -110,14 +112,28 @@ "options": "STO-PICK-.YYYY.-", "reqd": 1, "set_only_once": 1 + }, + { + "fieldname": "print_settings_section", + "fieldtype": "Section Break", + "label": "Print Settings" + }, + { + "allow_on_submit": 1, + "default": "0", + "fieldname": "group_same_items", + "fieldtype": "Check", + "label": "Group Same Items", + "print_hide": 1 } ], "is_submittable": 1, "links": [], - "modified": "2020-03-17 11:38:41.932875", + "modified": "2021-10-05 15:08:40.369957", "modified_by": "Administrator", "module": "Stock", "name": "Pick List", + "naming_rule": "By \"Naming Series\" field", "owner": "Administrator", "permissions": [ { @@ -184,4 +200,4 @@ "sort_field": "modified", "sort_order": "DESC", "track_changes": 1 -} +} \ No newline at end of file diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index dffbe80fa3..7b2f44b084 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -121,6 +121,32 @@ class PickList(Document): and (self.for_qty is None or self.for_qty == 0): frappe.throw(_("Qty of Finished Goods Item should be greater than 0.")) + def before_print(self, settings=None): + if self.get("group_same_items"): + self.group_similar_items() + + def group_similar_items(self): + group_item_qty = {} + group_picked_qty = {} + count = 0 + + for item in self.locations: + group_item_qty[(item.item_code, item.warehouse)] = group_item_qty.get((item.item_code,item.warehouse), 0) + item.qty + group_picked_qty[(item.item_code, item.warehouse)] = group_picked_qty.get((item.item_code,item.warehouse), 0) + item.picked_qty + + duplicate_list = [] + for item in self.locations: + if (item.item_code, item.warehouse) in group_item_qty: + count += 1 + item.qty = group_item_qty[(item.item_code, item.warehouse)] + item.picked_qty = group_picked_qty[(item.item_code, item.warehouse)] + item.stock_qty = group_item_qty[(item.item_code, item.warehouse)] + item.idx = count + del group_item_qty[(item.item_code, item.warehouse)] + else: + duplicate_list.append(item) + for item in duplicate_list: + self.remove(item) def validate_item_locations(pick_list): if not pick_list.locations: From 69429005551161e63cda5c2b2fcda1a685280775 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 27 Oct 2021 10:36:06 +0530 Subject: [PATCH 18/23] refactor: use defaultdict and enumeration --- erpnext/stock/doctype/pick_list/pick_list.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index 7b2f44b084..4c02f3db43 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -2,10 +2,8 @@ # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals - import json -from collections import OrderedDict +from collections import OrderedDict, defaultdict import frappe from frappe import _ @@ -126,28 +124,30 @@ class PickList(Document): self.group_similar_items() def group_similar_items(self): - group_item_qty = {} - group_picked_qty = {} - count = 0 + group_item_qty = defaultdict(float) + group_picked_qty = defaultdict(float) for item in self.locations: - group_item_qty[(item.item_code, item.warehouse)] = group_item_qty.get((item.item_code,item.warehouse), 0) + item.qty - group_picked_qty[(item.item_code, item.warehouse)] = group_picked_qty.get((item.item_code,item.warehouse), 0) + item.picked_qty + group_item_qty[(item.item_code, item.warehouse)] += item.qty + group_picked_qty[(item.item_code, item.warehouse)] += item.picked_qty duplicate_list = [] for item in self.locations: if (item.item_code, item.warehouse) in group_item_qty: - count += 1 item.qty = group_item_qty[(item.item_code, item.warehouse)] item.picked_qty = group_picked_qty[(item.item_code, item.warehouse)] item.stock_qty = group_item_qty[(item.item_code, item.warehouse)] - item.idx = count del group_item_qty[(item.item_code, item.warehouse)] else: duplicate_list.append(item) + for item in duplicate_list: self.remove(item) + for idx, item in enumerate(self.locations, start=1): + item.idx = idx + + def validate_item_locations(pick_list): if not pick_list.locations: frappe.throw(_("Add items in the Item Locations table")) From 479ecb8de0c77beafddd243c1b5fe38793ea32de Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 27 Oct 2021 10:51:47 +0530 Subject: [PATCH 19/23] test: picklist item grouping --- .../stock/doctype/pick_list/test_pick_list.py | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/erpnext/stock/doctype/pick_list/test_pick_list.py b/erpnext/stock/doctype/pick_list/test_pick_list.py index fd0b3680df..58b46e1eef 100644 --- a/erpnext/stock/doctype/pick_list/test_pick_list.py +++ b/erpnext/stock/doctype/pick_list/test_pick_list.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import frappe +from frappe import _dict test_dependencies = ['Item', 'Sales Invoice', 'Stock Entry', 'Batch'] @@ -356,6 +357,39 @@ class TestPickList(ERPNextTestCase): sales_order.cancel() purchase_receipt.cancel() + def test_pick_list_grouping_before_print(self): + def _compare_dicts(a, b): + "compare dicts but ignore missing keys in `a`" + for key, value in a.items(): + self.assertEqual(b.get(key), value, msg=f"{key} doesn't match") + + # nothing should be grouped + pl = frappe.get_doc(doctype="Pick List", group_same_items=True, locations=[ + _dict(item_code="A", warehouse="X", qty=1, picked_qty=2), + _dict(item_code="B", warehouse="X", qty=1, picked_qty=2), + _dict(item_code="A", warehouse="Y", qty=1, picked_qty=2), + _dict(item_code="B", warehouse="Y", qty=1, picked_qty=2), + ]) + pl.before_print() + self.assertEqual(len(pl.locations), 4) + + # grouping should halve the number of items + pl = frappe.get_doc(doctype="Pick List", group_same_items=True, locations=[ + _dict(item_code="A", warehouse="X", qty=5, picked_qty=1), + _dict(item_code="B", warehouse="Y", qty=4, picked_qty=2), + _dict(item_code="A", warehouse="X", qty=3, picked_qty=2), + _dict(item_code="B", warehouse="Y", qty=2, picked_qty=2), + ]) + pl.before_print() + self.assertEqual(len(pl.locations), 2) + + expected_items = [ + _dict(item_code="A", warehouse="X", qty=8, picked_qty=3), + _dict(item_code="B", warehouse="Y", qty=6, picked_qty=4), + ] + for expected_item, created_item in zip(expected_items, pl.locations): + _compare_dicts(expected_item, created_item) + # def test_pick_list_skips_items_in_expired_batch(self): # pass From 2920f2f61479448e6467c97b7ba696bb90d9c092 Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Wed, 27 Oct 2021 11:17:48 +0530 Subject: [PATCH 20/23] fix: change modified timestamp to apply changes on migrate #28095 fix: change modified timestamp to apply changes on migrate --- .../expense_taxes_and_charges/expense_taxes_and_charges.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json index 4a1064b66b..2f7b8fcf67 100644 --- a/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json +++ b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json @@ -100,7 +100,7 @@ ], "istable": 1, "links": [], - "modified": "2020-09-23 20:27:36.027728", + "modified": "2021-10-26 20:27:36.027728", "modified_by": "Administrator", "module": "HR", "name": "Expense Taxes and Charges", From 25d1c1ce86ec9d66b50bdf12d4954631d22d50c5 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 27 Oct 2021 11:21:26 +0530 Subject: [PATCH 21/23] fix: add filter to query to avoid send reminder for zero years (#28092) (#28096) Co-authored-by: Rucha Mahabal (cherry picked from commit 8cad23b8fb4d830a5703e107c371ae9319bc003d) Co-authored-by: gsi-maruiz <62341390+gsi-maruiz@users.noreply.github.com> --- erpnext/hr/doctype/employee/employee_reminders.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/hr/doctype/employee/employee_reminders.py b/erpnext/hr/doctype/employee/employee_reminders.py index 216d8f6bb3..559bd393e6 100644 --- a/erpnext/hr/doctype/employee/employee_reminders.py +++ b/erpnext/hr/doctype/employee/employee_reminders.py @@ -156,6 +156,8 @@ def get_employees_having_an_event_today(event_type): DAY({condition_column}) = DAY(%(today)s) AND MONTH({condition_column}) = MONTH(%(today)s) + AND + YEAR({condition_column}) < YEAR(%(today)s) AND `status` = 'Active' """, @@ -166,6 +168,8 @@ def get_employees_having_an_event_today(event_type): DATE_PART('day', {condition_column}) = date_part('day', %(today)s) AND DATE_PART('month', {condition_column}) = date_part('month', %(today)s) + AND + DATE_PART('year', {condition_column}) < date_part('year', %(today)s) AND "status" = 'Active' """, From 05831b18ad08ffcbc8a332ed74697efae1bd870a Mon Sep 17 00:00:00 2001 From: Alan <2.alan.tom@gmail.com> Date: Wed, 27 Oct 2021 11:36:37 +0530 Subject: [PATCH 22/23] fix: update production plan status #27567 fix: update production plan status --- .../production_plan/production_plan.py | 11 ++++++- erpnext/patches.txt | 1 + .../v12_0/update_production_plan_status.py | 31 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 erpnext/patches/v12_0/update_production_plan_status.py diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 7e6fc3c4a6..2424ef9a71 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -311,7 +311,7 @@ class ProductionPlan(Document): if self.total_produced_qty > 0: self.status = "In Process" - if self.total_produced_qty >= self.total_planned_qty: + if self.check_have_work_orders_completed(): self.status = "Completed" if self.status != 'Completed': @@ -575,6 +575,15 @@ class ProductionPlan(Document): self.append("sub_assembly_items", data) + def check_have_work_orders_completed(self): + wo_status = frappe.db.get_list( + "Work Order", + filters={"production_plan": self.name}, + fields="status", + pluck="status" + ) + return all(s == "Completed" for s in wo_status) + @frappe.whitelist() def download_raw_materials(doc, warehouses=None): if isinstance(doc, str): diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 20e54e08e6..1dac50c6e1 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -308,6 +308,7 @@ erpnext.patches.v13_0.set_status_in_maintenance_schedule_table erpnext.patches.v13_0.add_default_interview_notification_templates erpnext.patches.v13_0.enable_scheduler_job_for_item_reposting erpnext.patches.v13_0.requeue_failed_reposts +erpnext.patches.v12_0.update_production_plan_status erpnext.patches.v13_0.healthcare_deprecation_warning erpnext.patches.v14_0.delete_healthcare_doctypes erpnext.patches.v13_0.create_pan_field_for_india #2 diff --git a/erpnext/patches/v12_0/update_production_plan_status.py b/erpnext/patches/v12_0/update_production_plan_status.py new file mode 100644 index 0000000000..06fc503a33 --- /dev/null +++ b/erpnext/patches/v12_0/update_production_plan_status.py @@ -0,0 +1,31 @@ +# Copyright (c) 2021, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +import frappe + + +def execute(): + frappe.reload_doc("manufacturing", "doctype", "production_plan") + frappe.db.sql(""" + UPDATE `tabProduction Plan` ppl + SET status = "Completed" + WHERE ppl.name IN ( + SELECT ss.name FROM ( + SELECT + ( + count(wo.status = "Completed") = + count(pp.name) + ) = + ( + pp.status != "Completed" + AND pp.total_produced_qty >= pp.total_planned_qty + ) AS should_set, + pp.name AS name + FROM + `tabWork Order` wo INNER JOIN`tabProduction Plan` pp + ON wo.production_plan = pp.name + GROUP BY pp.name + HAVING should_set = 1 + ) ss + ) + """) From 0806e32049fee67b731cb8c742fc6654faae6143 Mon Sep 17 00:00:00 2001 From: Summayya Hashmani <58825865+sumaiya2908@users.noreply.github.com> Date: Wed, 27 Oct 2021 11:46:10 +0530 Subject: [PATCH 23/23] fix(ux): add naming series to ERPNext setting workspace (#28090) * fix(ux): add naming series to setting workspace * fix: doctype link to naming series Co-authored-by: Ankush Menat Co-authored-by: Summayya Co-authored-by: Ankush Menat --- .../workspace/erpnext_settings/erpnext_settings.json | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/erpnext/setup/workspace/erpnext_settings/erpnext_settings.json b/erpnext/setup/workspace/erpnext_settings/erpnext_settings.json index 320cb7ba84..1412acfcea 100644 --- a/erpnext/setup/workspace/erpnext_settings/erpnext_settings.json +++ b/erpnext/setup/workspace/erpnext_settings/erpnext_settings.json @@ -1,6 +1,6 @@ { "charts": [], - "content": "[{\"type\": \"header\", \"data\": {\"text\": \"Your Shortcuts\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Projects Settings\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Accounts Settings\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Stock Settings\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"HR Settings\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Selling Settings\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Buying Settings\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Support Settings\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Shopping Cart Settings\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Portal Settings\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Manufacturing Settings\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Education Settings\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Hotel Settings\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Healthcare Settings\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Domain Settings\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Products Settings\", \"col\": 4}}]", + "content": "[{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Projects Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"HR Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Selling Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Buying Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Support Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Shopping Cart Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Portal Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Domain Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Products Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Naming Series\",\"col\":4}}]", "creation": "2020-03-12 14:47:51.166455", "docstatus": 0, "doctype": "Workspace", @@ -10,7 +10,7 @@ "idx": 0, "label": "ERPNext Settings", "links": [], - "modified": "2021-08-05 12:15:59.052328", + "modified": "2021-10-26 21:32:55.323591", "modified_by": "Administrator", "module": "Setup", "name": "ERPNext Settings", @@ -27,6 +27,14 @@ "link_to": "Projects Settings", "type": "DocType" }, + { + "color": "Grey", + "doc_view": "", + "icon": "dot-horizontal", + "label": "Naming Series", + "link_to": "Naming Series", + "type": "DocType" + }, { "icon": "accounting", "label": "Accounts Settings",